[llvm] [SPIR-V] Implement SPV_KHR_float_controls2 (PR #146941)
Dmitry Sidorov via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 21 04:54:45 PDT 2025
================
@@ -0,0 +1,92 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_float_controls2 %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_float_controls2 %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: Capability FloatControls2
+; CHECK: Extension "SPV_KHR_float_controls2"
+
+; CHECK: OpName %[[#addRes:]] "addRes"
+; CHECK: OpName %[[#subRes:]] "subRes"
+; CHECK: OpName %[[#mulRes:]] "mulRes"
+; CHECK: OpName %[[#divRes:]] "divRes"
+; CHECK: OpName %[[#remRes:]] "remRes"
+; CHECK: OpName %[[#negRes:]] "negRes"
+; CHECK: OpName %[[#oeqRes:]] "oeqRes"
+; CHECK: OpName %[[#oneRes:]] "oneRes"
+; CHECK: OpName %[[#oltRes:]] "oltRes"
+; CHECK: OpName %[[#ogtRes:]] "ogtRes"
+; CHECK: OpName %[[#oleRes:]] "oleRes"
+; CHECK: OpName %[[#ogeRes:]] "ogeRes"
+; CHECK: OpName %[[#ordRes:]] "ordRes"
+; CHECK: OpName %[[#ueqRes:]] "ueqRes"
+; CHECK: OpName %[[#uneRes:]] "uneRes"
+; CHECK: OpName %[[#ultRes:]] "ultRes"
+; CHECK: OpName %[[#ugtRes:]] "ugtRes"
+; CHECK: OpName %[[#uleRes:]] "uleRes"
+; CHECK: OpName %[[#ugeRes:]] "ugeRes"
+; CHECK: OpName %[[#unoRes:]] "unoRes"
+; CHECK: OpName %[[#modRes:]] "modRes"
+; CHECK: OpName %[[#maxRes:]] "maxRes"
+; CHECK: OpName %[[#maxCommonRes:]] "maxCommonRes"
+; CHECK: OpDecorate %[[#subRes]] FPFastMathMode NotNaN
+; CHECK: OpDecorate %[[#mulRes]] FPFastMathMode NotInf
+; CHECK: OpDecorate %[[#divRes]] FPFastMathMode NSZ
+; CHECK: OpDecorate %[[#remRes]] FPFastMathMode AllowRecip
+; CHECK: OpDecorate %[[#negRes]] FPFastMathMode NotNaN|NotInf|NSZ|AllowRecip|AllowContract|AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#oeqRes]] FPFastMathMode NotNaN|NotInf
+; CHECK: OpDecorate %[[#oneRes]] FPFastMathMode AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#oltRes]] FPFastMathMode NotNaN|AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#ogtRes]] FPFastMathMode NotInf|AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#oleRes]] FPFastMathMode NSZ|AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#ogeRes]] FPFastMathMode AllowRecip|AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#ordRes]] FPFastMathMode NotNaN|NotInf|NSZ|AllowRecip|AllowContract|AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#ueqRes]] FPFastMathMode NotNaN|NotInf|AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#uneRes]] FPFastMathMode AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#ultRes]] FPFastMathMode AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#ugtRes]] FPFastMathMode AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#uleRes]] FPFastMathMode AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#ugeRes]] FPFastMathMode AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#unoRes]] FPFastMathMode AllowReassoc|AllowTransform
+; CHECK-NOT: OpDecorate %[[#modRes]] FPFastMathMode
+; CHECK: OpDecorate %[[#maxRes]] FPFastMathMode NotNaN|NotInf|NSZ|AllowRecip|AllowContract|AllowReassoc|AllowTransform
+; CHECK: OpDecorate %[[#maxCommonRes:]] FPFastMathMode NotNaN|NotInf
+
+target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
+target triple = "spir"
+
+; Function Attrs: convergent mustprogress nofree nounwind willreturn memory(none)
+declare spir_func float @_Z4fmodff(float, float)
+declare dso_local spir_func noundef nofpclass(nan inf) float @_Z16__spirv_ocl_fmaxff(float noundef nofpclass(nan inf), float noundef nofpclass(nan inf)) local_unnamed_addr #1
+declare dso_local spir_func noundef nofpclass(nan inf) float @_Z23__spirv_ocl_fmax_commonff(float noundef nofpclass(nan inf), float noundef nofpclass(nan inf)) local_unnamed_addr #1
+
+; Function Attrs: convergent mustprogress norecurse nounwind
+define weak_odr dso_local spir_kernel void @foo(float %1, float %2) {
+entry:
+ %addRes = fadd float %1, %2
+ %subRes = fsub nnan float %1, %2
+ %mulRes = fmul ninf float %1, %2
+ %divRes = fdiv nsz float %1, %2
+ %remRes = frem arcp float %1, %2
+ %negRes = fneg fast float %1
+ %oeqRes = fcmp nnan ninf oeq float %1, %2
+ %oneRes = fcmp one float %1, %2, !spirv.Decorations !3
----------------
MrSidims wrote:
I think that is the place, where SPIR-V to LLVM IR translator and SPIR-V BE behaviours should diverge.
It so happen, that the translator just translates any spirv.Decoration metadata (in case if the appropriate decoration was registered) out of a box (and may be should consider disallowing spirv.Decoration notation for fast math flags there).
Meanwhile if SPIR-V BE requires to explicitly write handlers for the metadata to lower FP flags - just don't do that and don't handle it in the backend.
[The formal guideline](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/docs/SPIRVRepresentationInLLVM.rst#id1) says:
"As one of the goals of SPIR-V is to ["map easily to other IRs, including LLVM IR"](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_goals), most of SPIR-V entities (global variables, constants, types, functions, basic blocks, instructions) have straightforward counterparts in LLVM. Therefore the focus of this document is those entities in SPIR-V which do not map to LLVM in an obvious way."
So as FP flags has obvious match between LLVM IR and SPIR-V (with an exception of reassoc <-> AllowTransform, but it's unrelated to this discussion) we should be fine to drop support for spirv.Decoration for FP flags in this PR. If anybody in the future would find it useful - they can re-add this support.
https://github.com/llvm/llvm-project/pull/146941
More information about the llvm-commits
mailing list