Skip to content

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

@Maetveis

Description

@Maetveis

The @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 llvm/llvm-project#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 llvm/llvm-project#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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions