[RFC] FMF on more instructions

This was a section of an RFC I’m working on around the contract flag, but in the interests of keeping RFCs shorter and more narrowly focused, I’ve pulled this out into its own RFC.

Proposal

Adjust the set of operations that can have fast-math flags to include fpext, fptrunc, uitofp, and sitofp. Optionally, I would also include the fptoui and fptosi instructions in this list for completeness sake, but I also see good arguments against their inclusion.

Like the flags on the other cast instructions, the position of the fast-math flags would be immediately after the instruction name, i.e., fpext fast float %x to double).

Motivation

The main motivation I have for doing this is that, while auditing the current use of fast-math flags (specifically the contract flag), I found several DAGCombine patterns that involved fpext. Furthermore, there was PR added yesterday that was essentially trying to query the fast-math flags on fpext and fptrunc by poking at the uses: [InstCombine] Eliminate fptrunc/fpext if fast math flags allow it by john-brawn-arm · Pull Request #115027 · llvm/llvm-project · GitHub.

As a matter of completeness, most of these instructions are part of the basic IEEE 754 operations, convertFormat (fpext, fptrunc) and convertFromInteger (uitofp, sitofp), both of which are found in §5.4, the general computational operations. The fptoui and fptosi operations technically don’t correspond to an IEEE 754 operation, which instead has two families of convertToInteger operations, one for signaling inexactness and one that doesn’t, and each family has one operation for each rounding mode.

The rationale for fpext and fptrunc gaining FMF seems clear to me–we already have cases where these are part of FMF-related expression rewrites. The integer conversions seem less relevant; I recall once thinking of a scenario where I wanted FMF on an integer conversion, but I forget the specific pattern. It is not difficult to deal with the instructions that result in a floating-point value, so I consider it low risk to include uitofp and sitofp as part of this proposal, but if people are disinclined to support them until there’s a specific use case, that would be acceptable.

However, fptoui and fptosi have the unfortunate problem that their corresponding constrained intrinsics would not be considered available to have FMF, nor would the intrinsics that implement similar operations, such as llvm.lrint and llvm.llrint. (The other FP operation that is not currently considered a FPMathOperator is llvm.frexp, which returns a struct with a floating-point and integer type, and similarly has some special-case concerns).

I agree that extending FMF support to these cast instructions makes sense.

I also agree that we should not support fptoui/fptosi for the time being. Currently, all instructions that support FMF return a float (or aggregate of float), while these instructions don’t. This is not a property we have to preserve, but we probably shouldn’t break it either if we don’t have any motivating cases.

One issue I’ve been thinking about is the lack of an exact flag on fptrunc. The DAG equivalent has its own special case “flag” immediate operand without an IR equivalent. I suppose we could repurpose afn for this, but it’s not an exact match.

I’ve posted a patch which adds fast math flags to fptrunc and fpext at [IR] Allow fast math flags on fptrunc and fpext by john-brawn-arm · Pull Request #115894 · llvm/llvm-project · GitHub