[llvm] [llvm] [InstCombine] fold "icmp eq (X + (V - 1)) & -V, X" to "icmp eq 0, (and X, V - 1)" (PR #152851)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 10 09:24:01 PDT 2025
================
@@ -1320,6 +1320,67 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
return nullptr;
}
+// Fold icmp eq (num + (val - 1)) & -val, num
+// to
+// icmp eq 0, (and num, val - 1)
+// For value being power of two
+Instruction *InstCombinerImpl::foldNextMultiply(ICmpInst &Cmp) {
+ Value *Op0 = Cmp.getOperand(0);
+ Value *Neg, *Add, *Num, *Mask, *Value;
+ CmpPredicate Pred;
+ const APInt *NegConst, *MaskConst;
+
+ // Match num + neg
+ if (!match(Op0, m_OneUse(m_c_And(m_Value(Add), m_Value(Neg)))))
+ return nullptr;
+
+ // Match num & mask and handle commutative care
+ if (!match(Op0, m_c_And(m_c_Add(m_Value(Num), m_Value(Mask)), m_Value(Neg))))
+ return nullptr;
+
+ // Check the constant case
+ if (match(Neg, m_APInt(NegConst)) && match(Mask, m_APInt(MaskConst))) {
+ // Mask + 1 should be a power-of-two
+ if (!(*MaskConst + 1).isPowerOf2())
+ return nullptr;
+
+ // Neg = -(Mask + 1)
+ if (*NegConst != -(*MaskConst + 1))
+ return nullptr;
+ } else {
+ // Match neg = sub 0, val
+ if (!match(Neg, m_Sub(m_Zero(), m_Value(Value))))
+ return nullptr;
+
+ // mask = add %val, -1. No commutative here, since it's canonical
+ // representation for sub %val, -1
+ if (!match(Mask, m_Add(m_Value(Value), m_AllOnes()))) {
+ if (match(Num, m_Add(m_Value(Value), m_AllOnes()))) {
+ std::swap(Mask, Num);
+ } else {
+ return nullptr;
+ }
+ }
+
+ // Value should be a known power-of-two.
+ if (!isKnownToBeAPowerOfTwo(Value, false, &Cmp))
+ return nullptr;
+ }
+
+ // Verify that Add and Num are connected by ICmp.
+ if (!match(&Cmp, m_c_ICmp(Pred, m_Value(Add), m_Specific(Num))))
+ return nullptr;
----------------
dtcxzyw wrote:
```suggestion
```
Remember not to overwrite an assigned value with `m_Value`.
https://github.com/llvm/llvm-project/pull/152851
More information about the llvm-commits
mailing list