[llvm] [InstCombine] Add transforms for `(or/and (icmp eq/ne X,0),(icmp eq/ne X,Pow2OrZero))` (PR #94648)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 8 09:44:00 PDT 2024
================
@@ -701,6 +701,42 @@ Value *InstCombinerImpl::simplifyRangeCheck(ICmpInst *Cmp0, ICmpInst *Cmp1,
return Builder.CreateICmp(NewPred, Input, RangeEnd);
}
+// (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)
+static Value *
+foldAndOrOfICmpsWithPow2AndWithZero(InstCombiner::BuilderTy &Builder,
+ ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
+ const SimplifyQuery &Q) {
+ CmpInst::Predicate Pred = IsAnd ? CmpInst::ICMP_NE : CmpInst::ICMP_EQ;
+ // Make sure we have right compares for our op.
+ if (LHS->getPredicate() != Pred || RHS->getPredicate() != Pred)
+ return nullptr;
+
+ // Make it so we can match LHS against the (icmp eq/ne X, 0) just for
+ // simplicity.
+ if (match(RHS->getOperand(1), m_Zero()))
+ std::swap(LHS, RHS);
+
+ Value *Pow2, *Op;
+ // Match the desired pattern:
+ // LHS: (icmp eq/ne X, 0)
+ // RHS: (icmp eq/ne X, Pow2OrZero)
+ // We could potentially be more sophisticated than requiring LHS/RHS be
+ // one-use. We don't create additional instructions if only one of them is
+ // one-use. So cases where one is one-use and the other is two-use might be
+ // profitable.
+ if (!match(LHS, m_OneUse(m_ICmp(Pred, m_Value(Op), m_Zero()))) ||
+ !match(RHS, m_OneUse(m_c_ICmp(Pred, m_Specific(Op), m_Value(Pow2)))) ||
+ !isKnownToBeAPowerOfTwo(Pow2, Q.DL, /*OrZero=*/true, /*Depth=*/0, Q.AC,
----------------
goldsteinn wrote:
I guess it doesn't matter either way, it always turns into `x u> 1`: https://godbolt.org/z/4vE4nMKTb
although we should teach whichever pattern is looking at consecutative `ne` to handle that
https://github.com/llvm/llvm-project/pull/94648
More information about the llvm-commits
mailing list