[llvm] [InstCombine] Use the select condition to try to constant fold binops into select (PR #84696)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 18 01:58:15 PDT 2024
================
@@ -2002,14 +2002,61 @@ Instruction *InstCombinerImpl::foldBinopWithPhiOperands(BinaryOperator &BO) {
return NewPhi;
}
-Instruction *InstCombinerImpl::foldBinOpIntoSelectOrPhi(BinaryOperator &I) {
+// Return std::nullopt if we should not fold. Return true if we should fold
+// multi-use select and false for single-use select.
+static std::optional<bool> shouldFoldOpIntoSelect(BinaryOperator &I, Value *Op,
+ Value *OpOther,
+ bool AllowMultiUse) {
+ if (!AllowMultiUse && !Op->hasOneUse())
+ return std::nullopt;
+ if (isa<SelectInst>(Op)) {
+ // If we will be able to constant fold the incorporated binop, then
+ // multi-use. Otherwise single-use.
+ return match(OpOther, m_ImmConstant()) &&
+ match(Op, m_Select(m_Value(), m_ImmConstant(), m_ImmConstant()));
+ }
+
+ return std::nullopt;
+}
+
+Instruction *InstCombinerImpl::foldBinOpIntoSelect(BinaryOperator &I,
+ bool AllowMultiUse) {
+ std::optional<bool> CanSpeculativelyExecuteRes;
+ for (unsigned OpIdx = 0; OpIdx < 2; ++OpIdx) {
+ // Slightly more involved logic for select. For select we use the condition
+ // to to infer information about the arm. This allows us to constant-fold
+ // even when the select arm(s) are not constant. For example if we have: `(X
+ // == 10 ? 19 : Y) * X`, we can entirely contant fold the true arm as `X ==
+ // 10` dominates it. So we end up with `X == 10 ? 190 : (X * Y))`.
+ if (auto MultiUse = shouldFoldOpIntoSelect(
+ I, I.getOperand(OpIdx), I.getOperand(1 - OpIdx), AllowMultiUse)) {
+ if (!*MultiUse) {
+ if (!CanSpeculativelyExecuteRes) {
+ const SimplifyQuery Q = SQ.getWithInstruction(&I);
+ CanSpeculativelyExecuteRes =
+ isSafeToSpeculativelyExecute(&I, Q.CxtI, Q.AC, Q.DT, &TLI);
+ }
+ if (!*CanSpeculativelyExecuteRes)
+ return nullptr;
----------------
arsenm wrote:
Why can't this early exit immediately after calling isSafeToSpeculativelyExecute? Why is this intermediate optional<bool> needed?
https://github.com/llvm/llvm-project/pull/84696
More information about the llvm-commits
mailing list