[llvm] [SLP]Fix fmul/fadd fusion costs and retry FMA seeds after all blocks (PR #226117)

Dmitry Sidorov via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 15:02:51 PDT 2026


================
@@ -13180,12 +13197,89 @@ bool BoUpSLP::areAllUsersVectorized(
          });
 }
 
-static InstructionCost canConvertToFMA(ArrayRef<Value *> VL,
-                                       const InstructionsState &S,
-                                       DominatorTree &DT, const DataLayout &DL,
-                                       TargetTransformInfo &TTI,
-                                       const TargetLibraryInfo &TLI,
-                                       const BoUpSLP &R);
+static InstructionCost
+canConvertToFMA(ArrayRef<Value *> VL, const InstructionsState &S,
+                DominatorTree &DT, const DataLayout &DL,
+                TargetTransformInfo &TTI, const TargetLibraryInfo &TLI,
+                const BoUpSLP &R, bool FuseEitherOperand = true);
+
+/// \returns the fmul operand of the fadd/fsub \p I that the backend fuses with
+/// \p I into an fmuladd: a contractable single-use fmul from the same block,
+/// from either operand, the first one preferred, c - a*b included. \p I must
+/// allow contraction.
+static Instruction *getFusableFMulOperand(Instruction *I) {
+  if ((I->getOpcode() != Instruction::FAdd &&
+       I->getOpcode() != Instruction::FSub) ||
+      !I->hasAllowContract())
+    return nullptr;
+  for (Value *Op : I->operands()) {
+    auto *FMul = dyn_cast<Instruction>(Op);
+    if (FMul && FMul->getOpcode() == Instruction::FMul && FMul->hasOneUse() &&
+        FMul->hasAllowContract() && FMul->getParent() == I->getParent())
----------------
MrSidims wrote:

Rather than checking, if `fmul` and `fadd/fsub` are in the same block I suggest to also ask `TTI.isProfitableToSinkOperands` whether the target sinks the `fmul` to its user.

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


More information about the llvm-commits mailing list