]> granicus.if.org Git - llvm/commitdiff
[InstSimplify] simplify power-of-2 (single bit set) sequences
authorSanjay Patel <spatel@rotateright.com>
Thu, 20 Jun 2019 22:55:28 +0000 (22:55 +0000)
committerSanjay Patel <spatel@rotateright.com>
Thu, 20 Jun 2019 22:55:28 +0000 (22:55 +0000)
As discussed in PR42314:
https://bugs.llvm.org/show_bug.cgi?id=42314

Improving the canonicalization for these patterns:
rL363956
...means we should adjust/enhance the related simplification.

https://rise4fun.com/Alive/w1cp

  Name: isPow2 or zero
  %x = and i32 %xx, 2048
  %a = add i32 %x, -1
  %r = and i32 %a, %x
  =>
  %r = i32 0

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363997 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/InstructionSimplify.cpp
test/Transforms/InstSimplify/AndOrXor.ll

index ba76c5b047979fe26371a802a2f235a5545fe7e8..ce0b8a0fe64d80b7df91a9573afc13303506ec06 100644 (file)
@@ -1845,6 +1845,16 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
       return Op1;
   }
 
+  // This is a similar pattern used for checking if a value is a power-of-2:
+  // (A - 1) & A --> 0 (if A is a power-of-2 or 0)
+  // A & (A - 1) --> 0 (if A is a power-of-2 or 0)
+  if (match(Op0, m_Add(m_Specific(Op1), m_AllOnes())) &&
+      isKnownToBeAPowerOfTwo(Op1, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI, Q.DT))
+    return Constant::getNullValue(Op1->getType());
+  if (match(Op1, m_Add(m_Specific(Op0), m_AllOnes())) &&
+      isKnownToBeAPowerOfTwo(Op0, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI, Q.DT))
+    return Constant::getNullValue(Op0->getType());
+
   if (Value *V = simplifyAndOrOfCmps(Q, Op0, Op1, true))
     return V;
 
index e2c17e2402848fe1794c3e2b3ae2244f75c2923a..a5c8108d0a5dde5e089f57b2056e8757dfed8abe 100644 (file)
@@ -93,10 +93,7 @@ define i64 @pow2b(i32 %x) {
 
 define i32 @pow2_decrement(i32 %p) {
 ; CHECK-LABEL: @pow2_decrement(
-; CHECK-NEXT:    [[X:%.*]] = shl i32 1, [[P:%.*]]
-; CHECK-NEXT:    [[A:%.*]] = add i32 [[X]], -1
-; CHECK-NEXT:    [[R:%.*]] = and i32 [[A]], [[X]]
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 0
 ;
   %x = shl i32 1, %p
   %a = add i32 %x, -1
@@ -106,10 +103,7 @@ define i32 @pow2_decrement(i32 %p) {
 
 define <2 x i32> @pow2_decrement_commute_vec(<2 x i32> %p) {
 ; CHECK-LABEL: @pow2_decrement_commute_vec(
-; CHECK-NEXT:    [[X:%.*]] = and <2 x i32> [[P:%.*]], <i32 2048, i32 2048>
-; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[X]], <i32 -1, i32 -1>
-; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[X]], [[A]]
-; CHECK-NEXT:    ret <2 x i32> [[R]]
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
 ;
   %x = and <2 x i32> %p, <i32 2048, i32 2048>
   %a = add <2 x i32> %x, <i32 -1, i32 -1>