[llvm] [LangRef] Clarify the semantics of fast-math flags (PR #89442)

Andy Kaylor via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 19 13:49:56 PDT 2024


================
@@ -3656,6 +3656,45 @@ floating-point transformations.
 ``fast``
    This flag implies all of the others.
 
+When performing a transformation that involves more that one instruction, the
+flags required to enable the transformation must be set on all instructions
+involved in the transformation, and any new instructions created by the
+transformation should have only those flags set which were set on all the
+original instructions that are being transformed.
----------------
andykaylor wrote:

Yes, I suppose you're right that the semantics we've defined for `nnan` and `ninf` make that true in many cases. This leads to an increasing sense I have that those two flags are fundamentally different from the other fast-math flags. Those two flags provide clear, consistent, and rather strict semantics, whereas the other flags all have a sort of "you're allowed to do something here that you normally couldn't" character.

This also significantly complicates the reasoning involved. For instance
```
%mul1 = fmul reassoc float %x, %y
%mul2 = fmul fast float %mul1, %z
```
becomes
```
%mul1.1 = fmul reassoc nnan float %x, %z
%mul2.1 = fmul reassoc nnan float %mul1, %y
```
which is already tricky because the possibility of %x=INF, %y=0 prevents me from setting `ninf` on %mul2.1 and %x=0. %y=INF prevents me from setting `ninf` on %mul1.1

but also
```
%mul1 = fmul fast float %x, %y
%mul2 = fmul reassoc float %mul1, %z
```
becomes
```
%mul1.1 = fmul reassoc float %x, %z
%mul2.1 = fmul reassoc float %mul1, %y
```
because we don't have enough information to set `ninf` or `nnan` on either transformed instruction.

In practice, I think this would be difficult to implement any way other than to apply the rule I stated and rely on a later pass to infer `nnan` and `ninf` where it can. Of course, for the purposes of describing the semantics, it may be best to say something like

> any new instructions created by the transformation should have only those flags set which were set on all the original instructions that are being transformed **unless additional flags can be strictly deduced from the original IR**.

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


More information about the llvm-commits mailing list