[PATCH] D14392: [ValueTracking] Teach isImpliedCondition a new bitwise trick

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 5 13:27:16 PST 2015


sanjoy created this revision.
sanjoy added reviewers: majnemer, reames, hfinkel.
sanjoy added a subscriber: llvm-commits.
sanjoy added a dependency: D14391: [ValueTracking] Add parameters to isImpliedCondition; NFC.

This change teaches isImpliedCondition to prove things like

  (A | 15) < L  ==>  (A | 14) < L

if the low 4 bits of A are known to be zero.

Depends on D14391

http://reviews.llvm.org/D14392

Files:
  lib/Analysis/ValueTracking.cpp
  test/Transforms/InstSimplify/implies.ll

Index: test/Transforms/InstSimplify/implies.ll
===================================================================
--- test/Transforms/InstSimplify/implies.ll
+++ test/Transforms/InstSimplify/implies.ll
@@ -127,6 +127,46 @@
   ret i1 %res
 }
 
+define i1 @test10(i32 %length.i, i32 %x.full) {
+; CHECK-LABEL: @test10(
+; CHECK:  ret i1 true
+
+  %x = and i32 %x.full, 4294901760  ;; 4294901760 == 0xffff0000
+  %large = or i32 %x, 100
+  %small = or i32 %x, 90
+  %known = icmp ult i32 %large, %length.i
+  %to.prove = icmp ult i32 %small, %length.i
+  %res = icmp ule i1 %known, %to.prove
+  ret i1 %res
+}
+
+define i1 @test11(i32 %length.i, i32 %x) {
+; CHECK-LABEL: @test11(
+; CHECK: %res = icmp ule i1 %known, %to.prove
+; CHECK: ret i1 %res
+
+  %large = or i32 %x, 100
+  %small = or i32 %x, 90
+  %known = icmp ult i32 %large, %length.i
+  %to.prove = icmp ult i32 %small, %length.i
+  %res = icmp ule i1 %known, %to.prove
+  ret i1 %res
+}
+
+define i1 @test12(i32 %length.i, i32 %x.full) {
+; CHECK-LABEL: @test12(
+; CHECK: %res = icmp ule i1 %known, %to.prove
+; CHECK: ret i1 %res
+
+  %x = and i32 %x.full, 4294901760  ;; 4294901760 == 0xffff0000
+  %large = or i32 %x, 65536 ;; 65536 == 0x00010000
+  %small = or i32 %x, 90
+  %known = icmp ult i32 %large, %length.i
+  %to.prove = icmp ult i32 %small, %length.i
+  %res = icmp ule i1 %known, %to.prove
+  ret i1 %res
+}
+
 ; X >=(s) Y == X ==> Y (i1 1 becomes -1 for reasoning)
 define i1 @test_sge(i32 %length.i, i32 %i) {
 ; CHECK-LABEL: @test_sge
Index: lib/Analysis/ValueTracking.cpp
===================================================================
--- lib/Analysis/ValueTracking.cpp
+++ lib/Analysis/ValueTracking.cpp
@@ -4119,6 +4119,36 @@
         return !CI->isZero();
       return true;
     }
+
+    // If the low K bits of X are known to be zero, and both C0 and C1
+    // fit in K bits, then
+    //
+    // (X | C0) u<  (X | C1)    iff C0 u<  C1
+    // (X | C0) u<= (X | C1)    iff C0 u<= C1
+    //
+    // Informally, the easiest way to justify this is to see that
+    // "X | C" if C fits in K bits (where the low K bits of X are
+    // zero) is equal to "X +_{nuw} C".  Then this rule is effectively
+    // the same as "C0 u< C1" ==> "(X +_{nuw} C0) u< (X +_{nuw} C1)".
+
+    Value *X;
+    ConstantInt *CI0, *CI1;
+    if (match(LHS, m_Or(m_Value(X), m_ConstantInt(CI0))) &&
+        match(RHS, m_Or(m_Specific(X), m_ConstantInt(CI1)))) {
+      unsigned BitWidth = cast<IntegerType>(LHS->getType())->getBitWidth();
+      APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0);
+      computeKnownBits(X, KnownZero, KnownOne, DL, Depth + 1, AC, CxtI, DT);
+
+      unsigned LowZeroes = KnownZero.countTrailingOnes();
+      APInt UpperLimit =
+          APInt::getBitsSet(KnownZero.getBitWidth(), LowZeroes, LowZeroes + 1);
+
+      if (UpperLimit.ugt(CI0->getValue()) && UpperLimit.ugt(CI1->getValue())) {
+        if (Pred == CmpInst::ICMP_ULE)
+          return CI0->getValue().ule(CI1->getValue());
+        return CI0->getValue().ult(CI1->getValue());
+      }
+    }
     return false;
   }
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D14392.39407.patch
Type: text/x-patch
Size: 3095 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151105/b2a5a615/attachment.bin>


More information about the llvm-commits mailing list