Index: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp @@ -19491,29 +19491,52 @@ if (isNullConstant(Op1)) return EmitTest(Op0, X86CC, dl, DAG, Subtarget); - if ((Op0.getValueType() == MVT::i8 || Op0.getValueType() == MVT::i16 || - Op0.getValueType() == MVT::i32 || Op0.getValueType() == MVT::i64)) { - // Only promote the compare up to I32 if it is a 16 bit operation - // with an immediate. 16 bit immediates are to be avoided. - if (Op0.getValueType() == MVT::i16 && - ((isa(Op0) && - !cast(Op0)->getAPIntValue().isSignedIntN(8)) || - (isa(Op1) && - !cast(Op1)->getAPIntValue().isSignedIntN(8))) && - !DAG.getMachineFunction().getFunction().hasMinSize() && - !Subtarget.isAtom()) { + EVT CmpVT = Op0.getValueType(); + + if (CmpVT.isFloatingPoint()) + return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op0, Op1); + + assert((CmpVT == MVT::i8 || CmpVT == MVT::i16 || + CmpVT == MVT::i32 || CmpVT == MVT::i64) && "Unexpected VT!"); + + // Only promote the compare up to I32 if it is a 16 bit operation + // with an immediate. 16 bit immediates are to be avoided. + if (CmpVT == MVT::i16 && !Subtarget.isAtom() && + !DAG.getMachineFunction().getFunction().hasMinSize()) { + ConstantSDNode *COp0 = dyn_cast(Op0); + ConstantSDNode *COp1 = dyn_cast(Op1); + // Don't do this if the immediate can fit in 8-bits. + if ((COp0 && !COp0->getAPIntValue().isSignedIntN(8)) || + (COp1 && !COp1->getAPIntValue().isSignedIntN(8))) { unsigned ExtendOp = isX86CCUnsigned(X86CC) ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND; - Op0 = DAG.getNode(ExtendOp, dl, MVT::i32, Op0); - Op1 = DAG.getNode(ExtendOp, dl, MVT::i32, Op1); + if (X86CC == X86::COND_E || X86CC == X86::COND_NE) { + // For equality comparisons try to use SIGN_EXTEND if the input was + // truncate from something with enough sign bits. + if (Op0.getOpcode() == ISD::TRUNCATE) { + SDValue In = Op0.getOperand(0); + unsigned EffBits = + In.getScalarValueSizeInBits() - DAG.ComputeNumSignBits(In) + 1; + if (EffBits <= 16) + ExtendOp = ISD::SIGN_EXTEND; + } else if (Op1.getOpcode() == ISD::TRUNCATE) { + SDValue In = Op1.getOperand(0); + unsigned EffBits = + In.getScalarValueSizeInBits() - DAG.ComputeNumSignBits(In) + 1; + if (EffBits <= 16) + ExtendOp = ISD::SIGN_EXTEND; + } + } + + CmpVT = MVT::i32; + Op0 = DAG.getNode(ExtendOp, dl, CmpVT, Op0); + Op1 = DAG.getNode(ExtendOp, dl, CmpVT, Op1); } - // Use SUB instead of CMP to enable CSE between SUB and CMP. - SDVTList VTs = DAG.getVTList(Op0.getValueType(), MVT::i32); - SDValue Sub = DAG.getNode(X86ISD::SUB, dl, VTs, Op0, Op1); - return SDValue(Sub.getNode(), 1); } - assert(Op0.getValueType().isFloatingPoint() && "Unexpected VT!"); - return DAG.getNode(X86ISD::CMP, dl, MVT::i32, Op0, Op1); + // Use SUB instead of CMP to enable CSE between SUB and CMP. + SDVTList VTs = DAG.getVTList(CmpVT, MVT::i32); + SDValue Sub = DAG.getNode(X86ISD::SUB, dl, VTs, Op0, Op1); + return Sub.getValue(1); } /// Convert a comparison if required by the subtarget. Index: llvm/trunk/test/CodeGen/X86/cmp.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/cmp.ll +++ llvm/trunk/test/CodeGen/X86/cmp.ll @@ -483,3 +483,42 @@ %9 = insertvalue { i64, i64 } %8, i64 %6, 1 ret { i64, i64 } %9 } + +; Make sure we use a 32-bit comparison without an extend based on the input +; being pre-sign extended by caller. +define i32 @pr42189(i16 signext %c) { +; CHECK-LABEL: pr42189: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: cmpl $32767, %edi # encoding: [0x81,0xff,0xff,0x7f,0x00,0x00] +; CHECK-NEXT: # imm = 0x7FFF +; CHECK-NEXT: jne .LBB26_2 # encoding: [0x75,A] +; CHECK-NEXT: # fixup A - offset: 1, value: .LBB26_2-1, kind: FK_PCRel_1 +; CHECK-NEXT: # %bb.1: # %if.then +; CHECK-NEXT: jmp g # TAILCALL +; CHECK-NEXT: # encoding: [0xeb,A] +; CHECK-NEXT: # fixup A - offset: 1, value: g-1, kind: FK_PCRel_1 +; CHECK-NEXT: .LBB26_2: # %if.end +; CHECK-NEXT: jmp f # TAILCALL +; CHECK-NEXT: # encoding: [0xeb,A] +; CHECK-NEXT: # fixup A - offset: 1, value: f-1, kind: FK_PCRel_1 +entry: + %cmp = icmp eq i16 %c, 32767 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + %call = tail call i32 @g() + br label %return + +if.end: ; preds = %entry + %call2 = tail call i32 @f() + br label %return + +return: ; preds = %if.end, %if.then + %retval.0 = phi i32 [ %call, %if.then ], [ %call2, %if.end ] + ret i32 %retval.0 +} + +declare i32 @g() + +declare i32 @f() +