[llvm] 9edc454 - [InstCombine] Drop range attributes in `foldIsPowerOf2OrZero` (#112178)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 14 05:52:58 PDT 2024
Author: Yingwei Zheng
Date: 2024-10-14T20:52:55+08:00
New Revision: 9edc454ee601e04500529c98b753d3bd8f427d01
URL: https://github.com/llvm/llvm-project/commit/9edc454ee601e04500529c98b753d3bd8f427d01
DIFF: https://github.com/llvm/llvm-project/commit/9edc454ee601e04500529c98b753d3bd8f427d01.diff
LOG: [InstCombine] Drop range attributes in `foldIsPowerOf2OrZero` (#112178)
Closes https://github.com/llvm/llvm-project/issues/112078.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/ispow2.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 453071f3f982cd..64bee4ab974ede 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -935,9 +935,11 @@ static Value *foldSignedTruncationCheck(ICmpInst *ICmp0, ICmpInst *ICmp1,
/// Fold (icmp eq ctpop(X) 1) | (icmp eq X 0) into (icmp ult ctpop(X) 2) and
/// fold (icmp ne ctpop(X) 1) & (icmp ne X 0) into (icmp ugt ctpop(X) 1).
-/// Also used for logical and/or, must be poison safe.
+/// Also used for logical and/or, must be poison safe if range attributes are
+/// dropped.
static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
- InstCombiner::BuilderTy &Builder) {
+ InstCombiner::BuilderTy &Builder,
+ InstCombinerImpl &IC) {
CmpInst::Predicate Pred0, Pred1;
Value *X;
if (!match(Cmp0, m_ICmp(Pred0, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
@@ -945,11 +947,19 @@ static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
!match(Cmp1, m_ICmp(Pred1, m_Specific(X), m_ZeroInt())))
return nullptr;
- Value *CtPop = Cmp0->getOperand(0);
- if (IsAnd && Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_NE)
+ auto *CtPop = cast<Instruction>(Cmp0->getOperand(0));
+ if (IsAnd && Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_NE) {
+ // Drop range attributes and re-infer them in the next iteration.
+ CtPop->dropPoisonGeneratingAnnotations();
+ IC.addToWorklist(CtPop);
return Builder.CreateICmpUGT(CtPop, ConstantInt::get(CtPop->getType(), 1));
- if (!IsAnd && Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_EQ)
+ }
+ if (!IsAnd && Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_EQ) {
+ // Drop range attributes and re-infer them in the next iteration.
+ CtPop->dropPoisonGeneratingAnnotations();
+ IC.addToWorklist(CtPop);
return Builder.CreateICmpULT(CtPop, ConstantInt::get(CtPop->getType(), 2));
+ }
return nullptr;
}
@@ -3362,9 +3372,9 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
/*IsLogical*/ false, Builder, Q))
return V;
- if (Value *V = foldIsPowerOf2OrZero(LHS, RHS, IsAnd, Builder))
+ if (Value *V = foldIsPowerOf2OrZero(LHS, RHS, IsAnd, Builder, *this))
return V;
- if (Value *V = foldIsPowerOf2OrZero(RHS, LHS, IsAnd, Builder))
+ if (Value *V = foldIsPowerOf2OrZero(RHS, LHS, IsAnd, Builder, *this))
return V;
// TODO: One of these directions is fine with logical and/or, the other could
diff --git a/llvm/test/Transforms/InstCombine/ispow2.ll b/llvm/test/Transforms/InstCombine/ispow2.ll
index 41649da847a7e7..348508769c581f 100644
--- a/llvm/test/Transforms/InstCombine/ispow2.ll
+++ b/llvm/test/Transforms/InstCombine/ispow2.ll
@@ -1546,3 +1546,29 @@ entry:
%sel = select i1 %cmp1, i1 true, i1 %cmp2
ret i1 %sel
}
+
+define i1 @is_power2_or_zero_with_range(i32 %x) {
+; CHECK-LABEL: @is_power2_or_zero_with_range(
+; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
+; CHECK-NEXT: [[RES:%.*]] = icmp ult i32 [[CTPOP]], 2
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %ctpop = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
+ %cmp = icmp eq i32 %ctpop, 1
+ %notzero = icmp eq i32 %x, 0
+ %res = select i1 %notzero, i1 true, i1 %cmp
+ ret i1 %res
+}
+
+define i1 @is_power2_or_zero_inv_with_range(i32 %x) {
+; CHECK-LABEL: @is_power2_or_zero_inv_with_range(
+; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
+; CHECK-NEXT: [[RES:%.*]] = icmp ugt i32 [[CTPOP]], 1
+; CHECK-NEXT: ret i1 [[RES]]
+;
+ %ctpop = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
+ %cmp = icmp ne i32 %ctpop, 1
+ %notzero = icmp ne i32 %x, 0
+ %res = select i1 %notzero, i1 %cmp, i1 false
+ ret i1 %res
+}
More information about the llvm-commits
mailing list