[llvm] [InstCombine] Simplify select if it combinated `and/or/xor` (PR #73362)

via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 24 12:04:39 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-analysis

Author: hanbum (ParkHanbum)

<details>
<summary>Changes</summary>

- `(X & Y) == 0 ? X | Y : X ^ Y   --> X ^ Y`
- `(X | Y) == 0 ? X & Y : X ^ Y   --> X ^ Y`
- `(X ^ Y) == 0 ? X | Y : X & Y   --> X & Y`

certain combinations of bitwise operators can be simplified to returning the value of the True or False clause.

Proofs : https://alive2.llvm.org/ce/z/9jidcw

Fixed llvm#<!-- -->71792.


hello! It's an honor to send a PR to LLVM!
thanks for review first!

I'm sending this to get your opinion on whether it's okay to write a patch this way. 



---
Full diff: https://github.com/llvm/llvm-project/pull/73362.diff


1 Files Affected:

- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+67) 


``````````diff
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 7ef2ffd23b95e76..a69de0da8b6d046 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4425,6 +4425,48 @@ Value *llvm::simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
                                   RecursionLimit);
 }
 
+/// Try simplifying the selection command when condition, trueValue, and
+/// falseValue are combinations of special bitwise operators.
+static Value *simplifySelectBitTestSpec(Value *TrueVal, Value *FalseVal,
+                                        Value *X, Value *Y,
+                                        bool TrueWhenUnset) {
+  // (X & Y) == 0 ? X | Y : X ^ Y   --> X ^ Y
+  // (X & Y) == 0 ? X ^ Y : X | Y   --> X | Y
+  // (X & Y) == 1 ? X | Y : X ^ Y   --> X | Y
+  // (X & Y) == 1 ? X ^ Y : X | Y   --> X ^ Y
+  if (match(TrueVal, m_Or(m_Specific(X), m_Specific(Y))) &&
+      match(FalseVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+    return TrueWhenUnset ? TrueVal : FalseVal;
+  } else if (match(FalseVal, m_Or(m_Specific(X), m_Specific(Y))) &&
+             match(TrueVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+    return TrueWhenUnset ? TrueVal : FalseVal;
+  }
+  // (X | Y) == 0 ? X & Y : X ^ Y   --> X ^ Y
+  // (X | Y) == 0 ? X ^ Y : X & Y   --> X & Y
+  // (X | Y) == 1 ? X & Y : X ^ Y   --> X & Y
+  // (X | Y) == 1 ? X ^ Y : X & Y   --> X ^ Y
+  if (match(TrueVal, m_And(m_Specific(X), m_Specific(Y))) &&
+      match(FalseVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+    return TrueWhenUnset ? TrueVal : FalseVal;
+  } else if (match(FalseVal, m_And(m_Specific(X), m_Specific(Y))) &&
+             match(TrueVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+    return TrueWhenUnset ? TrueVal : FalseVal;
+  }
+  // (X ^ Y) == 0 ? X | Y : X & Y   --> X & Y
+  // (X ^ Y) == 0 ? X & Y : X | Y   --> X | Y
+  // (X ^ Y) == 1 ? X | Y : X & Y   --> X | Y
+  // (X ^ Y) == 1 ? X & Y : X | Y   --> X & Y
+  if (match(TrueVal, m_Or(m_Specific(X), m_Specific(Y))) &&
+      match(FalseVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+    return TrueWhenUnset ? TrueVal : FalseVal;
+  } else if (match(FalseVal, m_Or(m_Specific(X), m_Specific(Y))) &&
+             match(TrueVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+    return TrueWhenUnset ? TrueVal : FalseVal;
+  }
+
+  return nullptr;
+}
+
 /// Try to simplify a select instruction when its condition operand is an
 /// integer comparison where one operand of the compare is a constant.
 static Value *simplifySelectBitTest(Value *TrueVal, Value *FalseVal, Value *X,
@@ -4572,12 +4614,37 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
                                          unsigned MaxRecurse) {
   ICmpInst::Predicate Pred;
   Value *CmpLHS, *CmpRHS;
+  const APInt *C;
   if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
     return nullptr;
 
   if (Value *V = simplifyCmpSelOfMaxMin(CmpLHS, CmpRHS, Pred, TrueVal, FalseVal))
     return V;
 
+  if (ICmpInst::isEquality(Pred) && match(CmpRHS, m_APInt(C)) &&
+      (C->isZero() | C->isOne())) {
+    bool which;
+    Value *X, *Y;
+
+    if (Pred == ICmpInst::ICMP_EQ)
+      which = C->isZero() ? false : true;
+    else
+      which = C->isZero() ? true : false;
+
+    if (match(CmpLHS, m_And(m_Value(X), m_Value(Y)))) {
+      if (Value *V = simplifySelectBitTestSpec(TrueVal, FalseVal, X, Y, which))
+        return V;
+    }
+    if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y)))) {
+      if (Value *V = simplifySelectBitTestSpec(TrueVal, FalseVal, X, Y, which))
+        return V;
+    }
+    if (match(CmpLHS, m_Xor(m_Value(X), m_Value(Y)))) {
+      if (Value *V = simplifySelectBitTestSpec(TrueVal, FalseVal, X, Y, which))
+        return V;
+    }
+  }
+
   // Canonicalize ne to eq predicate.
   if (Pred == ICmpInst::ICMP_NE) {
     Pred = ICmpInst::ICMP_EQ;

``````````

</details>


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


More information about the llvm-commits mailing list