[llvm] adf42df - [ValueTracking] peek through min/max to find isKnownToBeAPowerOfTwo

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 24 15:02:34 PDT 2021


Author: Sanjay Patel
Date: 2021-03-24T17:54:38-04:00
New Revision: adf42dff421c0509cc8d2fe103d6e6fe3a30f855

URL: https://github.com/llvm/llvm-project/commit/adf42dff421c0509cc8d2fe103d6e6fe3a30f855
DIFF: https://github.com/llvm/llvm-project/commit/adf42dff421c0509cc8d2fe103d6e6fe3a30f855.diff

LOG: [ValueTracking] peek through min/max to find isKnownToBeAPowerOfTwo

This is similar to the select logic just ahead of the new code.
Min/max choose exactly one value from the inputs, so if both of
those are a power-of-2, then the result must be a power-of-2.

This might help with D98152, but we likely still need other
pieces of the puzzle to avoid regressions.

The change in PatternMatch.h is needed to build with clang.
It's possible there is a better way to deal with the 'const'
incompatibities.

Differential Revision: https://reviews.llvm.org/D99276

Added: 
    

Modified: 
    llvm/include/llvm/IR/PatternMatch.h
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/InstSimplify/AndOrXor.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index 575eff4650e15..544d4187b3b27 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -1735,10 +1735,10 @@ struct MaxMin_match {
       return false;
     // At this point we have a select conditioned on a comparison.  Check that
     // it is the values returned by the select that are being compared.
-    Value *TrueVal = SI->getTrueValue();
-    Value *FalseVal = SI->getFalseValue();
-    Value *LHS = Cmp->getOperand(0);
-    Value *RHS = Cmp->getOperand(1);
+    auto *TrueVal = SI->getTrueValue();
+    auto *FalseVal = SI->getFalseValue();
+    auto *LHS = Cmp->getOperand(0);
+    auto *RHS = Cmp->getOperand(1);
     if ((TrueVal != LHS || FalseVal != RHS) &&
         (TrueVal != RHS || FalseVal != LHS))
       return false;

diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 798450056d12e..cd08c4e09a45e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1977,6 +1977,12 @@ bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
     return isKnownToBeAPowerOfTwo(SI->getTrueValue(), OrZero, Depth, Q) &&
            isKnownToBeAPowerOfTwo(SI->getFalseValue(), OrZero, Depth, Q);
 
+  // Peek through min/max.
+  if (match(V, m_MaxOrMin(m_Value(X), m_Value(Y)))) {
+    return isKnownToBeAPowerOfTwo(X, OrZero, Depth, Q) &&
+           isKnownToBeAPowerOfTwo(Y, OrZero, Depth, Q);
+  }
+
   if (OrZero && match(V, m_And(m_Value(X), m_Value(Y)))) {
     // A power of two and'd with anything is a power of two or zero.
     if (isKnownToBeAPowerOfTwo(X, /*OrZero*/ true, Depth, Q) ||

diff  --git a/llvm/test/Transforms/InstSimplify/AndOrXor.ll b/llvm/test/Transforms/InstSimplify/AndOrXor.ll
index 9940691453146..2e364a789675c 100644
--- a/llvm/test/Transforms/InstSimplify/AndOrXor.ll
+++ b/llvm/test/Transforms/InstSimplify/AndOrXor.ll
@@ -97,9 +97,7 @@ define i32 @pow2b_max(i32 %x, i32 %y) {
 ; CHECK-NEXT:    [[SHX:%.*]] = shl i32 2, [[X:%.*]]
 ; CHECK-NEXT:    [[SHY:%.*]] = shl i32 32, [[Y:%.*]]
 ; CHECK-NEXT:    [[M:%.*]] = call i32 @llvm.smax.i32(i32 [[SHX]], i32 [[SHY]])
-; CHECK-NEXT:    [[NEG:%.*]] = sub i32 0, [[M]]
-; CHECK-NEXT:    [[R:%.*]] = and i32 [[M]], [[NEG]]
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 [[M]]
 ;
   %shx = shl i32 2, %x
   %shy = shl i32 32, %y
@@ -133,12 +131,7 @@ define <2 x i32> @pow2_decrement_commute_vec(<2 x i32> %p) {
 
 define <2 x i32> @pow2_decrement_min_vec(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: @pow2_decrement_min_vec(
-; CHECK-NEXT:    [[P1:%.*]] = and <2 x i32> [[X:%.*]], <i32 2048, i32 2048>
-; CHECK-NEXT:    [[P2:%.*]] = shl <2 x i32> <i32 1, i32 1>, [[Y:%.*]]
-; CHECK-NEXT:    [[M:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[P1]], <2 x i32> [[P2]])
-; CHECK-NEXT:    [[A:%.*]] = add <2 x i32> [[M]], <i32 -1, i32 -1>
-; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[M]], [[A]]
-; CHECK-NEXT:    ret <2 x i32> [[R]]
+; CHECK-NEXT:    ret <2 x i32> zeroinitializer
 ;
   %p1 = and <2 x i32> %x, <i32 2048, i32 2048>
   %p2 = shl <2 x i32> <i32 1, i32 1>, %y


        


More information about the llvm-commits mailing list