[clang] [llvm] [InstCombine] Fold `X > C2 ? X + C1 : C2 + C1` to `max(X, C2) + C1` (PR #116888)

Yingwei Zheng via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 25 23:47:58 PST 2024


================
@@ -1898,6 +1882,55 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
   return nullptr;
 }
 
+// Turn select (Cmp X C1) (BOp X C2) C3
+//   -> BOp (min/max X C1) C2
+// iff C3 == BOp C1 C2
+// Fold `select` with a const operand to a binary operation.
+// This allows for better canonicalization.
+static Value *foldSelectWithConstOpToBinOp(ICmpInst *Cmp, Value *TrueVal,
+                                           Value *FalseVal,
+                                           IRBuilderBase &Builder) {
+  BinaryOperator *BOp;
+  Constant *C1, *C2, *C3;
+  Value *X, *NewTrue, *NewFalse;
+  ICmpInst::Predicate Predicate;
+
+  if (!match(Cmp, m_ICmp(Predicate, m_Value(X), m_Constant(C1))))
+    return nullptr;
+
+  if (match(TrueVal, m_Constant())) {
+    std::swap(FalseVal, TrueVal);
+    NewTrue = C1;
+    NewFalse = X;
+  } else {
+    NewTrue = X;
+    NewFalse = C1;
+  }
+
+  if (!match(TrueVal, m_BinOp(BOp)) || !match(FalseVal, m_Constant(C3)))
+    return nullptr;
+
+  if (!match(BOp, m_OneUse(m_c_BinOp(m_Specific(X), m_Constant(C2)))))
+    return nullptr;
+
+  // `select (Cmp X C1) (sub C2 X) (sub C1 C2)` cannot be transformed
+  // into something like `sub (select (Cmp X C1) X C1) C2`
+  if (!BOp->isCommutative() && BOp->getOperand(0) != X)
+    return nullptr;
----------------
dtcxzyw wrote:

```suggestion
  if (!match(BOp, m_OneUse(m_BinOp(m_Specific(X), m_Constant(C2)))))
    return nullptr;
```
It is unnecessary to use `m_c_BinOp` if you don't want to handle `sub C, X` cases.


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


More information about the cfe-commits mailing list