diff options
Diffstat (limited to 'lib/Target/X86/X86ISelLowering.cpp')
| -rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 67 |
1 files changed, 66 insertions, 1 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 05db7cb886..ebf9eecf20 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -5100,6 +5100,71 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) { Cond = Cmp; addTest = false; } + // Also, recognize the pattern generated by an FCMP_UNE. We can emit + // two branches instead of an explicit OR instruction with a + // separate test. + } else if (Cond.getOpcode() == ISD::OR && + Cond.hasOneUse() && + Cond.getOperand(0).getOpcode() == X86ISD::SETCC && + Cond.getOperand(0).hasOneUse() && + Cond.getOperand(1).getOpcode() == X86ISD::SETCC && + Cond.getOperand(1).hasOneUse()) { + SDValue Cmp = Cond.getOperand(0).getOperand(1); + unsigned Opc = Cmp.getOpcode(); + if (Cmp == Cond.getOperand(1).getOperand(1) && + (Opc == X86ISD::CMP || + Opc == X86ISD::COMI || + Opc == X86ISD::UCOMI)) { + CC = Cond.getOperand(0).getOperand(0); + Chain = DAG.getNode(X86ISD::BRCOND, Op.getValueType(), + Chain, Dest, CC, Cmp); + CC = Cond.getOperand(1).getOperand(0); + Cond = Cmp; + addTest = false; + } + // Also, recognize the pattern generated by an FCMP_OEQ. We can emit + // two branches instead of an explicit AND instruction with a + // separate test. However, we only do this if this block doesn't + // have a fall-through edge, because this requires an explicit + // jmp when the condition is false. + } else if (Cond.getOpcode() == ISD::AND && + Cond.hasOneUse() && + Cond.getOperand(0).getOpcode() == X86ISD::SETCC && + Cond.getOperand(0).hasOneUse() && + Cond.getOperand(1).getOpcode() == X86ISD::SETCC && + Cond.getOperand(1).hasOneUse()) { + SDValue Cmp = Cond.getOperand(0).getOperand(1); + unsigned Opc = Cmp.getOpcode(); + if (Cmp == Cond.getOperand(1).getOperand(1) && + (Opc == X86ISD::CMP || + Opc == X86ISD::COMI || + Opc == X86ISD::UCOMI) && + Op.getNode()->hasOneUse()) { + X86::CondCode CCode = + (X86::CondCode)Cond.getOperand(0).getConstantOperandVal(0); + CCode = X86::GetOppositeBranchCondition(CCode); + CC = DAG.getConstant(CCode, MVT::i8); + SDValue User = SDValue(*Op.getNode()->use_begin(), 0); + // Look for an unconditional branch following this conditional branch. + // We need this because we need to reverse the successors in order + // to implement FCMP_OEQ. + if (User.getOpcode() == ISD::BR) { + SDValue FalseBB = User.getOperand(1); + SDValue NewBR = + DAG.UpdateNodeOperands(User, User.getOperand(0), Dest); + assert(NewBR == User); + Dest = FalseBB; + + Chain = DAG.getNode(X86ISD::BRCOND, Op.getValueType(), + Chain, Dest, CC, Cmp); + X86::CondCode CCode = + (X86::CondCode)Cond.getOperand(1).getConstantOperandVal(0); + CCode = X86::GetOppositeBranchCondition(CCode); + CC = DAG.getConstant(CCode, MVT::i8); + Cond = Cmp; + addTest = false; + } + } } if (addTest) { @@ -5107,7 +5172,7 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) { Cond= DAG.getNode(X86ISD::CMP, MVT::i32, Cond, DAG.getConstant(0, MVT::i8)); } return DAG.getNode(X86ISD::BRCOND, Op.getValueType(), - Chain, Op.getOperand(2), CC, Cond); + Chain, Dest, CC, Cond); } |
