Skip to content

Commit 71aa5ab

Browse files
committed
[InstCombine] Add transforms for (or/and (icmp eq/ne X,0),(icmp eq/ne X,Pow2OrZero))
`(or (icmp eq X, 0), (icmp eq X, Pow2OrZero))` --> `(icmp eq (and X, Pow2OrZero), X)` `(and (icmp ne X, 0), (icmp ne X, Pow2OrZero))` --> `(icmp ne (and X, Pow2OrZero), X)` Proofs: https://alive2.llvm.org/ce/z/nPo2BN
1 parent b93b909 commit 71aa5ab

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,43 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
701701
return Builder.CreateICmp(NewPred, Input, RangeEnd);
702702
}
703703

704+
// (or (icmp eq X, 0), (icmp eq X, Pow2OrZero))
705+
// -> (icmp eq (and X, Pow2OrZero), X)
706+
// (and (icmp ne X, 0), (icmp ne X, Pow2OrZero))
707+
// -> (icmp ne (and X, Pow2OrZero), X)
708+
static Value *
709+
foldAndOrOfICmpsWithPow2AndWithZero(InstCombiner::BuilderTy &Builder,
710+
ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
711+
const SimplifyQuery &Q) {
712+
CmpInst::Predicate Pred = IsAnd ? CmpInst::ICMP_NE : CmpInst::ICMP_EQ;
713+
// Make sure we have right compares for our op.
714+
if (LHS->getPredicate() != Pred || RHS->getPredicate() != Pred)
715+
return nullptr;
716+
717+
// Make it so we can match LHS against the (icmp eq/ne X, 0) just for
718+
// simplicity.
719+
if (match(RHS->getOperand(1), m_Zero()))
720+
std::swap(LHS, RHS);
721+
722+
Value *Pow2, *Op;
723+
// Match the desired pattern:
724+
// LHS: (icmp eq/ne X, 0)
725+
// RHS: (icmp eq/ne X, Pow2OrZero)
726+
// We could potentially be more sophisticated than requiring LHS/RHS be
727+
// one-use. We don't create additional instructions if only one of them is
728+
// one-use. So cases where one is one-use and the other is two-use might be
729+
// profitable.
730+
if (!match(LHS, m_OneUse(m_ICmp(Pred, m_Value(Op), m_Zero()))) ||
731+
!match(RHS, m_OneUse(m_c_ICmp(Pred, m_Specific(Op), m_Value(Pow2)))) ||
732+
!match(Pow2, m_One()) ||
733+
!isKnownToBeAPowerOfTwo(Pow2, Q.DL, /*OrZero=*/true, /*Depth=*/0, Q.AC,
734+
Q.CxtI, Q.DT))
735+
return nullptr;
736+
737+
Value *And = Builder.CreateAnd(Op, Pow2);
738+
return Builder.CreateICmp(Pred, And, Op);
739+
}
740+
704741
// Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2)
705742
// Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2)
706743
Value *InstCombinerImpl::foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS,
@@ -3240,6 +3277,11 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
32403277
ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
32413278
Value *LHS0 = LHS->getOperand(0), *RHS0 = RHS->getOperand(0);
32423279
Value *LHS1 = LHS->getOperand(1), *RHS1 = RHS->getOperand(1);
3280+
if (!IsLogical)
3281+
if (Value *V =
3282+
foldAndOrOfICmpsWithPow2AndWithZero(Builder, LHS, RHS, IsAnd, Q))
3283+
return V;
3284+
32433285
const APInt *LHSC = nullptr, *RHSC = nullptr;
32443286
match(LHS1, m_APInt(LHSC));
32453287
match(RHS1, m_APInt(RHSC));

0 commit comments

Comments
 (0)