1 // RUN: mlir-opt -allow-unregistered-dialect -split-input-file -verify-diagnostics %s | FileCheck %s
3 //===----------------------------------------------------------------------===//
5 //===----------------------------------------------------------------------===//
7 func.func @branch() -> () {
8 // CHECK: spirv.Branch ^bb1
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):
26 func.func @missing_accessor() -> () {
27 // expected-error @+1 {{expected block name}}
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] : () -> ()
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
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)
75 ^false2(%arg3: i32, %arg4: i32):
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
93 func.func @missing_condition() -> () {
94 // expected-error @+1 {{expected SSA operand}}
95 spirv.BranchConditional ^one, ^two
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
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) -> ()
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) -> ()
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
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
171 spirv.func @f_0(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> (vector<4xf32>) "None" {
172 spirv.ReturnValue %arg0 : vector<4xf32>
175 spirv.func @f_1(%arg0 : vector<4xf32>, %arg1 : vector<4xf32>) -> () "None" {
179 spirv.func @f_2() -> () "None" {
183 spirv.func @f_3(%arg0 : i32) -> (i32) "None" {
184 spirv.ReturnValue %arg0 : i32
190 // Allow calling functions in other module-like ops
191 spirv.func @callee() "None" {
195 func.func @caller() {
196 // CHECK: spirv.FunctionCall
197 spirv.FunctionCall @callee() : () -> ()
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)
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)
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) -> ()
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) -> ()
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
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
265 //===----------------------------------------------------------------------===//
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 {
277 // CHECK-NEXT: spirv.Branch ^bb1
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
290 // CHECK-NEXT: spirv.Branch ^bb3
291 spirv.Branch ^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
310 // CHECK-LABEL: @empty_region
311 func.func @empty_region() -> () {
312 // CHECK: spirv.mlir.loop
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) {
330 func.func @wrong_merge_block() -> () {
331 // expected-error @+1 {{last block must be the merge block with only one 'spirv.mlir.merge' op}}
340 func.func @missing_entry_block() -> () {
341 // expected-error @+1 {{must have an entry block branching to the loop header block}}
350 func.func @missing_header_block() -> () {
351 // expected-error @+1 {{must have a loop header block branched from the entry block}}
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}}
378 func.func @missing_continue_block() -> () {
379 // expected-error @+1 {{requires a loop continue block branching to the loop header block}}
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}}
399 spirv.Branch ^continue
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}}
429 //===----------------------------------------------------------------------===//
431 //===----------------------------------------------------------------------===//
433 func.func @merge() -> () {
434 // expected-error @+1 {{expected parent op to be 'spirv.mlir.selection' or 'spirv.mlir.loop'}}
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
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'}}
462 func.func @only_allowed_in_last_block() -> () {
463 %true = spirv.Constant true
467 spirv.BranchConditional %true, ^body, ^merge
469 // expected-error @+1 {{can only be used in the last block of 'spirv.mlir.selection' or 'spirv.mlir.loop'}}
481 //===----------------------------------------------------------------------===//
483 //===----------------------------------------------------------------------===//
485 // CHECK-LABEL: func @in_selection
486 func.func @in_selection(%cond : i1) -> () {
487 spirv.mlir.selection {
488 spirv.BranchConditional %cond, ^then, ^merge
490 // CHECK: spirv.Return
498 // CHECK-LABEL: func @in_loop
499 func.func @in_loop(%cond : i1) -> () {
503 spirv.BranchConditional %cond, ^body, ^merge
505 // CHECK: spirv.Return
515 // CHECK-LABEL: in_other_func_like_op
516 func.func @in_other_func_like_op() {
517 // CHECK: spirv.Return
524 // expected-error @+1 {{op must appear in a function-like op's block}}
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}}
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
545 // expected-error @+1 {{cannot be used in functions returning value}}
551 %zero = spirv.Constant 0: i32
552 spirv.ReturnValue %zero: i32
558 //===----------------------------------------------------------------------===//
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
573 %zero = spirv.Constant 0 : i32
574 // CHECK: spirv.ReturnValue
575 spirv.ReturnValue %zero : i32
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) {
588 spirv.BranchConditional %cond, ^body, ^merge
590 %zero = spirv.Constant 0 : i32
591 // CHECK: spirv.ReturnValue
592 spirv.ReturnValue %zero : i32
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
611 %0 = spirv.Constant true
612 // expected-error @+1 {{op must appear in a function-like op's block}}
613 spirv.ReturnValue %0 : i1
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
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
638 spirv.module Logical GLSL450 {
639 spirv.func @in_nested_region(%cond: i1) -> () "None" {
640 spirv.mlir.selection {
641 spirv.BranchConditional %cond, ^then, ^merge
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
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
672 spirv.Store "Function" %var, %one : i32
673 // CHECK: spirv.Branch ^bb2
678 // CHECK-NEXT: spirv.mlir.merge
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
700 spirv.Store "Function" %var, %one : i32
701 // CHECK: spirv.Branch ^bb3
706 spirv.Store "Function" %var, %two : i32
707 // CHECK: spirv.Branch ^bb3
712 // CHECK-NEXT: spirv.mlir.merge
721 // CHECK-LABEL: @empty_region
722 func.func @empty_region() -> () {
723 // CHECK: spirv.mlir.selection
724 spirv.mlir.selection {
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) {
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 {
751 func.func @missing_entry_block() -> () {
752 // expected-error @+1 {{must have a selection header block}}
753 spirv.mlir.selection {
761 //===----------------------------------------------------------------------===//
763 //===----------------------------------------------------------------------===//
765 // CHECK-LABEL: func @unreachable_no_pred
766 func.func @unreachable_no_pred() {
770 // CHECK: spirv.Unreachable
774 // CHECK-LABEL: func @unreachable_with_pred
775 func.func @unreachable_with_pred() {
779 spirv.Branch ^unreachable
782 // CHECK: spirv.Unreachable
788 func.func @unreachable() {
789 // expected-error @+1 {{cannot be used in reachable block}}