KhronosGroup / KhronosGroup/SPIRV-LLVM-Translator

[Question / Feature Request] Translation of floating point canonicalize (`@llvm.canonicalize`)

Open
#3,559 5 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.