[llvm] [InstCombine] Canonicalize reassoc contract fmuladd to fmul + fadd (PR #90434)

Andy Kaylor via llvm-commits llvm-commits at lists.llvm.org
Mon May 6 15:25:52 PDT 2024


andykaylor wrote:

> `fmuladd` is basically "`fma`, but if there's no hardware instruction, give me `fmul + fadd` instead"

I don't know if I'd agree with that interpretation. I think it's more open-ended than that. The definition specifically says that fusion is not guaranteed, even if the target platform supports it. As such, transforming `llvm.fmuladd` into separate `fmul` and `fadd` operations is always legal (though not necessarily profitable). The question here is whether it is also legal to attach the `contract` flag to those operations after they have been split out.

Does `contract` on an intrinsic only give permission to contract that entire operation with another operation? Or does it also imply `contract` semantics with regard to the "inner" operations implied by the intrinsic? I would lean towards the latter, but I don't think it's clear.

While we're on the topic, the "overview" section of the `llvm.fmuladd` intrinsic says this:

> The ‘llvm.fmuladd.*’ intrinsic functions represent multiply-add expressions that can be fused if the code generator determines that (a) **the target instruction set has support for a fused operation**, and (b) that the fused operation is more efficient than the equivalent, separate pair of mul and add instructions.

I've added emphasis on the first condition, because we aren't currently respecting this condition in the constant folder. The constant folder will fold `llvm.fmuladd` as if it were a fused operation even if the target instruction set does not support FMA. I think this is incorrect, but I'm bringing it up here because it means that the proposed canonicalization will have a potentially observable effect. The constant folder does not evaluate separate `fmul` and `fadd` operations using fused semantics even if they have the `contract` flag set, but it does do so with `llvm.fmuladd`.

If the target instruction set supports FMA, constant folding these operations without intermediate rounding may be preferred. Of course, the `contract` flag does specifically allow value-changing transformations, so maybe this is OK either way when that flag is present.

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


More information about the llvm-commits mailing list