xref: /llvm-project/mlir/test/Dialect/SPIRV/IR/cast-ops.mlir (revision 6e90f13cc9bc9dbc5c2c248d95c6e18a5fb021b4)
1// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
2
3//===----------------------------------------------------------------------===//
4// spirv.Bitcast
5//===----------------------------------------------------------------------===//
6
7func.func @cast1(%arg0 : f32) {
8  // CHECK: {{%.*}} = spirv.Bitcast {{%.*}} : f32 to i32
9  %0 = spirv.Bitcast %arg0 : f32 to i32
10  return
11}
12
13func.func @cast2(%arg0 : vector<2xf32>) {
14  // CHECK: {{%.*}} = spirv.Bitcast {{%.*}} : vector<2xf32> to vector<2xi32>
15  %0 = spirv.Bitcast %arg0 : vector<2xf32> to vector<2xi32>
16  return
17}
18
19func.func @cast3(%arg0 : vector<2xf32>) {
20  // CHECK: {{%.*}} = spirv.Bitcast {{%.*}} : vector<2xf32> to i64
21  %0 = spirv.Bitcast %arg0 : vector<2xf32> to i64
22  return
23}
24
25func.func @cast4(%arg0 : !spirv.ptr<f32, Function>) {
26  // CHECK: {{%.*}} = spirv.Bitcast {{%.*}} : !spirv.ptr<f32, Function> to !spirv.ptr<i32, Function>
27  %0 = spirv.Bitcast %arg0 : !spirv.ptr<f32, Function> to !spirv.ptr<i32, Function>
28  return
29}
30
31func.func @cast5(%arg0 : !spirv.ptr<f32, Function>) {
32  // CHECK: {{%.*}} = spirv.Bitcast {{%.*}} : !spirv.ptr<f32, Function> to !spirv.ptr<vector<2xi32>, Function>
33  %0 = spirv.Bitcast %arg0 : !spirv.ptr<f32, Function> to !spirv.ptr<vector<2xi32>, Function>
34  return
35}
36
37func.func @cast6(%arg0 : vector<4xf32>) {
38  // CHECK: {{%.*}} = spirv.Bitcast {{%.*}} : vector<4xf32> to vector<2xi64>
39  %0 = spirv.Bitcast %arg0 : vector<4xf32> to vector<2xi64>
40  return
41}
42
43// -----
44
45func.func @cast1(%arg0 : f32) {
46  // expected-error @+1 {{result type must be different from operand type}}
47  %0 = spirv.Bitcast %arg0 : f32 to f32
48  return
49}
50
51// -----
52
53func.func @cast1(%arg0 : f32) {
54  // expected-error @+1 {{mismatch in result type bitwidth 64 and operand type bitwidth 32}}
55  %0 = spirv.Bitcast %arg0 : f32 to i64
56  return
57}
58
59// -----
60
61func.func @cast1(%arg0 : vector<2xf32>) {
62  // expected-error @+1 {{mismatch in result type bitwidth 96 and operand type bitwidth 64}}
63  %0 = spirv.Bitcast %arg0 : vector<2xf32> to vector<3xf32>
64  return
65}
66
67// -----
68
69func.func @cast3(%arg0 : !spirv.ptr<f32, Function>) {
70  // expected-error @+1 {{unhandled bit cast conversion from pointer type to non-pointer type}}
71  %0 = spirv.Bitcast %arg0 : !spirv.ptr<f32, Function> to i64
72  return
73}
74
75// -----
76
77func.func @cast3(%arg0 : i64) {
78  // expected-error @+1 {{unhandled bit cast conversion from non-pointer type to pointer type}}
79  %0 = spirv.Bitcast %arg0 : i64 to !spirv.ptr<f32, Function>
80  return
81}
82
83// -----
84
85//===----------------------------------------------------------------------===//
86// spirv.ConvertFToS
87//===----------------------------------------------------------------------===//
88
89func.func @convert_f_to_s_scalar(%arg0 : f32) -> i32 {
90  // CHECK: {{%.*}} = spirv.ConvertFToS {{%.*}} : f32 to i32
91  %0 = spirv.ConvertFToS %arg0 : f32 to i32
92  spirv.ReturnValue %0 : i32
93}
94
95// -----
96
97func.func @convert_f64_to_s32_scalar(%arg0 : f64) -> i32 {
98  // CHECK: {{%.*}} = spirv.ConvertFToS {{%.*}} : f64 to i32
99  %0 = spirv.ConvertFToS %arg0 : f64 to i32
100  spirv.ReturnValue %0 : i32
101}
102
103// -----
104
105func.func @convert_f_to_s_vector(%arg0 : vector<3xf32>) -> vector<3xi32> {
106  // CHECK: {{%.*}} = spirv.ConvertFToS {{%.*}} : vector<3xf32> to vector<3xi32>
107  %0 = spirv.ConvertFToS %arg0 : vector<3xf32> to vector<3xi32>
108  spirv.ReturnValue %0 : vector<3xi32>
109}
110
111// -----
112
113//===----------------------------------------------------------------------===//
114// spirv.ConvertFToU
115//===----------------------------------------------------------------------===//
116
117func.func @convert_f_to_u_scalar(%arg0 : f32) -> i32 {
118  // CHECK: {{%.*}} = spirv.ConvertFToU {{%.*}} : f32 to i32
119  %0 = spirv.ConvertFToU %arg0 : f32 to i32
120  spirv.ReturnValue %0 : i32
121}
122
123// -----
124
125func.func @convert_f64_to_u32_scalar(%arg0 : f64) -> i32 {
126  // CHECK: {{%.*}} = spirv.ConvertFToU {{%.*}} : f64 to i32
127  %0 = spirv.ConvertFToU %arg0 : f64 to i32
128  spirv.ReturnValue %0 : i32
129}
130
131// -----
132
133func.func @convert_f_to_u_vector(%arg0 : vector<3xf32>) -> vector<3xi32> {
134  // CHECK: {{%.*}} = spirv.ConvertFToU {{%.*}} : vector<3xf32> to vector<3xi32>
135  %0 = spirv.ConvertFToU %arg0 : vector<3xf32> to vector<3xi32>
136  spirv.ReturnValue %0 : vector<3xi32>
137}
138
139// -----
140
141func.func @convert_f_to_u.coopmatrix(%arg0 : !spirv.coopmatrix<8x16xf32, Subgroup, MatrixB>) {
142  // CHECK: {{%.*}} = spirv.ConvertFToU {{%.*}} : !spirv.coopmatrix<8x16xf32, Subgroup, MatrixB> to !spirv.coopmatrix<8x16xi32, Subgroup, MatrixB>
143  %0 = spirv.ConvertFToU %arg0 : !spirv.coopmatrix<8x16xf32, Subgroup, MatrixB> to !spirv.coopmatrix<8x16xi32, Subgroup, MatrixB>
144  spirv.Return
145}
146
147// -----
148
149//===----------------------------------------------------------------------===//
150// spirv.ConvertSToF
151//===----------------------------------------------------------------------===//
152
153func.func @convert_s_to_f_scalar(%arg0 : i32) -> f32 {
154  // CHECK: {{%.*}} = spirv.ConvertSToF {{%.*}} : i32 to f32
155  %0 = spirv.ConvertSToF %arg0 : i32 to f32
156  spirv.ReturnValue %0 : f32
157}
158
159// -----
160
161func.func @convert_s64_to_f32_scalar(%arg0 : i64) -> f32 {
162  // CHECK: {{%.*}} = spirv.ConvertSToF {{%.*}} : i64 to f32
163  %0 = spirv.ConvertSToF %arg0 : i64 to f32
164  spirv.ReturnValue %0 : f32
165}
166
167// -----
168
169func.func @convert_s_to_f_vector(%arg0 : vector<3xi32>) -> vector<3xf32> {
170  // CHECK: {{%.*}} = spirv.ConvertSToF {{%.*}} : vector<3xi32> to vector<3xf32>
171  %0 = spirv.ConvertSToF %arg0 : vector<3xi32> to vector<3xf32>
172  spirv.ReturnValue %0 : vector<3xf32>
173}
174
175// -----
176
177//===----------------------------------------------------------------------===//
178// spirv.ConvertUToF
179//===----------------------------------------------------------------------===//
180
181func.func @convert_u_to_f_scalar(%arg0 : i32) -> f32 {
182  // CHECK: {{%.*}} = spirv.ConvertUToF {{%.*}} : i32 to f32
183  %0 = spirv.ConvertUToF %arg0 : i32 to f32
184  spirv.ReturnValue %0 : f32
185}
186
187// -----
188
189func.func @convert_u64_to_f32_scalar(%arg0 : i64) -> f32 {
190  // CHECK: {{%.*}} = spirv.ConvertUToF {{%.*}} : i64 to f32
191  %0 = spirv.ConvertUToF %arg0 : i64 to f32
192  spirv.ReturnValue %0 : f32
193}
194
195// -----
196
197func.func @convert_u_to_f_vector(%arg0 : vector<3xi32>) -> vector<3xf32> {
198  // CHECK: {{%.*}} = spirv.ConvertUToF {{%.*}} : vector<3xi32> to vector<3xf32>
199  %0 = spirv.ConvertUToF %arg0 : vector<3xi32> to vector<3xf32>
200  spirv.ReturnValue %0 : vector<3xf32>
201}
202
203// -----
204
205//===----------------------------------------------------------------------===//
206// spirv.FConvert
207//===----------------------------------------------------------------------===//
208
209func.func @f_convert_scalar(%arg0 : f32) -> f64 {
210  // CHECK: {{%.*}} = spirv.FConvert {{%.*}} : f32 to f64
211  %0 = spirv.FConvert %arg0 : f32 to f64
212  spirv.ReturnValue %0 : f64
213}
214
215// -----
216
217func.func @f_convert_vector(%arg0 : vector<3xf32>) -> vector<3xf64> {
218  // CHECK: {{%.*}} = spirv.FConvert {{%.*}} : vector<3xf32> to vector<3xf64>
219  %0 = spirv.FConvert %arg0 : vector<3xf32> to vector<3xf64>
220  spirv.ReturnValue %0 : vector<3xf64>
221}
222
223// -----
224
225func.func @f_convert_coop_matrix(%arg0 : !spirv.coopmatrix<8x16xf32, Subgroup, MatrixA>) {
226  // CHECK: {{%.*}} = spirv.FConvert {{%.*}} : !spirv.coopmatrix<8x16xf32, Subgroup, MatrixA> to !spirv.coopmatrix<8x16xf64, Subgroup, MatrixA>
227  %0 = spirv.FConvert %arg0 : !spirv.coopmatrix<8x16xf32, Subgroup, MatrixA> to !spirv.coopmatrix<8x16xf64, Subgroup, MatrixA>
228  spirv.Return
229}
230
231// -----
232
233func.func @f_convert_vector(%arg0 : f32) -> f32 {
234  // expected-error @+1 {{expected the different bit widths for operand type and result type, but provided 'f32' and 'f32'}}
235  %0 = spirv.FConvert %arg0 : f32 to f32
236  spirv.ReturnValue %0 : f32
237}
238
239// -----
240
241//===----------------------------------------------------------------------===//
242// spirv.SConvert
243//===----------------------------------------------------------------------===//
244
245func.func @s_convert_scalar(%arg0 : i32) -> i64 {
246  // CHECK: {{%.*}} = spirv.SConvert {{%.*}} : i32 to i64
247  %0 = spirv.SConvert %arg0 : i32 to i64
248  spirv.ReturnValue %0 : i64
249}
250
251// -----
252
253//===----------------------------------------------------------------------===//
254// spirv.UConvert
255//===----------------------------------------------------------------------===//
256
257func.func @u_convert_scalar(%arg0 : i32) -> i64 {
258  // CHECK: {{%.*}} = spirv.UConvert {{%.*}} : i32 to i64
259  %0 = spirv.UConvert %arg0 : i32 to i64
260  spirv.ReturnValue %0 : i64
261}
262
263// -----
264
265//===----------------------------------------------------------------------===//
266// spirv.PtrCastToGeneric
267//===----------------------------------------------------------------------===//
268
269func.func @ptrcasttogeneric1(%arg0 : !spirv.ptr<f32, CrossWorkgroup>) {
270  // CHECK: {{%.*}} = spirv.PtrCastToGeneric {{%.*}} : !spirv.ptr<f32, CrossWorkgroup> to !spirv.ptr<f32, Generic>
271  %0 = spirv.PtrCastToGeneric %arg0 : !spirv.ptr<f32, CrossWorkgroup> to !spirv.ptr<f32, Generic>
272  return
273}
274// -----
275
276func.func @ptrcasttogeneric2(%arg0 : !spirv.ptr<f32, StorageBuffer>) {
277  // expected-error @+1 {{pointer must point to the Workgroup, CrossWorkgroup, or Function Storage Class}}
278  %0 = spirv.PtrCastToGeneric %arg0 : !spirv.ptr<f32, StorageBuffer> to !spirv.ptr<f32, Generic>
279  return
280}
281
282// -----
283
284func.func @ptrcasttogeneric3(%arg0 : !spirv.ptr<f32, CrossWorkgroup>) {
285  // expected-error @+1 {{result type must be of storage class Generic}}
286  %0 = spirv.PtrCastToGeneric %arg0 : !spirv.ptr<f32, CrossWorkgroup> to !spirv.ptr<f32, Uniform>
287  return
288}
289
290// -----
291
292func.func @ptrcasttogeneric4(%arg0 : !spirv.ptr<f32, CrossWorkgroup>) {
293  // expected-error @+1 {{pointee type must have the same as the op result type}}
294  %0 = spirv.PtrCastToGeneric %arg0 : !spirv.ptr<f32, CrossWorkgroup> to !spirv.ptr<vector<2xi32>, Generic>
295  return
296}
297
298// -----
299
300//===----------------------------------------------------------------------===//
301// spirv.GenericCastToPtr
302//===----------------------------------------------------------------------===//
303
304func.func @genericcasttoptr1(%arg0 : !spirv.ptr<vector<2xi32>, Generic>) {
305  // CHECK: {{%.*}} = spirv.GenericCastToPtr {{%.*}} : !spirv.ptr<vector<2xi32>, Generic> to !spirv.ptr<vector<2xi32>, CrossWorkgroup>
306  %0 = spirv.GenericCastToPtr %arg0 : !spirv.ptr<vector<2xi32>, Generic> to !spirv.ptr<vector<2xi32>, CrossWorkgroup>
307  return
308}
309// -----
310
311func.func @genericcasttoptr2(%arg0 : !spirv.ptr<f32, Uniform>) {
312  // expected-error @+1 {{pointer type must be of storage class Generic}}
313  %0 = spirv.GenericCastToPtr %arg0 : !spirv.ptr<f32, Uniform> to !spirv.ptr<f32, Workgroup>
314  return
315}
316
317// -----
318
319func.func @genericcasttoptr3(%arg0 : !spirv.ptr<f32, Generic>) {
320  // expected-error @+1 {{result must point to the Workgroup, CrossWorkgroup, or Function Storage Class}}
321  %0 = spirv.GenericCastToPtr %arg0 : !spirv.ptr<f32, Generic> to !spirv.ptr<f32, Uniform>
322  return
323}
324
325// -----
326
327func.func @genericcasttoptr4(%arg0 : !spirv.ptr<f32, Generic>) {
328  // expected-error @+1 {{pointee type must have the same as the op result type}}
329  %0 = spirv.GenericCastToPtr %arg0 : !spirv.ptr<f32, Generic> to !spirv.ptr<vector<2xi32>, Workgroup>
330  return
331}
332// -----
333
334//===----------------------------------------------------------------------===//
335// spirv.GenericCastToPtrExplicit
336//===----------------------------------------------------------------------===//
337
338func.func @genericcasttoptrexplicit1(%arg0 : !spirv.ptr<vector<2xi32>, Generic>) {
339  // CHECK: {{%.*}} = spirv.GenericCastToPtrExplicit {{%.*}} : !spirv.ptr<vector<2xi32>, Generic> to !spirv.ptr<vector<2xi32>, CrossWorkgroup>
340  %0 = spirv.GenericCastToPtrExplicit %arg0 : !spirv.ptr<vector<2xi32>, Generic> to !spirv.ptr<vector<2xi32>, CrossWorkgroup>
341  return
342}
343// -----
344
345func.func @genericcasttoptrexplicit2(%arg0 : !spirv.ptr<f32, Uniform>) {
346  // expected-error @+1 {{pointer type must be of storage class Generic}}
347  %0 = spirv.GenericCastToPtrExplicit %arg0 : !spirv.ptr<f32, Uniform> to !spirv.ptr<f32, Workgroup>
348  return
349}
350
351// -----
352
353func.func @genericcasttoptrexplicit3(%arg0 : !spirv.ptr<f32, Generic>) {
354  // expected-error @+1 {{result must point to the Workgroup, CrossWorkgroup, or Function Storage Class}}
355  %0 = spirv.GenericCastToPtrExplicit %arg0 : !spirv.ptr<f32, Generic> to !spirv.ptr<f32, Uniform>
356  return
357}
358
359// -----
360
361func.func @genericcasttoptrexplicit4(%arg0 : !spirv.ptr<f32, Generic>) {
362  // expected-error @+1 {{pointee type must have the same as the op result type}}
363  %0 = spirv.GenericCastToPtrExplicit %arg0 : !spirv.ptr<f32, Generic> to !spirv.ptr<vector<2xi32>, Workgroup>
364  return
365}
366
367// -----
368
369//===----------------------------------------------------------------------===//
370// spirv.ConvertPtrToU
371//===----------------------------------------------------------------------===//
372spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
373  spirv.func @covert_ptr_to_u(%arg0 : !spirv.ptr<i32, Generic>) "None" {
374    // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i32
375    %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
376    spirv.Return
377  }
378  spirv.func @covert_ptr_to_u_truncate(%arg0 : !spirv.ptr<i64, Generic>) "None" {
379    // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i64, Generic> to i32
380    %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i64, Generic> to i32
381    spirv.Return
382  }
383  spirv.func @covert_ptr_to_u_extend(%arg0 : !spirv.ptr<i32, Generic>) "None" {
384    // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, Generic> to i64
385    %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i64
386    spirv.Return
387  }
388}
389
390// -----
391
392spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
393  spirv.func @covert_ptr_to_u_PhysicalStorageBuffer(%arg0 : !spirv.ptr<i32, PhysicalStorageBuffer> { spirv.decoration = #spirv.decoration<Aliased> }) "None" {
394    // CHECK: {{%.*}} = spirv.ConvertPtrToU {{%.*}} : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
395    %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, PhysicalStorageBuffer> to i32
396    spirv.Return
397  }
398}
399
400// -----
401
402spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
403  spirv.func @covert_ptr_to_u_fail(%arg0 : !spirv.ptr<i32, Generic>) "None" {
404    // expected-error @+1 {{operand must be a physical pointer}}
405    %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
406    spirv.Return
407  }
408}
409
410// -----
411
412spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
413  spirv.func @covert_ptr_to_u_fail_2(%arg0 : !spirv.ptr<i32, Generic>) "None" {
414    // expected-error @+1 {{operand must be a physical pointer}}
415    %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
416    spirv.Return
417  }
418}
419
420// -----
421
422//===----------------------------------------------------------------------===//
423// spirv.ConvertUToPtr
424//===----------------------------------------------------------------------===//
425spirv.module Physical64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses], []> {
426  spirv.func @covert_u_to_ptr(%arg0 : i32) "None" {
427    // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, Generic>
428    %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
429    spirv.Return
430  }
431  spirv.func @covert_u_to_ptr_truncate(%arg0 : i64) "None" {
432    // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i64 to !spirv.ptr<i32, Generic>
433    %0 = spirv.ConvertUToPtr %arg0 : i64 to !spirv.ptr<i32, Generic>
434    spirv.Return
435  }
436  spirv.func @covert_u_to_ptr_extend(%arg0 : i32) "None" {
437    // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i64, Generic>
438    %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i64, Generic>
439    spirv.Return
440  }
441}
442
443// -----
444
445spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
446  spirv.func @covert_u_to_ptr_PhysicalStorageBuffer(%arg0 : i32) "None" {
447    // CHECK: {{%.*}} = spirv.ConvertUToPtr {{%.*}} : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
448    %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, PhysicalStorageBuffer>
449    spirv.Return
450  }
451}
452
453// -----
454
455spirv.module PhysicalStorageBuffer64 OpenCL requires #spirv.vce<v1.0, [Kernel, Addresses, PhysicalStorageBufferAddresses], []> {
456  spirv.func @covert_u_to_ptr_fail(%arg0 : i32) "None" {
457    // expected-error @+1 {{result must be a physical pointer}}
458    %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
459    spirv.Return
460  }
461}
462
463// -----
464
465spirv.module Logical GLSL450 requires #spirv.vce<v1.0, [Shader], []> {
466  spirv.func @covert_u_to_ptr_fail_2(%arg0 : i32) "None" {
467    // expected-error @+1 {{result must be a physical pointer}}
468    %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
469    spirv.Return
470  }
471}
472