• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -verify-diagnostics
2
3func @loop_for_lb(%arg0: f32, %arg1: index) {
4  // expected-error@+1 {{operand #0 must be index}}
5  "scf.for"(%arg0, %arg1, %arg1) ({}) : (f32, index, index) -> ()
6  return
7}
8
9// -----
10
11func @loop_for_ub(%arg0: f32, %arg1: index) {
12  // expected-error@+1 {{operand #1 must be index}}
13  "scf.for"(%arg1, %arg0, %arg1) ({}) : (index, f32, index) -> ()
14  return
15}
16
17// -----
18
19func @loop_for_step(%arg0: f32, %arg1: index) {
20  // expected-error@+1 {{operand #2 must be index}}
21  "scf.for"(%arg1, %arg1, %arg0) ({}) : (index, index, f32) -> ()
22  return
23}
24
25// -----
26
27func @loop_for_step_positive(%arg0: index) {
28  // expected-error@+2 {{constant step operand must be positive}}
29  %c0 = constant 0 : index
30  "scf.for"(%arg0, %arg0, %c0) ({
31    ^bb0(%arg1: index):
32      scf.yield
33  }) : (index, index, index) -> ()
34  return
35}
36
37// -----
38
39func @loop_for_one_region(%arg0: index) {
40  // expected-error@+1 {{requires one region}}
41  "scf.for"(%arg0, %arg0, %arg0) (
42    {scf.yield},
43    {scf.yield}
44  ) : (index, index, index) -> ()
45  return
46}
47
48// -----
49
50func @loop_for_single_block(%arg0: index) {
51  // expected-error@+1 {{expects region #0 to have 0 or 1 blocks}}
52  "scf.for"(%arg0, %arg0, %arg0) (
53    {
54    ^bb1:
55      scf.yield
56    ^bb2:
57      scf.yield
58    }
59  ) : (index, index, index) -> ()
60  return
61}
62
63// -----
64
65func @loop_for_single_index_argument(%arg0: index) {
66  // expected-error@+1 {{op expected body first argument to be an index argument for the induction variable}}
67  "scf.for"(%arg0, %arg0, %arg0) (
68    {
69    ^bb0(%i0 : f32):
70      scf.yield
71    }
72  ) : (index, index, index) -> ()
73  return
74}
75
76// -----
77
78func @loop_if_not_i1(%arg0: index) {
79  // expected-error@+1 {{operand #0 must be 1-bit signless integer}}
80  "scf.if"(%arg0) ({}, {}) : (index) -> ()
81  return
82}
83
84// -----
85
86func @loop_if_more_than_2_regions(%arg0: i1) {
87  // expected-error@+1 {{expected 2 regions}}
88  "scf.if"(%arg0) ({}, {}, {}): (i1) -> ()
89  return
90}
91
92// -----
93
94func @loop_if_not_one_block_per_region(%arg0: i1) {
95  // expected-error@+1 {{expects region #0 to have 0 or 1 blocks}}
96  "scf.if"(%arg0) ({
97    ^bb0:
98      scf.yield
99    ^bb1:
100      scf.yield
101  }, {}): (i1) -> ()
102  return
103}
104
105// -----
106
107func @loop_if_illegal_block_argument(%arg0: i1) {
108  // expected-error@+1 {{region #0 should have no arguments}}
109  "scf.if"(%arg0) ({
110    ^bb0(%0 : index):
111      scf.yield
112  }, {}): (i1) -> ()
113  return
114}
115
116// -----
117
118func @parallel_arguments_different_tuple_size(
119    %arg0: index, %arg1: index, %arg2: index) {
120  // expected-error@+1 {{custom op 'scf.parallel' expected 1 operands}}
121  scf.parallel (%i0) = (%arg0) to (%arg1, %arg2) step () {
122  }
123  return
124}
125
126// -----
127
128func @parallel_body_arguments_wrong_type(
129    %arg0: index, %arg1: index, %arg2: index) {
130  // expected-error@+1 {{'scf.parallel' op expects arguments for the induction variable to be of index type}}
131  "scf.parallel"(%arg0, %arg1, %arg2) ({
132    ^bb0(%i0: f32):
133      scf.yield
134  }) {operand_segment_sizes = dense<[1, 1, 1, 0]>: vector<4xi32>}: (index, index, index) -> ()
135  return
136}
137
138// -----
139
140func @parallel_body_wrong_number_of_arguments(
141    %arg0: index, %arg1: index, %arg2: index) {
142  // expected-error@+1 {{'scf.parallel' op expects the same number of induction variables: 2 as bound and step values: 1}}
143  "scf.parallel"(%arg0, %arg1, %arg2) ({
144    ^bb0(%i0: index, %i1: index):
145      scf.yield
146  }) {operand_segment_sizes = dense<[1, 1, 1, 0]>: vector<4xi32>}: (index, index, index) -> ()
147  return
148}
149
150// -----
151
152func @parallel_no_tuple_elements() {
153  // expected-error@+1 {{'scf.parallel' op needs at least one tuple element for lowerBound, upperBound and step}}
154  scf.parallel () = () to () step () {
155  }
156  return
157}
158
159// -----
160
161func @parallel_step_not_positive(
162    %arg0: index, %arg1: index, %arg2: index, %arg3: index) {
163  // expected-error@+3 {{constant step operand must be positive}}
164  %c0 = constant 1 : index
165  %c1 = constant 0 : index
166  scf.parallel (%i0, %i1) = (%arg0, %arg1) to (%arg2, %arg3) step (%c0, %c1) {
167  }
168  return
169}
170
171// -----
172
173func @parallel_fewer_results_than_reduces(
174    %arg0 : index, %arg1: index, %arg2: index) {
175  // expected-error@+1 {{expects number of results: 0 to be the same as number of reductions: 1}}
176  scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) {
177    %c0 = constant 1.0 : f32
178    scf.reduce(%c0) : f32 {
179      ^bb0(%lhs: f32, %rhs: f32):
180        scf.reduce.return %lhs : f32
181    }
182  }
183  return
184}
185
186// -----
187
188func @parallel_more_results_than_reduces(
189    %arg0 : index, %arg1 : index, %arg2 : index) {
190  // expected-error@+2 {{expects number of results: 1 to be the same as number of reductions: 0}}
191  %zero = constant 1.0 : f32
192  %res = scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) init (%zero) -> f32 {
193  }
194
195  return
196}
197
198// -----
199
200func @parallel_more_results_than_initial_values(
201    %arg0 : index, %arg1: index, %arg2: index) {
202  // expected-error@+1 {{expects number of results: 1 to be the same as number of initial values: 0}}
203  %res = scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) -> f32 {
204    scf.reduce(%arg0) : index {
205      ^bb0(%lhs: index, %rhs: index):
206        scf.reduce.return %lhs : index
207    }
208  }
209}
210
211// -----
212
213func @parallel_different_types_of_results_and_reduces(
214    %arg0 : index, %arg1: index, %arg2: index) {
215  %zero = constant 0.0 : f32
216  %res = scf.parallel (%i0) = (%arg0) to (%arg1)
217                                       step (%arg2) init (%zero) -> f32 {
218    // expected-error@+1 {{expects type of reduce: 'index' to be the same as result type: 'f32'}}
219    scf.reduce(%arg0) : index {
220      ^bb0(%lhs: index, %rhs: index):
221        scf.reduce.return %lhs : index
222    }
223  }
224  return
225}
226
227// -----
228
229func @top_level_reduce(%arg0 : f32) {
230  // expected-error@+1 {{expects parent op 'scf.parallel'}}
231  scf.reduce(%arg0) : f32 {
232    ^bb0(%lhs : f32, %rhs : f32):
233      scf.reduce.return %lhs : f32
234  }
235  return
236}
237
238// -----
239
240func @reduce_empty_block(%arg0 : index, %arg1 : f32) {
241  %zero = constant 0.0 : f32
242  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
243                                       step (%arg0) init (%zero) -> f32 {
244    // expected-error@+1 {{the block inside reduce should not be empty}}
245    scf.reduce(%arg1) : f32 {
246      ^bb0(%lhs : f32, %rhs : f32):
247    }
248  }
249  return
250}
251
252// -----
253
254func @reduce_too_many_args(%arg0 : index, %arg1 : f32) {
255  %zero = constant 0.0 : f32
256  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
257                                       step (%arg0) init (%zero) -> f32 {
258    // expected-error@+1 {{expects two arguments to reduce block of type 'f32'}}
259    scf.reduce(%arg1) : f32 {
260      ^bb0(%lhs : f32, %rhs : f32, %other : f32):
261        scf.reduce.return %lhs : f32
262    }
263  }
264  return
265}
266
267// -----
268
269func @reduce_wrong_args(%arg0 : index, %arg1 : f32) {
270  %zero = constant 0.0 : f32
271  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
272                                       step (%arg0) init (%zero) -> f32 {
273    // expected-error@+1 {{expects two arguments to reduce block of type 'f32'}}
274    scf.reduce(%arg1) : f32 {
275      ^bb0(%lhs : f32, %rhs : i32):
276        scf.reduce.return %lhs : f32
277    }
278  }
279  return
280}
281
282
283// -----
284
285func @reduce_wrong_terminator(%arg0 : index, %arg1 : f32) {
286  %zero = constant 0.0 : f32
287  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
288                                       step (%arg0) init (%zero) -> f32 {
289    // expected-error@+1 {{the block inside reduce should be terminated with a 'scf.reduce.return' op}}
290    scf.reduce(%arg1) : f32 {
291      ^bb0(%lhs : f32, %rhs : f32):
292        scf.yield
293    }
294  }
295  return
296}
297
298// -----
299
300func @reduceReturn_wrong_type(%arg0 : index, %arg1: f32) {
301  %zero = constant 0.0 : f32
302  %res = scf.parallel (%i0) = (%arg0) to (%arg0)
303                                       step (%arg0) init (%zero) -> f32 {
304    scf.reduce(%arg1) : f32 {
305      ^bb0(%lhs : f32, %rhs : f32):
306        %c0 = constant 1 : index
307        // expected-error@+1 {{needs to have type 'f32' (the type of the enclosing ReduceOp)}}
308        scf.reduce.return %c0 : index
309    }
310  }
311  return
312}
313
314// -----
315
316func @reduceReturn_not_inside_reduce(%arg0 : f32) {
317  "foo.region"() ({
318    // expected-error@+1 {{expects parent op 'scf.reduce'}}
319    scf.reduce.return %arg0 : f32
320  }): () -> ()
321  return
322}
323
324// -----
325
326func @std_if_incorrect_yield(%arg0: i1, %arg1: f32)
327{
328  // expected-error@+1 {{region control flow edge from Region #0 to parent results: source has 1 operands, but target successor needs 2}}
329  %x, %y = scf.if %arg0 -> (f32, f32) {
330    %0 = addf %arg1, %arg1 : f32
331    scf.yield %0 : f32
332  } else {
333    %0 = subf %arg1, %arg1 : f32
334    scf.yield %0, %0 : f32, f32
335  }
336  return
337}
338
339// -----
340
341func @std_if_missing_else(%arg0: i1, %arg1: f32)
342{
343  // expected-error@+1 {{must have an else block if defining values}}
344  %x = scf.if %arg0 -> (f32) {
345    %0 = addf %arg1, %arg1 : f32
346    scf.yield %0 : f32
347  }
348  return
349}
350
351// -----
352
353func @std_for_operands_mismatch(%arg0 : index, %arg1 : index, %arg2 : index) {
354  %s0 = constant 0.0 : f32
355  %t0 = constant 1 : i32
356  // expected-error@+1 {{mismatch in number of loop-carried values and defined values}}
357  %result1:3 = scf.for %i0 = %arg0 to %arg1 step %arg2
358                    iter_args(%si = %s0, %ti = %t0) -> (f32, i32, f32) {
359    %sn = addf %si, %si : f32
360    %tn = addi %ti, %ti : i32
361    scf.yield %sn, %tn, %sn : f32, i32, f32
362  }
363  return
364}
365
366// -----
367
368func @std_for_operands_mismatch_2(%arg0 : index, %arg1 : index, %arg2 : index) {
369  %s0 = constant 0.0 : f32
370  %t0 = constant 1 : i32
371  %u0 = constant 1.0 : f32
372  // expected-error@+1 {{mismatch in number of loop-carried values and defined values}}
373  %result1:2 = scf.for %i0 = %arg0 to %arg1 step %arg2
374                    iter_args(%si = %s0, %ti = %t0, %ui = %u0) -> (f32, i32) {
375    %sn = addf %si, %si : f32
376    %tn = addi %ti, %ti : i32
377    %un = subf %ui, %ui : f32
378    scf.yield %sn, %tn, %un : f32, i32, f32
379  }
380  return
381}
382
383// -----
384
385func @std_for_operands_mismatch_3(%arg0 : index, %arg1 : index, %arg2 : index) {
386  // expected-note@+1 {{prior use here}}
387  %s0 = constant 0.0 : f32
388  %t0 = constant 1.0 : f32
389  // expected-error@+2 {{expects different type than prior uses: 'i32' vs 'f32'}}
390  %result1:2 = scf.for %i0 = %arg0 to %arg1 step %arg2
391                    iter_args(%si = %s0, %ti = %t0) -> (i32, i32) {
392    %sn = addf %si, %si : i32
393    %tn = addf %ti, %ti : i32
394    scf.yield %sn, %tn : i32, i32
395  }
396  return
397}
398
399// -----
400
401func @std_for_operands_mismatch_4(%arg0 : index, %arg1 : index, %arg2 : index) {
402  %s0 = constant 0.0 : f32
403  %t0 = constant 1.0 : f32
404  // expected-error @+1 {{along control flow edge from Region #0 to Region #0: source type #1 'i32' should match input type #1 'f32'}}
405  %result1:2 = scf.for %i0 = %arg0 to %arg1 step %arg2
406                    iter_args(%si = %s0, %ti = %t0) -> (f32, f32) {
407    %sn = addf %si, %si : f32
408    %ic = constant 1 : i32
409    scf.yield %sn, %ic : f32, i32
410  }
411  return
412}
413
414
415// -----
416
417func @parallel_invalid_yield(
418    %arg0: index, %arg1: index, %arg2: index) {
419  scf.parallel (%i0) = (%arg0) to (%arg1) step (%arg2) {
420    %c0 = constant 1.0 : f32
421    // expected-error@+1 {{'scf.yield' op not allowed to have operands inside 'scf.parallel'}}
422    scf.yield %c0 : f32
423  }
424  return
425}
426
427// -----
428
429func @yield_invalid_parent_op() {
430  "my.op"() ({
431   // expected-error@+1 {{'scf.yield' op expects parent op to be one of 'scf.if, scf.for, scf.parallel, scf.while'}}
432   scf.yield
433  }) : () -> ()
434  return
435}
436
437// -----
438
439func @while_parser_type_mismatch() {
440  %true = constant true
441  // expected-error@+1 {{expected as many input types as operands (expected 0 got 1)}}
442  scf.while : (i32) -> () {
443    scf.condition(%true)
444  } do {
445    scf.yield
446  }
447}
448
449// -----
450
451func @while_bad_terminator() {
452  // expected-error@+1 {{expects the 'before' region to terminate with 'scf.condition'}}
453  scf.while : () -> () {
454    // expected-note@+1 {{terminator here}}
455    "some.other_terminator"() : () -> ()
456  } do {
457    scf.yield
458  }
459}
460
461// -----
462
463func @while_cross_region_type_mismatch() {
464  %true = constant true
465  // expected-error@+1 {{expects the same number of trailing operands of the 'before' block terminator and 'after' region arguments}}
466  scf.while : () -> () {
467    scf.condition(%true)
468  } do {
469  ^bb0(%arg0: i32):
470    scf.yield
471  }
472}
473
474// -----
475
476func @while_cross_region_type_mismatch() {
477  %true = constant true
478  // expected-error@+2 {{expects the same types for trailing operands of the 'before' block terminator and 'after' region arguments}}
479  // expected-note@+1 {{for argument 0, found 'i1' and 'i32}}
480  scf.while : () -> () {
481    scf.condition(%true) %true : i1
482  } do {
483  ^bb0(%arg0: i32):
484    scf.yield
485  }
486}
487
488// -----
489
490func @while_result_type_mismatch() {
491  %true = constant true
492  // expected-error@+1 {{expects the same number of trailing operands of the 'before' block terminator and op results}}
493  scf.while : () -> () {
494    scf.condition(%true) %true : i1
495  } do {
496  ^bb0(%arg0: i1):
497    scf.yield
498  }
499}
500
501// -----
502
503func @while_bad_terminator() {
504  %true = constant true
505  // expected-error@+1 {{expects the 'after' region to terminate with 'scf.yield'}}
506  scf.while : () -> () {
507    scf.condition(%true)
508  } do {
509    // expected-note@+1 {{terminator here}}
510    "some.other_terminator"() : () -> ()
511  }
512}
513