[llvm] 5de89b4 - [ValueTracking] Support non-zero pow2 for shl with nowrap flags

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 7 08:05:10 PDT 2023


Author: Nikita Popov
Date: 2023-08-07T17:04:55+02:00
New Revision: 5de89b4d99c913e3c7c2735886f2519a2ed39d8a

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

LOG: [ValueTracking] Support non-zero pow2 for shl with nowrap flags

If the shl has either nuw or nsw flags, then we know that bits
cannot be shifted out, so a power of two cannot become zero.

Proofs: https://alive2.llvm.org/ce/z/4QfebE

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 6fa7d5fa9a9316..3198020c1a3813 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -2045,9 +2045,8 @@ bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
   case Instruction::ZExt:
     return isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q);
   case Instruction::Shl:
-    if (OrZero)
-      return isKnownToBeAPowerOfTwo(I->getOperand(0), /*OrZero*/ true, Depth,
-             Q);
+    if (OrZero || Q.IIQ.hasNoUnsignedWrap(I) || Q.IIQ.hasNoSignedWrap(I))
+      return isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q);
     return false;
   case Instruction::LShr:
     if (OrZero || Q.IIQ.isExact(cast<BinaryOperator>(I)))

diff  --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll
index b0fcdc572f2137..666d85d6cc3210 100644
--- a/llvm/test/Transforms/InstCombine/icmp.ll
+++ b/llvm/test/Transforms/InstCombine/icmp.ll
@@ -1885,10 +1885,9 @@ define i1 @icmp_and_shl_neg_ne_0_shl2_no_flags(i32 %A, i32 %B) {
 
 define i1 @icmp_and_shl_neg_ne_0_shl2_nuw(i32 %A, i32 %B) {
 ; CHECK-LABEL: @icmp_and_shl_neg_ne_0_shl2_nuw(
-; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[A:%.*]], -1
 ; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i32 2, [[B:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[SHL]], [[NEG]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[AND]], 0
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[SHL]], [[A:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %neg = xor i32 %A, -1
@@ -1900,14 +1899,13 @@ define i1 @icmp_and_shl_neg_ne_0_shl2_nuw(i32 %A, i32 %B) {
 
 define i1 @icmp_and_shl_neg_ne_0_shl2_nsw(i32 %A, i32 %B) {
 ; CHECK-LABEL: @icmp_and_shl_neg_ne_0_shl2_nsw(
-; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[A:%.*]], -1
-; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i32 2, [[B:%.*]]
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[SHL]], [[NEG]]
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[AND]], 0
+; CHECK-NEXT:    [[SHL:%.*]] = shl nsw i32 2, [[B:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[SHL]], [[A:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
   %neg = xor i32 %A, -1
-  %shl = shl nuw i32 2, %B
+  %shl = shl nsw i32 2, %B
   %and = and i32 %shl, %neg
   %cmp = icmp ne i32 %and, 0
   ret i1 %cmp


        


More information about the llvm-commits mailing list