xref: /llvm-project/mlir/test/Dialect/SPIRV/IR/control-flow-ops.mlir (revision 363b655920c49a4bcb0869f820ed40aac834eebd)
1// RUN: mlir-opt -allow-unregistered-dialect -split-input-file -verify-diagnostics %s | FileCheck %s
2
3//===----------------------------------------------------------------------===//
4// spirv.Branch
5//===----------------------------------------------------------------------===//
6
7func.func @branch() -> () {
8  // CHECK: spirv.Branch ^bb1
9  spirv.Branch ^next
10^next:
11  spirv.Return
12}
13
14// -----
15
16func.func @branch_argument() -> () {
17  %zero = spirv.Constant 0 : i32
18  // CHECK: spirv.Branch ^bb1(%{{.*}}, %{{.*}} : i32, i32)
19  spirv.Branch ^next(%zero, %zero: i32, i32)
20^next(%arg0: i32, %arg1: i32):
21  spirv.Return
22}
23
24// -----
25
26func.func @missing_accessor() -> () {
27  // expected-error @+1 {{expected block name}}
28  spirv.Branch
29}
30
31// -----
32
33func.func @wrong_accessor_count() -> () {
34  %true = spirv.Constant true
35  // expected-error @+1 {{requires 1 successor but found 2}}
36  "spirv.Branch"()[^one, ^two] : () -> ()
37^one:
38  spirv.Return
39^two:
40  spirv.Return
41}
42
43// -----
44
45//===----------------------------------------------------------------------===//
46// spirv.BranchConditional
47//===----------------------------------------------------------------------===//
48
49func.func @cond_branch() -> () {
50  %true = spirv.Constant true
51  // CHECK: spirv.BranchConditional %{{.*}}, ^bb1, ^bb2
52  spirv.BranchConditional %true, ^one, ^two
53// CHECK: ^bb1
54^one:
55  spirv.Return
56// CHECK: ^bb2
57^two:
58  spirv.Return
59}
60
61// -----
62
63func.func @cond_branch_argument() -> () {
64  %true = spirv.Constant true
65  %zero = spirv.Constant 0 : i32
66  // CHECK: spirv.BranchConditional %{{.*}}, ^bb1(%{{.*}}, %{{.*}} : i32, i32), ^bb2
67  spirv.BranchConditional %true, ^true1(%zero, %zero: i32, i32), ^false1
68^true1(%arg0: i32, %arg1: i32):
69  // CHECK: spirv.BranchConditional %{{.*}}, ^bb3, ^bb4(%{{.*}}, %{{.*}} : i32, i32)
70  spirv.BranchConditional %true, ^true2, ^false2(%zero, %zero: i32, i32)
71^false1:
72  spirv.Return
73^true2:
74  spirv.Return
75^false2(%arg3: i32, %arg4: i32):
76  spirv.Return
77}
78
79// -----
80
81func.func @cond_branch_with_weights() -> () {
82  %true = spirv.Constant true
83  // CHECK: spirv.BranchConditional %{{.*}} [5, 10]
84  spirv.BranchConditional %true [5, 10], ^one, ^two
85^one:
86  spirv.Return
87^two:
88  spirv.Return
89}
90
91// -----
92
93func.func @missing_condition() -> () {
94  // expected-error @+1 {{expected SSA operand}}
95  spirv.BranchConditional ^one, ^two
96^one:
97  spirv.Return
98^two:
99  spirv.Return
100}
101
102// -----
103
104func.func @wrong_condition_type() -> () {
105  // expected-note @+1 {{prior use here}}
106  %zero = spirv.Constant 0 : i32
107  // expected-error @+1 {{use of value '%zero' expects different type than prior uses: 'i1' vs 'i32'}}
108  spirv.BranchConditional %zero, ^one, ^two
109^one:
110  spirv.Return
111^two:
112  spirv.Return
113}
114
115// -----
116
117func.func @wrong_accessor_count() -> () {
118  %true = spirv.Constant true
119  // expected-error @+1 {{requires 2 successors but found 1}}
120  "spirv.BranchConditional"(%true)[^one] {operandSegmentSizes = array<i32: 1, 0, 0>} : (i1) -> ()
121^one:
122  spirv.Return
123^two:
124  spirv.Return
125}
126
127// -----
128
129func.func @wrong_number_of_weights() -> () {
130  %true = spirv.Constant true
131  // expected-error @+1 {{must have exactly two branch weights}}
132  "spirv.BranchConditional"(%true)[^one, ^two] {branch_weights = [1 : i32, 2 : i32, 3 : i32],
133                                              operandSegmentSizes = array<i32: 1, 0, 0>} : (i1) -> ()
134^one:
135  spirv.Return
136^two:
137  spirv.Return
138}
139
140// -----
141
142func.func @weights_cannot_both_be_zero() -> () {
143  %true = spirv.Constant true
144  // expected-error @+1 {{branch weights cannot both be zero}}
145  spirv.BranchConditional %true [0, 0], ^one, ^two
146^one:
147  spirv.Return
148^two:
149  spirv.Return
150}
151
152// -----
153
154//===----------------------------------------------------------------------===//
155// spirv.FunctionCall
156//===----------------------------------------------------------------------===//
157
158spirv.module Logical GLSL450 {
159  spirv.func @fmain(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>, %arg2 : i32) -> i32 "None" {
160    // CHECK: {{%.*}} = spirv.FunctionCall @f_0({{%.*}}, {{%.*}}) : (vector<4xf32>, vector<4xf32>) -> vector<4xf32>
161    %0 = spirv.FunctionCall @f_0(%arg0, %arg1) : (vector<4xf32>, vector<4xf32>) -> vector<4xf32>
162    // CHECK: spirv.FunctionCall @f_1({{%.*}}, {{%.*}}) : (vector<4xf32>, vector<4xf32>) -> ()
163    spirv.FunctionCall @f_1(%0, %arg1) : (vector<4xf32>, vector<4xf32>) ->  ()
164    // CHECK: spirv.FunctionCall @f_2() : () -> ()
165    spirv.FunctionCall @f_2() : () -> ()
166    // CHECK: {{%.*}} = spirv.FunctionCall @f_3({{%.*}}) : (i32) -> i32
167    %1 = spirv.FunctionCall @f_3(%arg2) : (i32) -> i32
168    spirv.ReturnValue %1 : i32
169  }
170
171  spirv.func @f_0(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> (vector<4xf32>) "None" {
172    spirv.ReturnValue %arg0 : vector<4xf32>
173  }
174
175  spirv.func @f_1(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> () "None" {
176    spirv.Return
177  }
178
179  spirv.func @f_2() -> () "None" {
180    spirv.Return
181  }
182
183  spirv.func @f_3(%arg0 : i32) -> (i32) "None" {
184    spirv.ReturnValue %arg0 : i32
185  }
186}
187
188// -----
189
190// Allow calling functions in other module-like ops
191spirv.func @callee() "None" {
192  spirv.Return
193}
194
195func.func @caller() {
196  // CHECK: spirv.FunctionCall
197  spirv.FunctionCall @callee() : () -> ()
198  spirv.Return
199}
200
201// -----
202
203spirv.module Logical GLSL450 {
204  spirv.func @f_invalid_result_type(%arg0 : i32, %arg1 : i32) -> () "None" {
205    // expected-error @+1 {{result group starting at #0 requires 0 or 1 element, but found 2}}
206    %0:2 = spirv.FunctionCall @f_invalid_result_type(%arg0, %arg1) : (i32, i32) -> (i32, i32)
207    spirv.Return
208  }
209}
210
211// -----
212
213spirv.module Logical GLSL450 {
214  spirv.func @f_result_type_mismatch(%arg0 : i32, %arg1 : i32) -> () "None" {
215    // expected-error @+1 {{has incorrect number of results has for callee: expected 0, but provided 1}}
216    %1 = spirv.FunctionCall @f_result_type_mismatch(%arg0, %arg0) : (i32, i32) -> (i32)
217    spirv.Return
218  }
219}
220
221// -----
222
223spirv.module Logical GLSL450 {
224  spirv.func @f_type_mismatch(%arg0 : i32, %arg1 : i32) -> () "None" {
225    // expected-error @+1 {{has incorrect number of operands for callee: expected 2, but provided 1}}
226    spirv.FunctionCall @f_type_mismatch(%arg0) : (i32) -> ()
227    spirv.Return
228  }
229}
230
231// -----
232
233spirv.module Logical GLSL450 {
234  spirv.func @f_type_mismatch(%arg0 : i32, %arg1 : i32) -> () "None" {
235    %0 = spirv.Constant 2.0 : f32
236    // expected-error @+1 {{operand type mismatch: expected operand type 'i32', but provided 'f32' for operand number 1}}
237    spirv.FunctionCall @f_type_mismatch(%arg0, %0) : (i32, f32) -> ()
238    spirv.Return
239  }
240}
241
242// -----
243
244spirv.module Logical GLSL450 {
245  spirv.func @f_type_mismatch(%arg0 : i32, %arg1 : i32) -> i32 "None" {
246    %cst = spirv.Constant 0: i32
247    // expected-error @+1 {{result type mismatch: expected 'i32', but provided 'f32'}}
248    %0 = spirv.FunctionCall @f_type_mismatch(%arg0, %arg0) : (i32, i32) -> f32
249    spirv.ReturnValue %cst: i32
250  }
251}
252
253// -----
254
255spirv.module Logical GLSL450 {
256  spirv.func @f_foo(%arg0 : i32, %arg1 : i32) -> i32 "None" {
257    // expected-error @+1 {{op callee function 'f_undefined' not found in nearest symbol table}}
258    %0 = spirv.FunctionCall @f_undefined(%arg0, %arg0) : (i32, i32) -> i32
259    spirv.ReturnValue %0: i32
260  }
261}
262
263// -----
264
265//===----------------------------------------------------------------------===//
266// spirv.mlir.loop
267//===----------------------------------------------------------------------===//
268
269// for (int i = 0; i < count; ++i) {}
270func.func @loop(%count : i32) -> () {
271  %zero = spirv.Constant 0: i32
272  %one = spirv.Constant 1: i32
273  %var = spirv.Variable init(%zero) : !spirv.ptr<i32, Function>
274
275  // CHECK: spirv.mlir.loop {
276  spirv.mlir.loop {
277    // CHECK-NEXT: spirv.Branch ^bb1
278    spirv.Branch ^header
279
280  // CHECK-NEXT: ^bb1:
281  ^header:
282    %val0 = spirv.Load "Function" %var : i32
283    %cmp = spirv.SLessThan %val0, %count : i32
284    // CHECK: spirv.BranchConditional %{{.*}}, ^bb2, ^bb4
285    spirv.BranchConditional %cmp, ^body, ^merge
286
287  // CHECK-NEXT: ^bb2:
288  ^body:
289    // Do nothing
290    // CHECK-NEXT: spirv.Branch ^bb3
291    spirv.Branch ^continue
292
293  // CHECK-NEXT: ^bb3:
294  ^continue:
295    %val1 = spirv.Load "Function" %var : i32
296    %add = spirv.IAdd %val1, %one : i32
297    spirv.Store "Function" %var, %add : i32
298    // CHECK: spirv.Branch ^bb1
299    spirv.Branch ^header
300
301  // CHECK-NEXT: ^bb4:
302  ^merge:
303    spirv.mlir.merge
304  }
305  return
306}
307
308// -----
309
310// CHECK-LABEL: @empty_region
311func.func @empty_region() -> () {
312  // CHECK: spirv.mlir.loop
313  spirv.mlir.loop {
314  }
315  return
316}
317
318// -----
319
320// CHECK-LABEL: @loop_with_control
321func.func @loop_with_control() -> () {
322  // CHECK: spirv.mlir.loop control(Unroll)
323  spirv.mlir.loop control(Unroll) {
324  }
325  return
326}
327
328// -----
329
330func.func @wrong_merge_block() -> () {
331  // expected-error @+1 {{last block must be the merge block with only one 'spirv.mlir.merge' op}}
332  spirv.mlir.loop {
333    spirv.Return
334  }
335  return
336}
337
338// -----
339
340func.func @missing_entry_block() -> () {
341  // expected-error @+1 {{must have an entry block branching to the loop header block}}
342  spirv.mlir.loop {
343    spirv.mlir.merge
344  }
345  return
346}
347
348// -----
349
350func.func @missing_header_block() -> () {
351  // expected-error @+1 {{must have a loop header block branched from the entry block}}
352  spirv.mlir.loop {
353  ^entry:
354    spirv.Branch ^merge
355  ^merge:
356    spirv.mlir.merge
357  }
358  return
359}
360
361// -----
362
363func.func @entry_should_branch_to_header() -> () {
364  // expected-error @+1 {{entry block must only have one 'spirv.Branch' op to the second block}}
365  spirv.mlir.loop {
366  ^entry:
367    spirv.Branch ^merge
368  ^header:
369    spirv.Branch ^merge
370  ^merge:
371    spirv.mlir.merge
372  }
373  return
374}
375
376// -----
377
378func.func @missing_continue_block() -> () {
379  // expected-error @+1 {{requires a loop continue block branching to the loop header block}}
380  spirv.mlir.loop {
381  ^entry:
382    spirv.Branch ^header
383  ^header:
384    spirv.Branch ^merge
385  ^merge:
386    spirv.mlir.merge
387  }
388  return
389}
390
391// -----
392
393func.func @continue_should_branch_to_header() -> () {
394  // expected-error @+1 {{second to last block must be the loop continue block that branches to the loop header block}}
395  spirv.mlir.loop {
396  ^entry:
397    spirv.Branch ^header
398  ^header:
399    spirv.Branch ^continue
400  ^continue:
401    spirv.Branch ^merge
402  ^merge:
403    spirv.mlir.merge
404  }
405  return
406}
407
408// -----
409
410func.func @only_entry_and_continue_branch_to_header() -> () {
411  // expected-error @+1 {{can only have the entry and loop continue block branching to the loop header block}}
412  spirv.mlir.loop {
413  ^entry:
414    spirv.Branch ^header
415  ^header:
416    spirv.Branch ^cont1
417  ^cont1:
418    spirv.Branch ^header
419  ^cont2:
420    spirv.Branch ^header
421  ^merge:
422    spirv.mlir.merge
423  }
424  return
425}
426
427// -----
428
429//===----------------------------------------------------------------------===//
430// spirv.mlir.merge
431//===----------------------------------------------------------------------===//
432
433func.func @merge() -> () {
434  // expected-error @+1 {{expected parent op to be 'spirv.mlir.selection' or 'spirv.mlir.loop'}}
435  spirv.mlir.merge
436}
437
438// -----
439
440func.func @only_allowed_in_last_block(%cond : i1) -> () {
441  %zero = spirv.Constant 0: i32
442  %one = spirv.Constant 1: i32
443  %var = spirv.Variable init(%zero) : !spirv.ptr<i32, Function>
444
445  spirv.mlir.selection {
446    spirv.BranchConditional %cond, ^then, ^merge
447
448  ^then:
449    spirv.Store "Function" %var, %one : i32
450    // expected-error @+1 {{can only be used in the last block of 'spirv.mlir.selection' or 'spirv.mlir.loop'}}
451    spirv.mlir.merge
452
453  ^merge:
454    spirv.mlir.merge
455  }
456
457  spirv.Return
458}
459
460// -----
461
462func.func @only_allowed_in_last_block() -> () {
463  %true = spirv.Constant true
464  spirv.mlir.loop {
465    spirv.Branch ^header
466  ^header:
467    spirv.BranchConditional %true, ^body, ^merge
468  ^body:
469    // expected-error @+1 {{can only be used in the last block of 'spirv.mlir.selection' or 'spirv.mlir.loop'}}
470    spirv.mlir.merge
471  ^continue:
472    spirv.Branch ^header
473  ^merge:
474    spirv.mlir.merge
475  }
476  return
477}
478
479// -----
480
481//===----------------------------------------------------------------------===//
482// spirv.Return
483//===----------------------------------------------------------------------===//
484
485// CHECK-LABEL: func @in_selection
486func.func @in_selection(%cond : i1) -> () {
487  spirv.mlir.selection {
488    spirv.BranchConditional %cond, ^then, ^merge
489  ^then:
490    // CHECK: spirv.Return
491    spirv.Return
492  ^merge:
493    spirv.mlir.merge
494  }
495  spirv.Return
496}
497
498// CHECK-LABEL: func @in_loop
499func.func @in_loop(%cond : i1) -> () {
500  spirv.mlir.loop {
501    spirv.Branch ^header
502  ^header:
503    spirv.BranchConditional %cond, ^body, ^merge
504  ^body:
505    // CHECK: spirv.Return
506    spirv.Return
507  ^continue:
508    spirv.Branch ^header
509  ^merge:
510    spirv.mlir.merge
511  }
512  spirv.Return
513}
514
515// CHECK-LABEL: in_other_func_like_op
516func.func @in_other_func_like_op() {
517  // CHECK: spirv.Return
518  spirv.Return
519}
520
521// -----
522
523"foo.function"() ({
524  // expected-error @+1 {{op must appear in a function-like op's block}}
525  spirv.Return
526})  : () -> ()
527
528// -----
529
530// Return mismatches function signature
531spirv.module Logical GLSL450 {
532  spirv.func @work() -> (i32) "None" {
533    // expected-error @+1 {{cannot be used in functions returning value}}
534    spirv.Return
535  }
536}
537
538// -----
539
540spirv.module Logical GLSL450 {
541  spirv.func @in_nested_region(%cond: i1) -> (i32) "None" {
542    spirv.mlir.selection {
543      spirv.BranchConditional %cond, ^then, ^merge
544    ^then:
545      // expected-error @+1 {{cannot be used in functions returning value}}
546      spirv.Return
547    ^merge:
548      spirv.mlir.merge
549    }
550
551    %zero = spirv.Constant 0: i32
552    spirv.ReturnValue %zero: i32
553  }
554}
555
556// -----
557
558//===----------------------------------------------------------------------===//
559// spirv.ReturnValue
560//===----------------------------------------------------------------------===//
561
562func.func @ret_val() -> (i32) {
563  %0 = spirv.Constant 42 : i32
564  // CHECK: spirv.ReturnValue %{{.*}} : i32
565  spirv.ReturnValue %0 : i32
566}
567
568// CHECK-LABEL: func @in_selection
569func.func @in_selection(%cond : i1) -> (i32) {
570  spirv.mlir.selection {
571    spirv.BranchConditional %cond, ^then, ^merge
572  ^then:
573    %zero = spirv.Constant 0 : i32
574    // CHECK: spirv.ReturnValue
575    spirv.ReturnValue %zero : i32
576  ^merge:
577    spirv.mlir.merge
578  }
579  %one = spirv.Constant 1 : i32
580  spirv.ReturnValue %one : i32
581}
582
583// CHECK-LABEL: func @in_loop
584func.func @in_loop(%cond : i1) -> (i32) {
585  spirv.mlir.loop {
586    spirv.Branch ^header
587  ^header:
588    spirv.BranchConditional %cond, ^body, ^merge
589  ^body:
590    %zero = spirv.Constant 0 : i32
591    // CHECK: spirv.ReturnValue
592    spirv.ReturnValue %zero : i32
593  ^continue:
594    spirv.Branch ^header
595  ^merge:
596    spirv.mlir.merge
597  }
598  %one = spirv.Constant 1 : i32
599  spirv.ReturnValue %one : i32
600}
601
602// CHECK-LABEL: in_other_func_like_op
603func.func @in_other_func_like_op(%arg: i32) -> i32 {
604  // CHECK: spirv.ReturnValue
605  spirv.ReturnValue %arg: i32
606}
607
608// -----
609
610"foo.function"() ({
611  %0 = spirv.Constant true
612  // expected-error @+1 {{op must appear in a function-like op's block}}
613  spirv.ReturnValue %0 : i1
614})  : () -> ()
615
616// -----
617
618spirv.module Logical GLSL450 {
619  spirv.func @value_count_mismatch() -> () "None" {
620    %0 = spirv.Constant 42 : i32
621    // expected-error @+1 {{op returns 1 value but enclosing function requires 0 results}}
622    spirv.ReturnValue %0 : i32
623  }
624}
625
626// -----
627
628spirv.module Logical GLSL450 {
629  spirv.func @value_type_mismatch() -> (f32) "None" {
630    %0 = spirv.Constant 42 : i32
631    // expected-error @+1 {{return value's type ('i32') mismatch with function's result type ('f32')}}
632    spirv.ReturnValue %0 : i32
633  }
634}
635
636// -----
637
638spirv.module Logical GLSL450 {
639  spirv.func @in_nested_region(%cond: i1) -> () "None" {
640    spirv.mlir.selection {
641      spirv.BranchConditional %cond, ^then, ^merge
642    ^then:
643      %cst = spirv.Constant 0: i32
644      // expected-error @+1 {{op returns 1 value but enclosing function requires 0 results}}
645      spirv.ReturnValue %cst: i32
646    ^merge:
647      spirv.mlir.merge
648    }
649
650    spirv.Return
651  }
652}
653
654// -----
655
656//===----------------------------------------------------------------------===//
657// spirv.mlir.selection
658//===----------------------------------------------------------------------===//
659
660func.func @selection(%cond: i1) -> () {
661  %zero = spirv.Constant 0: i32
662  %one = spirv.Constant 1: i32
663  %var = spirv.Variable init(%zero) : !spirv.ptr<i32, Function>
664
665  // CHECK: spirv.mlir.selection {
666  spirv.mlir.selection {
667    // CHECK-NEXT: spirv.BranchConditional %{{.*}}, ^bb1, ^bb2
668    spirv.BranchConditional %cond, ^then, ^merge
669
670  // CHECK: ^bb1
671  ^then:
672    spirv.Store "Function" %var, %one : i32
673    // CHECK: spirv.Branch ^bb2
674    spirv.Branch ^merge
675
676  // CHECK: ^bb2
677  ^merge:
678    // CHECK-NEXT: spirv.mlir.merge
679    spirv.mlir.merge
680  }
681
682  spirv.Return
683}
684
685// -----
686
687func.func @selection(%cond: i1) -> () {
688  %zero = spirv.Constant 0: i32
689  %one = spirv.Constant 1: i32
690  %two = spirv.Constant 2: i32
691  %var = spirv.Variable init(%zero) : !spirv.ptr<i32, Function>
692
693  // CHECK: spirv.mlir.selection {
694  spirv.mlir.selection {
695    // CHECK-NEXT: spirv.BranchConditional %{{.*}}, ^bb1, ^bb2
696    spirv.BranchConditional %cond, ^then, ^else
697
698  // CHECK: ^bb1
699  ^then:
700    spirv.Store "Function" %var, %one : i32
701    // CHECK: spirv.Branch ^bb3
702    spirv.Branch ^merge
703
704  // CHECK: ^bb2
705  ^else:
706    spirv.Store "Function" %var, %two : i32
707    // CHECK: spirv.Branch ^bb3
708    spirv.Branch ^merge
709
710  // CHECK: ^bb3
711  ^merge:
712    // CHECK-NEXT: spirv.mlir.merge
713    spirv.mlir.merge
714  }
715
716  spirv.Return
717}
718
719// -----
720
721// CHECK-LABEL: @empty_region
722func.func @empty_region() -> () {
723  // CHECK: spirv.mlir.selection
724  spirv.mlir.selection {
725  }
726  return
727}
728
729// -----
730
731// CHECK-LABEL: @selection_with_control
732func.func @selection_with_control() -> () {
733  // CHECK: spirv.mlir.selection control(Flatten)
734  spirv.mlir.selection control(Flatten) {
735  }
736  return
737}
738
739// -----
740
741func.func @wrong_merge_block() -> () {
742  // expected-error @+1 {{last block must be the merge block with only one 'spirv.mlir.merge' op}}
743  spirv.mlir.selection {
744    spirv.Return
745  }
746  return
747}
748
749// -----
750
751func.func @missing_entry_block() -> () {
752  // expected-error @+1 {{must have a selection header block}}
753  spirv.mlir.selection {
754    spirv.mlir.merge
755  }
756  return
757}
758
759// -----
760
761//===----------------------------------------------------------------------===//
762// spirv.Unreachable
763//===----------------------------------------------------------------------===//
764
765// CHECK-LABEL: func @unreachable_no_pred
766func.func @unreachable_no_pred() {
767    spirv.Return
768
769  ^next:
770    // CHECK: spirv.Unreachable
771    spirv.Unreachable
772}
773
774// CHECK-LABEL: func @unreachable_with_pred
775func.func @unreachable_with_pred() {
776    spirv.Return
777
778  ^parent:
779    spirv.Branch ^unreachable
780
781  ^unreachable:
782    // CHECK: spirv.Unreachable
783    spirv.Unreachable
784}
785
786// -----
787
788func.func @unreachable() {
789  // expected-error @+1 {{cannot be used in reachable block}}
790  spirv.Unreachable
791}
792