xref: /llvm-project/llvm/test/CodeGen/SPIRV/instructions/integer-casts.ll (revision 978de2d6664a74864471d62244700c216fdc6741)
1; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
2; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3
4; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
5; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
6
7; CHECK-DAG: OpName [[TRUNC32_16:%.*]] "i32toi16"
8; CHECK-DAG: OpName [[TRUNC32_8:%.*]] "i32toi8"
9; CHECK-DAG: OpName [[TRUNC16_8:%.*]] "i16toi8"
10; CHECK-DAG: OpName [[SEXT8_32:%.*]] "s8tos32"
11; CHECK-DAG: OpName [[SEXT8_16:%.*]] "s8tos16"
12; CHECK-DAG: OpName [[SEXT16_32:%.*]] "s16tos32"
13; CHECK-DAG: OpName [[ZEXT8_32:%.*]] "u8tou32"
14; CHECK-DAG: OpName [[ZEXT8_16:%.*]] "u8tou16"
15; CHECK-DAG: OpName [[ZEXT16_32:%.*]] "u16tou32"
16
17; CHECK-DAG: OpName %[[#R17:]] "r17"
18; CHECK-DAG: OpName %[[#R18:]] "r18"
19; CHECK-DAG: OpName %[[#R19:]] "r19"
20; CHECK-DAG: OpName %[[#R20:]] "r20"
21; CHECK-DAG: OpName %[[#R21:]] "r21"
22
23; CHECK-DAG: OpName [[TRUNC32_16v4:%.*]] "i32toi16v4"
24; CHECK-DAG: OpName [[TRUNC32_8v4:%.*]] "i32toi8v4"
25; CHECK-DAG: OpName [[TRUNC16_8v4:%.*]] "i16toi8v4"
26; CHECK-DAG: OpName [[SEXT8_32v4:%.*]] "s8tos32v4"
27; CHECK-DAG: OpName [[SEXT8_16v4:%.*]] "s8tos16v4"
28; CHECK-DAG: OpName [[SEXT16_32v4:%.*]] "s16tos32v4"
29; CHECK-DAG: OpName [[ZEXT8_32v4:%.*]] "u8tou32v4"
30; CHECK-DAG: OpName [[ZEXT8_16v4:%.*]] "u8tou16v4"
31; CHECK-DAG: OpName [[ZEXT16_32v4:%.*]] "u16tou32v4"
32
33; CHECK-DAG: OpDecorate %[[#R17]] FPRoundingMode RTZ
34; CHECK-DAG: OpDecorate %[[#R18]] FPRoundingMode RTE
35; CHECK-DAG: OpDecorate %[[#R19]] FPRoundingMode RTP
36; CHECK-DAG: OpDecorate %[[#R20]] FPRoundingMode RTN
37; CHECK-DAG: OpDecorate %[[#R21]] SaturatedConversion
38
39; CHECK-DAG: [[F32:%.*]] = OpTypeFloat 32
40; CHECK-DAG: [[F16:%.*]] = OpTypeFloat 16
41; CHECK-DAG: [[U64:%.*]] = OpTypeInt 64 0
42; CHECK-DAG: [[U32:%.*]] = OpTypeInt 32 0
43; CHECK-DAG: [[U16:%.*]] = OpTypeInt 16 0
44; CHECK-DAG: [[U8:%.*]] = OpTypeInt 8 0
45; CHECK-DAG: [[F32v2:%.*]] = OpTypeVector [[F32]] 2
46; CHECK-DAG: [[U32v4:%.*]] = OpTypeVector [[U32]] 4
47; CHECK-DAG: [[U16v4:%.*]] = OpTypeVector [[U16]] 4
48; CHECK-DAG: [[U8v4:%.*]] = OpTypeVector [[U8]] 4
49
50
51; CHECK:      [[TRUNC32_16]] = OpFunction [[U16]]
52; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U32]]
53; CHECK:      OpLabel
54; CHECK:      [[R:%.*]] = OpUConvert [[U16]] [[A]]
55; CHECK:      OpReturnValue [[R]]
56; CHECK-NEXT: OpFunctionEnd
57define i16 @i32toi16(i32 %a) {
58    %r = trunc i32 %a to i16
59    ret i16 %r
60}
61
62; CHECK:      [[TRUNC32_8]] = OpFunction [[U8]]
63; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U32]]
64; CHECK:      OpLabel
65; CHECK:      [[R:%.*]] = OpUConvert [[U8]] [[A]]
66; CHECK:      OpReturnValue [[R]]
67; CHECK-NEXT: OpFunctionEnd
68define i8 @i32toi8(i32 %a) {
69    %r = trunc i32 %a to i8
70    ret i8 %r
71}
72
73; CHECK:      [[TRUNC16_8]] = OpFunction [[U8]]
74; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U16]]
75; CHECK:      OpLabel
76; CHECK:      [[R:%.*]] = OpUConvert [[U8]] [[A]]
77; CHECK:      OpReturnValue [[R]]
78; CHECK-NEXT: OpFunctionEnd
79define i8 @i16toi8(i16 %a) {
80    %r = trunc i16 %a to i8
81    ret i8 %r
82}
83
84
85; CHECK:      [[SEXT8_32]] = OpFunction [[U32]]
86; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U8]]
87; CHECK:      OpLabel
88; CHECK:      [[R:%.*]] = OpSConvert [[U32]] [[A]]
89; CHECK:      OpReturnValue [[R]]
90; CHECK-NEXT: OpFunctionEnd
91define i32 @s8tos32(i8 %a) {
92  %r = sext i8 %a to i32
93  ret i32 %r
94}
95
96; CHECK:      [[SEXT8_16]] = OpFunction [[U16]]
97; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U8]]
98; CHECK:      OpLabel
99; CHECK:      [[R:%.*]] = OpSConvert [[U16]] [[A]]
100; CHECK:      OpReturnValue [[R]]
101; CHECK-NEXT: OpFunctionEnd
102define i16 @s8tos16(i8 %a) {
103  %r = sext i8 %a to i16
104  ret i16 %r
105}
106
107; CHECK:      [[SEXT16_32]] = OpFunction [[U32]]
108; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U16]]
109; CHECK:      OpLabel
110; CHECK:      [[R:%.*]] = OpSConvert [[U32]] [[A]]
111; CHECK:      OpReturnValue [[R]]
112; CHECK-NEXT: OpFunctionEnd
113define i32 @s16tos32(i16 %a) {
114  %r = sext i16 %a to i32
115  ret i32 %r
116}
117
118; CHECK:      [[ZEXT8_32]] = OpFunction [[U32]]
119; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U8]]
120; CHECK:      OpLabel
121; CHECK:      [[R:%.*]] = OpUConvert [[U32]] [[A]]
122; CHECK:      OpReturnValue [[R]]
123; CHECK-NEXT: OpFunctionEnd
124define i32 @u8tou32(i8 %a) {
125  %r = zext i8 %a to i32
126  ret i32 %r
127}
128
129; CHECK:      [[ZEXT8_16]] = OpFunction [[U16]]
130; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U8]]
131; CHECK:      OpLabel
132; CHECK:      [[R:%.*]] = OpUConvert [[U16]] [[A]]
133; CHECK:      OpReturnValue [[R]]
134; CHECK-NEXT: OpFunctionEnd
135define i16 @u8tou16(i8 %a) {
136  %r = zext i8 %a to i16
137  ret i16 %r
138}
139
140; CHECK:      [[ZEXT16_32]] = OpFunction [[U32]]
141; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U16]]
142; CHECK:      OpLabel
143; CHECK:      [[R:%.*]] = OpUConvert [[U32]] [[A]]
144; CHECK:      OpReturnValue [[R]]
145; CHECK-NEXT: OpFunctionEnd
146define i32 @u16tou32(i16 %a) {
147  %r = zext i16 %a to i32
148  ret i32 %r
149}
150
151; CHECK:      [[TRUNC32_16v4]] = OpFunction [[U16v4]]
152; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U32v4]]
153; CHECK:      OpLabel
154; CHECK:      [[R:%.*]] = OpUConvert [[U16v4]] [[A]]
155; CHECK:      OpReturnValue [[R]]
156; CHECK-NEXT: OpFunctionEnd
157define <4 x i16> @i32toi16v4(<4 x i32> %a) {
158    %r = trunc <4 x i32> %a to <4 x i16>
159    ret <4 x i16> %r
160}
161
162; CHECK:      [[TRUNC32_8v4]] = OpFunction [[U8v4]]
163; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U32v4]]
164; CHECK:      OpLabel
165; CHECK:      [[R:%.*]] = OpUConvert [[U8v4]] [[A]]
166; CHECK:      OpReturnValue [[R]]
167; CHECK-NEXT: OpFunctionEnd
168define <4 x i8> @i32toi8v4(<4 x i32> %a) {
169    %r = trunc <4 x i32> %a to <4 x i8>
170    ret <4 x i8> %r
171}
172
173; CHECK:      [[TRUNC16_8v4]] = OpFunction [[U8v4]]
174; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U16v4]]
175; CHECK:      OpLabel
176; CHECK:      [[R:%.*]] = OpUConvert [[U8v4]] [[A]]
177; CHECK:      OpReturnValue [[R]]
178; CHECK-NEXT: OpFunctionEnd
179define <4 x i8> @i16toi8v4(<4 x i16> %a) {
180    %r = trunc <4 x i16> %a to <4 x i8>
181    ret <4 x i8> %r
182}
183
184
185; CHECK:      [[SEXT8_32v4]] = OpFunction [[U32v4]]
186; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U8v4]]
187; CHECK:      OpLabel
188; CHECK:      [[R:%.*]] = OpSConvert [[U32v4]] [[A]]
189; CHECK:      OpReturnValue [[R]]
190; CHECK-NEXT: OpFunctionEnd
191define <4 x i32>  @s8tos32v4(<4 x i8> %a) {
192  %r = sext <4 x i8> %a to <4 x i32>
193  ret <4 x i32>  %r
194}
195
196; CHECK:      [[SEXT8_16v4]] = OpFunction [[U16v4]]
197; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U8v4]]
198; CHECK:      OpLabel
199; CHECK:      [[R:%.*]] = OpSConvert [[U16v4]] [[A]]
200; CHECK:      OpReturnValue [[R]]
201; CHECK-NEXT: OpFunctionEnd
202define <4 x i16> @s8tos16v4(<4 x i8> %a) {
203  %r = sext <4 x i8> %a to <4 x i16>
204  ret <4 x i16> %r
205}
206
207; CHECK:      [[SEXT16_32v4]] = OpFunction [[U32v4]]
208; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U16v4]]
209; CHECK:      OpLabel
210; CHECK:      [[R:%.*]] = OpSConvert [[U32v4]] [[A]]
211; CHECK:      OpReturnValue [[R]]
212; CHECK-NEXT: OpFunctionEnd
213define <4 x i32>  @s16tos32v4(<4 x i16> %a) {
214  %r = sext <4 x i16> %a to <4 x i32>
215  ret <4 x i32>  %r
216}
217
218; CHECK:      [[ZEXT8_32v4]] = OpFunction [[U32v4]]
219; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U8v4]]
220; CHECK:      OpLabel
221; CHECK:      [[R:%.*]] = OpUConvert [[U32v4]] [[A]]
222; CHECK:      OpReturnValue [[R]]
223; CHECK-NEXT: OpFunctionEnd
224define <4 x i32>  @u8tou32v4(<4 x i8> %a) {
225  %r = zext <4 x i8> %a to <4 x i32>
226  ret <4 x i32>  %r
227}
228
229; CHECK:      [[ZEXT8_16v4]] = OpFunction [[U16v4]]
230; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U8v4]]
231; CHECK:      OpLabel
232; CHECK:      [[R:%.*]] = OpUConvert [[U16v4]] [[A]]
233; CHECK:      OpReturnValue [[R]]
234; CHECK-NEXT: OpFunctionEnd
235define <4 x i16> @u8tou16v4(<4 x i8> %a) {
236  %r = zext <4 x i8> %a to <4 x i16>
237  ret <4 x i16> %r
238}
239
240; CHECK:      [[ZEXT16_32v4]] = OpFunction [[U32v4]]
241; CHECK-NEXT: [[A:%.*]] = OpFunctionParameter [[U16v4]]
242; CHECK:      OpLabel
243; CHECK:      [[R:%.*]] = OpUConvert [[U32v4]] [[A]]
244; CHECK:      OpReturnValue [[R]]
245; CHECK-NEXT: OpFunctionEnd
246define <4 x i32>  @u16tou32v4(<4 x i16> %a) {
247  %r = zext <4 x i16> %a to <4 x i32>
248  ret <4 x i32>  %r
249}
250
251; CHECK: OpFunction
252; CHECK: [[Arg1:%.*]] = OpFunctionParameter
253; CHECK: [[Arg2:%.*]] = OpFunctionParameter
254; CHECK: %[[#]] = OpConvertFToU [[U32]] %[[#]]
255; CHECK: %[[#]] = OpConvertFToS [[U32]] %[[#]]
256; CHECK: %[[#]] = OpConvertSToF [[F32]] %[[#]]
257; CHECK: %[[#]] = OpConvertUToF [[F32]] %[[#]]
258; CHECK: %[[#]] = OpUConvert [[U32]] %[[#]]
259; CHECK: %[[#]] = OpSConvert [[U32]] %[[#]]
260; CHECK: %[[#]] = OpFConvert [[F16]] %[[#]]
261; CHECK: %[[#]] = OpQuantizeToF16 [[F32]] %[[#]]
262; CHECK: %[[#]] = OpSatConvertSToU [[U64]] %[[#]]
263; CHECK: %[[#]] = OpSatConvertUToS [[U64]] %[[#]]
264; CHECK: %[[#]] = OpConvertPtrToU [[U64]] [[Arg1]]
265; CHECK: %[[#]] = OpConvertUToPtr %[[#]] [[Arg2]]
266; CHECK: %[[#]] = OpUConvert [[U32v4]] %[[#]]
267; CHECK: %[[#]] = OpSConvert [[U32v4]] %[[#]]
268; CHECK: %[[#]] = OpConvertUToF [[F32]] %[[#]]
269; CHECK: %[[#]] = OpConvertUToF [[F32]] %[[#]]
270; CHECK: %[[#R17]] = OpFConvert [[F32v2]] %[[#]]
271; CHECK: %[[#R18]] = OpFConvert [[F32v2]] %[[#]]
272; CHECK: %[[#R19]] = OpFConvert [[F32v2]] %[[#]]
273; CHECK: %[[#R20]] = OpFConvert [[F32v2]] %[[#]]
274; CHECK: %[[#R21]] = OpConvertFToU [[U8]] %[[#]]
275; CHECK: OpFunctionEnd
276define dso_local spir_kernel void @test_wrappers(ptr addrspace(4) %arg, i64 %arg_ptr, <4 x i8> %arg_v2) {
277  %r1 = call spir_func i32 @__spirv_ConvertFToU(float 0.000000e+00)
278  %r2 = call spir_func i32 @__spirv_ConvertFToS(float 0.000000e+00)
279  %r3 = call spir_func float @__spirv_ConvertSToF(i32 1)
280  %r4 = call spir_func float @__spirv_ConvertUToF(i32 1)
281  %r5 = call spir_func i32 @__spirv_UConvert(i64 1)
282  %r6 = call spir_func i32 @__spirv_SConvert(i64 1)
283  %r7 = call spir_func half @__spirv_FConvert(float 0.000000e+00)
284  %r8 = call spir_func float @__spirv_QuantizeToF16(float 0.000000e+00)
285  %r9 = call spir_func i64 @__spirv_SatConvertSToU(i64 1)
286  %r10 = call spir_func i64 @__spirv_SatConvertUToS(i64 1)
287  %r11 = call spir_func i64 @__spirv_ConvertPtrToU(ptr addrspace(4) %arg)
288  %r12 = call spir_func ptr addrspace(4) @__spirv_ConvertUToPtr(i64 %arg_ptr)
289  %r13 = call spir_func <4 x i32> @_Z22__spirv_UConvert_Rint2Dv2_a(<4 x i8> %arg_v2)
290  %r14 = call spir_func <4 x i32> @_Z22__spirv_SConvert_Rint2Dv2_a(<4 x i8> %arg_v2)
291  %r15 = call spir_func float @_Z30__spirv_ConvertUToF_Rfloat_rtz(i64 %arg_ptr)
292  %r16 = call spir_func float @__spirv_ConvertUToF_Rfloat_rtz(i64 %arg_ptr)
293  %r17 = call spir_func <2 x float> @_Z28__spirv_FConvert_Rfloat2_rtzDv2_DF16_(<2 x half> noundef <half 0xH409A, half 0xH439A>)
294  %r18 = call spir_func <2 x float> @_Z28__spirv_FConvert_Rfloat2_rteDv2_DF16_(<2 x half> noundef <half 0xH409A, half 0xH439A>)
295  %r19 = call spir_func <2 x float> @_Z28__spirv_FConvert_Rfloat2_rtpDv2_DF16_(<2 x half> noundef <half 0xH409A, half 0xH439A>)
296  %r20 = call spir_func <2 x float> @_Z28__spirv_FConvert_Rfloat2_rtnDv2_DF16_(<2 x half> noundef <half 0xH409A, half 0xH439A>)
297  %r21 = call spir_func i8 @_Z30__spirv_ConvertFToU_Ruchar_satf(float noundef 42.0)
298  ret void
299}
300
301declare dso_local spir_func i32 @__spirv_ConvertFToU(float)
302declare dso_local spir_func i32 @__spirv_ConvertFToS(float)
303declare dso_local spir_func float @__spirv_ConvertSToF(i32)
304declare dso_local spir_func float @__spirv_ConvertUToF(i32)
305declare dso_local spir_func i32 @__spirv_UConvert(i64)
306declare dso_local spir_func i32 @__spirv_SConvert(i64)
307declare dso_local spir_func half @__spirv_FConvert(float)
308declare dso_local spir_func float @__spirv_QuantizeToF16(float)
309declare dso_local spir_func i64 @__spirv_SatConvertSToU(i64)
310declare dso_local spir_func i64 @__spirv_SatConvertUToS(i64)
311declare dso_local spir_func i64 @__spirv_ConvertPtrToU(ptr addrspace(4))
312declare dso_local spir_func ptr addrspace(4) @__spirv_ConvertUToPtr(i64)
313declare dso_local spir_func <4 x i32> @_Z22__spirv_UConvert_Rint2Dv2_a(<4 x i8>)
314declare dso_local spir_func <4 x i32> @_Z22__spirv_SConvert_Rint2Dv2_a(<4 x i8>)
315declare dso_local spir_func float @_Z30__spirv_ConvertUToF_Rfloat_rtz(i64)
316declare dso_local spir_func float @__spirv_ConvertUToF_Rfloat_rtz(i64)
317declare dso_local spir_func <2 x float> @_Z28__spirv_FConvert_Rfloat2_rtzDv2_DF16_(<2 x half> noundef)
318declare dso_local spir_func <2 x float> @_Z28__spirv_FConvert_Rfloat2_rteDv2_DF16_(<2 x half> noundef)
319declare dso_local spir_func <2 x float> @_Z28__spirv_FConvert_Rfloat2_rtpDv2_DF16_(<2 x half> noundef)
320declare dso_local spir_func <2 x float> @_Z28__spirv_FConvert_Rfloat2_rtnDv2_DF16_(<2 x half> noundef)
321declare dso_local spir_func i8 @_Z30__spirv_ConvertFToU_Ruchar_satf(float)
322