[llvm] [InstCombine] Add transforms for `(or/and (icmp eq/ne X,0),(icmp eq/ne X,Pow2OrZero))` (PR #94648)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 8 09:58:13 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,
----------------
dtcxzyw wrote:

Yeah, but there is a phase ordering problem blocking this fold:
https://github.com/dtcxzyw/llvm-opt-benchmark/pull/667/files#r1632021232

What do you think of the following fold?
https://alive2.llvm.org/ce/z/tmkPvm
```
define i1 @src(i16 %x) {
 %35 = and i16 %x, 255
 call void @use(i16 %35)
  %36 = and i16 %x, 1
  %or.cond = icmp ne i16 %36, %35
  ret i1 %or.cond
}

define i1 @tgt(i16 %x) {
  %35 = and i16 %x, 255
  call void @use(i16 %35)
  %cmp = icmp ugt i16 %35, 1
  ret i1 %cmp
}

declare void @use(i16)
```

https://github.com/llvm/llvm-project/pull/94648


More information about the llvm-commits mailing list