[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