I am trying to understand the use of Fast Math Flags (FMF) in LLVM IR.
I wondered if someone could please provide me with some code samples
or examples of transformations where FMF is used. I am mostly confused
about the use of arcp, contract, afn, reassoc.
The main optimization pass that is going to take advantage of fast math flags will be the InstCombine pass, which is the primary peephole pass in LLVM. For the flags in question:
* arcp allows x / y to be converted to x * (1 / y). An example transformation is here: https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp#L1216-L1242 (this converts x / N, for some constant N, to x * N if the division has arcp flag).
* contract allows x + (y * z) to be converted into an FMA instruction. This actually tends to occur in the backends more; this flag causes SelectionDAG to emit specific FMA nodes that backends can match into target-specific instructions.
* afn allows functions to be computed approximately. There's not as many optimizations in play here, but here's one from simplify lib calls that approximates pow: https://github.com/llvm/llvm-project/blob/5f5974aeacac979de81713332ff80e5928e408b7/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp#L1564
* reassoc allows expressions like x + (y + z) to be converted to (x + y) + z. This comes up a few places in instcombine (for example, shifting constants in an add/multiply chain around to be combined), but it also allows vectorization of reduction chains.
Thanks a lot for the detailed explanation and the code samples.