This is another case where instcombine demanded bits optimization created
authorEvan Cheng <evan.cheng@apple.com>
Tue, 17 Jul 2012 06:53:39 +0000 (06:53 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Tue, 17 Jul 2012 06:53:39 +0000 (06:53 +0000)
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

lib/CodeGen/SelectionDAG/TargetLowering.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
test/CodeGen/X86/cmp.ll

index 891d401201f2a5fd0a30dc77327ccdde8694c305..9902ed76fa78990eb9a956f40bd8c1fdad67c829 100644 (file)
@@ -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())) {
index 1d72aad6754fa29b6d6d89c8abe6c8a6d0aec641..347f1977e7136e0bafc1c324d79f9df64d2d8a94 100644 (file)
@@ -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;
index 41bdd06f37e3ee7410466e3c8f66ecc7ce0a81d1..1afe68ad67f0d8135e7db27c6586d7a8134f7a2e 100644 (file)
@@ -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.
index c9c85abad85837fffbdb21d4b86a4d41f9cd794f..8343cece4590c792e03aac91c5d555c4cf7dd4cd 100644 (file)
@@ -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
+}