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

via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 13 13:32:23 PST 2024


================
@@ -1672,6 +1672,115 @@ static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI,
   return nullptr;
 }
 
+static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
+                                     InstCombinerImpl &IC) {
+  ICmpInst::Predicate Pred = ICI->getPredicate();
+  if (!ICmpInst::isEquality(Pred))
+    return nullptr;
+
+  Value *TrueVal = SI.getTrueValue();
+  Value *FalseVal = SI.getFalseValue();
+  Value *CmpLHS = ICI->getOperand(0);
+  Value *CmpRHS = ICI->getOperand(1);
+
+  if (Pred == ICmpInst::ICMP_NE) {
+    Pred = ICmpInst::ICMP_EQ;
+    std::swap(TrueVal, FalseVal);
+  }
+
+  // Transform (X == C) ? X : Y -> (X == C) ? C : Y
+  // specific handling for Bitwise operation.
+  // https://alive2.llvm.org/ce/z/WW8iRR
+  // x&y -> (x|y) ^ (x^y)
+  // x|y -> (x&y) | (x^y)
+  // x^y -> (x|y) ^ (x&y)
+  Value *X, *Y;
+  if (!(match(CmpLHS, m_BitwiseLogic(m_Value(X), m_Value(Y)))) ||
+      !(match(TrueVal, m_BitwiseLogic(m_Specific(X), m_Specific(Y)))))
+    return nullptr;
+
+  Value *AllOnes = Constant::getAllOnesValue(TrueVal->getType());
+  Value *Null = Constant::getNullValue(TrueVal->getType());
+  Instruction *ISI = &cast<Instruction>(SI);
+  unsigned AndOps = Instruction::And, OrOps = Instruction::Or,
+           XorOps = Instruction::Xor, NoOps = 0;
+
+  auto matchFalseVal = [&](Value *FalseVal, Value *CmpRHS, Value *X, Value *Y,
+                           unsigned OuterOpc, unsigned InnerOpc, bool NotRHS) {
+    if (match(CmpRHS, m_Zero()))
+      return match(FalseVal, m_c_BinOp(InnerOpc, m_Specific(X), m_Specific(Y)));
+
+    if (NotRHS)
+      return match(FalseVal,
+                   m_c_BinOp(OuterOpc,
+                             m_c_BinOp(InnerOpc, m_Specific(X), m_Specific(Y)),
+                             m_Not(m_Specific(CmpRHS))));
+    else
+      return match(FalseVal,
+                   m_c_BinOp(OuterOpc,
+                             m_c_BinOp(InnerOpc, m_Specific(X), m_Specific(Y)),
+                             m_Specific(CmpRHS)));
+  };
+
+  // https://alive2.llvm.org/ce/z/EzU4sx
+  // (X&Y) == C ? X|Y : X^Y -> (X&Y) == C ? (X^Y) | C : X^Y
+  // (X&Y) == C ? X^Y : X|Y -> (X&Y) == C ? (X|Y) &~C : X|Y
+  // if C== 0, X^Y:X|Y -> ~0&X|Y:X|Y ->   X|Y, X|Y:X^Y ->  0|X^Y:X^Y ->   X^Y
+  // if C==-1, X^Y:X|Y ->~-1&X|Y:X|Y -> 0:X|Y, X|Y:X^Y -> -1|X^Y:X^Y ->-1:X^Y
+  // otherwise, X|Y:(X^Y)|C -> (X^Y)|C, X^Y:(X|Y)&~C -> (X|Y)&~C
+  if (match(CmpLHS, m_And(m_Value(X), m_Value(Y)))) {
+    if (match(TrueVal, m_c_Or(m_Specific(X), m_Specific(Y)))) {
+      if (matchFalseVal(FalseVal, CmpRHS, X, Y, NoOps, XorOps, false) ||
+          matchFalseVal(FalseVal, CmpRHS, X, Y, OrOps, XorOps, false))
+        return IC.replaceInstUsesWith(*ISI, FalseVal);
+      else if (match(CmpRHS, m_AllOnes()))
+        return IC.replaceOperand(SI, 1, AllOnes);
+    } else if (match(TrueVal, m_c_Xor(m_Specific(X), m_Specific(Y)))) {
+      if (matchFalseVal(FalseVal, CmpRHS, X, Y, NoOps, OrOps, false) ||
+          matchFalseVal(FalseVal, CmpRHS, X, Y, AndOps, OrOps, true))
+        return IC.replaceInstUsesWith(*ISI, FalseVal);
+      else if (match(CmpRHS, m_AllOnes()))
+        return IC.replaceOperand(SI, 1, Null);
+    }
+  }
+  // https://alive2.llvm.org/ce/z/MnTYwj
+  // (X | Y) == C ? X & Y : FV  ->  (X | Y) == C ? C ^ (X^Y) : FV
----------------
goldsteinn wrote:

FV is `X ^ Y` iirc

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


More information about the llvm-commits mailing list