[llvm-branch-commits] [llvm] Backport "[InstCombine] Drop range attributes in `foldIsPowerOf2` (#111946)" (PR #111984)
Yingwei Zheng via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Oct 11 04:23:31 PDT 2024
https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/111984
Backport https://github.com/llvm/llvm-project/commit/6a65e98fa7901dc1de91172d065fafb16ce89d77.
As https://github.com/llvm/llvm-project/pull/100899 exists in 19.x code base, I guess 19.x is also a vulnerable version.
>From aaa8b792a82e29e8e5931a3c7705f623a1bb7e50 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 11 Oct 2024 18:19:21 +0800
Subject: [PATCH] [InstCombine] Drop range attributes in `foldIsPowerOf2`
(#111946)
Fixes https://github.com/llvm/llvm-project/issues/111934.
---
.../InstCombine/InstCombineAndOrXor.cpp | 18 ++++++++---
llvm/test/Transforms/InstCombine/ispow2.ll | 32 +++++++++++++++++++
2 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index f9caa4da44931a..3222e8298c3f0b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -926,9 +926,11 @@ static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
}
/// Reduce a pair of compares that check if a value has exactly 1 bit set.
-/// 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 *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
- InstCombiner::BuilderTy &Builder) {
+ InstCombiner::BuilderTy &Builder,
+ InstCombinerImpl &IC) {
// Handle 'and' / 'or' commutation: make the equality check the first operand.
if (JoinedByAnd && Cmp1->getPredicate() == ICmpInst::ICMP_NE)
std::swap(Cmp0, Cmp1);
@@ -942,7 +944,10 @@ static Value *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
match(Cmp1, m_ICmp(Pred1, m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
m_SpecificInt(2))) &&
Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_ULT) {
- Value *CtPop = Cmp1->getOperand(0);
+ auto *CtPop = cast<Instruction>(Cmp1->getOperand(0));
+ // Drop range attributes and re-infer them in the next iteration.
+ CtPop->dropPoisonGeneratingAnnotations();
+ IC.addToWorklist(CtPop);
return Builder.CreateICmpEQ(CtPop, ConstantInt::get(CtPop->getType(), 1));
}
// (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1
@@ -950,7 +955,10 @@ static Value *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
match(Cmp1, m_ICmp(Pred1, m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
m_SpecificInt(1))) &&
Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_UGT) {
- Value *CtPop = Cmp1->getOperand(0);
+ auto *CtPop = cast<Instruction>(Cmp1->getOperand(0));
+ // Drop range attributes and re-infer them in the next iteration.
+ CtPop->dropPoisonGeneratingAnnotations();
+ IC.addToWorklist(CtPop);
return Builder.CreateICmpNE(CtPop, ConstantInt::get(CtPop->getType(), 1));
}
return nullptr;
@@ -3347,7 +3355,7 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
if (Value *V = foldSignedTruncationCheck(LHS, RHS, I, Builder))
return V;
- if (Value *V = foldIsPowerOf2(LHS, RHS, IsAnd, Builder))
+ if (Value *V = foldIsPowerOf2(LHS, RHS, IsAnd, Builder, *this))
return V;
if (Value *V = foldPowerOf2AndShiftedMask(LHS, RHS, IsAnd, Builder))
diff --git a/llvm/test/Transforms/InstCombine/ispow2.ll b/llvm/test/Transforms/InstCombine/ispow2.ll
index a143b1347ccee5..216ccc5c77257b 100644
--- a/llvm/test/Transforms/InstCombine/ispow2.ll
+++ b/llvm/test/Transforms/InstCombine/ispow2.ll
@@ -1522,3 +1522,35 @@ define <2 x i1> @not_pow2_or_z_known_bits_fail_wrong_cmp(<2 x i32> %xin) {
%r = icmp ugt <2 x i32> %cnt, <i32 2, i32 2>
ret <2 x i1> %r
}
+
+; Make sure that range attributes on return values are dropped after merging these two icmps
+
+define i1 @has_single_bit(i32 %x) {
+; CHECK-LABEL: @has_single_bit(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[POPCNT:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
+; CHECK-NEXT: [[SEL:%.*]] = icmp eq i32 [[POPCNT]], 1
+; CHECK-NEXT: ret i1 [[SEL]]
+;
+entry:
+ %cmp1 = icmp ne i32 %x, 0
+ %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
+ %cmp2 = icmp ult i32 %popcnt, 2
+ %sel = select i1 %cmp1, i1 %cmp2, i1 false
+ ret i1 %sel
+}
+
+define i1 @has_single_bit_inv(i32 %x) {
+; CHECK-LABEL: @has_single_bit_inv(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[POPCNT:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
+; CHECK-NEXT: [[SEL:%.*]] = icmp ne i32 [[POPCNT]], 1
+; CHECK-NEXT: ret i1 [[SEL]]
+;
+entry:
+ %cmp1 = icmp eq i32 %x, 0
+ %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
+ %cmp2 = icmp ugt i32 %popcnt, 1
+ %sel = select i1 %cmp1, i1 true, i1 %cmp2
+ ret i1 %sel
+}
More information about the llvm-branch-commits
mailing list