1// RUN: mlir-opt -split-input-file -verify-diagnostics %s | FileCheck %s
2
3//===----------------------------------------------------------------------===//
4// spv.AccessChain
5//===----------------------------------------------------------------------===//
6
7func @access_chain_struct() -> () {
8  %0 = spv.constant 1: i32
9  %1 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
10  // CHECK: spv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spv.ptr<!spv.struct<f32, !spv.array<4 x f32>>, Function>
11  %2 = spv.AccessChain %1[%0, %0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
12  return
13}
14
15func @access_chain_1D_array(%arg0 : i32) -> () {
16  %0 = spv.Variable : !spv.ptr<!spv.array<4xf32>, Function>
17  // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.array<4 x f32>, Function>
18  %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.array<4xf32>, Function>
19  return
20}
21
22func @access_chain_2D_array_1(%arg0 : i32) -> () {
23  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
24  // CHECK: spv.AccessChain {{.*}}[{{.*}}, {{.*}}] : !spv.ptr<!spv.array<4 x !spv.array<4 x f32>>, Function>
25  %1 = spv.AccessChain %0[%arg0, %arg0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
26  %2 = spv.Load "Function" %1 ["Volatile"] : f32
27  return
28}
29
30func @access_chain_2D_array_2(%arg0 : i32) -> () {
31  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
32  // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.array<4 x !spv.array<4 x f32>>, Function>
33  %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
34  %2 = spv.Load "Function" %1 ["Volatile"] : !spv.array<4xf32>
35  return
36}
37
38func @access_chain_rtarray(%arg0 : i32) -> () {
39  %0 = spv.Variable : !spv.ptr<!spv.rtarray<f32>, Function>
40  // CHECK: spv.AccessChain {{.*}}[{{.*}}] : !spv.ptr<!spv.rtarray<f32>, Function>
41  %1 = spv.AccessChain %0[%arg0] : !spv.ptr<!spv.rtarray<f32>, Function>
42  %2 = spv.Load "Function" %1 ["Volatile"] : f32
43  return
44}
45
46// -----
47
48func @access_chain_non_composite() -> () {
49  %0 = spv.constant 1: i32
50  %1 = spv.Variable : !spv.ptr<f32, Function>
51  // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}}
52  %2 = spv.AccessChain %1[%0] : !spv.ptr<f32, Function>
53  return
54}
55
56// -----
57
58func @access_chain_no_indices(%index0 : i32) -> () {
59  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
60  // expected-error @+1 {{expected at least one index}}
61  %1 = spv.AccessChain %0[] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
62  return
63}
64
65// -----
66
67func @access_chain_invalid_type(%index0 : i32) -> () {
68  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
69  %1 = spv.Load "Function" %0 ["Volatile"] : !spv.array<4x!spv.array<4xf32>>
70  // expected-error @+1 {{expected a pointer to composite type, but provided '!spv.array<4 x !spv.array<4 x f32>>'}}
71  %2 = spv.AccessChain %1[%index0] : !spv.array<4x!spv.array<4xf32>>
72  return
73}
74
75// -----
76
77func @access_chain_invalid_index_1(%index0 : i32) -> () {
78   %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
79  // expected-error @+1 {{expected SSA operand}}
80  %1 = spv.AccessChain %0[%index, 4] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
81  return
82}
83
84// -----
85
86func @access_chain_invalid_index_2(%index0 : i32) -> () {
87  %0 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
88  // expected-error @+1 {{index must be an integer spv.constant to access element of spv.struct}}
89  %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
90  return
91}
92
93// -----
94
95func @access_chain_invalid_constant_type_1() -> () {
96  %0 = std.constant 1: i32
97  %1 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
98  // expected-error @+1 {{index must be an integer spv.constant to access element of spv.struct, but provided std.constant}}
99  %2 = spv.AccessChain %1[%0, %0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
100  return
101}
102
103// -----
104
105func @access_chain_out_of_bounds() -> () {
106  %index0 = "spv.constant"() { value = 12: i32} : () -> i32
107  %0 = spv.Variable : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
108  // expected-error @+1 {{'spv.AccessChain' op index 12 out of bounds for '!spv.struct<f32, !spv.array<4 x f32>>'}}
109  %1 = spv.AccessChain %0[%index0, %index0] : !spv.ptr<!spv.struct<f32, !spv.array<4xf32>>, Function>
110  return
111}
112
113// -----
114
115func @access_chain_invalid_accessing_type(%index0 : i32) -> () {
116  %0 = spv.Variable : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
117  // expected-error @+1 {{cannot extract from non-composite type 'f32' with index 0}}
118  %1 = spv.AccessChain %0[%index, %index0, %index0] : !spv.ptr<!spv.array<4x!spv.array<4xf32>>, Function>
119  return
120
121// -----
122
123//===----------------------------------------------------------------------===//
124// spv.Bitcast
125//===----------------------------------------------------------------------===//
126
127func @cast1(%arg0 : f32) {
128  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : f32 to i32
129  %0 = spv.Bitcast %arg0 : f32 to i32
130  return
131}
132
133func @cast2(%arg0 : vector<2xf32>) {
134  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<2xf32> to vector<2xi32>
135  %0 = spv.Bitcast %arg0 : vector<2xf32> to vector<2xi32>
136  return
137}
138
139func @cast3(%arg0 : vector<2xf32>) {
140  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<2xf32> to i64
141  %0 = spv.Bitcast %arg0 : vector<2xf32> to i64
142  return
143}
144
145func @cast4(%arg0 : !spv.ptr<f32, Function>) {
146  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : !spv.ptr<f32, Function> to !spv.ptr<i32, Function>
147  %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to !spv.ptr<i32, Function>
148  return
149}
150
151func @cast5(%arg0 : !spv.ptr<f32, Function>) {
152  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : !spv.ptr<f32, Function> to !spv.ptr<vector<2xi32>, Function>
153  %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to !spv.ptr<vector<2xi32>, Function>
154  return
155}
156
157func @cast6(%arg0 : vector<4xf32>) {
158  // CHECK: {{%.*}} = spv.Bitcast {{%.*}} : vector<4xf32> to vector<2xi64>
159  %0 = spv.Bitcast %arg0 : vector<4xf32> to vector<2xi64>
160  return
161}
162
163// -----
164
165func @cast1(%arg0 : f32) {
166  // expected-error @+1 {{result type must be different from operand type}}
167  %0 = spv.Bitcast %arg0 : f32 to f32
168  return
169}
170
171// -----
172
173func @cast1(%arg0 : f32) {
174  // expected-error @+1 {{mismatch in result type bitwidth 64 and operand type bitwidth 32}}
175  %0 = spv.Bitcast %arg0 : f32 to i64
176  return
177}
178
179// -----
180
181func @cast1(%arg0 : vector<2xf32>) {
182  // expected-error @+1 {{mismatch in result type bitwidth 96 and operand type bitwidth 64}}
183  %0 = spv.Bitcast %arg0 : vector<2xf32> to vector<3xf32>
184  return
185}
186
187// -----
188
189func @cast3(%arg0 : !spv.ptr<f32, Function>) {
190  // expected-error @+1 {{unhandled bit cast conversion from pointer type to non-pointer type}}
191  %0 = spv.Bitcast %arg0 : !spv.ptr<f32, Function> to i64
192  return
193}
194
195// -----
196
197func @cast3(%arg0 : i64) {
198  // expected-error @+1 {{unhandled bit cast conversion from non-pointer type to pointer type}}
199  %0 = spv.Bitcast %arg0 : i64 to !spv.ptr<f32, Function>
200  return
201}
202
203// -----
204
205//===----------------------------------------------------------------------===//
206// spv.BitCount
207//===----------------------------------------------------------------------===//
208
209func @bitcount(%arg: i32) -> i32 {
210  // CHECK: spv.BitCount {{%.*}} : i32
211  %0 = spv.BitCount %arg : i32
212  spv.ReturnValue %0 : i32
213}
214
215// -----
216
217//===----------------------------------------------------------------------===//
218// spv.BitFieldInsert
219//===----------------------------------------------------------------------===//
220
221func @bit_field_insert_vec(%base: vector<3xi32>, %insert: vector<3xi32>, %offset: i32, %count: i16) -> vector<3xi32> {
222  // CHECK: {{%.*}} = spv.BitFieldInsert {{%.*}}, {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i32, i16
223  %0 = spv.BitFieldInsert %base, %insert, %offset, %count : vector<3xi32>, i32, i16
224  spv.ReturnValue %0 : vector<3xi32>
225}
226
227// -----
228
229func @bit_field_insert_invalid_insert_type(%base: vector<3xi32>, %insert: vector<2xi32>, %offset: i32, %count: i16) -> vector<3xi32> {
230  // expected-error @+1 {{expected the same type for the base operand, insert operand, and result, but provided 'vector<3xi32>', 'vector<2xi32>' and 'vector<3xi32>'}}
231  %0 = "spv.BitFieldInsert" (%base, %insert, %offset, %count) : (vector<3xi32>, vector<2xi32>, i32, i16) -> vector<3xi32>
232  spv.ReturnValue %0 : vector<3xi32>
233}
234
235// -----
236
237//===----------------------------------------------------------------------===//
238// spv.BitFieldSExtract
239//===----------------------------------------------------------------------===//
240
241func @bit_field_s_extract_vec(%base: vector<3xi32>, %offset: i8, %count: i8) -> vector<3xi32> {
242  // CHECK: {{%.*}} = spv.BitFieldSExtract {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i8, i8
243  %0 = spv.BitFieldSExtract %base, %offset, %count : vector<3xi32>, i8, i8
244  spv.ReturnValue %0 : vector<3xi32>
245}
246
247//===----------------------------------------------------------------------===//
248// spv.BitFieldUExtract
249//===----------------------------------------------------------------------===//
250
251func @bit_field_u_extract_vec(%base: vector<3xi32>, %offset: i8, %count: i8) -> vector<3xi32> {
252  // CHECK: {{%.*}} = spv.BitFieldUExtract {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi32>, i8, i8
253  %0 = spv.BitFieldUExtract %base, %offset, %count : vector<3xi32>, i8, i8
254  spv.ReturnValue %0 : vector<3xi32>
255}
256
257// -----
258
259func @bit_field_u_extract_invalid_result_type(%base: vector<3xi32>, %offset: i32, %count: i16) -> vector<4xi32> {
260  // expected-error @+1 {{expected the same type for the first operand and result, but provided 'vector<3xi32>' and 'vector<4xi32>'}}
261  %0 = "spv.BitFieldUExtract" (%base, %offset, %count) : (vector<3xi32>, i32, i16) -> vector<4xi32>
262  spv.ReturnValue %0 : vector<4xi32>
263}
264
265// -----
266
267//===----------------------------------------------------------------------===//
268// spv.BitReverse
269//===----------------------------------------------------------------------===//
270
271func @bitreverse(%arg: i32) -> i32 {
272  // CHECK: spv.BitReverse {{%.*}} : i32
273  %0 = spv.BitReverse %arg : i32
274  spv.ReturnValue %0 : i32
275}
276
277// -----
278
279//===----------------------------------------------------------------------===//
280// spv.ControlBarrier
281//===----------------------------------------------------------------------===//
282
283func @control_barrier_0() -> () {
284  // CHECK:  spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory"
285  spv.ControlBarrier "Workgroup", "Device", "Acquire|UniformMemory"
286  return
287}
288
289// -----
290
291func @control_barrier_1() -> () {
292  // expected-error @+1 {{invalid scope attribute specification: "Something"}}
293  spv.ControlBarrier "Something", "Device", "Acquire|UniformMemory"
294  return
295}
296
297// -----
298
299//===----------------------------------------------------------------------===//
300// spv.ConvertFToS
301//===----------------------------------------------------------------------===//
302
303func @convert_f_to_s_scalar(%arg0 : f32) -> i32 {
304  // CHECK: {{%.*}} = spv.ConvertFToS {{%.*}} : f32 to i32
305  %0 = spv.ConvertFToS %arg0 : f32 to i32
306  spv.ReturnValue %0 : i32
307}
308
309// -----
310
311//===----------------------------------------------------------------------===//
312// spv.ConvertFToU
313//===----------------------------------------------------------------------===//
314
315func @convert_f_to_u_scalar(%arg0 : f32) -> i32 {
316  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : f32 to i32
317  %0 = spv.ConvertFToU %arg0 : f32 to i32
318  spv.ReturnValue %0 : i32
319}
320
321// -----
322
323func @convert_f_to_u_vector(%arg0 : vector<3xf32>) -> vector<3xi32> {
324  // CHECK: {{%.*}} = spv.ConvertFToU {{%.*}} : vector<3xf32> to vector<3xi32>
325  %0 = spv.ConvertFToU %arg0 : vector<3xf32> to vector<3xi32>
326  spv.ReturnValue %0 : vector<3xi32>
327}
328
329// -----
330
331func @convert_f_to_u_scalar_invalid(%arg0 : f16) -> i32 {
332  // expected-error @+1 {{expected the same bit widths for operand type and result type, but provided 'f16' and 'i32'}}
333  %0 = spv.ConvertFToU %arg0 : f16 to i32
334  spv.ReturnValue %0 : i32
335}
336
337// -----
338
339//===----------------------------------------------------------------------===//
340// spv.ConvertSToF
341//===----------------------------------------------------------------------===//
342
343func @convert_s_to_f_scalar(%arg0 : i32) -> f32 {
344  // CHECK: {{%.*}} = spv.ConvertSToF {{%.*}} : i32 to f32
345  %0 = spv.ConvertSToF %arg0 : i32 to f32
346  spv.ReturnValue %0 : f32
347}
348
349// -----
350
351//===----------------------------------------------------------------------===//
352// spv.ConvertUToF
353//===----------------------------------------------------------------------===//
354
355func @convert_u_to_f_scalar(%arg0 : i32) -> f32 {
356  // CHECK: {{%.*}} = spv.ConvertUToF {{%.*}} : i32 to f32
357  %0 = spv.ConvertUToF %arg0 : i32 to f32
358  spv.ReturnValue %0 : f32
359}
360
361// -----
362
363//===----------------------------------------------------------------------===//
364// spv.FConvert
365//===----------------------------------------------------------------------===//
366
367func @f_convert_scalar(%arg0 : f32) -> f64 {
368  // CHECK: {{%.*}} = spv.FConvert {{%.*}} : f32 to f64
369  %0 = spv.FConvert %arg0 : f32 to f64
370  spv.ReturnValue %0 : f64
371}
372
373// -----
374
375func @f_convert_vector(%arg0 : vector<3xf32>) -> vector<3xf64> {
376  // CHECK: {{%.*}} = spv.FConvert {{%.*}} : vector<3xf32> to vector<3xf64>
377  %0 = spv.FConvert %arg0 : vector<3xf32> to vector<3xf64>
378  spv.ReturnValue %0 : vector<3xf64>
379}
380
381// -----
382
383func @f_convert_vector(%arg0 : f32) -> f32 {
384  // expected-error @+1 {{expected the different bit widths for operand type and result type, but provided 'f32' and 'f32'}}
385  %0 = spv.FConvert %arg0 : f32 to f32
386  spv.ReturnValue %0 : f32
387}
388
389// -----
390
391//===----------------------------------------------------------------------===//
392// spv.SConvert
393//===----------------------------------------------------------------------===//
394
395func @s_convert_scalar(%arg0 : i32) -> i64 {
396  // CHECK: {{%.*}} = spv.SConvert {{%.*}} : i32 to i64
397  %0 = spv.SConvert %arg0 : i32 to i64
398  spv.ReturnValue %0 : i64
399}
400
401// -----
402
403//===----------------------------------------------------------------------===//
404// spv.UConvert
405//===----------------------------------------------------------------------===//
406
407func @u_convert_scalar(%arg0 : i32) -> i64 {
408  // CHECK: {{%.*}} = spv.UConvert {{%.*}} : i32 to i64
409  %0 = spv.UConvert %arg0 : i32 to i64
410  spv.ReturnValue %0 : i64
411}
412
413// -----
414
415//===----------------------------------------------------------------------===//
416// spv.ExecutionMode
417//===----------------------------------------------------------------------===//
418
419spv.module "Logical" "GLSL450" {
420   func @do_nothing() -> () {
421     spv.Return
422   }
423   spv.EntryPoint "GLCompute" @do_nothing
424   // CHECK: spv.ExecutionMode {{@.*}} "ContractionOff"
425   spv.ExecutionMode @do_nothing "ContractionOff"
426}
427
428spv.module "Logical" "GLSL450" {
429   func @do_nothing() -> () {
430     spv.Return
431   }
432   spv.EntryPoint "GLCompute" @do_nothing
433   // CHECK: spv.ExecutionMode {{@.*}} "LocalSizeHint", 3, 4, 5
434   spv.ExecutionMode @do_nothing "LocalSizeHint", 3, 4, 5
435}
436
437// -----
438
439spv.module "Logical" "GLSL450" {
440   func @do_nothing() -> () {
441     spv.Return
442   }
443   spv.EntryPoint "GLCompute" @do_nothing
444   // expected-error @+1 {{custom op 'spv.ExecutionMode' invalid execution_mode attribute specification: "GLCompute"}}
445   spv.ExecutionMode @do_nothing "GLCompute", 3, 4, 5
446}
447
448// -----
449
450//===----------------------------------------------------------------------===//
451// spv.LoadOp
452//===----------------------------------------------------------------------===//
453
454// CHECK-LABEL: @simple_load
455func @simple_load() -> () {
456  %0 = spv.Variable : !spv.ptr<f32, Function>
457  // CHECK: spv.Load "Function" %{{.*}} : f32
458  %1 = spv.Load "Function" %0 : f32
459  return
460}
461
462// CHECK-LABEL: @load_none_access
463func @load_none_access() -> () {
464  %0 = spv.Variable : !spv.ptr<f32, Function>
465  // CHECK: spv.Load "Function" %{{.*}} ["None"] : f32
466  %1 = spv.Load "Function" %0 ["None"] : f32
467  return
468}
469
470// CHECK-LABEL: @volatile_load
471func @volatile_load() -> () {
472  %0 = spv.Variable : !spv.ptr<f32, Function>
473  // CHECK: spv.Load "Function" %{{.*}} ["Volatile"] : f32
474  %1 = spv.Load "Function" %0 ["Volatile"] : f32
475  return
476}
477
478// CHECK-LABEL: @aligned_load
479func @aligned_load() -> () {
480  %0 = spv.Variable : !spv.ptr<f32, Function>
481  // CHECK: spv.Load "Function" %{{.*}} ["Aligned", 4] : f32
482  %1 = spv.Load "Function" %0 ["Aligned", 4] : f32
483  return
484}
485
486// CHECK-LABEL: @volatile_aligned_load
487func @volatile_aligned_load() -> () {
488  %0 = spv.Variable : !spv.ptr<f32, Function>
489  // CHECK: spv.Load "Function" %{{.*}} ["Volatile|Aligned", 4] : f32
490  %1 = spv.Load "Function" %0 ["Volatile|Aligned", 4] : f32
491  return
492}
493
494// -----
495
496// CHECK-LABEL: load_none_access
497func @load_none_access() -> () {
498  %0 = spv.Variable : !spv.ptr<f32, Function>
499  // CHECK: spv.Load
500  // CHECK-SAME: ["None"]
501  %1 = "spv.Load"(%0) {memory_access = 0 : i32} : (!spv.ptr<f32, Function>) -> (f32)
502  return
503}
504
505// CHECK-LABEL: volatile_load
506func @volatile_load() -> () {
507  %0 = spv.Variable : !spv.ptr<f32, Function>
508  // CHECK: spv.Load
509  // CHECK-SAME: ["Volatile"]
510  %1 = "spv.Load"(%0) {memory_access = 1 : i32} : (!spv.ptr<f32, Function>) -> (f32)
511  return
512}
513
514// CHECK-LABEL: aligned_load
515func @aligned_load() -> () {
516  %0 = spv.Variable : !spv.ptr<f32, Function>
517  // CHECK: spv.Load
518  // CHECK-SAME: ["Aligned", 4]
519  %1 = "spv.Load"(%0) {memory_access = 2 : i32, alignment = 4 : i32} : (!spv.ptr<f32, Function>) -> (f32)
520  return
521}
522
523// CHECK-LABEL: volatile_aligned_load
524func @volatile_aligned_load() -> () {
525  %0 = spv.Variable : !spv.ptr<f32, Function>
526  // CHECK: spv.Load
527  // CHECK-SAME: ["Volatile|Aligned", 4]
528  %1 = "spv.Load"(%0) {memory_access = 3 : i32, alignment = 4 : i32} : (!spv.ptr<f32, Function>) -> (f32)
529  return
530}
531
532// -----
533
534func @simple_load_missing_storageclass() -> () {
535  %0 = spv.Variable : !spv.ptr<f32, Function>
536  // expected-error @+1 {{expected non-function type}}
537  %1 = spv.Load %0 : f32
538  return
539}
540
541// -----
542
543func @simple_load_missing_operand() -> () {
544  %0 = spv.Variable : !spv.ptr<f32, Function>
545  // expected-error @+1 {{expected SSA operand}}
546  %1 = spv.Load "Function" : f32
547  return
548}
549
550// -----
551
552func @simple_load_missing_rettype() -> () {
553  %0 = spv.Variable : !spv.ptr<f32, Function>
554  // expected-error @+2 {{expected ':'}}
555  %1 = spv.Load "Function" %0
556  return
557}
558
559// -----
560
561func @volatile_load_missing_lbrace() -> () {
562  %0 = spv.Variable : !spv.ptr<f32, Function>
563  // expected-error @+1 {{expected ':'}}
564  %1 = spv.Load "Function" %0 "Volatile"] : f32
565  return
566}
567
568// -----
569
570func @volatile_load_missing_rbrace() -> () {
571  %0 = spv.Variable : !spv.ptr<f32, Function>
572  // expected-error @+1 {{expected ']'}}
573  %1 = spv.Load "Function" %0 ["Volatile"} : f32
574  return
575}
576
577// -----
578
579func @aligned_load_missing_alignment() -> () {
580  %0 = spv.Variable : !spv.ptr<f32, Function>
581  // expected-error @+1 {{expected ','}}
582  %1 = spv.Load "Function" %0 ["Aligned"] : f32
583  return
584}
585
586// -----
587
588func @aligned_load_missing_comma() -> () {
589  %0 = spv.Variable : !spv.ptr<f32, Function>
590  // expected-error @+1 {{expected ','}}
591  %1 = spv.Load "Function" %0 ["Aligned" 4] : f32
592  return
593}
594
595// -----
596
597func @load_incorrect_attributes() -> () {
598  %0 = spv.Variable : !spv.ptr<f32, Function>
599  // expected-error @+1 {{expected ']'}}
600  %1 = spv.Load "Function" %0 ["Volatile", 4] : f32
601  return
602}
603
604// -----
605
606func @load_unknown_memory_access() -> () {
607  %0 = spv.Variable : !spv.ptr<f32, Function>
608  // expected-error @+1 {{custom op 'spv.Load' invalid memory_access attribute specification: "Something"}}
609  %1 = spv.Load "Function" %0 ["Something"] : f32
610  return
611}
612
613// -----
614
615func @load_unknown_memory_access() -> () {
616  %0 = spv.Variable : !spv.ptr<f32, Function>
617  // expected-error @+1 {{custom op 'spv.Load' invalid memory_access attribute specification: "Volatile|Something"}}
618  %1 = spv.Load "Function" %0 ["Volatile|Something"] : f32
619  return
620}
621
622// -----
623
624func @load_unknown_memory_access() -> () {
625  %0 = spv.Variable : !spv.ptr<f32, Function>
626  // expected-error @+1 {{failed to satisfy constraint: valid SPIR-V MemoryAccess}}
627  %1 = "spv.Load"(%0) {memory_access = 0x80000000 : i32} : (!spv.ptr<f32, Function>) -> (f32)
628  return
629}
630
631// -----
632
633func @aligned_load_incorrect_attributes() -> () {
634  %0 = spv.Variable : !spv.ptr<f32, Function>
635  // expected-error @+1 {{expected ']'}}
636  %1 = spv.Load "Function" %0 ["Aligned", 4, 23] : f32
637  return
638}
639
640// -----
641
642spv.module "Logical" "GLSL450" {
643  spv.globalVariable @var0 : !spv.ptr<f32, Input>
644  // CHECK_LABEL: @simple_load
645  func @simple_load() -> () {
646    // CHECK: spv.Load "Input" {{%.*}} : f32
647    %0 = spv._address_of @var0 : !spv.ptr<f32, Input>
648    %1 = spv.Load "Input" %0 : f32
649    spv.Return
650  }
651}
652
653// -----
654
655//===----------------------------------------------------------------------===//
656// spv.LogicalAnd
657//===----------------------------------------------------------------------===//
658
659func @logicalBinary(%arg0 : i1, %arg1 : i1, %arg2 : i1)
660{
661  // CHECK: [[TMP:%.*]] = spv.LogicalAnd {{%.*}}, {{%.*}} : i1
662  %0 = spv.LogicalAnd %arg0, %arg1 : i1
663  // CHECK: {{%.*}} = spv.LogicalAnd [[TMP]], {{%.*}} : i1
664  %1 = spv.LogicalAnd %0, %arg2 : i1
665  return
666}
667
668func @logicalBinary2(%arg0 : vector<4xi1>, %arg1 : vector<4xi1>)
669{
670  // CHECK: {{%.*}} = spv.LogicalAnd {{%.*}}, {{%.*}} : vector<4xi1>
671  %0 = spv.LogicalAnd %arg0, %arg1 : vector<4xi1>
672  return
673}
674
675// -----
676
677func @logicalBinary(%arg0 : i1, %arg1 : i1)
678{
679  // expected-error @+2 {{expected ':'}}
680  %0 = spv.LogicalAnd %arg0, %arg1
681  return
682}
683
684// -----
685
686func @logicalBinary(%arg0 : i1, %arg1 : i1)
687{
688  // expected-error @+2 {{expected non-function type}}
689  %0 = spv.LogicalAnd %arg0, %arg1 :
690  return
691}
692
693// -----
694
695func @logicalBinary(%arg0 : i1, %arg1 : i1)
696{
697  // expected-error @+1 {{custom op 'spv.LogicalAnd' expected 2 operands}}
698  %0 = spv.LogicalAnd %arg0 : i1
699  return
700}
701
702// -----
703
704//===----------------------------------------------------------------------===//
705// spv.LogicalNot
706//===----------------------------------------------------------------------===//
707
708func @logicalUnary(%arg0 : i1, %arg1 : i1)
709{
710  // CHECK: [[TMP:%.*]] = spv.LogicalNot {{%.*}} : i1
711  %0 = spv.LogicalNot %arg0 : i1
712  // CHECK: {{%.*}} = spv.LogicalNot [[TMP]] : i1
713  %1 = spv.LogicalNot %0 : i1
714  return
715}
716
717func @logicalUnary2(%arg0 : vector<4xi1>)
718{
719  // CHECK: {{%.*}} = spv.LogicalNot {{%.*}} : vector<4xi1>
720  %0 = spv.LogicalNot %arg0 : vector<4xi1>
721  return
722}
723
724// -----
725
726func @logicalUnary(%arg0 : i1)
727{
728  // expected-error @+2 {{expected ':'}}
729  %0 = spv.LogicalNot %arg0
730  return
731}
732
733// -----
734
735func @logicalUnary(%arg0 : i1)
736{
737  // expected-error @+2 {{expected non-function type}}
738  %0 = spv.LogicalNot %arg0 :
739  return
740}
741
742// -----
743
744func @logicalUnary(%arg0 : i1)
745{
746  // expected-error @+1 {{expected SSA operand}}
747  %0 = spv.LogicalNot : i1
748  return
749}
750
751// -----
752
753func @logicalUnary(%arg0 : i32)
754{
755  // expected-error @+1 {{'spv.LogicalNot' op operand #0 must be 1-bit integer or vector of 1-bit integer values of length 2/3/4, but got 'i32'}}
756  %0 = spv.LogicalNot %arg0 : i32
757  return
758}
759
760// -----
761
762//===----------------------------------------------------------------------===//
763// spv.MemoryBarrier
764//===----------------------------------------------------------------------===//
765
766func @memory_barrier_0() -> () {
767  // CHECK: spv.MemoryBarrier "Device", "Acquire|UniformMemory"
768  spv.MemoryBarrier "Device", "Acquire|UniformMemory"
769  return
770}
771
772// -----
773
774func @memory_barrier_1() -> () {
775  // CHECK: spv.MemoryBarrier "Workgroup", "Acquire"
776  spv.MemoryBarrier "Workgroup", "Acquire"
777  return
778}
779
780// -----
781
782func @memory_barrier_2() -> () {
783 // expected-error @+1 {{expected at most one of these four memory constraints to be set: `Acquire`, `Release`,`AcquireRelease` or `SequentiallyConsistent`}}
784  spv.MemoryBarrier "Device", "Acquire|Release"
785  return
786}
787
788// -----
789
790//===----------------------------------------------------------------------===//
791// spv.Not
792//===----------------------------------------------------------------------===//
793
794func @not(%arg: i32) -> i32 {
795  // CHECK: spv.Not {{%.*}} : i32
796  %0 = spv.Not %arg : i32
797  spv.ReturnValue %0 : i32
798}
799
800// -----
801
802//===----------------------------------------------------------------------===//
803// spv.SelectOp
804//===----------------------------------------------------------------------===//
805
806func @select_op_bool(%arg0: i1) -> () {
807  %0 = spv.constant true
808  %1 = spv.constant false
809  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, i1
810  %2 = spv.Select %arg0, %0, %1 : i1, i1
811  return
812}
813
814func @select_op_int(%arg0: i1) -> () {
815  %0 = spv.constant 2 : i32
816  %1 = spv.constant 3 : i32
817  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, i32
818  %2 = spv.Select %arg0, %0, %1 : i1, i32
819  return
820}
821
822func @select_op_float(%arg0: i1) -> () {
823  %0 = spv.constant 2.0 : f32
824  %1 = spv.constant 3.0 : f32
825  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, f32
826  %2 = spv.Select %arg0, %0, %1 : i1, f32
827  return
828}
829
830func @select_op_ptr(%arg0: i1) -> () {
831  %0 = spv.Variable : !spv.ptr<f32, Function>
832  %1 = spv.Variable : !spv.ptr<f32, Function>
833  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, !spv.ptr<f32, Function>
834  %2 = spv.Select %arg0, %0, %1 : i1, !spv.ptr<f32, Function>
835  return
836}
837
838func @select_op_vec(%arg0: i1) -> () {
839  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
840  %1 = spv.constant dense<[5.0, 6.0, 7.0]> : vector<3xf32>
841  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : i1, vector<3xf32>
842  %2 = spv.Select %arg0, %0, %1 : i1, vector<3xf32>
843  return
844}
845
846func @select_op_vec_condn_vec(%arg0: vector<3xi1>) -> () {
847  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
848  %1 = spv.constant dense<[5.0, 6.0, 7.0]> : vector<3xf32>
849  // CHECK : spv.Select {{%.*}}, {{%.*}}, {{%.*}} : vector<3xi1>, vector<3xf32>
850  %2 = spv.Select %arg0, %0, %1 : vector<3xi1>, vector<3xf32>
851  return
852}
853
854// -----
855
856func @select_op(%arg0: i1) -> () {
857  %0 = spv.constant 2 : i32
858  %1 = spv.constant 3 : i32
859  // expected-error @+1 {{need exactly two trailing types for select condition and object}}
860  %2 = spv.Select %arg0, %0, %1 : i1
861  return
862}
863
864// -----
865
866func @select_op(%arg1: vector<3xi1>) -> () {
867  %0 = spv.constant 2 : i32
868  %1 = spv.constant 3 : i32
869  // expected-error @+1 {{result expected to be of vector type when condition is of vector type}}
870  %2 = spv.Select %arg1, %0, %1 : vector<3xi1>, i32
871  return
872}
873
874// -----
875
876func @select_op(%arg1: vector<4xi1>) -> () {
877  %0 = spv.constant dense<[2, 3, 4]> : vector<3xi32>
878  %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32>
879  // expected-error @+1 {{result should have the same number of elements as the condition when condition is of vector type}}
880  %2 = spv.Select %arg1, %0, %1 : vector<4xi1>, vector<3xi32>
881  return
882}
883
884// -----
885
886func @select_op(%arg1: vector<4xi1>) -> () {
887  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
888  %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32>
889  // expected-error @+1 {{op result type and true value type must be the same}}
890  %2 = "spv.Select"(%arg1, %0, %1) : (vector<4xi1>, vector<3xf32>, vector<3xi32>) -> vector<3xi32>
891  return
892}
893
894// -----
895
896func @select_op(%arg1: vector<4xi1>) -> () {
897  %0 = spv.constant dense<[2.0, 3.0, 4.0]> : vector<3xf32>
898  %1 = spv.constant dense<[5, 6, 7]> : vector<3xi32>
899  // expected-error @+1 {{op result type and false value type must be the same}}
900  %2 = "spv.Select"(%arg1, %1, %0) : (vector<4xi1>, vector<3xi32>, vector<3xf32>) -> vector<3xi32>
901  return
902}
903
904// -----
905
906//===----------------------------------------------------------------------===//
907// spv.ShiftLeftLogical
908//===----------------------------------------------------------------------===//
909
910func @shift_left_logical(%arg0: i32, %arg1 : i16) -> i32 {
911  // CHECK: {{%.*}} = spv.ShiftLeftLogical {{%.*}}, {{%.*}} : i32, i16
912  %0 = spv.ShiftLeftLogical %arg0, %arg1: i32, i16
913  spv.ReturnValue %0 : i32
914}
915
916// -----
917
918func @shift_left_logical_invalid_result_type(%arg0: i32, %arg1 : i16) -> i16 {
919  // expected-error @+1 {{expected the same type for the first operand and result, but provided 'i32' and 'i16'}}
920  %0 = "spv.ShiftLeftLogical" (%arg0, %arg1) : (i32, i16) -> (i16)
921  spv.ReturnValue %0 : i16
922}
923
924// -----
925
926//===----------------------------------------------------------------------===//
927// spv.ShiftRightArithmetic
928//===----------------------------------------------------------------------===//
929
930func @shift_right_arithmetic(%arg0: vector<4xi32>, %arg1 : vector<4xi8>) -> vector<4xi32> {
931  // CHECK: {{%.*}} = spv.ShiftRightArithmetic {{%.*}}, {{%.*}} : vector<4xi32>, vector<4xi8>
932  %0 = spv.ShiftRightArithmetic %arg0, %arg1: vector<4xi32>, vector<4xi8>
933  spv.ReturnValue %0 : vector<4xi32>
934}
935
936// -----
937
938//===----------------------------------------------------------------------===//
939// spv.ShiftRightLogical
940//===----------------------------------------------------------------------===//
941
942func @shift_right_logical(%arg0: vector<2xi32>, %arg1 : vector<2xi8>) -> vector<2xi32> {
943  // CHECK: {{%.*}} = spv.ShiftRightLogical {{%.*}}, {{%.*}} : vector<2xi32>, vector<2xi8>
944  %0 = spv.ShiftRightLogical %arg0, %arg1: vector<2xi32>, vector<2xi8>
945  spv.ReturnValue %0 : vector<2xi32>
946}
947
948// -----
949
950//===----------------------------------------------------------------------===//
951// spv.StoreOp
952//===----------------------------------------------------------------------===//
953
954func @simple_store(%arg0 : f32) -> () {
955  %0 = spv.Variable : !spv.ptr<f32, Function>
956  // CHECK: spv.Store  "Function" %0, %arg0 : f32
957  spv.Store  "Function" %0, %arg0 : f32
958  return
959}
960
961// CHECK_LABEL: @volatile_store
962func @volatile_store(%arg0 : f32) -> () {
963  %0 = spv.Variable : !spv.ptr<f32, Function>
964  // CHECK: spv.Store  "Function" %0, %arg0 ["Volatile"] : f32
965  spv.Store  "Function" %0, %arg0 ["Volatile"] : f32
966  return
967}
968
969// CHECK_LABEL: @aligned_store
970func @aligned_store(%arg0 : f32) -> () {
971  %0 = spv.Variable : !spv.ptr<f32, Function>
972  // CHECK: spv.Store  "Function" %0, %arg0 ["Aligned", 4] : f32
973  spv.Store  "Function" %0, %arg0 ["Aligned", 4] : f32
974  return
975}
976
977// -----
978
979func @simple_store_missing_ptr_type(%arg0 : f32) -> () {
980  %0 = spv.Variable : !spv.ptr<f32, Function>
981  // expected-error @+1 {{expected non-function type}}
982  spv.Store  %0, %arg0 : f32
983  return
984}
985
986// -----
987
988func @simple_store_missing_operand(%arg0 : f32) -> () {
989  %0 = spv.Variable : !spv.ptr<f32, Function>
990  // expected-error @+1 {{custom op 'spv.Store' invalid operand}} : f32
991  spv.Store  "Function" , %arg0 : f32
992  return
993}
994
995// -----
996
997func @simple_store_missing_operand(%arg0 : f32) -> () {
998  %0 = spv.Variable : !spv.ptr<f32, Function>
999  // expected-error @+1 {{custom op 'spv.Store' expected 2 operands}} : f32
1000  spv.Store  "Function" %0 : f32
1001  return
1002}
1003
1004// -----
1005
1006func @volatile_store_missing_lbrace(%arg0 : f32) -> () {
1007  %0 = spv.Variable : !spv.ptr<f32, Function>
1008  // expected-error @+1 {{expected ':'}}
1009  spv.Store  "Function" %0, %arg0 "Volatile"] : f32
1010  return
1011}
1012
1013// -----
1014
1015func @volatile_store_missing_rbrace(%arg0 : f32) -> () {
1016  %0 = spv.Variable : !spv.ptr<f32, Function>
1017  // expected-error @+1 {{expected ']'}}
1018  spv.Store "Function" %0, %arg0 ["Volatile"} : f32
1019  return
1020}
1021
1022// -----
1023
1024func @aligned_store_missing_alignment(%arg0 : f32) -> () {
1025  %0 = spv.Variable : !spv.ptr<f32, Function>
1026  // expected-error @+1 {{expected ','}}
1027  spv.Store  "Function" %0, %arg0 ["Aligned"] : f32
1028  return
1029}
1030
1031// -----
1032
1033func @aligned_store_missing_comma(%arg0 : f32) -> () {
1034  %0 = spv.Variable : !spv.ptr<f32, Function>
1035  // expected-error @+1 {{expected ','}}
1036  spv.Store  "Function" %0, %arg0 ["Aligned" 4] : f32
1037  return
1038}
1039
1040// -----
1041
1042func @load_incorrect_attributes(%arg0 : f32) -> () {
1043  %0 = spv.Variable : !spv.ptr<f32, Function>
1044  // expected-error @+1 {{expected ']'}}
1045  spv.Store  "Function" %0, %arg0 ["Volatile", 4] : f32
1046  return
1047}
1048
1049// -----
1050
1051func @aligned_store_incorrect_attributes(%arg0 : f32) -> () {
1052  %0 = spv.Variable : !spv.ptr<f32, Function>
1053  // expected-error @+1 {{expected ']'}}
1054  spv.Store  "Function" %0, %arg0 ["Aligned", 4, 23] : f32
1055  return
1056}
1057
1058// -----
1059
1060spv.module "Logical" "GLSL450" {
1061  spv.globalVariable @var0 : !spv.ptr<f32, Input>
1062  func @simple_store(%arg0 : f32) -> () {
1063    %0 = spv._address_of @var0 : !spv.ptr<f32, Input>
1064    // CHECK: spv.Store  "Input" {{%.*}}, {{%.*}} : f32
1065    spv.Store  "Input" %0, %arg0 : f32
1066    spv.Return
1067  }
1068}
1069
1070// -----
1071
1072//===----------------------------------------------------------------------===//
1073// spv.SubgroupBallotKHR
1074//===----------------------------------------------------------------------===//
1075
1076func @subgroup_ballot(%predicate: i1) -> vector<4xi32> {
1077  %0 = spv.SubgroupBallotKHR %predicate: vector<4xi32>
1078  return %0: vector<4xi32>
1079}
1080
1081// -----
1082
1083//===----------------------------------------------------------------------===//
1084// spv.undef
1085//===----------------------------------------------------------------------===//
1086
1087func @undef() -> () {
1088  %0 = spv.undef : f32
1089  %1 = spv.undef : vector<4xf32>
1090  spv.Return
1091}
1092
1093// -----
1094
1095func @undef() -> () {
1096  // expected-error @+2{{expected non-function type}}
1097  %0 = spv.undef :
1098  spv.Return
1099}
1100
1101// -----
1102
1103func @undef() -> () {
1104  // expected-error @+2{{expected ':'}}
1105  %0 = spv.undef
1106  spv.Return
1107}
1108
1109// -----
1110
1111
1112//===----------------------------------------------------------------------===//
1113// spv.Variable
1114//===----------------------------------------------------------------------===//
1115
1116func @variable(%arg0: f32) -> () {
1117  // CHECK: spv.Variable : !spv.ptr<f32, Function>
1118  %0 = spv.Variable : !spv.ptr<f32, Function>
1119  return
1120}
1121
1122// -----
1123
1124func @variable_init_normal_constant() -> () {
1125  %0 = spv.constant 4.0 : f32
1126  // CHECK: spv.Variable init(%0) : !spv.ptr<f32, Function>
1127  %1 = spv.Variable init(%0) : !spv.ptr<f32, Function>
1128  return
1129}
1130
1131// -----
1132
1133spv.module "Logical" "GLSL450" {
1134  spv.globalVariable @global : !spv.ptr<f32, Workgroup>
1135  func @variable_init_global_variable() -> () {
1136    %0 = spv._address_of @global : !spv.ptr<f32, Workgroup>
1137    // CHECK: spv.Variable init({{.*}}) : !spv.ptr<!spv.ptr<f32, Workgroup>, Function>
1138    %1 = spv.Variable init(%0) : !spv.ptr<!spv.ptr<f32, Workgroup>, Function>
1139    spv.Return
1140  }
1141} attributes {
1142  capability = ["VariablePointers"],
1143  extension = ["SPV_KHR_variable_pointers"]
1144}
1145
1146// -----
1147
1148spv.module "Logical" "GLSL450" {
1149  spv.specConstant @sc = 42 : i32
1150  // CHECK-LABEL: @variable_init_spec_constant
1151  func @variable_init_spec_constant() -> () {
1152    %0 = spv._reference_of @sc : i32
1153    // CHECK: spv.Variable init(%0) : !spv.ptr<i32, Function>
1154    %1 = spv.Variable init(%0) : !spv.ptr<i32, Function>
1155    spv.Return
1156  }
1157}
1158
1159// -----
1160
1161func @variable_bind() -> () {
1162  // expected-error @+1 {{cannot have 'descriptor_set' attribute (only allowed in spv.globalVariable)}}
1163  %0 = spv.Variable bind(1, 2) : !spv.ptr<f32, Function>
1164  return
1165}
1166
1167// -----
1168
1169func @variable_init_bind() -> () {
1170  %0 = spv.constant 4.0 : f32
1171  // expected-error @+1 {{cannot have 'binding' attribute (only allowed in spv.globalVariable)}}
1172  %1 = spv.Variable init(%0) {binding = 5 : i32} : !spv.ptr<f32, Function>
1173  return
1174}
1175
1176// -----
1177
1178func @variable_builtin() -> () {
1179  // expected-error @+1 {{cannot have 'built_in' attribute (only allowed in spv.globalVariable)}}
1180  %1 = spv.Variable built_in("GlobalInvocationID") : !spv.ptr<vector<3xi32>, Function>
1181  return
1182}
1183
1184// -----
1185
1186func @expect_ptr_result_type(%arg0: f32) -> () {
1187  // expected-error @+1 {{expected spv.ptr type}}
1188  %0 = spv.Variable : f32
1189  return
1190}
1191
1192// -----
1193
1194func @variable_init(%arg0: f32) -> () {
1195  // expected-error @+1 {{op initializer must be the result of a constant or spv.globalVariable op}}
1196  %0 = spv.Variable init(%arg0) : !spv.ptr<f32, Function>
1197  return
1198}
1199
1200// -----
1201
1202func @cannot_be_generic_storage_class(%arg0: f32) -> () {
1203  // expected-error @+1 {{op can only be used to model function-level variables. Use spv.globalVariable for module-level variables}}
1204  %0 = spv.Variable : !spv.ptr<f32, Generic>
1205  return
1206}
1207