Skip to content

Commit

Permalink
[InstCombine] Drop range attributes in foldIsPowerOf2OrZero (llvm#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
dtcxzyw authored and DanielCChen committed Oct 16, 2024
1 parent a180562 commit 5aa39a6
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
24 changes: 17 additions & 7 deletions llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -935,21 +935,31 @@ 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)),
m_SpecificInt(1))) ||
!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;
}
Expand Down Expand Up @@ -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
Expand Down
26 changes: 26 additions & 0 deletions llvm/test/Transforms/InstCombine/ispow2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit 5aa39a6

Please sign in to comment.