This is an archive of the discontinued LLVM Phabricator instance.

[Clang] Allow fmuladd for option -ffast-math
AbandonedPublic

Authored by Allen on Jul 31 2023, 1:28 AM.

Details

Summary

Discussion on https://discourse.llvm.org/t/fp-contraction-fma-on-by-default/64975

  • The behavior controlled by -ffp-contract=on is compliant with the C standard, double fma(double a, double b) { return a * b + 5; } can emit an fusedMultiplyAdd operation.
  • The behavior controlled by -ffp-contract=fast enables non-C-standard-compliant behavior that ignores the #pragma and will create contractions after other optimizations like inlining, and across expressions.

Fixes https://github.com/llvm/llvm-project/issues/64244

Diff Detail

Event Timeline

Allen created this revision.Jul 31 2023, 1:28 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 31 2023, 1:28 AM
Allen requested review of this revision.Jul 31 2023, 1:28 AM

This is permitted...but LLVM should be able to convert to FMA during IR optimization when in -ffp-contract=fast mode. So the frontend shouldn't need to do so. It'd be good to figure out why that's not happening as expected in the referenced example code.

arsenm added a subscriber: arsenm.Aug 9 2023, 1:14 PM

I think isFMAFasterThanFMulAndFAdd is just wrong for some targets. There have been a few patches and posts I've seen all trying to work around this while treating it like a representational issue to work around instead of fixing the backend making the wrong decision

clang/test/CodeGen/ffp-contract-fast-option.cpp
1

Switch to generated checks should be committed separately

5

I believe instcombine will just turn this right back into fmul+fadd with contract set (the flags for this are just stricter than they need to be, see D152166)

Allen added a comment.Aug 9 2023, 8:23 PM

So do you think the right direction to fix this issue is something like following ?

  • convert it to llvm.fmuladd at the front end of clang if possiable
  • then the instcombine turn right back into fmul+fadd with contract set
  • then the backend fold them into fmuladd if isFMAFasterThanFMulAndFAdd return true.

So do you think the right direction to fix this issue is something like following ?

  • convert it to llvm.fmuladd at the front end of clang if possiable

No. fmul contract+fadd contract is the right representation. If it produces slower code there's a backend issue to solve

  • then the instcombine turn right back into fmul+fadd with contract set

This makes any change to clang pointless here. We already do this, just in overly constrained conditions (only full fast flags)

  • then the backend fold them into fmuladd if isFMAFasterThanFMulAndFAdd return true.

Either some other combine went wrong and that broke the fusion, or isFMAFasterThanFMulAndFAdd was wrong for some reason. I don't think there's a representational issue here, just a bad transform somewhere

arsenm requested changes to this revision.Aug 11 2023, 8:27 AM

I think contract on everything is a better representation for this, if it ends up slower there's a backend issue

This revision now requires changes to proceed.Aug 11 2023, 8:27 AM
Allen abandoned this revision.Aug 19 2023, 11:09 PM