KhronosGroup / KhronosGroup/SPIRV-LLVM-Translator
[Question / Feature Request] Translation of floating point canonicalize (`@llvm.canonicalize`)
- Dominant language
- LLVM
- Stars
- 625
- Forks
- 279
- Avg merge
- 3d 5h
- Merged PRs (30d)
- 34
Description
The [`@llvm.canonicalize` intrinsic](https://llvm.org/docs/LangRef.html#llvm-canonicalize-intrinsic) is not supported by the bi-directional translator or the LLVM SPIR-V backend.
This is a basic intrinsic that is very useful in floating point math libraries, and ideally all LLVM backend should support it. LLVM's libclc uses it extensively for targets other than SPIR-V, having SPIR-V support the instruction would simplify the library code.
I've attempted an implementation in https://github.com/llvm/llvm-project/pull/178439, but I've run into issues. I would like to ask for help on what might be a reasonable lowering. The options I considered:
#### Option 1
Lower `@llvm.canonicalize(x)` -> `OpFMul / OpVectorTimesScalar x, 1.0`. Motivated by the sentence in the LLVM language reference "This function should always be implementable as multiplication by 1.0".
This is the approach taken in https://github.com/llvm/llvm-project/pull/178439. According to my understanding of the spec however, the SPIR-V consumer is allowed to optimize this away.
This happens in practice, the reverse translation of `OpFMul x, 1.0` is `fmul x, 1.0`, which is then folded by LLVM middle-end optimization passes (`InstSimplify`).
This could be worked around by special-casing `OpFMul x, 1.0` to translate to `@llvm.canonicalize`, thereby preserving the semantics. `OpFMul x, 1.0` could theoretically show up naturally in IR, not just from llvm.canonicalize, in which case we'd be pessimizing code. It also does not address SPIR-V consumers that do not translate to LLVM-IR.
#### Option 2
Lower to a different "identity" floating point instruction, hopefully one that is not folded out by LLVM transformations. For example `fmin x, x` from the OpenCL extended instruction set. Using these might hurt performance: the reverse translation is to call a function `fmin` or `__spirv_fmin`, this is going to optimize much worse than `llvm.canonicalize`.
#### Option 3
Explicitly support floating point canonicalization instruction in SPIR-V via an extension. This would be the cleanest approach. The semantics of such an instruction would have to be defined for what makes sense for SPIR-V.
Contributor guide
Research direction
Review the LLVM LangRef entry for llvm.canonicalize and the attempted implementation in llvm/llvm-project PR 178439, then compare the three proposed lowering approaches for the bi-directional translator and LLVM SPIR-V backend. Done means agreeing on a semantics-preserving SPIR-V representation or extension and documenting the chosen lowering path.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100