[RFC] Improving IR fast-math semantics

@jcranmer It occurs to me, in terms of searching for bits, that the ‘afn’ flag only has any meaning for call instructions. We could possibly reclaim that bit if necessary and add something extra to call instructions, even if it added an extra byte to the bitcode.

We could possibly also eject ‘nnan’ and ‘ninf’ (possibly even ‘nsz’) by introducing new types rather than using the flags. So, for example, we’d replace ‘float’ with ‘finite_float’ when ‘nnan’ and ‘ninf’ were both enabled. I think that models the intent of these modes better than fast-math flags anyway. On the other hand, I think we’re also running into limits with the number of types available, so this might just be moving the problem.

We’d need some way to detect that we were in the “new” mode for auto-upgrade purposes, but that will be true of any change made to these flags.

Finally, I wanted to note that the SPIR-V fast-math decorators are based on the LLVM flags before we added ‘reassoc’ and ‘afn’. We should probably consider LLVM-to-SPIRV translation in whatever we do here.

@jcranmer It occurs to me, in terms of searching for bits, that the ‘afn’ flag only has any meaning for call instructions. We could possibly reclaim that bit if necessary and add something extra to call instructions, even if it added an extra byte to the bitcode.

The thread on llvm::Value layout changes does seem to have support for ways that would allow us to reclaim extra bits, so I’m not as concerned with trying to reclaim existing flags (although I do believe afn is potentially ripe for redefinition anyways).

We could possibly also eject ‘nnan’ and ‘ninf’ (possibly even ‘nsz’) by introducing new types rather than using the flags. So, for example, we’d replace ‘float’ with ‘finite_float’ when ‘nnan’ and ‘ninf’ were both enabled. I think that models the intent of these modes better than fast-math flags anyway. On the other hand, I think we’re also running into limits with the number of types available, so this might just be moving the problem.

llvm::Type isn’t so space-constrained as llvm::Value is (there’s 8 bits for subclass ID, with like 20 subclasses, of which 7 are floating-point types); there’s also a 24-bit SubclassData that is plenty roomy for type-based FMF if it’s desirable… but there’s likely to be a decent amount of changing to move FMF onto a type, and I don’t even want to speculate on how much work it would be just to prototype a change to see its effects.

Finally, I wanted to note that the SPIR-V fast-math decorators are based on the LLVM flags before we added ‘reassoc’ and ‘afn’. We should probably consider LLVM-to-SPIRV translation in whatever we do here.

Apart from fast (whose specification text seems to imply it means reassoc while also implying all the other flags at the same time), none of the SPIR-V fast-math flags are the ones that have particularly problematic decisions. And given SPIR-V’s intended role as an IR for accelerators, I don’t think it’s a stretch of its semantics to interpret fast as “the user passed -ffast-math on the command-line”, with whatever effects that implies on the most recent compiler version.

Maybe I’m thinking of calling conventions. There was something I wanted to add recently that someone who works on clang told me I needed to stop asking for.

It’s a problem if you want ‘reassoc’ but don’t want ‘nnan’ and ‘ninf’. I think I may have run into a performance regression related to that earlier today, which is why I was thinking about this. Maybe we need to get SPIRV to update their decorators, but my point is that one way or another we’re going to want a way to get our fast-math flags across to offload devices after we clean this up.