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

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 10 01:17:08 PST 2024


================
@@ -4425,6 +4425,61 @@ 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 *CmpLHS, Value *CmpRHS,
+                                        Value *TrueVal, Value *FalseVal) {
+  Value *X, *Y;
+  // (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
+  // (X & Y) != 0 ? X ^ Y : X | Y   --> X ^ Y
+  if (match(CmpLHS, m_c_And(m_Value(X), m_Value(Y))) &&
+      match(CmpRHS, m_Zero())) {
+    if (match(TrueVal, m_c_Or(m_Specific(X), m_Specific(Y))) &&
+        match(FalseVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) {
+      return FalseVal;
+    } else if (match(FalseVal, m_c_Or(m_Specific(X), m_Specific(Y))) &&
+               match(TrueVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) {
+      return FalseVal;
+    }
----------------
ParkHanbum wrote:

As you know, the first patch I made tested whether it was eq or ne. The reason for this change is because before the current function is called, 

when ne was came, there is code that changes ne to eq while exchange true and false clause.

so, I think it will return `X | Y` at your example `(X & Y) != 0 ? X | Y : X ^ Y `. 

you can check code that exchange true and false clause from InstructiohnSimplify.cpp:4636
```
  // Canonicalize ne to eq predicate.
  if (Pred == ICmpInst::ICMP_NE) {
    Pred = ICmpInst::ICMP_EQ;
    std::swap(TrueVal, FalseVal);
  }
```
and you can check tests same as your example here:
select.ll:1682
```
; X&Y!=0 ? X|Y : X^Y  -> X|Y
define i32 @src_select_and_ne0_or_xor(i32 %x, i32 %y) {
; CHECK-LABEL: @src_select_and_ne0_or_xor(
; CHECK-NEXT:   [[OR:%.*]] = or i32 [[X]], [[Y]]
; CHECK-NEXT:   ret i32 [[OR:%.*]]
  %and = and i32 %x, %y
  %and1 = icmp ne i32 %and, 0
  %xor = xor i32 %x, %y
  %or = or i32 %x, %y
  %cond = select i1 %and1, i32 %or, i32 %xor
  ret i32 %cond
}
```

how do you think ?

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


More information about the llvm-commits mailing list