[llvm] [InstCombine] Simplify and/or by replacing operands with constants (PR #77231)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 17 11:43:41 PST 2024


================
@@ -2179,6 +2179,62 @@ foldBitwiseLogicWithIntrinsics(BinaryOperator &I,
   }
 }
 
+// Try to simplify X | Y by replacing occurrences of Y in X with 0.
+// Similarly, simplify X & Y by replacing occurrences of Y in X with -1.
+// Return the simplified result of X if successful, and nullptr otherwise.
+static Value *simplifyAndOrWithOpReplaced(Value *X, Value *Y, bool IsAnd,
+                                          InstCombinerImpl &IC,
+                                          unsigned Depth = 0) {
+  if (isa<Constant>(X) || X == Y)
+    return nullptr;
+
+  auto RecursivelyReplaceUses = [&](Instruction::BinaryOps Opcode, Value *Op0,
+                                    Value *Op1) -> Value * {
+    if (Depth == 2)
+      return nullptr;
+
+    // TODO: Relax the one-use constraint to clean up existing hard-coded
+    // simplifications.
+    if (!X->hasOneUse())
+      return nullptr;
+    Value *NewOp0 = simplifyAndOrWithOpReplaced(Op0, Y, IsAnd, IC, Depth + 1);
+    Value *NewOp1 = simplifyAndOrWithOpReplaced(Op1, Y, IsAnd, IC, Depth + 1);
+    if (!NewOp0 && !NewOp1)
+      return nullptr;
+    return IC.Builder.CreateBinOp(Opcode, NewOp0 ? NewOp0 : Op0,
+                                  NewOp1 ? NewOp1 : Op1);
+  };
+
+  Value *Op0, *Op1;
+  if (match(X, m_And(m_Value(Op0), m_Value(Op1)))) {
+    if (Op0 == Y || Op1 == Y)
+      return IsAnd ? (Op0 == Y ? Op1 : Op0)
+                   : Constant::getNullValue(X->getType());
+    return RecursivelyReplaceUses(Instruction::And, Op0, Op1);
+  } else if (match(X, m_Or(m_Value(Op0), m_Value(Op1)))) {
+    if (Op0 == Y || Op1 == Y)
+      return IsAnd ? Constant::getAllOnesValue(X->getType())
+                   : (Op0 == Y ? Op1 : Op0);
+    return RecursivelyReplaceUses(Instruction::Or, Op0, Op1);
+  } else if (match(X, m_Xor(m_Value(Op0), m_Value(Op1)))) {
+    if (Op0 == Y || Op1 == Y) {
+      Value *V = Op0 == Y ? Op1 : Op0;
+      if (IsAnd) {
+        if (Value *NotV =
+                simplifyXorInst(V, Constant::getAllOnesValue(V->getType()),
+                                IC.getSimplifyQuery()))
+          return NotV;
+        if (X->hasOneUse())
----------------
goldsteinn wrote:

If this comes up you might try to freely invert `V` if the OneUseCheck fails.

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


More information about the llvm-commits mailing list