[llvm] [InstCombine] fold `(a == c && b != c) || (a != c && b == c))` to `(a == c) == (b != c)` (PR #94915)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 20 00:48:38 PDT 2024


================
@@ -3421,6 +3421,23 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
   return foldAndOrOfICmpsUsingRanges(LHS, RHS, IsAnd);
 }
 
+Value *foldAorBZero(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
+  Value *Op0 = I.getOperand(0);
+  Value *Op1 = I.getOperand(1);
+
+  Value *Cmp1, *Cmp2, *Cmp3, *Cmp4;
+  if (!match(Op0, m_OneUse(m_And(m_Value(Cmp1), m_Value(Cmp2)))) ||
+      !match(Op1, m_OneUse(m_And(m_Value(Cmp3), m_Value(Cmp4)))))
+    return nullptr;
+
+  // check if any two pairs of the and operations are invertions of each other.
+  if (!(isKnownInversion(Cmp1, Cmp3) && isKnownInversion(Cmp2, Cmp4)) &&
+      !(isKnownInversion(Cmp1, Cmp4) && isKnownInversion(Cmp2, Cmp3)))
+    return nullptr;
+
+  return Builder.CreateICmpEQ(Cmp1, Cmp2);
----------------
nikic wrote:

...with the caveat that icmp eq on bool actually gets canonicalized to two instructions: https://llvm.godbolt.org/z/K9c44ohjf

It may be better to instead produce `xor Cmp1, inv(Cmp2)` instead (where inv(Cmp2) is either Cmp3 or Cmp4). This ensures that we really only end up with one instruction.

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


More information about the llvm-commits mailing list