[llvm] r182200 - isKnownToBeAPowerOfTwo: (X & Y) + Y is a power of 2 or zero if y is also.

David Majnemer david.majnemer at gmail.com
Sat May 18 12:30:37 PDT 2013


Author: majnemer
Date: Sat May 18 14:30:37 2013
New Revision: 182200

URL: http://llvm.org/viewvc/llvm-project?rev=182200&view=rev
Log:
isKnownToBeAPowerOfTwo: (X & Y) + Y is a power of 2 or zero if y is also.

This is useful if something that looks like (x & (1 << y)) ? 64 : 32 is
the divisor in a modulo operation.

Modified:
    llvm/trunk/lib/Analysis/ValueTracking.cpp
    llvm/trunk/test/Transforms/InstCombine/rem.ll

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=182200&r1=182199&r2=182200&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Sat May 18 14:30:37 2013
@@ -855,6 +855,17 @@ bool llvm::isKnownToBeAPowerOfTwo(Value
     return false;
   }
 
+  // Adding a power of two to the same power of two is a power of two or zero.
+  if (OrZero && match(V, m_Add(m_Value(X), m_Value(Y)))) {
+    if (match(X, m_And(m_Value(), m_Specific(Y)))) {
+      if (isKnownToBeAPowerOfTwo(Y, /*OrZero*/true, Depth))
+        return true;
+    } else if (match(Y, m_And(m_Value(), m_Specific(X)))) {
+      if (isKnownToBeAPowerOfTwo(X, /*OrZero*/true, Depth))
+        return true;
+    }
+  }
+
   // An exact divide or right shift can only shift off zero bits, so the result
   // is a power of two only if the first operand is a power of two and not
   // copying a sign bit (sdiv int_min, 2).

Modified: llvm/trunk/test/Transforms/InstCombine/rem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/rem.ll?rev=182200&r1=182199&r2=182200&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/rem.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/rem.ll Sat May 18 14:30:37 2013
@@ -149,3 +149,17 @@ define i64 @test15(i32 %x, i32 %y) {
 	%urem = urem i64 %zext1, %zext0
 	ret i64 %urem
 }
+
+define i32 @test16(i32 %x, i32 %y) {
+; CHECK: @test16
+; CHECK-NEXT: [[SHR:%.*]] = lshr i32 %y, 11
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHR]], 4
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[AND]], 3
+; CHECK-NEXT: [[REM:%.*]] = and i32 [[OR]], %x
+; CHECK-NEXT: ret i32 [[REM]]
+	%shr = lshr i32 %y, 11
+	%and = and i32 %shr, 4
+	%add = add i32 %and, 4
+	%rem = urem i32 %x, %add
+	ret i32 %rem
+}





More information about the llvm-commits mailing list