Skip to content

Commit 1c75c82

Browse files
VishMCWMrSidimsEbinJose2002michalpaszkowski
authored
[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 <[email protected]> Co-authored-by: Ebin-McW <[email protected]> Co-authored-by: Michal Paszkowski <[email protected]>
1 parent 723b40a commit 1c75c82

File tree

4 files changed

+224
-0
lines changed

4 files changed

+224
-0
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,6 +1458,24 @@ static void createSaturatedConversionDecoration(Instruction *I,
14581458
createDecorationIntrinsic(I, SaturatedConversionNode, B);
14591459
}
14601460

1461+
static void addSaturatedDecorationToIntrinsic(Instruction *I, IRBuilder<> &B) {
1462+
if (auto *CI = dyn_cast<CallInst>(I)) {
1463+
if (Function *Fu = CI->getCalledFunction()) {
1464+
if (Fu->isIntrinsic()) {
1465+
unsigned const int IntrinsicId = Fu->getIntrinsicID();
1466+
switch (IntrinsicId) {
1467+
case Intrinsic::fptosi_sat:
1468+
case Intrinsic::fptoui_sat:
1469+
createSaturatedConversionDecoration(I, B);
1470+
break;
1471+
default:
1472+
break;
1473+
}
1474+
}
1475+
}
1476+
}
1477+
}
1478+
14611479
Instruction *SPIRVEmitIntrinsics::visitCallInst(CallInst &Call) {
14621480
if (!Call.isInlineAsm())
14631481
return &Call;
@@ -2640,6 +2658,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
26402658
if (isConvergenceIntrinsic(I))
26412659
continue;
26422660

2661+
addSaturatedDecorationToIntrinsic(I, B);
26432662
processInstrAfterVisit(I, B);
26442663
}
26452664

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,11 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
665665
case TargetOpcode::G_FPTOUI:
666666
return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);
667667

668+
case TargetOpcode::G_FPTOSI_SAT:
669+
return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToS);
670+
case TargetOpcode::G_FPTOUI_SAT:
671+
return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);
672+
668673
case TargetOpcode::G_SITOFP:
669674
return selectIToF(ResVReg, ResType, I, true, SPIRV::OpConvertSToF);
670675
case TargetOpcode::G_UITOFP:

llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
203203
.legalForCartesianProduct(allIntScalarsAndVectors,
204204
allFloatScalarsAndVectors);
205205

206+
getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
207+
.legalForCartesianProduct(allIntScalarsAndVectors,
208+
allFloatScalarsAndVectors);
209+
206210
getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
207211
.legalForCartesianProduct(allFloatScalarsAndVectors,
208212
allScalarsAndVectors);
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unkown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unkown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK: OpDecorate %[[#SAT1:]] SaturatedConversion
5+
; CHECK: OpDecorate %[[#SAT2:]] SaturatedConversion
6+
; CHECK: OpDecorate %[[#SAT3:]] SaturatedConversion
7+
; CHECK: OpDecorate %[[#SAT4:]] SaturatedConversion
8+
; CHECK: OpDecorate %[[#SAT5:]] SaturatedConversion
9+
; CHECK: OpDecorate %[[#SAT6:]] SaturatedConversion
10+
; CHECK: OpDecorate %[[#SAT7:]] SaturatedConversion
11+
; CHECK: OpDecorate %[[#SAT8:]] SaturatedConversion
12+
; CHECK: OpDecorate %[[#SAT9:]] SaturatedConversion
13+
; CHECK: OpDecorate %[[#SAT10:]] SaturatedConversion
14+
; CHECK: OpDecorate %[[#SAT11:]] SaturatedConversion
15+
; CHECK: OpDecorate %[[#SAT12:]] SaturatedConversion
16+
; CHECK: OpDecorate %[[#SAT13:]] SaturatedConversion
17+
; CHECK: OpDecorate %[[#SAT14:]] SaturatedConversion
18+
; CHECK: OpDecorate %[[#SAT15:]] SaturatedConversion
19+
; CHECK: OpDecorate %[[#SAT16:]] SaturatedConversion
20+
21+
22+
; CHECK: %[[#SAT1]] = OpConvertFToS %[[#]] %[[#]]
23+
define spir_kernel void @testfunction_float_to_signed_i8(float %input) {
24+
entry:
25+
%ptr = alloca i8
26+
%signed_int = call i8 @llvm.fptosi.sat.i8.f32(float %input)
27+
store i8 %signed_int, i8* %ptr
28+
ret void
29+
30+
}
31+
declare i8 @llvm.fptosi.sat.i8.f32(float)
32+
33+
34+
; CHECK: %[[#SAT2]] = OpConvertFToS %[[#]] %[[#]]
35+
define spir_kernel void @testfunction_float_to_signed_i16(float %input) {
36+
entry:
37+
%ptr = alloca i16
38+
%signed_int = call i16 @llvm.fptosi.sat.i16.f32(float %input)
39+
store i16 %signed_int, i16* %ptr
40+
ret void
41+
42+
}
43+
declare i16 @llvm.fptosi.sat.i16.f32(float)
44+
45+
; CHECK: %[[#SAT3]] = OpConvertFToS %[[#]] %[[#]]
46+
define spir_kernel void @testfunction_float_to_signed_i32(float %input) {
47+
entry:
48+
%ptr = alloca i32
49+
%signed_int = call i32 @llvm.fptosi.sat.i32.f32(float %input)
50+
store i32 %signed_int, i32* %ptr
51+
ret void
52+
53+
}
54+
declare i32 @llvm.fptosi.sat.i32.f32(float)
55+
56+
57+
; CHECK: %[[#SAT4]] = OpConvertFToS %[[#]] %[[#]]
58+
define spir_kernel void @testfunction_float_to_signed_i64(float %input) {
59+
entry:
60+
%ptr = alloca i64
61+
%signed_int = call i64 @llvm.fptosi.sat.i64.f32(float %input)
62+
store i64 %signed_int, i64* %ptr
63+
ret void
64+
}
65+
declare i64 @llvm.fptosi.sat.i64.f32(float)
66+
67+
68+
; CHECK: %[[#SAT5]] = OpConvertFToS %[[#]] %[[#]]
69+
define spir_kernel void @testfunction_double_to_signed_i8(double %input) {
70+
entry:
71+
%ptr = alloca i8
72+
%signed_int = call i8 @llvm.fptosi.sat.i8.f64(double %input)
73+
store i8 %signed_int, i8* %ptr
74+
ret void
75+
}
76+
declare i8 @llvm.fptosi.sat.i8.f64(double)
77+
78+
79+
; CHECK: %[[#SAT6]] = OpConvertFToS %[[#]] %[[#]]
80+
define spir_kernel void @testfunction_double_to_signed_i16(double %input) {
81+
entry:
82+
%ptr = alloca i16
83+
%signed_int = call i16 @llvm.fptosi.sat.i16.f64(double %input)
84+
store i16 %signed_int, i16* %ptr
85+
ret void
86+
}
87+
declare i16 @llvm.fptosi.sat.i16.f64(double)
88+
89+
90+
; CHECK: %[[#SAT7]] = OpConvertFToS %[[#]] %[[#]]
91+
define spir_kernel void @testfunction_double_to_signed_i32(double %input) {
92+
entry:
93+
%ptr = alloca i32
94+
%signed_int = call i32 @llvm.fptosi.sat.i32.f64(double %input)
95+
store i32 %signed_int, i32* %ptr
96+
ret void
97+
}
98+
declare i32 @llvm.fptosi.sat.i32.f64(double)
99+
100+
101+
; CHECK: %[[#SAT8]] = OpConvertFToS %[[#]] %[[#]]
102+
define spir_kernel void @testfunction_double_to_signed_i64(double %input) {
103+
entry:
104+
%ptr = alloca i64
105+
%signed_int = call i64 @llvm.fptosi.sat.i64.f64(double %input)
106+
store i64 %signed_int, i64* %ptr
107+
ret void
108+
}
109+
declare i64 @llvm.fptosi.sat.i64.f64(double)
110+
111+
; CHECK: %[[#SAT9]] = OpConvertFToU %[[#]] %[[#]]
112+
define spir_kernel void @testfunction_float_to_unsigned_i8(float %input) {
113+
entry:
114+
%ptr = alloca i8
115+
%unsigned_int = call i8 @llvm.fptoui.sat.i8.f32(float %input)
116+
store i8 %unsigned_int, i8* %ptr
117+
ret void
118+
}
119+
declare i8 @llvm.fptoui.sat.i8.f32(float)
120+
121+
122+
; CHECK: %[[#SAT10]] = OpConvertFToU %[[#]] %[[#]]
123+
define spir_kernel void @testfunction_float_to_unsigned_i16(float %input) {
124+
entry:
125+
%ptr = alloca i16
126+
%unsigned_int = call i16 @llvm.fptoui.sat.i16.f32(float %input)
127+
store i16 %unsigned_int, i16* %ptr
128+
ret void
129+
}
130+
declare i16 @llvm.fptoui.sat.i16.f32(float)
131+
132+
133+
; CHECK: %[[#SAT11]] = OpConvertFToU %[[#]] %[[#]]
134+
define spir_kernel void @testfunction_float_to_unsigned_i32(float %input) {
135+
entry:
136+
%ptr = alloca i32
137+
%unsigned_int = call i32 @llvm.fptoui.sat.i32.f32(float %input)
138+
store i32 %unsigned_int, i32* %ptr
139+
ret void
140+
}
141+
declare i32 @llvm.fptoui.sat.i32.f32(float)
142+
143+
144+
; CHECK: %[[#SAT12]] = OpConvertFToU %[[#]] %[[#]]
145+
define spir_kernel void @testfunction_float_to_unsigned_i64(float %input) {
146+
entry:
147+
%ptr = alloca i64
148+
%unsigned_int = call i64 @llvm.fptoui.sat.i64.f32(float %input)
149+
store i64 %unsigned_int, i64* %ptr
150+
ret void
151+
}
152+
declare i64 @llvm.fptoui.sat.i64.f32(float)
153+
154+
155+
; CHECK: %[[#SAT13]] = OpConvertFToU %[[#]] %[[#]]
156+
define spir_kernel void @testfunction_double_to_unsigned_i8(double %input) {
157+
entry:
158+
%ptr = alloca i8
159+
%unsigned_int = call i8 @llvm.fptoui.sat.i8.f64(double %input)
160+
store i8 %unsigned_int, i8* %ptr
161+
ret void
162+
}
163+
declare i8 @llvm.fptoui.sat.i8.f64(double)
164+
165+
166+
; CHECK: %[[#SAT14]] = OpConvertFToU %[[#]] %[[#]]
167+
define spir_kernel void @testfunction_double_to_unsigned_i16(double %input) {
168+
entry:
169+
%ptr = alloca i16
170+
%unsigned_int = call i16 @llvm.fptoui.sat.i16.f64(double %input)
171+
store i16 %unsigned_int, i16* %ptr
172+
ret void
173+
}
174+
declare i16 @llvm.fptoui.sat.i16.f64(double)
175+
176+
177+
; CHECK: %[[#SAT15]] = OpConvertFToU %[[#]] %[[#]]
178+
define spir_kernel void @testfunction_double_to_unsigned_i32(double %input) {
179+
entry:
180+
%ptr = alloca i32
181+
%unsigned_int = call i32 @llvm.fptoui.sat.i32.f64(double %input)
182+
store i32 %unsigned_int, i32* %ptr
183+
ret void
184+
}
185+
declare i32 @llvm.fptoui.sat.i32.f64(double)
186+
187+
188+
; CHECK: %[[#SAT16]] = OpConvertFToU %[[#]] %[[#]]
189+
define spir_kernel void @testfunction_double_to_unsigned_i64(double %input) {
190+
entry:
191+
%ptr = alloca i64
192+
%unsigned_int = call i64 @llvm.fptoui.sat.i64.f64(double %input)
193+
store i64 %unsigned_int, i64* %ptr
194+
ret void
195+
}
196+
declare i64 @llvm.fptoui.sat.i64.f64(double)

0 commit comments

Comments
 (0)