aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVISHAKH PRAKASH <vishakh.prakash@multicorewareinc.com>2025-08-04 03:06:54 +0530
committerGitHub <noreply@github.com>2025-08-03 23:36:54 +0200
commit1c75c829dc4f47575e1e702009b511f9cd0da2cb (patch)
tree621be33f8155dc85b69242093b8626d637870b9d
parent723b40a8d92f76fc913ef21061fc3d74e8c47441 (diff)
downloadllvm-1c75c829dc4f47575e1e702009b511f9cd0da2cb.zip
llvm-1c75c829dc4f47575e1e702009b511f9cd0da2cb.tar.gz
llvm-1c75c829dc4f47575e1e702009b511f9cd0da2cb.tar.bz2
[SPIRV] support for the intrinsic @llvm.fptosi.sat.* and @llvm.fptoui.sat.* (#129222)
Add support for the intrinsic @llvm.fptosi.sat.* and @llvm.fptoui.sat.* - add legalizer for G_FPTOSI_SAT and G_FPTOUI_SAT - add instructionSelector for G_FPTOSI_SAT and G_FPTOUI_SAT - add function to add saturatedConversion decoration to the intrinsic --------- Co-authored-by: Dmitry Sidorov <dmitry.sidorov@intel.com> Co-authored-by: Ebin-McW <ebin.jose@multicorewareinc.com> Co-authored-by: Michal Paszkowski <michal@michalpaszkowski.com>
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp19
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp5
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp4
-rw-r--r--llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp-to-int-intrinsics.ll196
4 files changed, 224 insertions, 0 deletions
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 947b574..9f55330 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -1458,6 +1458,24 @@ static void createSaturatedConversionDecoration(Instruction *I,
createDecorationIntrinsic(I, SaturatedConversionNode, B);
}
+static void addSaturatedDecorationToIntrinsic(Instruction *I, IRBuilder<> &B) {
+ if (auto *CI = dyn_cast<CallInst>(I)) {
+ if (Function *Fu = CI->getCalledFunction()) {
+ if (Fu->isIntrinsic()) {
+ unsigned const int IntrinsicId = Fu->getIntrinsicID();
+ switch (IntrinsicId) {
+ case Intrinsic::fptosi_sat:
+ case Intrinsic::fptoui_sat:
+ createSaturatedConversionDecoration(I, B);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
+
Instruction *SPIRVEmitIntrinsics::visitCallInst(CallInst &Call) {
if (!Call.isInlineAsm())
return &Call;
@@ -2640,6 +2658,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
if (isConvergenceIntrinsic(I))
continue;
+ addSaturatedDecorationToIntrinsic(I, B);
processInstrAfterVisit(I, B);
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index d4fa62a..e9f5ffa 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -665,6 +665,11 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
case TargetOpcode::G_FPTOUI:
return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);
+ case TargetOpcode::G_FPTOSI_SAT:
+ return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToS);
+ case TargetOpcode::G_FPTOUI_SAT:
+ return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);
+
case TargetOpcode::G_SITOFP:
return selectIToF(ResVReg, ResType, I, true, SPIRV::OpConvertSToF);
case TargetOpcode::G_UITOFP:
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 1995e0f..170bddd 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -203,6 +203,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
.legalForCartesianProduct(allIntScalarsAndVectors,
allFloatScalarsAndVectors);
+ getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
+ .legalForCartesianProduct(allIntScalarsAndVectors,
+ allFloatScalarsAndVectors);
+
getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
.legalForCartesianProduct(allFloatScalarsAndVectors,
allScalarsAndVectors);
diff --git a/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp-to-int-intrinsics.ll b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp-to-int-intrinsics.ll
new file mode 100644
index 0000000..66c744f
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/llvm-intrinsics/fp-to-int-intrinsics.ll
@@ -0,0 +1,196 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unkown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unkown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpDecorate %[[#SAT1:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT2:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT3:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT4:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT5:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT6:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT7:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT8:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT9:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT10:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT11:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT12:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT13:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT14:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT15:]] SaturatedConversion
+; CHECK: OpDecorate %[[#SAT16:]] SaturatedConversion
+
+
+; CHECK: %[[#SAT1]] = OpConvertFToS %[[#]] %[[#]]
+define spir_kernel void @testfunction_float_to_signed_i8(float %input) {
+entry:
+ %ptr = alloca i8
+ %signed_int = call i8 @llvm.fptosi.sat.i8.f32(float %input)
+ store i8 %signed_int, i8* %ptr
+ ret void
+
+}
+declare i8 @llvm.fptosi.sat.i8.f32(float)
+
+
+; CHECK: %[[#SAT2]] = OpConvertFToS %[[#]] %[[#]]
+define spir_kernel void @testfunction_float_to_signed_i16(float %input) {
+entry:
+ %ptr = alloca i16
+ %signed_int = call i16 @llvm.fptosi.sat.i16.f32(float %input)
+ store i16 %signed_int, i16* %ptr
+ ret void
+
+}
+declare i16 @llvm.fptosi.sat.i16.f32(float)
+
+; CHECK: %[[#SAT3]] = OpConvertFToS %[[#]] %[[#]]
+define spir_kernel void @testfunction_float_to_signed_i32(float %input) {
+entry:
+ %ptr = alloca i32
+ %signed_int = call i32 @llvm.fptosi.sat.i32.f32(float %input)
+ store i32 %signed_int, i32* %ptr
+ ret void
+
+}
+declare i32 @llvm.fptosi.sat.i32.f32(float)
+
+
+; CHECK: %[[#SAT4]] = OpConvertFToS %[[#]] %[[#]]
+define spir_kernel void @testfunction_float_to_signed_i64(float %input) {
+entry:
+ %ptr = alloca i64
+ %signed_int = call i64 @llvm.fptosi.sat.i64.f32(float %input)
+ store i64 %signed_int, i64* %ptr
+ ret void
+}
+declare i64 @llvm.fptosi.sat.i64.f32(float)
+
+
+; CHECK: %[[#SAT5]] = OpConvertFToS %[[#]] %[[#]]
+define spir_kernel void @testfunction_double_to_signed_i8(double %input) {
+entry:
+ %ptr = alloca i8
+ %signed_int = call i8 @llvm.fptosi.sat.i8.f64(double %input)
+ store i8 %signed_int, i8* %ptr
+ ret void
+}
+declare i8 @llvm.fptosi.sat.i8.f64(double)
+
+
+; CHECK: %[[#SAT6]] = OpConvertFToS %[[#]] %[[#]]
+define spir_kernel void @testfunction_double_to_signed_i16(double %input) {
+entry:
+ %ptr = alloca i16
+ %signed_int = call i16 @llvm.fptosi.sat.i16.f64(double %input)
+ store i16 %signed_int, i16* %ptr
+ ret void
+}
+declare i16 @llvm.fptosi.sat.i16.f64(double)
+
+
+; CHECK: %[[#SAT7]] = OpConvertFToS %[[#]] %[[#]]
+define spir_kernel void @testfunction_double_to_signed_i32(double %input) {
+entry:
+ %ptr = alloca i32
+ %signed_int = call i32 @llvm.fptosi.sat.i32.f64(double %input)
+ store i32 %signed_int, i32* %ptr
+ ret void
+}
+declare i32 @llvm.fptosi.sat.i32.f64(double)
+
+
+; CHECK: %[[#SAT8]] = OpConvertFToS %[[#]] %[[#]]
+define spir_kernel void @testfunction_double_to_signed_i64(double %input) {
+entry:
+ %ptr = alloca i64
+ %signed_int = call i64 @llvm.fptosi.sat.i64.f64(double %input)
+ store i64 %signed_int, i64* %ptr
+ ret void
+}
+declare i64 @llvm.fptosi.sat.i64.f64(double)
+
+; CHECK: %[[#SAT9]] = OpConvertFToU %[[#]] %[[#]]
+define spir_kernel void @testfunction_float_to_unsigned_i8(float %input) {
+entry:
+ %ptr = alloca i8
+ %unsigned_int = call i8 @llvm.fptoui.sat.i8.f32(float %input)
+ store i8 %unsigned_int, i8* %ptr
+ ret void
+}
+declare i8 @llvm.fptoui.sat.i8.f32(float)
+
+
+; CHECK: %[[#SAT10]] = OpConvertFToU %[[#]] %[[#]]
+define spir_kernel void @testfunction_float_to_unsigned_i16(float %input) {
+entry:
+ %ptr = alloca i16
+ %unsigned_int = call i16 @llvm.fptoui.sat.i16.f32(float %input)
+ store i16 %unsigned_int, i16* %ptr
+ ret void
+}
+declare i16 @llvm.fptoui.sat.i16.f32(float)
+
+
+; CHECK: %[[#SAT11]] = OpConvertFToU %[[#]] %[[#]]
+define spir_kernel void @testfunction_float_to_unsigned_i32(float %input) {
+entry:
+ %ptr = alloca i32
+ %unsigned_int = call i32 @llvm.fptoui.sat.i32.f32(float %input)
+ store i32 %unsigned_int, i32* %ptr
+ ret void
+}
+declare i32 @llvm.fptoui.sat.i32.f32(float)
+
+
+; CHECK: %[[#SAT12]] = OpConvertFToU %[[#]] %[[#]]
+define spir_kernel void @testfunction_float_to_unsigned_i64(float %input) {
+entry:
+ %ptr = alloca i64
+ %unsigned_int = call i64 @llvm.fptoui.sat.i64.f32(float %input)
+ store i64 %unsigned_int, i64* %ptr
+ ret void
+}
+declare i64 @llvm.fptoui.sat.i64.f32(float)
+
+
+; CHECK: %[[#SAT13]] = OpConvertFToU %[[#]] %[[#]]
+define spir_kernel void @testfunction_double_to_unsigned_i8(double %input) {
+entry:
+ %ptr = alloca i8
+ %unsigned_int = call i8 @llvm.fptoui.sat.i8.f64(double %input)
+ store i8 %unsigned_int, i8* %ptr
+ ret void
+}
+declare i8 @llvm.fptoui.sat.i8.f64(double)
+
+
+; CHECK: %[[#SAT14]] = OpConvertFToU %[[#]] %[[#]]
+define spir_kernel void @testfunction_double_to_unsigned_i16(double %input) {
+entry:
+ %ptr = alloca i16
+ %unsigned_int = call i16 @llvm.fptoui.sat.i16.f64(double %input)
+ store i16 %unsigned_int, i16* %ptr
+ ret void
+}
+declare i16 @llvm.fptoui.sat.i16.f64(double)
+
+
+; CHECK: %[[#SAT15]] = OpConvertFToU %[[#]] %[[#]]
+define spir_kernel void @testfunction_double_to_unsigned_i32(double %input) {
+entry:
+ %ptr = alloca i32
+ %unsigned_int = call i32 @llvm.fptoui.sat.i32.f64(double %input)
+ store i32 %unsigned_int, i32* %ptr
+ ret void
+}
+declare i32 @llvm.fptoui.sat.i32.f64(double)
+
+
+; CHECK: %[[#SAT16]] = OpConvertFToU %[[#]] %[[#]]
+define spir_kernel void @testfunction_double_to_unsigned_i64(double %input) {
+entry:
+ %ptr = alloca i64
+ %unsigned_int = call i64 @llvm.fptoui.sat.i64.f64(double %input)
+ store i64 %unsigned_int, i64* %ptr
+ ret void
+}
+declare i64 @llvm.fptoui.sat.i64.f64(double)