diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 203a589ab68..b8fc7e66125 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -5887,10 +5887,33 @@ SDValue X86TargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const { return DAG.getNode(X86ISD::FOR, dl, VT, Val, SignBit); } +// getSetCCPromoteOpcode - Return the opcode that should be used to promote +// operands of a setcc. FIXME: See DAGTypeLegalizer::PromoteSetCCOperands. +static unsigned getSetCCPromoteOpcode(ISD::CondCode CC) { + switch (CC) { + default: return 0; + case ISD::SETEQ: + case ISD::SETNE: + case ISD::SETUGE: + case ISD::SETUGT: + case ISD::SETULE: + case ISD::SETULT: + // ALL of these operations will work if we either sign or zero extend + // the operands (including the unsigned comparisons!). Zero extend is + // usually a simpler/cheaper operation, so prefer it. + return ISD::ZERO_EXTEND; + case ISD::SETGE: + case ISD::SETGT: + case ISD::SETLT: + case ISD::SETLE: + return ISD::SIGN_EXTEND; + } +} + /// Emit nodes that will be selected as "test Op0,Op0", or something /// equivalent. SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, - SelectionDAG &DAG) const { + ISD::CondCode CC, SelectionDAG &DAG) const { DebugLoc dl = Op.getDebugLoc(); // CF and OF aren't always set the way we want. Determine which @@ -6014,8 +6037,13 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, } // Otherwise just emit a CMP with 0, which is the TEST pattern. - if (Subtarget->shouldPromote16Bit() && Op.getValueType() == MVT::i16) - Op = DAG.getNode(ISD::ANY_EXTEND, Op.getDebugLoc(), MVT::i32, Op); + EVT PVT; + if (Subtarget->shouldPromote16Bit() && Op.getValueType() == MVT::i16 && + (isa(Op) || IsDesirableToPromoteOp(Op, PVT))) { + unsigned POpc = getSetCCPromoteOpcode(CC); + if (POpc) + Op = DAG.getNode(POpc, Op.getDebugLoc(), MVT::i32, Op); + } return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op, DAG.getConstant(0, Op.getValueType())); } @@ -6023,15 +6051,21 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, /// Emit nodes that will be selected as "cmp Op0,Op1", or something /// equivalent. SDValue X86TargetLowering::EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC, - SelectionDAG &DAG) const { + ISD::CondCode CC, SelectionDAG &DAG) const { if (ConstantSDNode *C = dyn_cast(Op1)) if (C->getAPIntValue() == 0) - return EmitTest(Op0, X86CC, DAG); + return EmitTest(Op0, X86CC, CC, DAG); DebugLoc dl = Op0.getDebugLoc(); - if (Subtarget->shouldPromote16Bit() && Op0.getValueType() == MVT::i16) { - Op0 = DAG.getNode(ISD::ANY_EXTEND, Op0.getDebugLoc(), MVT::i32, Op0); - Op1 = DAG.getNode(ISD::ANY_EXTEND, Op1.getDebugLoc(), MVT::i32, Op1); + EVT PVT; + if (Subtarget->shouldPromote16Bit() && Op0.getValueType() == MVT::i16 && + (isa(Op0) || IsDesirableToPromoteOp(Op0, PVT)) && + (isa(Op1) || IsDesirableToPromoteOp(Op1, PVT))) { + unsigned POpc = getSetCCPromoteOpcode(CC); + if (POpc) { + Op0 = DAG.getNode(POpc, Op0.getDebugLoc(), MVT::i32, Op0); + Op1 = DAG.getNode(POpc, Op1.getDebugLoc(), MVT::i32, Op1); + } } return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op0, Op1); } @@ -6134,7 +6168,7 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { if (X86CC == X86::COND_INVALID) return SDValue(); - SDValue Cond = EmitCmp(Op0, Op1, X86CC, DAG); + SDValue Cond = EmitCmp(Op0, Op1, X86CC, CC, DAG); // Use sbb x, x to materialize carry bit into a GPR. if (X86CC == X86::COND_B) @@ -6367,7 +6401,7 @@ SDValue X86TargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { if (addTest) { CC = DAG.getConstant(X86::COND_NE, MVT::i8); - Cond = EmitTest(Cond, X86::COND_NE, DAG); + Cond = EmitTest(Cond, X86::COND_NE, ISD::SETNE, DAG); } // X86ISD::CMOV means set the result (which is operand 1) to the RHS if @@ -6541,7 +6575,7 @@ SDValue X86TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { if (addTest) { CC = DAG.getConstant(X86::COND_NE, MVT::i8); - Cond = EmitTest(Cond, X86::COND_NE, DAG); + Cond = EmitTest(Cond, X86::COND_NE, ISD::SETNE, DAG); } return DAG.getNode(X86ISD::BRCOND, dl, Op.getValueType(), Chain, Dest, CC, Cond); diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 00d63960ef0..7996184f33f 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -815,11 +815,12 @@ namespace llvm { /// Emit nodes that will be selected as "test Op0,Op0", or something /// equivalent, for use with the given x86 condition code. - SDValue EmitTest(SDValue Op0, unsigned X86CC, SelectionDAG &DAG) const; + SDValue EmitTest(SDValue Op0, unsigned X86CC, ISD::CondCode CC, + SelectionDAG &DAG) const; /// Emit nodes that will be selected as "cmp Op0,Op1", or something /// equivalent, for use with the given x86 condition code. - SDValue EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC, + SDValue EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC, ISD::CondCode CC, SelectionDAG &DAG) const; };