================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits