[flang] Fix crash in HLFIR generation (#118399)
[llvm-project.git] / mlir / test / Dialect / SPIRV / IR / control-flow-ops.mlir
blob8496448759f0c99c08cd37629b03c5670134b852
1 // RUN: mlir-opt -allow-unregistered-dialect -split-input-file -verify-diagnostics %s | FileCheck %s
3 //===----------------------------------------------------------------------===//
4 // spirv.Branch
5 //===----------------------------------------------------------------------===//
7 func.func @branch() -> () {
8   // CHECK: spirv.Branch ^bb1
9   spirv.Branch ^next
10 ^next:
11   spirv.Return
14 // -----
16 func.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
24 // -----
26 func.func @missing_accessor() -> () {
27   // expected-error @+1 {{expected block name}}
28   spirv.Branch
31 // -----
33 func.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
43 // -----
45 //===----------------------------------------------------------------------===//
46 // spirv.BranchConditional
47 //===----------------------------------------------------------------------===//
49 func.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
61 // -----
63 func.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
79 // -----
81 func.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
91 // -----
93 func.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
102 // -----
104 func.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
115 // -----
117 func.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
127 // -----
129 func.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
140 // -----
142 func.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
152 // -----
154 //===----------------------------------------------------------------------===//
155 // spirv.FunctionCall
156 //===----------------------------------------------------------------------===//
158 spirv.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   }
171   spirv.func @f_0(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> (vector<4xf32>) "None" {
172     spirv.ReturnValue %arg0 : vector<4xf32>
173   }
175   spirv.func @f_1(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> () "None" {
176     spirv.Return
177   }
179   spirv.func @f_2() -> () "None" {
180     spirv.Return
181   }
183   spirv.func @f_3(%arg0 : i32) -> (i32) "None" {
184     spirv.ReturnValue %arg0 : i32
185   }
188 // -----
190 // Allow calling functions in other module-like ops
191 spirv.func @callee() "None" {
192   spirv.Return
195 func.func @caller() {
196   // CHECK: spirv.FunctionCall
197   spirv.FunctionCall @callee() : () -> ()
198   spirv.Return
201 // -----
203 spirv.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   }
211 // -----
213 spirv.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   }
221 // -----
223 spirv.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   }
231 // -----
233 spirv.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   }
242 // -----
244 spirv.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   }
253 // -----
255 spirv.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   }
263 // -----
265 //===----------------------------------------------------------------------===//
266 // spirv.mlir.loop
267 //===----------------------------------------------------------------------===//
269 // for (int i = 0; i < count; ++i) {}
270 func.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>
275   // CHECK: spirv.mlir.loop {
276   spirv.mlir.loop {
277     // CHECK-NEXT: spirv.Branch ^bb1
278     spirv.Branch ^header
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
287   // CHECK-NEXT: ^bb2:
288   ^body:
289     // Do nothing
290     // CHECK-NEXT: spirv.Branch ^bb3
291     spirv.Branch ^continue
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
301   // CHECK-NEXT: ^bb4:
302   ^merge:
303     spirv.mlir.merge
304   }
305   return
308 // -----
310 // CHECK-LABEL: @empty_region
311 func.func @empty_region() -> () {
312   // CHECK: spirv.mlir.loop
313   spirv.mlir.loop {
314   }
315   return
318 // -----
320 // CHECK-LABEL: @loop_with_control
321 func.func @loop_with_control() -> () {
322   // CHECK: spirv.mlir.loop control(Unroll)
323   spirv.mlir.loop control(Unroll) {
324   }
325   return
328 // -----
330 func.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
338 // -----
340 func.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
348 // -----
350 func.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
361 // -----
363 func.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
376 // -----
378 func.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
391 // -----
393 func.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
408 // -----
410 func.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
427 // -----
429 //===----------------------------------------------------------------------===//
430 // spirv.mlir.merge
431 //===----------------------------------------------------------------------===//
433 func.func @merge() -> () {
434   // expected-error @+1 {{expected parent op to be 'spirv.mlir.selection' or 'spirv.mlir.loop'}}
435   spirv.mlir.merge
438 // -----
440 func.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>
445   spirv.mlir.selection {
446     spirv.BranchConditional %cond, ^then, ^merge
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
453   ^merge:
454     spirv.mlir.merge
455   }
457   spirv.Return
460 // -----
462 func.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
479 // -----
481 //===----------------------------------------------------------------------===//
482 // spirv.Return
483 //===----------------------------------------------------------------------===//
485 // CHECK-LABEL: func @in_selection
486 func.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
498 // CHECK-LABEL: func @in_loop
499 func.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
515 // CHECK-LABEL: in_other_func_like_op
516 func.func @in_other_func_like_op() {
517   // CHECK: spirv.Return
518   spirv.Return
521 // -----
523 "foo.function"() ({
524   // expected-error @+1 {{op must appear in a function-like op's block}}
525   spirv.Return
526 })  : () -> ()
528 // -----
530 // Return mismatches function signature
531 spirv.module Logical GLSL450 {
532   spirv.func @work() -> (i32) "None" {
533     // expected-error @+1 {{cannot be used in functions returning value}}
534     spirv.Return
535   }
538 // -----
540 spirv.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     }
551     %zero = spirv.Constant 0: i32
552     spirv.ReturnValue %zero: i32
553   }
556 // -----
558 //===----------------------------------------------------------------------===//
559 // spirv.ReturnValue
560 //===----------------------------------------------------------------------===//
562 func.func @ret_val() -> (i32) {
563   %0 = spirv.Constant 42 : i32
564   // CHECK: spirv.ReturnValue %{{.*}} : i32
565   spirv.ReturnValue %0 : i32
568 // CHECK-LABEL: func @in_selection
569 func.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
583 // CHECK-LABEL: func @in_loop
584 func.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
602 // CHECK-LABEL: in_other_func_like_op
603 func.func @in_other_func_like_op(%arg: i32) -> i32 {
604   // CHECK: spirv.ReturnValue
605   spirv.ReturnValue %arg: i32
608 // -----
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 })  : () -> ()
616 // -----
618 spirv.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   }
626 // -----
628 spirv.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   }
636 // -----
638 spirv.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     }
650     spirv.Return
651   }
654 // -----
656 //===----------------------------------------------------------------------===//
657 // spirv.mlir.selection
658 //===----------------------------------------------------------------------===//
660 func.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>
665   // CHECK: spirv.mlir.selection {
666   spirv.mlir.selection {
667     // CHECK-NEXT: spirv.BranchConditional %{{.*}}, ^bb1, ^bb2
668     spirv.BranchConditional %cond, ^then, ^merge
670   // CHECK: ^bb1
671   ^then:
672     spirv.Store "Function" %var, %one : i32
673     // CHECK: spirv.Branch ^bb2
674     spirv.Branch ^merge
676   // CHECK: ^bb2
677   ^merge:
678     // CHECK-NEXT: spirv.mlir.merge
679     spirv.mlir.merge
680   }
682   spirv.Return
685 // -----
687 func.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>
693   // CHECK: spirv.mlir.selection {
694   spirv.mlir.selection {
695     // CHECK-NEXT: spirv.BranchConditional %{{.*}}, ^bb1, ^bb2
696     spirv.BranchConditional %cond, ^then, ^else
698   // CHECK: ^bb1
699   ^then:
700     spirv.Store "Function" %var, %one : i32
701     // CHECK: spirv.Branch ^bb3
702     spirv.Branch ^merge
704   // CHECK: ^bb2
705   ^else:
706     spirv.Store "Function" %var, %two : i32
707     // CHECK: spirv.Branch ^bb3
708     spirv.Branch ^merge
710   // CHECK: ^bb3
711   ^merge:
712     // CHECK-NEXT: spirv.mlir.merge
713     spirv.mlir.merge
714   }
716   spirv.Return
719 // -----
721 // CHECK-LABEL: @empty_region
722 func.func @empty_region() -> () {
723   // CHECK: spirv.mlir.selection
724   spirv.mlir.selection {
725   }
726   return
729 // -----
731 // CHECK-LABEL: @selection_with_control
732 func.func @selection_with_control() -> () {
733   // CHECK: spirv.mlir.selection control(Flatten)
734   spirv.mlir.selection control(Flatten) {
735   }
736   return
739 // -----
741 func.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
749 // -----
751 func.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
759 // -----
761 //===----------------------------------------------------------------------===//
762 // spirv.Unreachable
763 //===----------------------------------------------------------------------===//
765 // CHECK-LABEL: func @unreachable_no_pred
766 func.func @unreachable_no_pred() {
767     spirv.Return
769   ^next:
770     // CHECK: spirv.Unreachable
771     spirv.Unreachable
774 // CHECK-LABEL: func @unreachable_with_pred
775 func.func @unreachable_with_pred() {
776     spirv.Return
778   ^parent:
779     spirv.Branch ^unreachable
781   ^unreachable:
782     // CHECK: spirv.Unreachable
783     spirv.Unreachable
786 // -----
788 func.func @unreachable() {
789   // expected-error @+1 {{cannot be used in reachable block}}
790   spirv.Unreachable