aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2012-07-17 06:53:39 +0000
committerEvan Cheng <evan.cheng@apple.com>2012-07-17 06:53:39 +0000
commit70e10d3fe4c5df189348f64fce56254a5a32b51c (patch)
tree23550acde05b658d6b1b3ca3594121be0c51c3c1
parent06a27cc1aae20e3a2c985dd8dadab3b4ef5d032a (diff)
downloadexternal_llvm-70e10d3fe4c5df189348f64fce56254a5a32b51c.zip
external_llvm-70e10d3fe4c5df189348f64fce56254a5a32b51c.tar.gz
external_llvm-70e10d3fe4c5df189348f64fce56254a5a32b51c.tar.bz2
This is another case where instcombine demanded bits optimization created
large immediates. Add dag combine logic to recover in case the large immediates doesn't fit in cmp immediate operand field. int foo(unsigned long l) { return (l>> 47) == 1; } we produce %shr.mask = and i64 %l, -140737488355328 %cmp = icmp eq i64 %shr.mask, 140737488355328 %conv = zext i1 %cmp to i32 ret i32 %conv which codegens to movq $0xffff800000000000,%rax andq %rdi,%rax movq $0x0000800000000000,%rcx cmpq %rcx,%rax sete %al movzbl %al,%eax ret TargetLowering::SimplifySetCC would transform (X & -256) == 256 -> (X >> 8) == 1 if the immediate fails the isLegalICmpImmediate() test. For x86, that's immediates which are not a signed 32-bit immediate. Based on a patch by Eli Friedman. PR10328 rdar://9758774 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160346 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp21
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp8
-rw-r--r--lib/Target/X86/X86ISelLowering.h12
-rw-r--r--test/CodeGen/X86/cmp.ll21
4 files changed, 58 insertions, 4 deletions
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 891d401..9902ed7 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<ConstantSDNode>(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<ConstantFPSDNode>(N0.getNode())) {
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 1d72aad..347f197 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 41bdd06..1afe68a 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 c9c85ab..8343cec 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
+}