[llvm] [SPIRV] Added Support for the constrained conversion intrinsics (PR #157437)

via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 8 05:15:41 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-spir-v

Author: Subash B (SubashBoopathi)

<details>
<summary>Changes</summary>

Added SPIR-V support for constrained conversion intrinsics (sitofp, uitofp, fptosi, fptoui, fpext, fptrunc), including legalization, instruction selection, and corresponding tests.

---
Full diff: https://github.com/llvm/llvm-project/pull/157437.diff


6 Files Affected:

- (modified) llvm/include/llvm/Support/TargetOpcodes.def (+6) 
- (modified) llvm/include/llvm/Target/GenericOpcodes.td (+6) 
- (modified) llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (+12) 
- (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+12) 
- (modified) llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp (+11) 
- (added) llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-convert.ll (+41) 


``````````diff
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index b905576b61791..ea4eaff9cbd39 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -899,6 +899,12 @@ HANDLE_TARGET_OPCODE(G_STRICT_FREM)
 HANDLE_TARGET_OPCODE(G_STRICT_FMA)
 HANDLE_TARGET_OPCODE(G_STRICT_FSQRT)
 HANDLE_TARGET_OPCODE(G_STRICT_FLDEXP)
+HANDLE_TARGET_OPCODE(G_STRICT_FPTOSI)
+HANDLE_TARGET_OPCODE(G_STRICT_SITOFP)
+HANDLE_TARGET_OPCODE(G_STRICT_UITOFP)
+HANDLE_TARGET_OPCODE(G_STRICT_FPTOUI)
+HANDLE_TARGET_OPCODE(G_STRICT_FPEXT)
+HANDLE_TARGET_OPCODE(G_STRICT_FPTRUNC)
 
 /// read_register intrinsic
 HANDLE_TARGET_OPCODE(G_READ_REGISTER)
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index ce4750db88c9a..637eab4ad6c77 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1716,6 +1716,12 @@ def G_STRICT_FREM : ConstrainedInstruction<G_FREM>;
 def G_STRICT_FMA : ConstrainedInstruction<G_FMA>;
 def G_STRICT_FSQRT : ConstrainedInstruction<G_FSQRT>;
 def G_STRICT_FLDEXP : ConstrainedInstruction<G_FLDEXP>;
+def G_STRICT_SITOFP: ConstrainedInstruction<G_SITOFP>;
+def G_STRICT_UITOFP: ConstrainedInstruction<G_UITOFP>;
+def G_STRICT_FPTOSI: ConstrainedInstruction<G_FPTOSI>;
+def G_STRICT_FPTOUI: ConstrainedInstruction<G_FPTOUI>;
+def G_STRICT_FPEXT: ConstrainedInstruction<G_FPEXT>;
+def G_STRICT_FPTRUNC: ConstrainedInstruction<G_FPTRUNC>;
 
 //------------------------------------------------------------------------------
 // Memory intrinsics
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index d7280eaba2440..00866db2a943e 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -2061,6 +2061,18 @@ static unsigned getConstrainedOpcode(Intrinsic::ID ID) {
     return TargetOpcode::G_STRICT_FSQRT;
   case Intrinsic::experimental_constrained_ldexp:
     return TargetOpcode::G_STRICT_FLDEXP;
+  case Intrinsic::experimental_constrained_sitofp:
+    return TargetOpcode::G_STRICT_SITOFP;
+  case Intrinsic::experimental_constrained_uitofp:
+    return TargetOpcode::G_STRICT_UITOFP;
+  case Intrinsic::experimental_constrained_fptosi:
+    return TargetOpcode::G_STRICT_FPTOSI;
+  case Intrinsic::experimental_constrained_fptoui:
+    return TargetOpcode::G_STRICT_FPTOUI;
+  case Intrinsic::experimental_constrained_fpext:
+    return TargetOpcode::G_STRICT_FPEXT;
+   case Intrinsic::experimental_constrained_fptrunc:
+    return TargetOpcode::G_STRICT_FPTRUNC;
   default:
     return 0;
   }
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 6608b3f2cbefd..536692b435e7a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -668,6 +668,18 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
   case TargetOpcode::G_UITOFP:
     return selectIToF(ResVReg, ResType, I, false, SPIRV::OpConvertUToF);
 
+  case TargetOpcode::G_STRICT_SITOFP:
+    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertSToF);
+  case TargetOpcode::G_STRICT_UITOFP:
+    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertUToF);
+  case TargetOpcode::G_STRICT_FPTOSI:
+    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToS);
+  case TargetOpcode::G_STRICT_FPTOUI:
+    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);
+  case TargetOpcode::G_STRICT_FPEXT:
+  case TargetOpcode::G_STRICT_FPTRUNC:
+    return selectUnOp(ResVReg, ResType, I, SPIRV::OpFConvert);
+
   case TargetOpcode::G_CTPOP:
     return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitCount);
   case TargetOpcode::G_SMIN:
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 721f64a329d31..d8106f159fab5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -203,6 +203,17 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
       .legalForCartesianProduct(allIntScalarsAndVectors,
                                 allFloatScalarsAndVectors);
 
+  getActionDefinitionsBuilder({G_STRICT_SITOFP, G_STRICT_UITOFP})
+      .legalForCartesianProduct(allFloatScalarsAndVectors,
+                                allIntScalarsAndVectors);
+
+  getActionDefinitionsBuilder({G_STRICT_FPTOSI, G_STRICT_FPTOUI})
+      .legalForCartesianProduct(allIntScalarsAndVectors,
+                                allFloatScalarsAndVectors);
+
+  getActionDefinitionsBuilder({G_STRICT_FPEXT, G_STRICT_FPTRUNC})
+      .legalForCartesianProduct(allFloatScalarsAndVectors);
+
   getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
       .legalForCartesianProduct(allFloatScalarsAndVectors,
                                 allScalarsAndVectors);
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-convert.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-convert.ll
new file mode 100644
index 0000000000000..8ae45e3d8e30d
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/constrained-convert.ll
@@ -0,0 +1,41 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: OpName %[[#sf:]] "conv"
+; CHECK-DAG: OpName %[[#uf:]] "conv1"
+; CHECK-DAG: OpName %[[#fs:]] "conv2"
+; CHECK-DAG: OpName %[[#fu:]] "conv3"
+; CHECK-DAG: OpName %[[#fe:]] "conv4"
+; CHECK-DAG: OpName %[[#ft:]] "conv5"
+
+; CHECK-DAG: OpDecorate %[[#sf]] FPRoundingMode RTE
+; CHECK-DAG: OpDecorate %[[#uf]] FPRoundingMode RTZ
+; CHECK-DAG: OpDecorate %[[#ft]] FPRoundingMode RTP
+; CHECK-NOT: OpDecorate %[[#fs]] FPRoundingMode
+; CHECK-NOT: OpDecorate %[[#fu]] FPRoundingMode
+; CHECK-NOT: OpDecorate %[[#fe]] FPRoundingMode
+
+; CHECK: %[[#sf]] = OpConvertSToF
+; CHECK: %[[#uf]] = OpConvertUToF
+; CHECK: %[[#fs]] = OpConvertFToS
+; CHECK: %[[#fu]] = OpConvertFToU
+; CHECK: %[[#fe]] = OpFConvert
+; CHECK: %[[#ft]] = OpFConvert
+
+define dso_local spir_kernel void @test(float %a, i32 %in, i32 %ui) {
+entry:
+  %conv = tail call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %in, metadata !"round.tonearest", metadata !"fpexcept.strict") 
+  %conv1 = tail call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %ui, metadata !"round.towardzero", metadata !"fpexcept.ignore") 
+  %conv2 = tail call i32 @llvm.experimental.constrained.fptosi.i32.f32(float %conv1, metadata !"fpexcept.ignore") 
+  %conv3 = tail call i32 @llvm.experimental.constrained.fptoui.i32.f32(float %conv1, metadata !"fpexcept.ignore") 
+  %conv4 = tail call double @llvm.experimental.constrained.fpext.f64.f32(float %conv1, metadata !"fpexcept.ignore") 
+  %conv5 = tail call float @llvm.experimental.constrained.fptrunc.f32.f64(double %conv4, metadata !"round.upward", metadata !"fpexcept.ignore") 
+  ret void
+}
+
+declare float @llvm.experimental.constrained.sitofp.f32.i32(i32, metadata, metadata) 
+declare float @llvm.experimental.constrained.uitofp.f32.i32(i32, metadata, metadata) 
+declare i32 @llvm.experimental.constrained.fptosi.i32.f32(float, metadata) 
+declare i32 @llvm.experimental.constrained.fptoui.i32.f32(float, metadata) 
+declare double @llvm.experimental.constrained.fpext.f64.f32(float, metadata) 
+declare float @llvm.experimental.constrained.fptrunc.f32.f64(double, metadata, metadata) 

``````````

</details>


https://github.com/llvm/llvm-project/pull/157437


More information about the llvm-commits mailing list