xref: /llvm-project/mlir/test/Dialect/SCF/invalid.mlir (revision 2a30bfcef368667247ebbe30be84f73b92dbe800)
1// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -verify-diagnostics
2
3func.func @loop_for_lb(%arg0: f32, %arg1: index) {
4  // expected-error@+1 {{operand #0 must be signless integer or index}}
5  "scf.for"(%arg0, %arg1, %arg1) ({}) : (f32, index, index) -> ()
6  return
7}
8
9// -----
10
11func.func @loop_for_ub(%arg0: f32, %arg1: index) {
12  // expected-error@+1 {{operand #1 must be signless integer or index}}
13  "scf.for"(%arg1, %arg0, %arg1) ({}) : (index, f32, index) -> ()
14  return
15}
16
17// -----
18
19func.func @loop_for_step(%arg0: f32, %arg1: index) {
20  // expected-error@+1 {{operand #2 must be signless integer or index}}
21  "scf.for"(%arg1, %arg1, %arg0) ({}) : (index, index, f32) -> ()
22  return
23}
24
25// -----
26
27func.func @loop_for_mismatch(%arg0: i32, %arg1: index) {
28  // expected-error@+1 {{all of {lowerBound, upperBound, step} have same type}}
29  "scf.for"(%arg1, %arg0, %arg1) ({}) : (index, i32, index) -> ()
30  return
31}
32
33// -----
34
35func.func @loop_for_one_region(%arg0: index) {
36  // expected-error@+1 {{requires one region}}
37  "scf.for"(%arg0, %arg0, %arg0) (
38    {scf.yield},
39    {scf.yield}
40  ) : (index, index, index) -> ()
41  return
42}
43
44// -----
45
46func.func @loop_for_single_block(%arg0: index) {
47  // expected-error@+1 {{expects region #0 to have 0 or 1 blocks}}
48  "scf.for"(%arg0, %arg0, %arg0) (
49    {
50    ^bb1:
51      scf.yield
52    ^bb2:
53      scf.yield
54    }
55  ) : (index, index, index) -> ()
56  return
57}
58
59// -----
60
61func.func @loop_for_single_index_argument(%arg0: index) {
62  // expected-error@+1 {{expected induction variable to be same type as bounds}}
63  "scf.for"(%arg0, %arg0, %arg0) (
64    {
65    ^bb0(%i0 : f32):
66      scf.yield
67    }
68  ) : (index, index, index) -> ()
69  return
70}
71
72// -----
73
74func.func @not_enough_loop_results(%arg0: index, %init: f32) {
75  // expected-error @below{{mismatch in number of loop-carried values and defined values}}
76  "scf.for"(%arg0, %arg0, %arg0, %init) (
77    {
78    ^bb0(%i0 : index, %iter: f32):
79      scf.yield %iter : f32
80    }
81  ) : (index, index, index, f32) -> ()
82  return
83}
84
85// -----
86
87func.func @scf_for_incorrect_result_type(%arg0: index, %init: f32) {
88  // expected-error @below{{0-th region iter_arg and 0-th loop result have different type: 'f32' != 'f64'}}
89  "scf.for"(%arg0, %arg0, %arg0, %init) (
90    {
91    ^bb0(%i0 : index, %iter: f32):
92      scf.yield %iter : f32
93    }
94  ) : (index, index, index, f32) -> (f64)
95  return
96}
97
98// -----
99
100func.func @too_many_iter_args(%arg0: index, %init: f32) {
101  // expected-error @below{{different number of inits and region iter_args: 1 != 2}}
102  %x = "scf.for"(%arg0, %arg0, %arg0, %init) (
103    {
104    ^bb0(%i0 : index, %iter: f32, %iter2: f32):
105      scf.yield %iter, %iter : f32, f32
106    }
107  ) : (index, index, index, f32) -> (f32)
108  return
109}
110
111// -----
112
113func.func @too_few_yielded_values(%arg0: index, %init: f32) {
114  // expected-error @below{{different number of region iter_args and yielded values: 2 != 1}}
115  %x, %x2 = "scf.for"(%arg0, %arg0, %arg0, %init, %init) (
116    {
117    ^bb0(%i0 : index, %iter: f32, %iter2: f32):
118      scf.yield %iter : f32
119    }
120  ) : (index, index, index, f32, f32) -> (f32, f32)
121  return
122}
123
124// -----
125
126func.func @loop_if_not_i1(%arg0: index) {
127  // expected-error@+1 {{operand #0 must be 1-bit signless integer}}
128  "scf.if"(%arg0) ({}, {}) : (index) -> ()
129  return
130}
131
132// -----
133
134func.func @loop_if_more_than_2_regions(%arg0: i1) {
135  // expected-error@+1 {{expected 2 regions}}
136  "scf.if"(%arg0) ({}, {}, {}): (i1) -> ()
137  return
138}
139
140// -----
141
142func.func @loop_if_not_one_block_per_region(%arg0: i1) {
143  // expected-error@+1 {{expects region #0 to have 0 or 1 blocks}}
144  "scf.if"(%arg0) ({
145    ^bb0:
146      scf.yield
147    ^bb1:
148      scf.yield
149  }, {}): (i1) -> ()
150  return
151}
152
153// -----
154
155func.func @loop_if_illegal_block_argument(%arg0: i1) {
156  // expected-error@+1 {{region #0 should have no arguments}}
157  "scf.if"(%arg0) ({
158    ^bb0(%0 : index):
159      scf.yield
160  }, {}): (i1) -> ()
161  return
162}
163
164// -----
165
166func.func @parallel_arguments_different_tuple_size(
167    %arg0: index, %arg1: index, %arg2: index) {
168  // expected-error@+1 {{custom op 'scf.parallel' expected 1 operands}}
169  scf.parallel (%i0) = (%arg0) to (%arg1, %arg2) step () {
170  }
171  return
172}
173
174// -----
175
176func.func @parallel_body_arguments_wrong_type(
177    %arg0: index, %arg1: index, %arg2: index) {
178  // expected-error@+1 {{'scf.parallel' op expects arguments for the induction variable to be of index type}}
179  "scf.parallel"(%arg0, %arg1, %arg2) ({
180    ^bb0(%i0: f32):
181      scf.yield
182  }) {operandSegmentSizes = array<i32: 1, 1, 1, 0>}: (index, index, index) -> ()
183  return
184}
185
186// -----
187
188func.func @parallel_body_wrong_number_of_arguments(
189    %arg0: index, %arg1: index, %arg2: index) {
190  // expected-error@+1 {{'scf.parallel' op expects the same number of induction variables: 2 as bound and step values: 1}}
191  "scf.parallel"(%arg0, %arg1, %arg2) ({
192    ^bb0(%i0: index, %i1: index):
193      scf.yield
194  }) {operandSegmentSizes = array<i32: 1, 1, 1, 0>}: (index, index, index) -> ()
195  return
196}
197
198// -----
199
200func.func @parallel_no_tuple_elements() {
201  // expected-error@+1 {{'scf.parallel' op needs at least one tuple element for lowerBound, upperBound and step}}
202  scf.parallel () = () to () step () {
203  }
204  return
205}
206
207// -----
208
209func.func @parallel_step_not_positive(
210    %arg0: index, %arg1: index, %arg2: index, %arg3: index) {
211  // expected-error@+3 {{constant step operand must be positive}}
212  %c0 = arith.constant 1 : index
213  %c1 = arith.constant 0 : index
214  scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) step (%c0, %c1) {
215  }
216  return
217}
218
219// -----
220
221func.func @parallel_fewer_results_than_reduces(
222    %arg0 : index, %arg1: index, %arg2: index) {
223  // expected-error@+1 {{expects number of results: 0 to be the same as number of reductions: 1}}
224  scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) {
225    %c0 = arith.constant 1.0 : f32
226    scf.reduce(%c0 : f32) {
227      ^bb0(%lhs: f32, %rhs: f32):
228        scf.reduce.return %lhs : f32
229    }
230  }
231  return
232}
233
234// -----
235
236func.func @parallel_more_results_than_reduces(
237    %arg0 : index, %arg1 : index, %arg2 : index) {
238  // expected-error@+2 {{expects number of results: 1 to be the same as number of reductions: 0}}
239  %zero = arith.constant 1.0 : f32
240  %res = scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) init (%zero) -> f32 {
241  }
242
243  return
244}
245
246// -----
247
248func.func @parallel_more_results_than_initial_values(
249    %arg0 : index, %arg1: index, %arg2: index) {
250  // expected-error@+1 {{'scf.parallel' number of operands and types do not match: got 0 operands and 1 types}}
251  %res = scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) -> f32 {
252    scf.reduce(%arg0 : index) {
253      ^bb0(%lhs: index, %rhs: index):
254        scf.reduce.return %lhs : index
255    }
256  }
257}
258
259// -----
260
261func.func @parallel_different_types_of_results_and_reduces(
262    %arg0 : index, %arg1: index, %arg2: index) {
263  %zero = arith.constant 0.0 : f32
264  %res = scf.parallel (%i0) = (%arg0) to (%arg1)
265                                       step (%arg2) init (%zero) -> f32 {
266    // expected-error@+1 {{expects type of 0-th reduction operand: 'index' to be the same as the 0-th result type: 'f32'}}
267    scf.reduce(%arg0 : index) {
268      ^bb0(%lhs: index, %rhs: index):
269        scf.reduce.return %lhs : index
270    }
271  }
272  return
273}
274
275// -----
276
277func.func @top_level_reduce(%arg0 : f32) {
278  // expected-error@+1 {{expects parent op 'scf.parallel'}}
279  scf.reduce(%arg0 : f32) {
280    ^bb0(%lhs : f32, %rhs : f32):
281      scf.reduce.return %lhs : f32
282  }
283  return
284}
285
286// -----
287
288func.func @reduce_empty_block(%arg0 : index, %arg1 : f32) {
289  %zero = arith.constant 0.0 : f32
290  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
291                                       step (%arg0) init (%zero) -> f32 {
292    // expected-error@+1 {{empty block: expect at least a terminator}}
293    scf.reduce(%arg1 : f32) {
294      ^bb0(%lhs : f32, %rhs : f32):
295    }
296  }
297  return
298}
299
300// -----
301
302func.func @reduce_too_many_args(%arg0 : index, %arg1 : f32) {
303  %zero = arith.constant 0.0 : f32
304  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
305                                       step (%arg0) init (%zero) -> f32 {
306    // expected-error@+1 {{expected two block arguments with type 'f32' in the 0-th reduction region}}
307    scf.reduce(%arg1 : f32) {
308      ^bb0(%lhs : f32, %rhs : f32, %other : f32):
309        scf.reduce.return %lhs : f32
310    }
311  }
312  return
313}
314
315// -----
316
317func.func @reduce_wrong_args(%arg0 : index, %arg1 : f32) {
318  %zero = arith.constant 0.0 : f32
319  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
320                                       step (%arg0) init (%zero) -> f32 {
321    // expected-error@+1 {{expected two block arguments with type 'f32' in the 0-th reduction region}}
322    scf.reduce(%arg1 : f32) {
323      ^bb0(%lhs : f32, %rhs : i32):
324        scf.reduce.return %lhs : f32
325    }
326  }
327  return
328}
329
330
331// -----
332
333func.func @reduce_wrong_terminator(%arg0 : index, %arg1 : f32) {
334  %zero = arith.constant 0.0 : f32
335  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
336                                       step (%arg0) init (%zero) -> f32 {
337    // expected-error@+1 {{reduction bodies must be terminated with an 'scf.reduce.return' op}}
338    scf.reduce(%arg1 : f32) {
339      ^bb0(%lhs : f32, %rhs : f32):
340        "test.finish" () : () -> ()
341    }
342  }
343  return
344}
345
346// -----
347
348func.func @reduceReturn_wrong_type(%arg0 : index, %arg1: f32) {
349  %zero = arith.constant 0.0 : f32
350  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
351                                       step (%arg0) init (%zero) -> f32 {
352    scf.reduce(%arg1 : f32) {
353      ^bb0(%lhs : f32, %rhs : f32):
354        %c0 = arith.constant 1 : index
355        // expected-error@+1 {{must have type 'f32' (the type of the reduction inputs)}}
356        scf.reduce.return %c0 : index
357    }
358  }
359  return
360}
361
362// -----
363
364func.func @reduceReturn_not_inside_reduce(%arg0 : f32) {
365  "foo.region"() ({
366    // expected-error@+1 {{expects parent op 'scf.reduce'}}
367    scf.reduce.return %arg0 : f32
368  }): () -> ()
369  return
370}
371
372// -----
373
374func.func @std_if_incorrect_yield(%arg0: i1, %arg1: f32)
375{
376  // expected-error@+1 {{region control flow edge from Region #0 to parent results: source has 1 operands, but target successor needs 2}}
377  %x, %y = scf.if %arg0 -> (f32, f32) {
378    %0 = arith.addf %arg1, %arg1 : f32
379    scf.yield %0 : f32
380  } else {
381    %0 = arith.subf %arg1, %arg1 : f32
382    scf.yield %0, %0 : f32, f32
383  }
384  return
385}
386
387// -----
388
389func.func @std_if_missing_else(%arg0: i1, %arg1: f32)
390{
391  // expected-error@+1 {{must have an else block if defining values}}
392  %x = scf.if %arg0 -> (f32) {
393    %0 = arith.addf %arg1, %arg1 : f32
394    scf.yield %0 : f32
395  }
396  return
397}
398
399// -----
400
401func.func @std_for_operands_mismatch(%arg0 : index, %arg1 : index, %arg2 : index) {
402  %s0 = arith.constant 0.0 : f32
403  %t0 = arith.constant 1 : i32
404  // expected-error@+1 {{mismatch in number of loop-carried values and defined values}}
405  %result1:3 = scf.for %i0 = %arg0 to %arg1 step %arg2
406                    iter_args(%si = %s0, %ti = %t0) -> (f32, i32, f32) {
407    %sn = arith.addf %si, %si : f32
408    %tn = arith.addi %ti, %ti : i32
409    scf.yield %sn, %tn, %sn : f32, i32, f32
410  }
411  return
412}
413
414// -----
415
416func.func @std_for_operands_mismatch_2(%arg0 : index, %arg1 : index, %arg2 : index) {
417  %s0 = arith.constant 0.0 : f32
418  %t0 = arith.constant 1 : i32
419  %u0 = arith.constant 1.0 : f32
420  // expected-error@+1 {{mismatch in number of loop-carried values and defined values}}
421  %result1:2 = scf.for %i0 = %arg0 to %arg1 step %arg2
422                    iter_args(%si = %s0, %ti = %t0, %ui = %u0) -> (f32, i32) {
423    %sn = arith.addf %si, %si : f32
424    %tn = arith.addi %ti, %ti : i32
425    %un = arith.subf %ui, %ui : f32
426    scf.yield %sn, %tn, %un : f32, i32, f32
427  }
428  return
429}
430
431// -----
432
433func.func @std_for_operands_mismatch_3(%arg0 : index, %arg1 : index, %arg2 : index) {
434  // expected-note@+1 {{prior use here}}
435  %s0 = arith.constant 0.0 : f32
436  %t0 = arith.constant 1.0 : f32
437  // expected-error@+2 {{expects different type than prior uses: 'i32' vs 'f32'}}
438  %result1:2 = scf.for %i0 = %arg0 to %arg1 step %arg2
439                    iter_args(%si = %s0, %ti = %t0) -> (i32, i32) {
440    %sn = arith.addf %si, %si : i32
441    %tn = arith.addf %ti, %ti : i32
442    scf.yield %sn, %tn : i32, i32
443  }
444  return
445}
446
447// -----
448
449func.func @std_for_operands_mismatch_4(%arg0 : index, %arg1 : index, %arg2 : index) {
450  %s0 = arith.constant 0.0 : f32
451  %t0 = arith.constant 1.0 : f32
452  // expected-error @below {{1-th region iter_arg and 1-th yielded value have different type: 'f32' != 'i32'}}
453  %result1:2 = scf.for %i0 = %arg0 to %arg1 step %arg2
454                    iter_args(%si = %s0, %ti = %t0) -> (f32, f32) {
455    %sn = arith.addf %si, %si : f32
456    %ic = arith.constant 1 : i32
457    scf.yield %sn, %ic : f32, i32
458  }
459  return
460}
461
462// -----
463
464func.func @parallel_invalid_yield(
465    %arg0: index, %arg1: index, %arg2: index) {
466  // expected-error@below {{expects body to terminate with 'scf.reduce'}}
467  scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) {
468    %c0 = arith.constant 1.0 : f32
469    // expected-note@below {{terminator here}}
470    scf.yield %c0 : f32
471  }
472  return
473}
474
475// -----
476
477func.func @yield_invalid_parent_op() {
478  "my.op"() ({
479   // expected-error@+1 {{'scf.yield' op expects parent op to be one of 'scf.execute_region, scf.for, scf.if, scf.index_switch, scf.while'}}
480   scf.yield
481  }) : () -> ()
482  return
483}
484
485// -----
486
487func.func @while_parser_type_mismatch() {
488  %true = arith.constant true
489  // expected-error@+1 {{expected as many input types as operands (expected 0 got 1)}}
490  scf.while : (i32) -> () {
491    scf.condition(%true)
492  } do {
493    scf.yield
494  }
495}
496
497// -----
498
499func.func @while_bad_terminator() {
500  // expected-error@+1 {{expects the 'before' region to terminate with 'scf.condition'}}
501  scf.while : () -> () {
502    // expected-note@+1 {{terminator here}}
503    "some.other_terminator"() : () -> ()
504  } do {
505    scf.yield
506  }
507}
508
509// -----
510
511func.func @while_empty_region() {
512  // expected-error@+1 {{'scf.while' op region #0 ('before') failed to verify constraint: region with 1 blocks}}
513  scf.while : () -> () {
514  } do {
515  }
516}
517
518// -----
519
520func.func @while_empty_block() {
521  // expected-error @below {{expects a non-empty block}}
522  scf.while : () -> () {
523  ^bb0:
524  } do {
525  ^bb0:
526  }
527}
528
529// -----
530
531func.func @while_invalid_terminator() {
532  // expected-error @below {{expects the 'before' region to terminate with 'scf.condition'}}
533  scf.while : () -> () {
534  ^bb0:
535    // expected-note @below{{terminator here}}
536    "test.foo"() : () -> ()
537  } do {
538  ^bb0:
539    "test.bar"() : () -> ()
540  }
541}
542
543// -----
544
545func.func @while_cross_region_type_mismatch() {
546  %true = arith.constant true
547  // expected-error@+1 {{'scf.while' op  region control flow edge from Region #0 to Region #1: source has 0 operands, but target successor needs 1}}
548  scf.while : () -> () {
549    scf.condition(%true)
550  } do {
551  ^bb0(%arg0: i32):
552    scf.yield
553  }
554}
555
556// -----
557
558func.func @while_cross_region_type_mismatch() {
559  %true = arith.constant true
560  // expected-error@+1 {{'scf.while' op  along control flow edge from Region #0 to Region #1: source type #0 'i1' should match input type #0 'i32'}}
561  %0 = scf.while : () -> (i1) {
562    scf.condition(%true) %true : i1
563  } do {
564  ^bb0(%arg0: i32):
565    scf.yield
566  }
567}
568
569// -----
570
571func.func @while_result_type_mismatch() {
572  %true = arith.constant true
573  // expected-error@+1 {{'scf.while' op  region control flow edge from Region #0 to parent results: source has 1 operands, but target successor needs 0}}
574  scf.while : () -> () {
575    scf.condition(%true) %true : i1
576  } do {
577  ^bb0(%arg0: i1):
578    scf.yield
579  }
580}
581
582// -----
583
584func.func @while_bad_terminator() {
585  %true = arith.constant true
586  // expected-error@+1 {{expects the 'after' region to terminate with 'scf.yield'}}
587  scf.while : () -> () {
588    scf.condition(%true)
589  } do {
590    // expected-note@+1 {{terminator here}}
591    "some.other_terminator"() : () -> ()
592  }
593}
594
595// -----
596
597func.func @execute_region() {
598  // expected-error @+1 {{region cannot have any arguments}}
599  "scf.execute_region"() ({
600  ^bb0(%i : i32):
601    scf.yield
602  }) : () -> ()
603  return
604}
605
606// -----
607
608func.func @wrong_num_results(%in: tensor<100xf32>, %out: tensor<100xf32>) {
609  %c1 = arith.constant 1 : index
610  %num_threads = arith.constant 100 : index
611
612  // expected-error@+1 {{number of operands and types do not match: got 1 operands and 2 types}}
613  %result:2 = scf.forall (%thread_idx) in (%num_threads) shared_outs(%o = %out) -> (tensor<100xf32>, tensor<100xf32>) {
614      %1 = tensor.extract_slice %in[%thread_idx][1][1] : tensor<100xf32> to tensor<1xf32>
615      scf.forall.in_parallel {
616        tensor.parallel_insert_slice %1 into %o[%thread_idx][1][1] :
617          tensor<1xf32> into tensor<100xf32>
618      }
619  }
620  return
621}
622
623// -----
624
625func.func @invalid_insert_dest(%in: tensor<100xf32>, %out: tensor<100xf32>) {
626  %c1 = arith.constant 1 : index
627  %num_threads = arith.constant 100 : index
628
629  %result = scf.forall (%thread_idx) in (%num_threads) shared_outs(%o = %out) -> (tensor<100xf32>) {
630      %1 = tensor.extract_slice %in[%thread_idx][1][1] : tensor<100xf32> to tensor<1xf32>
631      scf.forall.in_parallel {
632        // expected-error @+1 {{may only insert into an output block argument}}
633        tensor.parallel_insert_slice %1 into %out[%thread_idx][1][1] :
634          tensor<1xf32> into tensor<100xf32>
635      }
636  }
637  return
638}
639
640// -----
641
642func.func @wrong_terminator_op(%in: tensor<100xf32>, %out: tensor<100xf32>) {
643  %c1 = arith.constant 1 : index
644  %num_threads = arith.constant 100 : index
645
646  %result = scf.forall (%thread_idx) in (%num_threads) shared_outs(%o = %out) -> (tensor<100xf32>) {
647      %1 = tensor.extract_slice %in[%thread_idx][1][1] : tensor<100xf32> to tensor<1xf32>
648      // expected-error @+1 {{expected only tensor.parallel_insert_slice ops}}
649      scf.forall.in_parallel {
650        tensor.parallel_insert_slice %1 into %o[%thread_idx][1][1] :
651          tensor<1xf32> into tensor<100xf32>
652        %0 = arith.constant 1: index
653      }
654  }
655  return
656}
657
658// -----
659
660func.func @mismatched_mapping(%x: memref<2 x 32 x f32>, %y: memref<2 x 32 x f32>, %t: memref<32 x f32>, %alpha : f32, %stream : !gpu.async.token) -> memref<2 x 32 x f32> {
661  %one = arith.constant 1 : index
662  %c65535 = arith.constant 65535 : index
663  // expected-error @below {{'scf.forall' op mapping attribute size must match op rank}}
664  scf.forall (%i, %j) in (%c65535, %c65535) {
665      %4 = memref.load %x[%i, %j] : memref<2 x 32 x f32>
666      %5 = memref.load %y[%i, %j] : memref<2 x 32 x f32>
667      %6 = math.fma %alpha, %4, %5 : f32
668      memref.store %6, %y[%i, %j] : memref<2 x 32 x f32>
669  }  { mapping = [#gpu.block<x>, #gpu.block<y>, #gpu.block<z>] }
670  return %y : memref<2 x 32 x f32>
671}
672
673// -----
674
675func.func @switch_wrong_case_count(%arg0: index) {
676  // expected-error @below {{'scf.index_switch' op has 0 case regions but 1 case values}}
677  "scf.index_switch"(%arg0) ({
678    scf.yield
679  }) {cases = array<i64: 1>} : (index) -> ()
680  return
681}
682
683// -----
684
685func.func @switch_duplicate_case(%arg0: index) {
686  // expected-error @below {{'scf.index_switch' op has duplicate case value: 0}}
687  scf.index_switch %arg0
688  case 0 {
689    scf.yield
690  }
691  case 0 {
692    scf.yield
693  }
694  default {
695    scf.yield
696  }
697  return
698}
699
700// -----
701
702func.func @switch_wrong_types(%arg0: index) {
703  // expected-error @below {{'scf.index_switch' op expected each region to return 0 values, but default region returns 1}}
704  scf.index_switch %arg0
705  default {
706    // expected-note @below {{see yield operation here}}
707    scf.yield %arg0 : index
708  }
709  return
710}
711
712// -----
713
714func.func @switch_wrong_types(%arg0: index, %arg1: i32) {
715  // expected-error @below {{'scf.index_switch' op expected result #0 of each region to be 'index'}}
716  scf.index_switch %arg0 -> index
717  case 0 {
718    // expected-note @below {{case region #0 returns 'i32' here}}
719    scf.yield %arg1 : i32
720  }
721  default {
722    scf.yield %arg0 : index
723  }
724  return
725}
726
727// -----
728
729func.func @switch_missing_terminator(%arg0: index, %arg1: i32) {
730  // expected-error @below {{'scf.index_switch' op expected region to end with scf.yield, but got func.return}}
731  "scf.index_switch"(%arg0) ({
732    "scf.yield"() : () -> ()
733  }, {
734    return
735  }) {cases = array<i64: 1>} : (index) -> ()
736}
737
738// -----
739
740func.func @parallel_missing_terminator(%0 : index) {
741  // expected-error @below {{expects body to terminate with 'scf.reduce'}}
742  "scf.parallel"(%0, %0, %0) ({
743  ^bb0(%arg1: index):
744    // expected-note @below {{terminator here}}
745    %2 = "arith.constant"() {value = 1.000000e+00 : f32} : () -> f32
746  }) {operandSegmentSizes = array<i32: 1, 1, 1, 0>} : (index, index, index) -> ()
747  return
748}
749
750