diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 891d401201f..9902ed76fa7 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2322,6 +2322,27 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, } } } + + if (!isLegalICmpImmediate(C1.getSExtValue())) { + // (X & -256) == 256 -> (X >> 8) == 1 + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + N0.getOpcode() == ISD::AND && N0.hasOneUse()) { + if (ConstantSDNode *AndRHS = + dyn_cast(N0.getOperand(1))) { + const APInt &AndRHSC = AndRHS->getAPIntValue(); + if ((-AndRHSC).isPowerOf2() && (AndRHSC & C1) == C1) { + unsigned ShiftBits = AndRHSC.countTrailingZeros(); + EVT ShiftTy = DCI.isBeforeLegalize() ? + getPointerTy() : getShiftAmountTy(N0.getValueType()); + EVT CmpTy = N0.getValueType(); + SDValue Shift = DAG.getNode(ISD::SRL, dl, CmpTy, N0.getOperand(0), + DAG.getConstant(ShiftBits, ShiftTy)); + SDValue CmpRHS = DAG.getConstant(C1.lshr(ShiftBits), CmpTy); + return DAG.getSetCC(dl, VT, Shift, CmpRHS, Cond); + } + } + } + } } if (isa(N0.getNode())) { diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 1d72aad6754..347f1977e71 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -11384,6 +11384,14 @@ bool X86TargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const { return true; } +bool X86TargetLowering::isLegalICmpImmediate(int64_t Imm) const { + return Imm == (int32_t)Imm; +} + +bool X86TargetLowering::isLegalAddImmediate(int64_t Imm) const { + return Imm == (int32_t)Imm; +} + bool X86TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { if (!VT1.isInteger() || !VT2.isInteger()) return false; diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 41bdd06f37e..1afe68ad67f 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -568,6 +568,18 @@ namespace llvm { /// by AM is legal for this target, for a load/store of the specified type. virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty)const; + /// isLegalICmpImmediate - Return true if the specified immediate is legal + /// icmp immediate, that is the target has icmp instructions which can + /// compare a register against the immediate without having to materialize + /// the immediate into a register. + virtual bool isLegalICmpImmediate(int64_t Imm) const; + + /// isLegalAddImmediate - Return true if the specified immediate is legal + /// add immediate, that is the target has add instructions which can + /// add a register and the immediate without having to materialize + /// the immediate into a register. + virtual bool isLegalAddImmediate(int64_t Imm) const; + /// isTruncateFree - Return true if it's free to truncate a value of /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in /// register EAX to i16 by referencing its sub-register AX. diff --git a/test/CodeGen/X86/cmp.ll b/test/CodeGen/X86/cmp.ll index c9c85abad85..8343cece459 100644 --- a/test/CodeGen/X86/cmp.ll +++ b/test/CodeGen/X86/cmp.ll @@ -91,7 +91,7 @@ F: } ; rdar://11866926 -define i32 @test7(i64 %res) nounwind uwtable readnone ssp { +define i32 @test7(i64 %res) nounwind { entry: ; CHECK: test7: ; CHECK-NOT: movabsq @@ -103,7 +103,7 @@ entry: ret i32 %lnot.ext } -define i32 @test8(i64 %res) nounwind uwtable readnone ssp { +define i32 @test8(i64 %res) nounwind { entry: ; CHECK: test8: ; CHECK-NOT: movabsq @@ -114,7 +114,7 @@ entry: ret i32 %lnot.ext } -define i32 @test9(i64 %res) nounwind uwtable readnone ssp { +define i32 @test9(i64 %res) nounwind { entry: ; CHECK: test9: ; CHECK-NOT: movabsq @@ -126,7 +126,7 @@ entry: ret i32 %lnot.ext } -define i32 @test10(i64 %res) nounwind uwtable readnone ssp { +define i32 @test10(i64 %res) nounwind { entry: ; CHECK: test10: ; CHECK-NOT: movabsq @@ -138,3 +138,16 @@ entry: ret i32 %lnot.ext } +; rdar://9758774 +define i32 @test11(i64 %l) nounwind { +entry: +; CHECK: test11: +; CHECK-NOT: movabsq +; CHECK-NOT: andq +; CHECK: shrq $47, %rdi +; CHECK: cmpq $1, %rdi + %shr.mask = and i64 %l, -140737488355328 + %cmp = icmp eq i64 %shr.mask, 140737488355328 + %conv = zext i1 %cmp to i32 + ret i32 %conv +}