Hi everyone,
This is related to the recent thread about fp-contract and front end pragma controls, but I want to generalize the discussion in terms of how the target-independent codegen in the backend is implemented.
Until sometime in 2017 (I think) the fast-math flags were not passed through to the Selection DAG, and so the only ways to control floating-point behavior were through settings in the TargetOptions or by settings function attributes. Since 2017, however, the fast-math flags have been attached to floating-point nodes in the selection DAG. This leads to some ambiguous situations where the TargetOptions or function attributes can override the absence of fast-math flags on individual nodes. An example of this is the fp-contract setting. If a source file is compiled with clang using the ‘-ffp-contract=fast’ setting but the file contains either “#pragma STDC FP_CONTRACT OFF” or “#pragma clang fp contract(off)” the front end will generate IR without the ‘contract’ fast-math flag set, but the X86 backend will generate an FMA instruction anyway.
https://godbolt.org/z/dov6EcE8G
This is particularly bad in the case of CUDA, because CUDA uses fp-contract=fast by default. So, the user’s code can explicitly say “don’t generate fma here” and the compiler will respond, “meh, I think I will anyway.”
https://godbolt.org/z/c4h1nK9M3
There are other cases where the backend code will check for TargetOption::UnsafeFPMath for things like reassociation that can be represented using fast-math flags.
That brings me to the RFC part of my message. I’d like to start updating the backend so that it doesn’t do things like this. As a general principle, I would say, “All semantics must be represented in the IR and the backend must respect the IR semantics.” And a corollary: “Anything which can be represented at the instruction level must be represented at the instruction level.” This corollary would eliminate potential conflicts between function attributes (like “unsafe-fp-math”) and individual IR instructions.
As a first step toward this goal, I’ve prepared a patch which closes the back door for fp-contract control.
https://reviews.llvm.org/D112760
This patch is currently incomplete, in as much as I didn’t update failing tests for several target architectures. I did update the X86 and AMDGPU tests to provide examples of how they can be made to work. I will fix the rest if we decide this is the correct direction. There is a failing CUDA test in the clang front end that I think will require a different approach involving some driver changes to get clang to generate IR for the semantics it intends rather than setting an option and counting on the backend to disregard the IR.
Thanks in advance for any feedback!
-Andy