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