[PATCH] D136786: Fix `unsafe-fp-math` attribute emission.

Michele Scandale via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 26 13:43:56 PDT 2022


michele.scandale created this revision.
michele.scandale added reviewers: zahiraam, aaron.ballman, andrew.w.kaylor, rjmccall, efriedma, fhahn.
Herald added a subscriber: ormris.
Herald added a project: All.
michele.scandale requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The conditions for which Clang emits the `unsafe-fp-math` function
attribute has been modified as part of
`84a9ec2ff1ee97fd7e8ed988f5e7b197aab84a7`.
In the backend code generators `"unsafe-fp-math"="true"` enable floating
point contraction for the whole function.
The intent of the change in `84a9ec2ff1ee97fd7e8ed988f5e7b197aab84a7`
was to prevent backend code generators performing contractions when that
is not expected.
However the change is inaccurate and incomplete because it allows
`unsafe-fp-math` to be set also when only in-statement contraction is
allowed.

Consider the following example

  float foo(float a, float b, float c) {
    float tmp = a * b;
    return tmp + c;
  }

and compile it with the command line

  clang -fno-math-errno -funsafe-math-optimizations -ffp-contract=on \
    -O2 -mavx512f -S -o -

The resulting assembly has a `vfmadd213ss` instruction which corresponds
to a fused multiply-add. From the user perspective there shouldn't be
any contraction because the multiplication and the addition are not in
the same statement.

The optimized IR is:

  define float @test(float noundef %a, float noundef %b, float noundef %c) #0 {
    %mul = fmul reassoc nsz arcp afn float %b, %a
    %add = fadd reassoc nsz arcp afn float %mul, %c
    ret float %add
  }
  
  attributes #0 = {
    [...]
    "no-signed-zeros-fp-math"="true"
    "no-trapping-math"="true"
    [...]
    "unsafe-fp-math"="true"
  }

The `"unsafe-fp-math"="true"` function attribute allows the backend code
generator to perform `(fadd (fmul a, b), c) -> (fmadd a, b, c)`.

In the current IR representation there is no way to determine the
statement boundaries from the original source code.
Because of this for in-statement only contraction the generated IR
doesn't have instructions with the `contract` fast-math flag and
`llvm.fmuladd` is being used to represent contractions opportunities
that occur within a single statement.
Therefore `"unsafe-fp-math"="true"` can only be emitted when contraction
across statements is allowed.

Moreover the change in `84a9ec2ff1ee97fd7e8ed988f5e7b197aab84a7` doesn't
take into account that the floating point math function attributes can
be refined during IR code generation of a function to handle the cases
where the floating point math options are modified within a compound
statement via pragmas (see `CGFPOptionsRAII`).
For consistency `unsafe-fp-math` needs to be disabled if the contraction
mode for any scope/operation is not `fast`.
Similarly for consistency reason the initialization of `UnsafeFPMath` of
in `TargetOptions` for the backend code generation should take into
account the contraction mode as well.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136786

Files:
  clang/lib/CodeGen/BackendUtil.cpp
  clang/lib/CodeGen/CGCall.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/test/CodeGen/fp-function-attrs.cpp
  clang/test/CodeGen/func-attr.c
  clang/test/CodeGenOpenCL/relaxed-fpmath.cl

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D136786.470920.patch
Type: text/x-patch
Size: 7093 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20221026/158596fe/attachment-0001.bin>


More information about the cfe-commits mailing list