Skip to content

Commit d252872

Browse files
author
git apple-llvm automerger
committed
Merge commit '35bd5ff4ca70' from llvm.org/release/19.x into stable/20240723
2 parents 1d2e2d1 + e73ad77 commit d252872

File tree

2 files changed

+55
-16
lines changed

2 files changed

+55
-16
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -926,32 +926,39 @@ static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
926926
}
927927

928928
/// Reduce a pair of compares that check if a value has exactly 1 bit set.
929-
/// Also used for logical and/or, must be poison safe.
929+
/// Also used for logical and/or, must be poison safe if range attributes are
930+
/// dropped.
930931
static Value *foldIsPowerOf2(ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
931-
InstCombiner::BuilderTy &Builder) {
932+
InstCombiner::BuilderTy &Builder,
933+
InstCombinerImpl &IC) {
932934
// Handle 'and' / 'or' commutation: make the equality check the first operand.
933935
if (JoinedByAnd && Cmp1->getPredicate() == ICmpInst::ICMP_NE)
934936
std::swap(Cmp0, Cmp1);
935937
else if (!JoinedByAnd && Cmp1->getPredicate() == ICmpInst::ICMP_EQ)
936938
std::swap(Cmp0, Cmp1);
937939

938940
// (X != 0) && (ctpop(X) u< 2) --> ctpop(X) == 1
939-
Value *X;
940-
if (JoinedByAnd &&
941-
match(Cmp0, m_SpecificICmp(ICmpInst::ICMP_NE, m_Value(X), m_ZeroInt())) &&
942-
match(Cmp1, m_SpecificICmp(ICmpInst::ICMP_ULT,
943-
m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
944-
m_SpecificInt(2)))) {
945-
Value *CtPop = Cmp1->getOperand(0);
941+
CmpInst::Predicate Pred0, Pred1;
942+
Value *X;
943+
if (JoinedByAnd && match(Cmp0, m_ICmp(Pred0, m_Value(X), m_ZeroInt())) &&
944+
match(Cmp1, m_ICmp(Pred1, m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
945+
m_SpecificInt(2))) &&
946+
Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_ULT) {
947+
auto *CtPop = cast<Instruction>(Cmp1->getOperand(0));
948+
// Drop range attributes and re-infer them in the next iteration.
949+
CtPop->dropPoisonGeneratingAnnotations();
950+
IC.addToWorklist(CtPop);
946951
return Builder.CreateICmpEQ(CtPop, ConstantInt::get(CtPop->getType(), 1));
947952
}
948953
// (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1
949-
if (!JoinedByAnd &&
950-
match(Cmp0, m_SpecificICmp(ICmpInst::ICMP_EQ, m_Value(X), m_ZeroInt())) &&
951-
match(Cmp1, m_SpecificICmp(ICmpInst::ICMP_UGT,
952-
m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
953-
m_SpecificInt(1)))) {
954-
Value *CtPop = Cmp1->getOperand(0);
954+
if (!JoinedByAnd && match(Cmp0, m_ICmp(Pred0, m_Value(X), m_ZeroInt())) &&
955+
match(Cmp1, m_ICmp(Pred1, m_Intrinsic<Intrinsic::ctpop>(m_Specific(X)),
956+
m_SpecificInt(1))) &&
957+
Pred0 == ICmpInst::ICMP_EQ && Pred1 == ICmpInst::ICMP_UGT) {
958+
auto *CtPop = cast<Instruction>(Cmp1->getOperand(0));
959+
// Drop range attributes and re-infer them in the next iteration.
960+
CtPop->dropPoisonGeneratingAnnotations();
961+
IC.addToWorklist(CtPop);
955962
return Builder.CreateICmpNE(CtPop, ConstantInt::get(CtPop->getType(), 1));
956963
}
957964
return nullptr;
@@ -3346,7 +3353,7 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
33463353
if (Value *V = foldSignedTruncationCheck(LHS, RHS, I, Builder))
33473354
return V;
33483355

3349-
if (Value *V = foldIsPowerOf2(LHS, RHS, IsAnd, Builder))
3356+
if (Value *V = foldIsPowerOf2(LHS, RHS, IsAnd, Builder, *this))
33503357
return V;
33513358

33523359
if (Value *V = foldPowerOf2AndShiftedMask(LHS, RHS, IsAnd, Builder))

llvm/test/Transforms/InstCombine/ispow2.ll

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,3 +1522,35 @@ define <2 x i1> @not_pow2_or_z_known_bits_fail_wrong_cmp(<2 x i32> %xin) {
15221522
%r = icmp ugt <2 x i32> %cnt, <i32 2, i32 2>
15231523
ret <2 x i1> %r
15241524
}
1525+
1526+
; Make sure that range attributes on return values are dropped after merging these two icmps
1527+
1528+
define i1 @has_single_bit(i32 %x) {
1529+
; CHECK-LABEL: @has_single_bit(
1530+
; CHECK-NEXT: entry:
1531+
; CHECK-NEXT: [[POPCNT:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
1532+
; CHECK-NEXT: [[SEL:%.*]] = icmp eq i32 [[POPCNT]], 1
1533+
; CHECK-NEXT: ret i1 [[SEL]]
1534+
;
1535+
entry:
1536+
%cmp1 = icmp ne i32 %x, 0
1537+
%popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
1538+
%cmp2 = icmp ult i32 %popcnt, 2
1539+
%sel = select i1 %cmp1, i1 %cmp2, i1 false
1540+
ret i1 %sel
1541+
}
1542+
1543+
define i1 @has_single_bit_inv(i32 %x) {
1544+
; CHECK-LABEL: @has_single_bit_inv(
1545+
; CHECK-NEXT: entry:
1546+
; CHECK-NEXT: [[POPCNT:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])
1547+
; CHECK-NEXT: [[SEL:%.*]] = icmp ne i32 [[POPCNT]], 1
1548+
; CHECK-NEXT: ret i1 [[SEL]]
1549+
;
1550+
entry:
1551+
%cmp1 = icmp eq i32 %x, 0
1552+
%popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)
1553+
%cmp2 = icmp ugt i32 %popcnt, 1
1554+
%sel = select i1 %cmp1, i1 true, i1 %cmp2
1555+
ret i1 %sel
1556+
}

0 commit comments

Comments
 (0)