xref: /llvm-project/mlir/test/Dialect/OpenMP/invalid.mlir (revision afcbcae668f1d8061974247f2828190173aef742)
1// RUN: mlir-opt -split-input-file -verify-diagnostics %s
2
3func.func @unknown_clause() {
4  // expected-error@+1 {{expected '{' to begin a region}}
5  omp.parallel invalid {
6  }
7
8  return
9}
10
11// -----
12
13func.func @if_once(%n : i1) {
14  // expected-error@+1 {{`if` clause can appear at most once in the expansion of the oilist directive}}
15  omp.parallel if(%n) if(%n) {
16  }
17
18  return
19}
20
21// -----
22
23func.func @num_threads_once(%n : si32) {
24  // expected-error@+1 {{`num_threads` clause can appear at most once in the expansion of the oilist directive}}
25  omp.parallel num_threads(%n : si32) num_threads(%n : si32) {
26  }
27
28  return
29}
30
31// -----
32
33func.func @nowait_not_allowed(%n : memref<i32>) {
34  // expected-error@+1 {{expected '{' to begin a region}}
35  omp.parallel nowait {}
36  return
37}
38
39// -----
40
41func.func @linear_not_allowed(%data_var : memref<i32>, %linear_var : i32) {
42  // expected-error@+1 {{expected '{' to begin a region}}
43  omp.parallel linear(%data_var = %linear_var : memref<i32>)  {}
44  return
45}
46
47// -----
48
49func.func @schedule_not_allowed() {
50  // expected-error@+1 {{expected '{' to begin a region}}
51  omp.parallel schedule(static) {}
52  return
53}
54
55// -----
56
57func.func @collapse_not_allowed() {
58  // expected-error@+1 {{expected '{' to begin a region}}
59  omp.parallel collapse(3) {}
60  return
61}
62
63// -----
64
65func.func @order_not_allowed() {
66  // expected-error@+1 {{expected '{' to begin a region}}
67  omp.parallel order(concurrent) {}
68  return
69}
70
71// -----
72
73func.func @ordered_not_allowed() {
74  // expected-error@+1 {{expected '{' to begin a region}}
75  omp.parallel ordered(2) {}
76}
77
78// -----
79
80func.func @proc_bind_once() {
81  // expected-error@+1 {{`proc_bind` clause can appear at most once in the expansion of the oilist directive}}
82  omp.parallel proc_bind(close) proc_bind(spread) {
83  }
84
85  return
86}
87
88// -----
89
90func.func @invalid_parent(%lb : index, %ub : index, %step : index) {
91  // expected-error@+1 {{op expects parent op to be a loop wrapper}}
92  omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
93    omp.yield
94  }
95}
96
97// -----
98
99func.func @type_mismatch(%lb : index, %ub : index, %step : index) {
100  omp.wsloop {
101    // expected-error@+1 {{range argument type does not match corresponding IV type}}
102    "omp.loop_nest" (%lb, %ub, %step) ({
103    ^bb0(%iv2: i32):
104      omp.yield
105    }) : (index, index, index) -> ()
106  }
107}
108
109// -----
110
111func.func @iv_number_mismatch(%lb : index, %ub : index, %step : index) {
112  omp.wsloop {
113    // expected-error@+1 {{number of range arguments and IVs do not match}}
114    "omp.loop_nest" (%lb, %ub, %step) ({
115    ^bb0(%iv1 : index, %iv2 : index):
116      omp.yield
117    }) : (index, index, index) -> ()
118  }
119}
120
121// -----
122
123func.func @no_wrapper(%lb : index, %ub : index, %step : index) {
124  // expected-error @below {{op loop wrapper does not contain exactly one nested op}}
125  omp.wsloop {
126    %0 = arith.constant 0 : i32
127    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
128      omp.yield
129    }
130  }
131}
132
133// -----
134
135func.func @invalid_nested_wrapper(%lb : index, %ub : index, %step : index) {
136  // expected-error @below {{only supported nested wrapper is 'omp.simd'}}
137  omp.wsloop {
138    omp.distribute {
139      omp.simd {
140        omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
141          omp.yield
142        }
143      } {omp.composite}
144    } {omp.composite}
145  } {omp.composite}
146}
147
148// -----
149
150func.func @no_loops(%lb : index, %ub : index, %step : index) {
151  omp.wsloop {
152    // expected-error@+1 {{op must represent at least one loop}}
153    "omp.loop_nest" () ({
154    ^bb0():
155      omp.yield
156    }) : () -> ()
157  }
158}
159
160// -----
161
162func.func @inclusive_not_a_clause(%lb : index, %ub : index, %step : index) {
163  // expected-error @below {{expected '{'}}
164  omp.wsloop nowait inclusive {
165    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
166      omp.yield
167    }
168  }
169}
170
171// -----
172
173func.func @order_value(%lb : index, %ub : index, %step : index) {
174  // expected-error @below {{invalid clause value: 'default'}}
175  omp.wsloop order(default) {
176    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
177      omp.yield
178    }
179  }
180}
181
182// -----
183func.func @reproducible_order(%lb : index, %ub : index, %step : index) {
184  // expected-error @below {{invalid clause value: 'default'}}
185  omp.wsloop order(reproducible:default) {
186    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
187      omp.yield
188    }
189  }
190}
191// -----
192func.func @unconstrained_order(%lb : index, %ub : index, %step : index) {
193  // expected-error @below {{invalid clause value: 'default'}}
194  omp.wsloop order(unconstrained:default) {
195    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
196      omp.yield
197    }
198  }
199}
200// -----
201
202func.func @if_not_allowed(%lb : index, %ub : index, %step : index, %bool_var : i1) {
203  // expected-error @below {{expected '{'}}
204  omp.wsloop if(%bool_var) {
205    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
206      omp.yield
207    }
208  }
209}
210
211// -----
212
213func.func @num_threads_not_allowed(%lb : index, %ub : index, %step : index, %int_var : i32) {
214  // expected-error @below {{expected '{'}}
215  omp.wsloop num_threads(%int_var: i32) {
216    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
217      omp.yield
218    }
219  }
220}
221
222// -----
223
224func.func @proc_bind_not_allowed(%lb : index, %ub : index, %step : index) {
225  // expected-error @below {{expected '{'}}
226  omp.wsloop proc_bind(close) {
227    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
228      omp.yield
229    }
230  }
231}
232
233// -----
234
235llvm.func @test_omp_wsloop_dynamic_bad_modifier(%lb : i64, %ub : i64, %step : i64) -> () {
236  // expected-error @+1 {{unknown modifier type: ginandtonic}}
237  omp.wsloop schedule(dynamic, ginandtonic) {
238    omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
239      omp.yield
240    }
241  }
242  llvm.return
243}
244
245// -----
246
247llvm.func @test_omp_wsloop_dynamic_many_modifier(%lb : i64, %ub : i64, %step : i64) -> () {
248  // expected-error @+1 {{unexpected modifier(s)}}
249  omp.wsloop schedule(dynamic, monotonic, monotonic, monotonic) {
250    omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
251      omp.yield
252    }
253  }
254  llvm.return
255}
256
257// -----
258
259llvm.func @test_omp_wsloop_dynamic_wrong_modifier(%lb : i64, %ub : i64, %step : i64) -> () {
260  // expected-error @+1 {{incorrect modifier order}}
261  omp.wsloop schedule(dynamic, simd, monotonic) {
262    omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
263      omp.yield
264    }
265  }
266  llvm.return
267}
268
269// -----
270
271llvm.func @test_omp_wsloop_dynamic_wrong_modifier2(%lb : i64, %ub : i64, %step : i64) -> () {
272  // expected-error @+1 {{incorrect modifier order}}
273  omp.wsloop schedule(dynamic, monotonic, monotonic) {
274    omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
275      omp.yield
276    }
277  }
278  llvm.return
279}
280
281// -----
282
283llvm.func @test_omp_wsloop_dynamic_wrong_modifier3(%lb : i64, %ub : i64, %step : i64) -> () {
284  // expected-error @+1 {{incorrect modifier order}}
285  omp.wsloop schedule(dynamic, simd, simd) {
286    omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
287      omp.yield
288    }
289  }
290  llvm.return
291}
292
293// -----
294
295func.func @omp_simd() -> () {
296  // expected-error @below {{op loop wrapper does not contain exactly one nested op}}
297  omp.simd {}
298  return
299}
300
301// -----
302
303func.func @omp_simd_nested_wrapper(%lb : index, %ub : index, %step : index) -> () {
304  // expected-error @below {{op must wrap an 'omp.loop_nest' directly}}
305  omp.simd {
306    omp.distribute {
307      omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
308        omp.yield
309      }
310    }
311  }
312  return
313}
314
315// -----
316
317func.func @omp_simd_pretty_aligned(%lb : index, %ub : index, %step : index,
318                                   %data_var : memref<i32>) -> () {
319  //  expected-error @below {{expected '->'}}
320  omp.simd aligned(%data_var : memref<i32>) {
321    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
322      omp.yield
323    }
324  }
325  return
326}
327
328// -----
329
330func.func @omp_simd_aligned_mismatch(%arg0 : index, %arg1 : index,
331                                     %arg2 : index, %arg3 : memref<i32>,
332                                     %arg4 : memref<i32>) -> () {
333  //  expected-error @below {{op expected as many alignment values as aligned variables}}
334  "omp.simd"(%arg3, %arg4) ({
335    omp.loop_nest (%iv) : index = (%arg0) to (%arg1) step (%arg2) {
336      omp.yield
337    }
338  }) {alignments = [128],
339      operandSegmentSizes = array<i32: 2, 0, 0, 0, 0, 0, 0>} : (memref<i32>, memref<i32>) -> ()
340  return
341}
342
343// -----
344
345func.func @omp_simd_aligned_negative(%arg0 : index, %arg1 : index,
346                                     %arg2 : index, %arg3 : memref<i32>,
347                                     %arg4 : memref<i32>) -> () {
348  //  expected-error @below {{op alignment should be greater than 0}}
349  "omp.simd"(%arg3, %arg4) ({
350    omp.loop_nest (%iv) : index = (%arg0) to (%arg1) step (%arg2) {
351      omp.yield
352    }
353  }) {alignments = [-1, 128], operandSegmentSizes = array<i32: 2, 0, 0, 0, 0, 0, 0>} : (memref<i32>, memref<i32>) -> ()
354  return
355}
356
357// -----
358
359func.func @omp_simd_unexpected_alignment(%arg0 : index, %arg1 : index,
360                                         %arg2 : index, %arg3 : memref<i32>,
361                                         %arg4 : memref<i32>) -> () {
362  //  expected-error @below {{unexpected alignment values attribute}}
363  "omp.simd"() ({
364    omp.loop_nest (%iv) : index = (%arg0) to (%arg1) step (%arg2) {
365      omp.yield
366    }
367  }) {alignments = [1, 128]} : () -> ()
368  return
369}
370
371// -----
372
373func.func @omp_simd_aligned_float(%arg0 : index, %arg1 : index,
374                                  %arg2 : index, %arg3 : memref<i32>,
375                                  %arg4 : memref<i32>) -> () {
376  //  expected-error @below {{failed to satisfy constraint: 64-bit integer array attribute}}
377  "omp.simd"(%arg3, %arg4) ({
378    omp.loop_nest (%iv) : index = (%arg0) to (%arg1) step (%arg2) {
379      omp.yield
380    }
381  }) {alignments = [1.5, 128], operandSegmentSizes = array<i32: 2, 0, 0, 0, 0, 0, 0>} : (memref<i32>, memref<i32>) -> ()
382  return
383}
384
385// -----
386
387func.func @omp_simd_aligned_the_same_var(%arg0 : index, %arg1 : index,
388                                         %arg2 : index, %arg3 : memref<i32>,
389                                         %arg4 : memref<i32>) -> () {
390  //  expected-error @below {{aligned variable used more than once}}
391  "omp.simd"(%arg3, %arg3) ({
392    omp.loop_nest (%iv) : index = (%arg0) to (%arg1) step (%arg2) {
393      omp.yield
394    }
395  }) {alignments = [1, 128], operandSegmentSizes = array<i32: 2, 0, 0, 0, 0, 0, 0>} : (memref<i32>, memref<i32>) -> ()
396  return
397}
398
399// -----
400
401func.func @omp_simd_nontemporal_the_same_var(%arg0 : index,  %arg1 : index,
402                                             %arg2 : index,
403                                             %arg3 : memref<i32>) -> () {
404  //  expected-error @below {{nontemporal variable used more than once}}
405  "omp.simd"(%arg3, %arg3) ({
406    omp.loop_nest (%iv) : index = (%arg0) to (%arg1) step (%arg2) {
407      omp.yield
408    }
409  }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 2, 0, 0>} : (memref<i32>, memref<i32>) -> ()
410  return
411}
412
413// -----
414
415func.func @omp_simd_order_value(%lb : index, %ub : index, %step : index) {
416  // expected-error @below {{invalid clause value: 'default'}}
417  omp.simd order(default) {
418    omp.loop_nest (%iv) : index = (%arg0) to (%arg1) step (%arg2) {
419      omp.yield
420    }
421  }
422  return
423}
424
425// -----
426
427func.func @omp_simd_reproducible_order(%lb : index, %ub : index, %step : index) {
428  // expected-error @below {{invalid clause value: 'default'}}
429  omp.simd order(reproducible:default) {
430    omp.loop_nest (%iv) : index = (%arg0) to (%arg1) step (%arg2) {
431      omp.yield
432    }
433  }
434  return
435}
436// -----
437func.func @omp_simd_unconstrained_order(%lb : index, %ub : index, %step : index) {
438  // expected-error @below {{invalid clause value: 'default'}}
439  omp.simd order(unconstrained:default) {
440    omp.loop_nest (%iv) : index = (%arg0) to (%arg1) step (%arg2) {
441      omp.yield
442    }
443  }
444  return
445}
446// -----
447func.func @omp_simd_pretty_simdlen(%lb : index, %ub : index, %step : index) -> () {
448  // expected-error @below {{op attribute 'simdlen' failed to satisfy constraint: 64-bit signless integer attribute whose value is positive}}
449  omp.simd simdlen(0) {
450    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
451      omp.yield
452    }
453  }
454  return
455}
456
457// -----
458
459func.func @omp_simd_pretty_safelen(%lb : index, %ub : index, %step : index) -> () {
460  // expected-error @below {{op attribute 'safelen' failed to satisfy constraint: 64-bit signless integer attribute whose value is positive}}
461  omp.simd safelen(0) {
462    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
463      omp.yield
464    }
465  }
466  return
467}
468
469// -----
470
471func.func @omp_simd_pretty_simdlen_safelen(%lb : index, %ub : index, %step : index) -> () {
472  // expected-error @below {{op simdlen clause and safelen clause are both present, but the simdlen value is not less than or equal to safelen value}}
473  omp.simd simdlen(2) safelen(1) {
474    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
475      omp.yield
476    }
477  }
478  return
479}
480
481// -----
482
483// expected-error @below {{op expects alloc region to yield a value of the reduction type}}
484omp.declare_reduction @add_f32 : f32
485alloc {
486^bb0(%arg: f32):
487// nonsense test code
488  %0 = arith.constant 0.0 : f64
489  omp.yield (%0 : f64)
490}
491init {
492^bb0(%arg0: f32, %arg1: f32):
493  %0 = arith.constant 0.0 : f32
494  omp.yield (%0 : f32)
495}
496combiner {
497^bb1(%arg0: f32, %arg1: f32):
498  %1 = arith.addf %arg0, %arg1 : f32
499  omp.yield (%1 : f32)
500}
501
502// -----
503
504// expected-error @below {{op expects two arguments to the initializer region when an allocation region is used}}
505omp.declare_reduction @add_f32 : f32
506alloc {
507^bb0(%arg: f32):
508// nonsense test code
509  omp.yield (%arg : f32)
510}
511init {
512^bb0(%arg0: f32):
513  %0 = arith.constant 0.0 : f32
514  omp.yield (%0 : f32)
515}
516combiner {
517^bb1(%arg0: f32, %arg1: f32):
518  %1 = arith.addf %arg0, %arg1 : f32
519  omp.yield (%1 : f32)
520}
521
522// -----
523
524// expected-error @below {{op expects one argument to the initializer region when no allocation region is used}}
525omp.declare_reduction @add_f32 : f32
526init {
527^bb0(%arg: f32, %arg2: f32):
528  %0 = arith.constant 0.0 : f32
529  omp.yield (%0 : f32)
530}
531combiner {
532^bb1(%arg0: f32, %arg1: f32):
533  %1 = arith.addf %arg0, %arg1 : f32
534  omp.yield (%1 : f32)
535}
536
537// -----
538
539// expected-error @below {{op expects initializer region argument to match the reduction type}}
540omp.declare_reduction @add_f32 : f64
541init {
542^bb0(%arg: f32):
543  %0 = arith.constant 0.0 : f32
544  omp.yield (%0 : f32)
545}
546combiner {
547^bb1(%arg0: f32, %arg1: f32):
548  %1 = arith.addf %arg0, %arg1 : f32
549  omp.yield (%1 : f32)
550}
551
552// -----
553
554// expected-error @below {{expects initializer region to yield a value of the reduction type}}
555omp.declare_reduction @add_f32 : f32
556init {
557^bb0(%arg: f32):
558  %0 = arith.constant 0.0 : f64
559  omp.yield (%0 : f64)
560}
561combiner {
562^bb1(%arg0: f32, %arg1: f32):
563  %1 = arith.addf %arg0, %arg1 : f32
564  omp.yield (%1 : f32)
565}
566
567// -----
568
569// expected-error @below {{expects reduction region with two arguments of the reduction type}}
570omp.declare_reduction @add_f32 : f32
571init {
572^bb0(%arg: f32):
573  %0 = arith.constant 0.0 : f32
574  omp.yield (%0 : f32)
575}
576combiner {
577^bb1(%arg0: f64, %arg1: f64):
578  %1 = arith.addf %arg0, %arg1 : f64
579  omp.yield (%1 : f64)
580}
581
582// -----
583
584// expected-error @below {{expects reduction region to yield a value of the reduction type}}
585omp.declare_reduction @add_f32 : f32
586init {
587^bb0(%arg: f32):
588  %0 = arith.constant 0.0 : f32
589  omp.yield (%0 : f32)
590}
591combiner {
592^bb1(%arg0: f32, %arg1: f32):
593  %1 = arith.addf %arg0, %arg1 : f32
594  %2 = arith.extf %1 : f32 to f64
595  omp.yield (%2 : f64)
596}
597
598// -----
599
600// expected-error @below {{expects atomic reduction region with two arguments of the same type}}
601omp.declare_reduction @add_f32 : f32
602init {
603^bb0(%arg: f32):
604  %0 = arith.constant 0.0 : f32
605  omp.yield (%0 : f32)
606}
607combiner {
608^bb1(%arg0: f32, %arg1: f32):
609  %1 = arith.addf %arg0, %arg1 : f32
610  omp.yield (%1 : f32)
611}
612atomic {
613^bb2(%arg0: memref<f32>, %arg1: memref<f64>):
614  omp.yield
615}
616
617// -----
618
619// expected-error @below {{expects atomic reduction region arguments to be accumulators containing the reduction type}}
620omp.declare_reduction @add_f32 : f32
621init {
622^bb0(%arg: f32):
623  %0 = arith.constant 0.0 : f32
624  omp.yield (%0 : f32)
625}
626combiner {
627^bb1(%arg0: f32, %arg1: f32):
628  %1 = arith.addf %arg0, %arg1 : f32
629  omp.yield (%1 : f32)
630}
631atomic {
632^bb2(%arg0: memref<f64>, %arg1: memref<f64>):
633  omp.yield
634}
635
636// -----
637
638// expected-error @below {{op expects cleanup region with one argument of the reduction type}}
639omp.declare_reduction @add_f32 : f32
640init {
641^bb0(%arg: f32):
642  %0 = arith.constant 0.0 : f32
643  omp.yield (%0 : f32)
644}
645combiner {
646^bb1(%arg0: f32, %arg1: f32):
647  %1 = arith.addf %arg0, %arg1 : f32
648  omp.yield (%1 : f32)
649}
650cleanup {
651^bb0(%arg: f64):
652  omp.yield
653}
654
655// -----
656
657// expected-error @below {{op region #0 ('allocRegion') failed to verify constraint: region with at most 1 blocks}}
658omp.declare_reduction @alloc_reduction : !llvm.ptr
659alloc {
660^bb0(%arg: !llvm.ptr):
661  %c1 = arith.constant 1 : i32
662  %0 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr
663  cf.br ^bb1(%0: !llvm.ptr)
664^bb1(%ret: !llvm.ptr):
665  omp.yield (%ret : !llvm.ptr)
666}
667init {
668^bb0(%arg: !llvm.ptr):
669  %cst = arith.constant 1.0 : f32
670  llvm.store %cst, %arg : f32, !llvm.ptr
671  omp.yield (%arg : !llvm.ptr)
672}
673combiner {
674^bb1(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
675  %0 = llvm.load %arg0 : !llvm.ptr -> f32
676  %1 = llvm.load %arg1 : !llvm.ptr -> f32
677  %2 = arith.addf %0, %1 : f32
678  llvm.store %2, %arg0 : f32, !llvm.ptr
679  omp.yield (%arg0 : !llvm.ptr)
680}
681
682// -----
683
684func.func @foo(%lb : index, %ub : index, %step : index) {
685  %c1 = arith.constant 1 : i32
686  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
687  %1 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
688
689  // expected-error @below {{expected symbol reference @foo to point to a reduction declaration}}
690  omp.wsloop reduction(@foo %0 -> %prv : !llvm.ptr) {
691    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
692      %2 = arith.constant 2.0 : f32
693      omp.yield
694    }
695  }
696  return
697}
698
699// -----
700
701omp.declare_reduction @add_f32 : f32
702init {
703^bb0(%arg: f32):
704  %0 = arith.constant 0.0 : f32
705  omp.yield (%0 : f32)
706}
707combiner {
708^bb1(%arg0: f32, %arg1: f32):
709  %1 = arith.addf %arg0, %arg1 : f32
710  omp.yield (%1 : f32)
711}
712
713func.func @foo(%lb : index, %ub : index, %step : index) {
714  %c1 = arith.constant 1 : i32
715  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
716
717  // expected-error @below {{accumulator variable used more than once}}
718  omp.wsloop reduction(@add_f32 %0 -> %prv, @add_f32 %0 -> %prv1 : !llvm.ptr, !llvm.ptr) {
719    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
720      %2 = arith.constant 2.0 : f32
721      omp.yield
722    }
723  }
724  return
725}
726
727// -----
728
729omp.declare_reduction @add_f32 : f32
730init {
731^bb0(%arg: f32):
732  %0 = arith.constant 0.0 : f32
733  omp.yield (%0 : f32)
734}
735combiner {
736^bb1(%arg0: f32, %arg1: f32):
737  %1 = arith.addf %arg0, %arg1 : f32
738  omp.yield (%1 : f32)
739}
740atomic {
741^bb2(%arg2: !llvm.ptr, %arg3: !llvm.ptr):
742  %2 = llvm.load %arg3 : !llvm.ptr -> f32
743  llvm.atomicrmw fadd %arg2, %2 monotonic : !llvm.ptr, f32
744  omp.yield
745}
746
747func.func @foo(%lb : index, %ub : index, %step : index, %mem : memref<1xf32>) {
748  %c1 = arith.constant 1 : i32
749
750  // expected-error @below {{expected accumulator ('memref<1xf32>') to be the same type as reduction declaration ('!llvm.ptr')}}
751  omp.wsloop reduction(@add_f32 %mem -> %prv : memref<1xf32>) {
752    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
753      %2 = arith.constant 2.0 : f32
754      omp.yield
755    }
756  }
757  return
758}
759
760// -----
761
762func.func @omp_critical2() -> () {
763  // expected-error @below {{expected symbol reference @excl to point to a critical declaration}}
764  omp.critical(@excl) {
765    omp.terminator
766  }
767  return
768}
769
770// -----
771
772// expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
773omp.critical.declare @mutex hint(uncontended, contended)
774
775// -----
776
777// expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined}}
778omp.critical.declare @mutex hint(nonspeculative, speculative)
779
780// -----
781
782// expected-error @below {{invalid_hint is not a valid hint}}
783omp.critical.declare @mutex hint(invalid_hint)
784
785// -----
786
787func.func @omp_ordered_region1(%x : i32) -> () {
788  omp.distribute {
789    omp.loop_nest (%i) : i32 = (%x) to (%x) step (%x) {
790      // expected-error @below {{op must be nested inside of a worksharing, simd or worksharing simd loop}}
791      omp.ordered.region {
792        omp.terminator
793      }
794      omp.yield
795    }
796  }
797  return
798}
799
800// -----
801
802func.func @omp_ordered_region2(%x : i32) -> () {
803  omp.wsloop {
804    omp.loop_nest (%i) : i32 = (%x) to (%x) step (%x) {
805      // expected-error @below {{the enclosing worksharing-loop region must have an ordered clause}}
806      omp.ordered.region {
807        omp.terminator
808      }
809      omp.yield
810    }
811  }
812  return
813}
814
815// -----
816
817func.func @omp_ordered_region3(%x : i32) -> () {
818  omp.wsloop ordered(1) {
819    omp.loop_nest (%i) : i32 = (%x) to (%x) step (%x) {
820      // expected-error @below {{the enclosing loop's ordered clause must not have a parameter present}}
821      omp.ordered.region {
822        omp.terminator
823      }
824      omp.yield
825    }
826  }
827  return
828}
829
830// -----
831
832func.func @omp_ordered1(%vec0 : i64) -> () {
833  // expected-error @below {{op must be nested inside of a loop}}
834  omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {doacross_num_loops = 1 : i64}
835  return
836}
837
838// -----
839
840func.func @omp_ordered2(%arg1 : i32, %arg2 : i32, %arg3 : i32, %vec0 : i64) -> () {
841  omp.distribute {
842    omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
843      // expected-error @below {{op must be nested inside of a worksharing, simd or worksharing simd loop}}
844      omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {doacross_num_loops = 1 : i64}
845      omp.yield
846    }
847  }
848  return
849}
850
851// -----
852
853func.func @omp_ordered3(%arg1 : i32, %arg2 : i32, %arg3 : i32, %vec0 : i64) -> () {
854  omp.wsloop {
855    omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
856      // expected-error @below {{the enclosing worksharing-loop region must have an ordered clause}}
857      omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {doacross_num_loops = 1 : i64}
858      omp.yield
859    }
860  }
861  return
862}
863
864// -----
865
866func.func @omp_ordered4(%arg1 : i32, %arg2 : i32, %arg3 : i32, %vec0 : i64) -> () {
867  omp.wsloop ordered(0) {
868    omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
869      // expected-error @below {{the enclosing loop's ordered clause must have a parameter present}}
870      omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {doacross_num_loops = 1 : i64}
871      omp.yield
872    }
873  }
874  return
875}
876
877// -----
878
879func.func @omp_ordered5(%arg1 : i32, %arg2 : i32, %arg3 : i32, %vec0 : i64, %vec1 : i64) -> () {
880  omp.wsloop ordered(1) {
881    omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
882      // expected-error @below {{number of variables in depend clause does not match number of iteration variables in the doacross loop}}
883      omp.ordered depend_type(dependsource) depend_vec(%vec0, %vec1 : i64, i64) {doacross_num_loops = 2 : i64}
884      omp.yield
885    }
886  }
887  return
888}
889
890// -----
891
892func.func @omp_atomic_read1(%x: memref<i32>, %v: memref<i32>) {
893  // expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined.}}
894  omp.atomic.read %v = %x hint(speculative, nonspeculative) : memref<i32>, memref<i32>, i32
895  return
896}
897
898// -----
899
900func.func @omp_atomic_read2(%x: memref<i32>, %v: memref<i32>) {
901  // expected-error @below {{invalid clause value: 'xyz'}}
902  omp.atomic.read %v = %x memory_order(xyz) : memref<i32>, memref<i32>, i32
903  return
904}
905
906// -----
907
908func.func @omp_atomic_read3(%x: memref<i32>, %v: memref<i32>) {
909  // expected-error @below {{memory-order must not be acq_rel or release for atomic reads}}
910  omp.atomic.read %v = %x memory_order(acq_rel) : memref<i32>, memref<i32>, i32
911  return
912}
913
914// -----
915
916func.func @omp_atomic_read4(%x: memref<i32>, %v: memref<i32>) {
917  // expected-error @below {{memory-order must not be acq_rel or release for atomic reads}}
918  omp.atomic.read %v = %x memory_order(release) : memref<i32>, memref<i32>, i32
919  return
920}
921
922// -----
923
924func.func @omp_atomic_read5(%x: memref<i32>, %v: memref<i32>) {
925  // expected-error @below {{`memory_order` clause can appear at most once in the expansion of the oilist directive}}
926  omp.atomic.read %v = %x memory_order(acquire) memory_order(relaxed) : memref<i32>, memref<i32>, i32
927  return
928}
929
930// -----
931
932func.func @omp_atomic_read6(%x: memref<i32>, %v: memref<i32>) {
933  // expected-error @below {{`hint` clause can appear at most once in the expansion of the oilist directive}}
934  omp.atomic.read %v =  %x hint(speculative) hint(contended) : memref<i32>, memref<i32>, i32
935  return
936}
937
938// -----
939
940func.func @omp_atomic_read6(%x: memref<i32>, %v: memref<i32>) {
941  // expected-error @below {{read and write must not be to the same location for atomic reads}}
942  omp.atomic.read %x =  %x hint(speculative) : memref<i32>, memref<i32>, i32
943  return
944}
945
946// -----
947
948func.func @omp_atomic_write1(%addr : memref<i32>, %val : i32) {
949  // expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
950  omp.atomic.write  %addr = %val hint(contended, uncontended) : memref<i32>, i32
951  return
952}
953
954// -----
955
956func.func @omp_atomic_write2(%addr : memref<i32>, %val : i32) {
957  // expected-error @below {{memory-order must not be acq_rel or acquire for atomic writes}}
958  omp.atomic.write  %addr = %val memory_order(acq_rel) : memref<i32>, i32
959  return
960}
961
962// -----
963
964func.func @omp_atomic_write3(%addr : memref<i32>, %val : i32) {
965  // expected-error @below {{memory-order must not be acq_rel or acquire for atomic writes}}
966  omp.atomic.write  %addr = %val memory_order(acquire) : memref<i32>, i32
967  return
968}
969
970// -----
971
972func.func @omp_atomic_write4(%addr : memref<i32>, %val : i32) {
973  // expected-error @below {{`memory_order` clause can appear at most once in the expansion of the oilist directive}}
974  omp.atomic.write  %addr = %val memory_order(release) memory_order(seq_cst) : memref<i32>, i32
975  return
976}
977
978// -----
979
980func.func @omp_atomic_write5(%addr : memref<i32>, %val : i32) {
981  // expected-error @below {{`hint` clause can appear at most once in the expansion of the oilist directive}}
982  omp.atomic.write  %addr = %val hint(contended) hint(speculative) : memref<i32>, i32
983  return
984}
985
986// -----
987
988func.func @omp_atomic_write6(%addr : memref<i32>, %val : i32) {
989  // expected-error @below {{invalid clause value: 'xyz'}}
990  omp.atomic.write  %addr = %val memory_order(xyz) : memref<i32>, i32
991  return
992}
993
994// -----
995
996func.func @omp_atomic_write(%addr : memref<memref<i32>>, %val : i32) {
997  // expected-error @below {{address must dereference to value type}}
998  omp.atomic.write %addr = %val : memref<memref<i32>>, i32
999  return
1000}
1001
1002// -----
1003
1004func.func @omp_atomic_update1(%x: memref<i32>, %expr: f32) {
1005  // expected-error @below {{the type of the operand must be a pointer type whose element type is the same as that of the region argument}}
1006  omp.atomic.update %x : memref<i32> {
1007  ^bb0(%xval: f32):
1008    %newval = llvm.fadd %xval, %expr : f32
1009    omp.yield (%newval : f32)
1010  }
1011  return
1012}
1013
1014// -----
1015
1016func.func @omp_atomic_update2(%x: memref<i32>, %expr: i32) {
1017  // expected-error @+2 {{op expects regions to end with 'omp.yield', found 'omp.terminator'}}
1018  // expected-note @below {{in custom textual format, the absence of terminator implies 'omp.yield'}}
1019  omp.atomic.update %x : memref<i32> {
1020  ^bb0(%xval: i32):
1021    %newval = llvm.add %xval, %expr : i32
1022    omp.terminator
1023  }
1024  return
1025}
1026
1027// -----
1028
1029func.func @omp_atomic_update3(%x: memref<i32>, %expr: i32) {
1030  // expected-error @below {{memory-order must not be acq_rel or acquire for atomic updates}}
1031  omp.atomic.update memory_order(acq_rel) %x : memref<i32> {
1032  ^bb0(%xval: i32):
1033    %newval = llvm.add %xval, %expr : i32
1034    omp.yield (%newval : i32)
1035  }
1036  return
1037}
1038
1039// -----
1040
1041func.func @omp_atomic_update4(%x: memref<i32>, %expr: i32) {
1042  // expected-error @below {{memory-order must not be acq_rel or acquire for atomic updates}}
1043  omp.atomic.update memory_order(acquire) %x : memref<i32> {
1044  ^bb0(%xval: i32):
1045    %newval = llvm.add %xval, %expr : i32
1046    omp.yield (%newval : i32)
1047  }
1048  return
1049}
1050
1051// -----
1052
1053func.func @omp_atomic_update5(%x: memref<i32>, %expr: i32) {
1054  // expected-error @below {{invalid kind of type specified}}
1055  omp.atomic.update %x : i32 {
1056  ^bb0(%xval: i32):
1057    %newval = llvm.add %xval, %expr : i32
1058    omp.yield (%newval : i32)
1059  }
1060  return
1061}
1062
1063// -----
1064
1065func.func @omp_atomic_update6(%x: memref<i32>, %expr: i32) {
1066  // expected-error @below {{only updated value must be returned}}
1067  omp.atomic.update %x : memref<i32> {
1068  ^bb0(%xval: i32):
1069    %newval = llvm.add %xval, %expr : i32
1070    omp.yield (%newval, %expr : i32, i32)
1071  }
1072  return
1073}
1074
1075// -----
1076
1077func.func @omp_atomic_update7(%x: memref<i32>, %expr: i32, %y: f32) {
1078  // expected-error @below {{input and yielded value must have the same type}}
1079  omp.atomic.update %x : memref<i32> {
1080  ^bb0(%xval: i32):
1081    %newval = llvm.add %xval, %expr : i32
1082    omp.yield (%y: f32)
1083  }
1084  return
1085}
1086
1087// -----
1088
1089func.func @omp_atomic_update8(%x: memref<i32>, %expr: i32) {
1090  // expected-error @below {{the region must accept exactly one argument}}
1091  omp.atomic.update %x : memref<i32> {
1092  ^bb0(%xval: i32, %tmp: i32):
1093    %newval = llvm.add %xval, %expr : i32
1094    omp.yield (%newval : i32)
1095  }
1096  return
1097}
1098
1099// -----
1100
1101func.func @omp_atomic_update(%x: memref<i32>, %expr: i32) {
1102  // expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
1103  omp.atomic.update hint(uncontended, contended) %x : memref<i32> {
1104  ^bb0(%xval: i32):
1105    %newval = llvm.add %xval, %expr : i32
1106    omp.yield (%newval : i32)
1107  }
1108  return
1109}
1110
1111// -----
1112
1113func.func @omp_atomic_update(%x: memref<i32>, %expr: i32) {
1114  // expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined}}
1115  omp.atomic.update hint(nonspeculative, speculative) %x : memref<i32> {
1116  ^bb0(%xval: i32):
1117    %newval = llvm.add %xval, %expr : i32
1118    omp.yield (%newval : i32)
1119  }
1120  return
1121}
1122
1123// -----
1124
1125func.func @omp_atomic_update(%x: memref<i32>, %expr: i32) {
1126  // expected-error @below {{invalid_hint is not a valid hint}}
1127  omp.atomic.update hint(invalid_hint) %x : memref<i32> {
1128  ^bb0(%xval: i32):
1129    %newval = llvm.add %xval, %expr : i32
1130    omp.yield (%newval : i32)
1131  }
1132  return
1133}
1134
1135// -----
1136
1137func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1138  // expected-error @below {{expected three operations in atomic.capture region}}
1139  omp.atomic.capture {
1140    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1141    omp.terminator
1142  }
1143  return
1144}
1145
1146// -----
1147
1148func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1149  omp.atomic.capture {
1150    // expected-error @below {{invalid sequence of operations in the capture region}}
1151    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1152    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1153    omp.terminator
1154  }
1155  return
1156}
1157
1158// -----
1159
1160func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1161  omp.atomic.capture {
1162    // expected-error @below {{invalid sequence of operations in the capture region}}
1163    omp.atomic.update %x : memref<i32> {
1164    ^bb0(%xval: i32):
1165      %newval = llvm.add %xval, %expr : i32
1166      omp.yield (%newval : i32)
1167    }
1168    omp.atomic.update %x : memref<i32> {
1169    ^bb0(%xval: i32):
1170      %newval = llvm.add %xval, %expr : i32
1171      omp.yield (%newval : i32)
1172    }
1173    omp.terminator
1174  }
1175  return
1176}
1177
1178// -----
1179
1180func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1181  omp.atomic.capture {
1182    // expected-error @below {{invalid sequence of operations in the capture region}}
1183    omp.atomic.write %x = %expr : memref<i32>, i32
1184    omp.atomic.write %x = %expr : memref<i32>, i32
1185    omp.terminator
1186  }
1187  return
1188}
1189
1190// -----
1191
1192func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1193  omp.atomic.capture {
1194    // expected-error @below {{invalid sequence of operations in the capture region}}
1195    omp.atomic.write %x = %expr : memref<i32>, i32
1196    omp.atomic.update %x : memref<i32> {
1197    ^bb0(%xval: i32):
1198      %newval = llvm.add %xval, %expr : i32
1199      omp.yield (%newval : i32)
1200    }
1201    omp.terminator
1202  }
1203  return
1204}
1205
1206// -----
1207
1208func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1209  omp.atomic.capture {
1210    // expected-error @below {{invalid sequence of operations in the capture region}}
1211    omp.atomic.update %x : memref<i32> {
1212    ^bb0(%xval: i32):
1213      %newval = llvm.add %xval, %expr : i32
1214      omp.yield (%newval : i32)
1215    }
1216    omp.atomic.write %x = %expr : memref<i32>, i32
1217    omp.terminator
1218  }
1219  return
1220}
1221
1222// -----
1223
1224func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1225  omp.atomic.capture {
1226    // expected-error @below {{invalid sequence of operations in the capture region}}
1227    omp.atomic.write %x = %expr : memref<i32>, i32
1228    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1229    omp.terminator
1230  }
1231  return
1232}
1233
1234// -----
1235
1236func.func @omp_atomic_capture(%x: memref<i32>, %y: memref<i32>, %v: memref<i32>, %expr: i32) {
1237  omp.atomic.capture {
1238    // expected-error @below {{updated variable in atomic.update must be captured in second operation}}
1239    omp.atomic.update %x : memref<i32> {
1240    ^bb0(%xval: i32):
1241      %newval = llvm.add %xval, %expr : i32
1242      omp.yield (%newval : i32)
1243    }
1244    omp.atomic.read %v = %y : memref<i32>, memref<i32>, i32
1245    omp.terminator
1246  }
1247}
1248
1249// -----
1250
1251func.func @omp_atomic_capture(%x: memref<i32>, %y: memref<i32>, %v: memref<i32>, %expr: i32) {
1252  omp.atomic.capture {
1253    // expected-error @below {{captured variable in atomic.read must be updated in second operation}}
1254    omp.atomic.read %v = %y : memref<i32>, memref<i32>, i32
1255    omp.atomic.update %x : memref<i32> {
1256    ^bb0(%xval: i32):
1257      %newval = llvm.add %xval, %expr : i32
1258      omp.yield (%newval : i32)
1259    }
1260    omp.terminator
1261  }
1262}
1263
1264// -----
1265
1266func.func @omp_atomic_capture(%x: memref<i32>, %y: memref<i32>, %v: memref<i32>, %expr: i32) {
1267  omp.atomic.capture {
1268    // expected-error @below {{captured variable in atomic.read must be updated in second operation}}
1269    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1270    omp.atomic.write %y = %expr : memref<i32>, i32
1271    omp.terminator
1272  }
1273}
1274
1275// -----
1276
1277func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1278  // expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
1279  omp.atomic.capture hint(contended, uncontended) {
1280    omp.atomic.update %x : memref<i32> {
1281    ^bb0(%xval: i32):
1282      %newval = llvm.add %xval, %expr : i32
1283      omp.yield(%newval : i32)
1284    }
1285    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1286  }
1287  return
1288}
1289
1290// -----
1291
1292func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1293  // expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined}}
1294  omp.atomic.capture hint(nonspeculative, speculative) {
1295    omp.atomic.update %x : memref<i32> {
1296    ^bb0(%xval: i32):
1297      %newval = llvm.add %xval, %expr : i32
1298      omp.yield(%newval : i32)
1299    }
1300    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1301  }
1302  return
1303}
1304
1305// -----
1306
1307func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1308  // expected-error @below {{invalid_hint is not a valid hint}}
1309  omp.atomic.capture hint(invalid_hint) {
1310    omp.atomic.update %x : memref<i32> {
1311    ^bb0(%xval: i32):
1312      %newval = llvm.add %xval, %expr : i32
1313      omp.yield(%newval : i32)
1314    }
1315    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1316  }
1317  return
1318}
1319
1320// -----
1321
1322func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1323  // expected-error @below {{operations inside capture region must not have hint clause}}
1324  omp.atomic.capture {
1325    omp.atomic.update hint(uncontended) %x : memref<i32> {
1326    ^bb0(%xval: i32):
1327      %newval = llvm.add %xval, %expr : i32
1328      omp.yield(%newval : i32)
1329    }
1330    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1331  }
1332  return
1333}
1334
1335// -----
1336
1337func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1338  // expected-error @below {{operations inside capture region must not have memory_order clause}}
1339  omp.atomic.capture {
1340    omp.atomic.update memory_order(seq_cst) %x : memref<i32> {
1341    ^bb0(%xval: i32):
1342      %newval = llvm.add %xval, %expr : i32
1343      omp.yield(%newval : i32)
1344    }
1345    omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1346  }
1347  return
1348}
1349
1350// -----
1351
1352func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
1353  // expected-error @below {{operations inside capture region must not have memory_order clause}}
1354  omp.atomic.capture {
1355    omp.atomic.update %x : memref<i32> {
1356    ^bb0(%xval: i32):
1357      %newval = llvm.add %xval, %expr : i32
1358      omp.yield(%newval : i32)
1359    }
1360    omp.atomic.read %v = %x memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1361  }
1362  return
1363}
1364
1365// -----
1366
1367func.func @omp_teams_parent() {
1368  omp.parallel {
1369    // expected-error @below {{expected to be nested inside of omp.target or not nested in any OpenMP dialect operations}}
1370    omp.teams {
1371      omp.terminator
1372    }
1373    omp.terminator
1374  }
1375  return
1376}
1377
1378// -----
1379
1380func.func @omp_teams_allocate(%data_var : memref<i32>) {
1381  omp.target {
1382    // expected-error @below {{expected equal sizes for allocate and allocator variables}}
1383    "omp.teams" (%data_var) ({
1384      omp.terminator
1385    }) {operandSegmentSizes = array<i32: 1,0,0,0,0,0,0,0>} : (memref<i32>) -> ()
1386    omp.terminator
1387  }
1388  return
1389}
1390
1391// -----
1392
1393func.func @omp_teams_num_teams1(%lb : i32) {
1394  omp.target {
1395    // expected-error @below {{expected num_teams upper bound to be defined if the lower bound is defined}}
1396    "omp.teams" (%lb) ({
1397      omp.terminator
1398    }) {operandSegmentSizes = array<i32: 0,0,0,1,0,0,0,0>} : (i32) -> ()
1399    omp.terminator
1400  }
1401  return
1402}
1403
1404// -----
1405
1406func.func @omp_teams_num_teams2(%lb : i32, %ub : i16) {
1407  omp.target {
1408    // expected-error @below {{expected num_teams upper bound and lower bound to be the same type}}
1409    omp.teams num_teams(%lb : i32 to %ub : i16) {
1410      omp.terminator
1411    }
1412    omp.terminator
1413  }
1414  return
1415}
1416
1417// -----
1418
1419func.func @omp_sections(%data_var : memref<i32>) -> () {
1420  // expected-error @below {{expected equal sizes for allocate and allocator variables}}
1421  "omp.sections" (%data_var) ({
1422    omp.terminator
1423  }) {operandSegmentSizes = array<i32: 1,0,0,0>} : (memref<i32>) -> ()
1424  return
1425}
1426
1427// -----
1428
1429func.func @omp_sections(%data_var : memref<i32>) -> () {
1430  // expected-error @below {{expected as many reduction symbol references as reduction variables}}
1431  "omp.sections" (%data_var) ({
1432  ^bb0(%arg0: memref<i32>):
1433    omp.terminator
1434  }) {operandSegmentSizes = array<i32: 0,0,0,1>} : (memref<i32>) -> ()
1435  return
1436}
1437
1438// -----
1439
1440func.func @omp_sections(%data_var : memref<i32>) -> () {
1441  // expected-error @below {{expected omp.section op or terminator op inside region}}
1442  omp.sections {
1443    "test.payload" () : () -> ()
1444  }
1445  return
1446}
1447
1448// -----
1449
1450func.func @omp_sections(%cond : i1) {
1451  // expected-error @below {{expected '{' to begin a region}}
1452  omp.sections if(%cond) {
1453    omp.terminator
1454  }
1455  return
1456}
1457
1458// -----
1459
1460func.func @omp_sections() {
1461  // expected-error @below {{expected '{' to begin a region}}
1462  omp.sections num_threads(10) {
1463    omp.terminator
1464  }
1465  return
1466}
1467
1468// -----
1469
1470func.func @omp_sections() {
1471  // expected-error @below {{expected '{' to begin a region}}
1472  omp.sections proc_bind(close) {
1473    omp.terminator
1474  }
1475  return
1476}
1477
1478// -----
1479
1480func.func @omp_sections(%data_var : memref<i32>, %linear_var : i32) {
1481  // expected-error @below {{expected '{' to begin a region}}
1482  omp.sections linear(%data_var = %linear_var : memref<i32>) {
1483    omp.terminator
1484  }
1485  return
1486}
1487
1488// -----
1489
1490func.func @omp_sections() {
1491  // expected-error @below {{expected '{' to begin a region}}
1492  omp.sections schedule(static, none) {
1493    omp.terminator
1494  }
1495  return
1496}
1497
1498// -----
1499
1500func.func @omp_sections() {
1501  // expected-error @below {{expected '{' to begin a region}}
1502  omp.sections collapse(3) {
1503    omp.terminator
1504  }
1505  return
1506}
1507
1508// -----
1509
1510func.func @omp_sections() {
1511  // expected-error @below {{expected '{' to begin a region}}
1512  omp.sections ordered(2) {
1513    omp.terminator
1514  }
1515  return
1516}
1517
1518// -----
1519
1520func.func @omp_sections() {
1521  // expected-error @below {{expected '{' to begin a region}}
1522  omp.sections order(concurrent) {
1523    omp.terminator
1524  }
1525  return
1526}
1527
1528// -----
1529
1530func.func @omp_sections() {
1531  // expected-error @below {{failed to verify constraint: region with 1 blocks}}
1532  omp.sections {
1533    omp.section {
1534      omp.terminator
1535    }
1536    omp.terminator
1537  ^bb2:
1538    omp.terminator
1539  }
1540  return
1541}
1542
1543// -----
1544
1545omp.declare_reduction @add_f32 : f32
1546init {
1547^bb0(%arg: f32):
1548  %0 = arith.constant 0.0 : f32
1549  omp.yield (%0 : f32)
1550}
1551combiner {
1552^bb1(%arg0: f32, %arg1: f32):
1553  %1 = arith.addf %arg0, %arg1 : f32
1554  omp.yield (%1 : f32)
1555}
1556
1557func.func @omp_sections(%x : !llvm.ptr) {
1558  omp.sections reduction(@add_f32 %x -> %arg0 : !llvm.ptr) {
1559    // expected-error @below {{op expected at least 1 entry block argument(s)}}
1560    omp.section {
1561      omp.terminator
1562    }
1563    omp.terminator
1564  }
1565  return
1566}
1567
1568// -----
1569
1570func.func @omp_single(%data_var : memref<i32>) -> () {
1571  // expected-error @below {{expected equal sizes for allocate and allocator variables}}
1572  "omp.single" (%data_var) ({
1573    omp.barrier
1574  }) {operandSegmentSizes = array<i32: 1,0,0,0>} : (memref<i32>) -> ()
1575  return
1576}
1577
1578// -----
1579
1580func.func @omp_single_copyprivate(%data_var : memref<i32>) -> () {
1581  // expected-error @below {{inconsistent number of copyprivate vars (= 1) and functions (= 0), both must be equal}}
1582  "omp.single" (%data_var) ({
1583    omp.barrier
1584  }) {operandSegmentSizes = array<i32: 0,0,1,0>} : (memref<i32>) -> ()
1585  return
1586}
1587
1588// -----
1589
1590func.func @omp_single_copyprivate(%data_var : memref<i32>) -> () {
1591  // expected-error @below {{expected symbol reference @copy_func to point to a copy function}}
1592  omp.single copyprivate(%data_var -> @copy_func : memref<i32>) {
1593    omp.barrier
1594  }
1595  return
1596}
1597
1598// -----
1599
1600func.func private @copy_func(memref<i32>)
1601
1602func.func @omp_single_copyprivate(%data_var : memref<i32>) -> () {
1603  // expected-error @below {{expected copy function @copy_func to have 2 operands}}
1604  omp.single copyprivate(%data_var -> @copy_func : memref<i32>) {
1605    omp.barrier
1606  }
1607  return
1608}
1609
1610// -----
1611
1612func.func private @copy_func(memref<i32>, memref<f32>)
1613
1614func.func @omp_single_copyprivate(%data_var : memref<i32>) -> () {
1615  // expected-error @below {{expected copy function @copy_func arguments to have the same type}}
1616  omp.single copyprivate(%data_var -> @copy_func : memref<i32>) {
1617    omp.barrier
1618  }
1619  return
1620}
1621
1622// -----
1623
1624func.func private @copy_func(memref<f32>, memref<f32>)
1625
1626func.func @omp_single_copyprivate(%data_var : memref<i32>) -> () {
1627  // expected-error @below {{expected copy function arguments' type ('memref<f32>') to be the same as copyprivate variable's type ('memref<i32>')}}
1628  omp.single copyprivate(%data_var -> @copy_func : memref<i32>) {
1629    omp.barrier
1630  }
1631  return
1632}
1633
1634// -----
1635
1636func.func @omp_task_depend(%data_var: memref<i32>) {
1637  // expected-error @below {{'omp.task' op operand count (1) does not match with the total size (0) specified in attribute 'operandSegmentSizes'}}
1638    "omp.task"(%data_var) ({
1639      "omp.terminator"() : () -> ()
1640    }) {depend_kinds = [], operandSegmentSizes = array<i32: 0, 0, 1, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
1641   "func.return"() : () -> ()
1642}
1643
1644// -----
1645
1646func.func @omp_task(%ptr: !llvm.ptr) {
1647  // expected-error @below {{op expected symbol reference @add_f32 to point to a reduction declaration}}
1648  omp.task in_reduction(@add_f32 %ptr -> %arg0 : !llvm.ptr) {
1649    // CHECK: "test.foo"() : () -> ()
1650    "test.foo"() : () -> ()
1651    // CHECK: omp.terminator
1652    omp.terminator
1653  }
1654}
1655
1656// -----
1657
1658omp.declare_reduction @add_f32 : f32
1659init {
1660^bb0(%arg: f32):
1661  %0 = arith.constant 0.0 : f32
1662  omp.yield (%0 : f32)
1663}
1664combiner {
1665^bb1(%arg0: f32, %arg1: f32):
1666  %1 = arith.addf %arg0, %arg1 : f32
1667  omp.yield (%1 : f32)
1668}
1669
1670func.func @omp_task(%ptr: !llvm.ptr) {
1671  // expected-error @below {{op accumulator variable used more than once}}
1672  omp.task in_reduction(@add_f32 %ptr -> %arg0, @add_f32 %ptr -> %arg1 : !llvm.ptr, !llvm.ptr) {
1673    // CHECK: "test.foo"() : () -> ()
1674    "test.foo"() : () -> ()
1675    // CHECK: omp.terminator
1676    omp.terminator
1677  }
1678}
1679
1680// -----
1681
1682omp.declare_reduction @add_i32 : i32
1683init {
1684^bb0(%arg: i32):
1685  %0 = arith.constant 0 : i32
1686  omp.yield (%0 : i32)
1687}
1688combiner {
1689^bb1(%arg0: i32, %arg1: i32):
1690  %1 = arith.addi %arg0, %arg1 : i32
1691  omp.yield (%1 : i32)
1692}
1693atomic {
1694^bb2(%arg2: !llvm.ptr, %arg3: !llvm.ptr):
1695  %2 = llvm.load %arg3 : !llvm.ptr -> i32
1696  llvm.atomicrmw add %arg2, %2 monotonic : !llvm.ptr, i32
1697  omp.yield
1698}
1699
1700func.func @omp_task(%mem: memref<1xf32>) {
1701  // expected-error @below {{op expected accumulator ('memref<1xf32>') to be the same type as reduction declaration ('!llvm.ptr')}}
1702  omp.task in_reduction(@add_i32 %mem -> %arg0 : memref<1xf32>) {
1703    // CHECK: "test.foo"() : () -> ()
1704    "test.foo"() : () -> ()
1705    // CHECK: omp.terminator
1706    omp.terminator
1707  }
1708  return
1709}
1710
1711// -----
1712
1713func.func @omp_cancel() {
1714  omp.sections {
1715    // expected-error @below {{cancel parallel must appear inside a parallel region}}
1716    omp.cancel cancellation_construct_type(parallel)
1717    // CHECK: omp.terminator
1718    omp.terminator
1719  }
1720  return
1721}
1722
1723// -----
1724
1725func.func @omp_cancel1() {
1726  omp.parallel {
1727    // expected-error @below {{cancel sections must appear inside a sections region}}
1728    omp.cancel cancellation_construct_type(sections)
1729    // CHECK: omp.terminator
1730    omp.terminator
1731  }
1732  return
1733}
1734
1735// -----
1736
1737func.func @omp_cancel2() {
1738  omp.sections {
1739    // expected-error @below {{cancel loop must appear inside a worksharing-loop region}}
1740    omp.cancel cancellation_construct_type(loop)
1741    // CHECK: omp.terminator
1742    omp.terminator
1743  }
1744  return
1745}
1746
1747// -----
1748
1749func.func @omp_cancel3(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () {
1750  omp.wsloop nowait {
1751    omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
1752      // expected-error @below {{A worksharing construct that is canceled must not have a nowait clause}}
1753      omp.cancel cancellation_construct_type(loop)
1754      // CHECK: omp.yield
1755      omp.yield
1756    }
1757  }
1758  return
1759}
1760
1761// -----
1762
1763func.func @omp_cancel4(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () {
1764  omp.wsloop ordered(1) {
1765    omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
1766      // expected-error @below {{A worksharing construct that is canceled must not have an ordered clause}}
1767      omp.cancel cancellation_construct_type(loop)
1768      // CHECK: omp.yield
1769      omp.yield
1770    }
1771  }
1772  return
1773}
1774
1775// -----
1776
1777func.func @omp_cancel5() -> () {
1778  omp.sections nowait {
1779    omp.section {
1780      // expected-error @below {{A sections construct that is canceled must not have a nowait clause}}
1781      omp.cancel cancellation_construct_type(sections)
1782      omp.terminator
1783    }
1784    // CHECK: omp.terminator
1785    omp.terminator
1786  }
1787  return
1788}
1789
1790// -----
1791
1792func.func @omp_cancellationpoint() {
1793  omp.sections {
1794    // expected-error @below {{cancellation point parallel must appear inside a parallel region}}
1795    omp.cancellation_point cancellation_construct_type(parallel)
1796    // CHECK: omp.terminator
1797    omp.terminator
1798  }
1799  return
1800}
1801
1802// -----
1803
1804func.func @omp_cancellationpoint1() {
1805  omp.parallel {
1806    // expected-error @below {{cancellation point sections must appear inside a sections region}}
1807    omp.cancellation_point cancellation_construct_type(sections)
1808    // CHECK: omp.terminator
1809    omp.terminator
1810  }
1811  return
1812}
1813
1814// -----
1815
1816func.func @omp_cancellationpoint2() {
1817  omp.sections {
1818    // expected-error @below {{cancellation point loop must appear inside a worksharing-loop region}}
1819    omp.cancellation_point cancellation_construct_type(loop)
1820    // CHECK: omp.terminator
1821    omp.terminator
1822  }
1823  return
1824}
1825
1826// -----
1827
1828omp.declare_reduction @add_f32 : f32
1829init {
1830 ^bb0(%arg: f32):
1831  %0 = arith.constant 0.0 : f32
1832  omp.yield (%0 : f32)
1833}
1834combiner {
1835  ^bb1(%arg0: f32, %arg1: f32):
1836  %1 = arith.addf %arg0, %arg1 : f32
1837  omp.yield (%1 : f32)
1838}
1839
1840func.func @scan_test_2(%lb: i32, %ub: i32, %step: i32) {
1841  %test1f32 = "test.f32"() : () -> (!llvm.ptr)
1842  omp.wsloop reduction(mod:inscan, @add_f32 %test1f32 -> %arg1 : !llvm.ptr) {
1843    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
1844  // expected-error @below {{Exactly one of EXCLUSIVE or INCLUSIVE clause is expected}}
1845       omp.scan
1846        omp.yield
1847    }
1848  }
1849  return
1850}
1851
1852// -----
1853
1854omp.declare_reduction @add_f32 : f32
1855init {
1856 ^bb0(%arg: f32):
1857  %0 = arith.constant 0.0 : f32
1858  omp.yield (%0 : f32)
1859}
1860combiner {
1861  ^bb1(%arg0: f32, %arg1: f32):
1862  %1 = arith.addf %arg0, %arg1 : f32
1863  omp.yield (%1 : f32)
1864}
1865
1866func.func @scan_test_2(%lb: i32, %ub: i32, %step: i32) {
1867  %test1f32 = "test.f32"() : () -> (!llvm.ptr)
1868  omp.wsloop reduction(mod:inscan, @add_f32 %test1f32 -> %arg1 : !llvm.ptr) {
1869    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
1870  // expected-error @below {{Exactly one of EXCLUSIVE or INCLUSIVE clause is expected}}
1871       omp.scan inclusive(%test1f32 : !llvm.ptr) exclusive(%test1f32: !llvm.ptr)
1872        omp.yield
1873    }
1874  }
1875  return
1876}
1877
1878// -----
1879
1880omp.declare_reduction @add_f32 : f32
1881init {
1882 ^bb0(%arg: f32):
1883  %0 = arith.constant 0.0 : f32
1884  omp.yield (%0 : f32)
1885}
1886combiner {
1887  ^bb1(%arg0: f32, %arg1: f32):
1888  %1 = arith.addf %arg0, %arg1 : f32
1889  omp.yield (%1 : f32)
1890}
1891
1892func.func @scan_test_2(%lb: i32, %ub: i32, %step: i32) {
1893  %test1f32 = "test.f32"() : () -> (!llvm.ptr)
1894  omp.wsloop reduction(@add_f32 %test1f32 -> %arg1 : !llvm.ptr) {
1895    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
1896  // expected-error @below {{SCAN directive needs to be enclosed within a parent worksharing loop construct or SIMD construct with INSCAN reduction modifier}}
1897       omp.scan inclusive(%test1f32 : !llvm.ptr)
1898        omp.yield
1899    }
1900  }
1901  return
1902}
1903
1904// -----
1905
1906omp.declare_reduction @add_f32 : f32
1907init {
1908 ^bb0(%arg: f32):
1909  %0 = arith.constant 0.0 : f32
1910  omp.yield (%0 : f32)
1911}
1912combiner {
1913  ^bb1(%arg0: f32, %arg1: f32):
1914  %1 = arith.addf %arg0, %arg1 : f32
1915  omp.yield (%1 : f32)
1916}
1917
1918func.func @scan_test_2(%lb: i32, %ub: i32, %step: i32) {
1919  %test1f32 = "test.f32"() : () -> (!llvm.ptr)
1920  omp.taskloop reduction(mod:inscan, @add_f32 %test1f32 -> %arg1 : !llvm.ptr) {
1921    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
1922  // expected-error @below {{SCAN directive needs to be enclosed within a parent worksharing loop construct or SIMD construct with INSCAN reduction modifier}}
1923       omp.scan inclusive(%test1f32 : !llvm.ptr)
1924        omp.yield
1925    }
1926  }
1927  return
1928}
1929
1930// -----
1931
1932func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
1933  %testmemref = "test.memref"() : () -> (memref<i32>)
1934  // expected-error @below {{expected equal sizes for allocate and allocator variables}}
1935  "omp.taskloop"(%testmemref) ({
1936    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
1937      omp.yield
1938    }
1939  }) {operandSegmentSizes = array<i32: 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
1940  return
1941}
1942
1943// -----
1944
1945func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
1946  %testf32 = "test.f32"() : () -> (!llvm.ptr)
1947  %testf32_2 = "test.f32"() : () -> (!llvm.ptr)
1948  // expected-error @below {{expected as many reduction symbol references as reduction variables}}
1949  "omp.taskloop"(%testf32, %testf32_2) ({
1950  ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
1951    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
1952      omp.yield
1953    }
1954  }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 2>, reduction_syms = [@add_f32]} : (!llvm.ptr, !llvm.ptr) -> ()
1955  return
1956}
1957
1958// -----
1959
1960func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
1961  %testf32 = "test.f32"() : () -> (!llvm.ptr)
1962  // expected-error @below {{expected as many reduction symbol references as reduction variables}}
1963  "omp.taskloop"(%testf32) ({
1964  ^bb0(%arg0: !llvm.ptr):
1965    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
1966      omp.yield
1967    }
1968  }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 1>, reduction_syms = [@add_f32, @add_f32]} : (!llvm.ptr) -> ()
1969  return
1970}
1971
1972// -----
1973
1974func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
1975  %testf32 = "test.f32"() : () -> (!llvm.ptr)
1976  %testf32_2 = "test.f32"() : () -> (!llvm.ptr)
1977  // expected-error @below {{expected as many reduction symbol references as reduction variables}}
1978  "omp.taskloop"(%testf32, %testf32_2) ({
1979  ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
1980    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
1981      omp.yield
1982    }
1983  }) {in_reduction_syms = [@add_f32], operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 2, 0, 0, 0, 0>} : (!llvm.ptr, !llvm.ptr) -> ()
1984  return
1985}
1986
1987// -----
1988
1989func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
1990  %testf32 = "test.f32"() : () -> (!llvm.ptr)
1991  // expected-error @below {{expected as many reduction symbol references as reduction variables}}
1992  "omp.taskloop"(%testf32) ({
1993  ^bb0(%arg0: !llvm.ptr):
1994    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
1995      omp.yield
1996    }
1997  }) {in_reduction_syms = [@add_f32, @add_f32], operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 1, 0, 0, 0, 0>} : (!llvm.ptr) -> ()
1998  return
1999}
2000
2001// -----
2002
2003omp.declare_reduction @add_f32 : f32
2004init {
2005^bb0(%arg: f32):
2006  %0 = arith.constant 0.0 : f32
2007  omp.yield (%0 : f32)
2008}
2009combiner {
2010^bb1(%arg0: f32, %arg1: f32):
2011  %1 = arith.addf %arg0, %arg1 : f32
2012  omp.yield (%1 : f32)
2013}
2014
2015func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
2016  %testf32 = "test.f32"() : () -> (!llvm.ptr)
2017  %testf32_2 = "test.f32"() : () -> (!llvm.ptr)
2018  // expected-error @below {{if a reduction clause is present on the taskloop directive, the nogroup clause must not be specified}}
2019  omp.taskloop nogroup reduction(@add_f32 %testf32 -> %arg0, @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2020    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2021      omp.yield
2022    }
2023  }
2024  return
2025}
2026
2027// -----
2028
2029omp.declare_reduction @add_f32 : f32
2030init {
2031^bb0(%arg: f32):
2032  %0 = arith.constant 0.0 : f32
2033  omp.yield (%0 : f32)
2034}
2035combiner {
2036^bb1(%arg0: f32, %arg1: f32):
2037  %1 = arith.addf %arg0, %arg1 : f32
2038  omp.yield (%1 : f32)
2039}
2040
2041func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
2042  %testf32 = "test.f32"() : () -> (!llvm.ptr)
2043  // expected-error @below {{the same list item cannot appear in both a reduction and an in_reduction clause}}
2044  omp.taskloop in_reduction(@add_f32 %testf32 -> %arg0 : !llvm.ptr) reduction(@add_f32 %testf32 -> %arg1 : !llvm.ptr) {
2045    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2046      omp.yield
2047    }
2048  }
2049  return
2050}
2051
2052// -----
2053
2054func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
2055  %testi64 = "test.i64"() : () -> (i64)
2056  // expected-error @below {{the grainsize clause and num_tasks clause are mutually exclusive and may not appear on the same taskloop directive}}
2057  omp.taskloop grainsize(%testi64: i64) num_tasks(%testi64: i64) {
2058    omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2059      omp.yield
2060    }
2061  }
2062  return
2063}
2064
2065// -----
2066
2067func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
2068  // expected-error @below {{op nested in loop wrapper is not another loop wrapper or `omp.loop_nest`}}
2069  omp.taskloop {
2070    %0 = arith.constant 0 : i32
2071  }
2072  return
2073}
2074
2075// -----
2076
2077func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
2078  // expected-error @below {{only supported nested wrapper is 'omp.simd'}}
2079  omp.taskloop {
2080    omp.distribute {
2081      omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
2082        omp.yield
2083      }
2084    }
2085  } {omp.composite}
2086  return
2087}
2088
2089// -----
2090
2091func.func @omp_threadprivate() {
2092  %1 = llvm.mlir.addressof @_QFsubEx : !llvm.ptr
2093  // expected-error @below {{op failed to verify that all of {sym_addr, tls_addr} have same type}}
2094  %2 = omp.threadprivate %1 : !llvm.ptr -> memref<i32>
2095  return
2096}
2097
2098// -----
2099
2100func.func @omp_target(%map1: memref<?xi32>) {
2101  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)   map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""}
2102  // expected-error @below {{to, from, tofrom and alloc map types are permitted}}
2103  omp.target map_entries(%mapv -> %arg0: memref<?xi32>) {
2104    omp.terminator
2105  }
2106  return
2107}
2108
2109// -----
2110
2111func.func @omp_target_data(%map1: memref<?xi32>) {
2112  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)  map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""}
2113  // expected-error @below {{to, from, tofrom and alloc map types are permitted}}
2114  omp.target_data map_entries(%mapv : memref<?xi32>){}
2115  return
2116}
2117
2118// -----
2119
2120func.func @omp_target_data() {
2121  // expected-error @below {{At least one of map, use_device_ptr_vars, or use_device_addr_vars operand must be present}}
2122  omp.target_data {}
2123  return
2124}
2125
2126// -----
2127
2128func.func @omp_target_enter_data(%map1: memref<?xi32>) {
2129  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)   map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""}
2130  // expected-error @below {{to and alloc map types are permitted}}
2131  omp.target_enter_data map_entries(%mapv : memref<?xi32>){}
2132  return
2133}
2134
2135// -----
2136
2137func.func @omp_target_enter_data_depend(%a: memref<?xi32>) {
2138  %0 = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32>
2139  // expected-error @below {{op expected as many depend values as depend variables}}
2140  omp.target_enter_data map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 1, 0, 0, 0>}
2141  return
2142}
2143
2144// -----
2145
2146func.func @omp_target_exit_data(%map1: memref<?xi32>) {
2147  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)   map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""}
2148  // expected-error @below {{from, release and delete map types are permitted}}
2149  omp.target_exit_data map_entries(%mapv : memref<?xi32>){}
2150  return
2151}
2152
2153// -----
2154
2155func.func @omp_target_exit_data_depend(%a: memref<?xi32>) {
2156  %0 = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32>
2157  // expected-error @below {{op expected as many depend values as depend variables}}
2158  omp.target_exit_data map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 1, 0, 0, 0>}
2159  return
2160}
2161
2162// -----
2163
2164func.func @omp_target_update_invalid_motion_type(%map1 : memref<?xi32>) {
2165  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
2166
2167  // expected-error @below {{at least one of to or from map types must be specified, other map types are not permitted}}
2168  omp.target_update map_entries(%mapv : memref<?xi32>)
2169  return
2170}
2171
2172// -----
2173
2174func.func @omp_target_update_invalid_motion_type_2(%map1 : memref<?xi32>) {
2175  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(delete) capture(ByRef) -> memref<?xi32> {name = ""}
2176
2177  // expected-error @below {{at least one of to or from map types must be specified, other map types are not permitted}}
2178  omp.target_update map_entries(%mapv : memref<?xi32>)
2179  return
2180}
2181
2182// -----
2183
2184func.func @omp_target_update_invalid_motion_modifier(%map1 : memref<?xi32>) {
2185  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(always, to) capture(ByRef) -> memref<?xi32> {name = ""}
2186
2187  // expected-error @below {{present, mapper and iterator map type modifiers are permitted}}
2188  omp.target_update map_entries(%mapv : memref<?xi32>)
2189  return
2190}
2191
2192// -----
2193
2194func.func @omp_target_update_invalid_motion_modifier_2(%map1 : memref<?xi32>) {
2195  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(close, to) capture(ByRef) -> memref<?xi32> {name = ""}
2196
2197  // expected-error @below {{present, mapper and iterator map type modifiers are permitted}}
2198  omp.target_update map_entries(%mapv : memref<?xi32>)
2199  return
2200}
2201
2202// -----
2203
2204func.func @omp_target_update_invalid_motion_modifier_3(%map1 : memref<?xi32>) {
2205  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(implicit, to) capture(ByRef) -> memref<?xi32> {name = ""}
2206
2207  // expected-error @below {{present, mapper and iterator map type modifiers are permitted}}
2208  omp.target_update map_entries(%mapv : memref<?xi32>)
2209  return
2210}
2211
2212// -----
2213
2214func.func @omp_target_update_invalid_motion_modifier_4(%map1 : memref<?xi32>) {
2215  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(implicit, tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
2216
2217  // expected-error @below {{either to or from map types can be specified, not both}}
2218  omp.target_update map_entries(%mapv : memref<?xi32>)
2219  return
2220}
2221
2222// -----
2223
2224func.func @omp_target_update_invalid_motion_modifier_5(%map1 : memref<?xi32>) {
2225  %mapv = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""}
2226  %mapv2 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""}
2227
2228  // expected-error @below {{either to or from map types can be specified, not both}}
2229  omp.target_update map_entries(%mapv, %mapv2 : memref<?xi32>, memref<?xi32>)
2230  return
2231}
2232llvm.mlir.global internal @_QFsubEx() : i32
2233
2234// -----
2235
2236func.func @omp_target_update_data_depend(%a: memref<?xi32>) {
2237  %0 = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32>
2238  // expected-error @below {{op expected as many depend values as depend variables}}
2239  omp.target_update map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 1, 0, 0, 0>}
2240  return
2241}
2242
2243// -----
2244
2245func.func @omp_target_multiple_teams() {
2246  // expected-error @below {{target containing multiple 'omp.teams' nested ops}}
2247  omp.target {
2248    omp.teams {
2249      omp.terminator
2250    }
2251    omp.teams {
2252      omp.terminator
2253    }
2254    omp.terminator
2255  }
2256  return
2257}
2258
2259// -----
2260
2261func.func @omp_target_host_eval(%x : !llvm.ptr) {
2262  // expected-error @below {{op host_eval argument illegal use in 'llvm.load' operation}}
2263  omp.target host_eval(%x -> %arg0 : !llvm.ptr) {
2264    %0 = llvm.load %arg0 : !llvm.ptr -> f32
2265    omp.terminator
2266  }
2267  return
2268}
2269
2270// -----
2271
2272func.func @omp_target_host_eval_teams(%x : i1) {
2273  // expected-error @below {{op host_eval argument only legal as 'num_teams' and 'thread_limit' in 'omp.teams'}}
2274  omp.target host_eval(%x -> %arg0 : i1) {
2275    omp.teams if(%arg0) {
2276      omp.terminator
2277    }
2278    omp.terminator
2279  }
2280  return
2281}
2282
2283// -----
2284
2285func.func @omp_target_host_eval_parallel(%x : i32) {
2286  // expected-error @below {{op host_eval argument only legal as 'num_threads' in 'omp.parallel' when representing target SPMD}}
2287  omp.target host_eval(%x -> %arg0 : i32) {
2288    omp.parallel num_threads(%arg0 : i32) {
2289      omp.terminator
2290    }
2291    omp.terminator
2292  }
2293  return
2294}
2295
2296// -----
2297
2298func.func @omp_target_host_eval_loop1(%x : i32) {
2299  // expected-error @below {{op host_eval argument only legal as loop bounds and steps in 'omp.loop_nest' when representing target SPMD or Generic-SPMD}}
2300  omp.target host_eval(%x -> %arg0 : i32) {
2301    omp.wsloop {
2302      omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
2303        omp.yield
2304      }
2305    }
2306    omp.terminator
2307  }
2308  return
2309}
2310
2311// -----
2312
2313func.func @omp_target_host_eval_loop2(%x : i32) {
2314  // expected-error @below {{op host_eval argument only legal as loop bounds and steps in 'omp.loop_nest' when representing target SPMD or Generic-SPMD}}
2315  omp.target host_eval(%x -> %arg0 : i32) {
2316    omp.teams {
2317    ^bb0:
2318      %0 = arith.constant 0 : i1
2319      llvm.cond_br %0, ^bb1, ^bb2
2320    ^bb1:
2321      omp.distribute {
2322        omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
2323          omp.yield
2324        }
2325      }
2326      llvm.br ^bb2
2327    ^bb2:
2328      omp.terminator
2329    }
2330    omp.terminator
2331  }
2332  return
2333}
2334
2335// -----
2336
2337func.func @omp_target_depend(%data_var: memref<i32>) {
2338  // expected-error @below {{op expected as many depend values as depend variables}}
2339    "omp.target"(%data_var) ({
2340      "omp.terminator"() : () -> ()
2341    }) {depend_kinds = [], operandSegmentSizes = array<i32: 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
2342   "func.return"() : () -> ()
2343}
2344
2345// -----
2346
2347func.func @omp_distribute_schedule(%chunk_size : i32, %lb : i32, %ub : i32, %step : i32) -> () {
2348  // expected-error @below {{op chunk size set without dist_schedule_static being present}}
2349  "omp.distribute"(%chunk_size) <{operandSegmentSizes = array<i32: 0, 0, 1, 0>}> ({
2350    omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
2351      "omp.yield"() : () -> ()
2352    }
2353  }) : (i32) -> ()
2354}
2355
2356// -----
2357
2358func.func @omp_distribute_allocate(%data_var : memref<i32>, %lb : i32, %ub : i32, %step : i32) -> () {
2359  // expected-error @below {{expected equal sizes for allocate and allocator variables}}
2360  "omp.distribute"(%data_var) <{operandSegmentSizes = array<i32: 1, 0, 0, 0>}> ({
2361    omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
2362      "omp.yield"() : () -> ()
2363    }
2364  }) : (memref<i32>) -> ()
2365}
2366
2367// -----
2368
2369func.func @omp_distribute_nested_wrapper(%lb: index, %ub: index, %step: index) -> () {
2370  // expected-error @below {{an 'omp.wsloop' nested wrapper is only allowed when 'omp.parallel' is the direct parent}}
2371  omp.distribute {
2372    "omp.wsloop"() ({
2373      omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2374        "omp.yield"() : () -> ()
2375      }
2376    }) {omp.composite} : () -> ()
2377  } {omp.composite}
2378}
2379
2380// -----
2381
2382func.func @omp_distribute_nested_wrapper2(%lb: index, %ub: index, %step: index) -> () {
2383  // expected-error @below {{only supported nested wrappers are 'omp.simd' and 'omp.wsloop'}}
2384  omp.distribute {
2385    "omp.taskloop"() ({
2386      omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2387        "omp.yield"() : () -> ()
2388      }
2389    }) : () -> ()
2390  } {omp.composite}
2391}
2392
2393// -----
2394
2395func.func @omp_distribute_nested_wrapper3(%lb: index, %ub: index, %step: index) -> () {
2396  // expected-error @below {{'omp.composite' attribute missing from composite wrapper}}
2397  omp.distribute {
2398    "omp.simd"() ({
2399      omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2400        "omp.yield"() : () -> ()
2401      }
2402    }) {omp.composite} : () -> ()
2403  }
2404}
2405
2406// -----
2407
2408func.func @omp_distribute_order() -> () {
2409// expected-error @below {{invalid clause value: 'default'}}
2410  omp.distribute order(default) {
2411    omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
2412      omp.yield
2413    }
2414  }
2415  return
2416}
2417// -----
2418func.func @omp_distribute_reproducible_order() -> () {
2419// expected-error @below {{invalid clause value: 'default'}}
2420  omp.distribute order(reproducible:default) {
2421    omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
2422      omp.yield
2423    }
2424  }
2425  return
2426}
2427// -----
2428func.func @omp_distribute_unconstrained_order() -> () {
2429// expected-error @below {{invalid clause value: 'default'}}
2430  omp.distribute order(unconstrained:default) {
2431    omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
2432      omp.yield
2433    }
2434  }
2435  return
2436}
2437// -----
2438omp.private {type = private} @x.privatizer : i32 alloc {
2439^bb0(%arg0: i32):
2440  %0 = arith.constant 0.0 : f32
2441  // expected-error @below {{Invalid yielded value. Expected type: 'i32', got: 'f32'}}
2442  omp.yield(%0 : f32)
2443}
2444
2445// -----
2446
2447omp.private {type = private} @x.privatizer : i32 alloc {
2448^bb0(%arg0: i32):
2449  // expected-error @below {{Invalid yielded value. Expected type: 'i32', got: None}}
2450  omp.yield
2451}
2452
2453// -----
2454
2455omp.private {type = private} @x.privatizer : f32 alloc {
2456^bb0(%arg0: f32):
2457  omp.yield(%arg0 : f32)
2458} dealloc {
2459^bb0(%arg0: f32):
2460  // expected-error @below {{Did not expect any values to be yielded.}}
2461  omp.yield(%arg0 : f32)
2462}
2463
2464// -----
2465
2466omp.private {type = private} @x.privatizer : i32 alloc {
2467^bb0(%arg0: i32):
2468  // expected-error @below {{expected exit block terminator to be an `omp.yield` op.}}
2469  omp.terminator
2470}
2471
2472// -----
2473
2474// expected-error @below {{`alloc`: expected 1 region arguments, got: 2}}
2475omp.private {type = private} @x.privatizer : f32 alloc {
2476^bb0(%arg0: f32, %arg1: f32):
2477  omp.yield(%arg0 : f32)
2478}
2479
2480// -----
2481
2482// expected-error @below {{`copy`: expected 2 region arguments, got: 1}}
2483omp.private {type = firstprivate} @x.privatizer : f32 alloc {
2484^bb0(%arg0: f32):
2485  omp.yield(%arg0 : f32)
2486} copy {
2487^bb0(%arg0: f32):
2488  omp.yield(%arg0 : f32)
2489}
2490
2491// -----
2492
2493// expected-error @below {{`dealloc`: expected 1 region arguments, got: 2}}
2494omp.private {type = private} @x.privatizer : f32 alloc {
2495^bb0(%arg0: f32):
2496  omp.yield(%arg0 : f32)
2497} dealloc {
2498^bb0(%arg0: f32, %arg1: f32):
2499  omp.yield
2500}
2501
2502// -----
2503
2504// expected-error @below {{`private` clauses require only an `alloc` region.}}
2505omp.private {type = private} @x.privatizer : f32 alloc {
2506^bb0(%arg0: f32):
2507  omp.yield(%arg0 : f32)
2508} copy {
2509^bb0(%arg0: f32, %arg1 : f32):
2510  omp.yield(%arg0 : f32)
2511}
2512
2513// -----
2514
2515// expected-error @below {{`firstprivate` clauses require both `alloc` and `copy` regions.}}
2516omp.private {type = firstprivate} @x.privatizer : f32 alloc {
2517^bb0(%arg0: f32):
2518  omp.yield(%arg0 : f32)
2519}
2520
2521// -----
2522
2523func.func @private_type_mismatch(%arg0: index) {
2524// expected-error @below {{type mismatch between a private variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
2525  omp.parallel private(@var1.privatizer %arg0 -> %arg2 : index) {
2526    omp.terminator
2527  }
2528
2529  return
2530}
2531
2532omp.private {type = private} @var1.privatizer : !llvm.ptr alloc {
2533^bb0(%arg0: !llvm.ptr):
2534  omp.yield(%arg0 : !llvm.ptr)
2535}
2536
2537// -----
2538
2539func.func @firstprivate_type_mismatch(%arg0: index) {
2540  // expected-error @below {{type mismatch between a firstprivate variable and its privatizer op, var type: 'index' vs. privatizer op type: '!llvm.ptr'}}
2541  omp.parallel private(@var1.privatizer %arg0 -> %arg2 : index) {
2542    omp.terminator
2543  }
2544
2545  return
2546}
2547
2548omp.private {type = firstprivate} @var1.privatizer : !llvm.ptr alloc {
2549^bb0(%arg0: !llvm.ptr):
2550  omp.yield(%arg0 : !llvm.ptr)
2551} copy {
2552^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
2553  omp.yield(%arg0 : !llvm.ptr)
2554}
2555
2556// -----
2557
2558func.func @undefined_privatizer(%arg0: index) {
2559  // expected-error @below {{failed to lookup privatizer op with symbol: '@var1.privatizer'}}
2560  omp.parallel private(@var1.privatizer %arg0 -> %arg2 : index) {
2561    omp.terminator
2562  }
2563
2564  return
2565}
2566
2567// -----
2568func.func @undefined_privatizer(%arg0: !llvm.ptr) {
2569  // expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
2570  "omp.parallel"(%arg0) <{operandSegmentSizes = array<i32: 0, 0, 0, 0, 1, 0>, private_syms = [@x.privatizer, @y.privatizer]}> ({
2571    ^bb0(%arg2: !llvm.ptr):
2572      omp.terminator
2573    }) : (!llvm.ptr) -> ()
2574  return
2575}
2576
2577// -----
2578
2579omp.private {type = private} @var1.privatizer : !llvm.ptr alloc {
2580^bb0(%arg0: !llvm.ptr):
2581  omp.yield(%arg0 : !llvm.ptr)
2582} copy {
2583^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
2584  omp.yield(%arg0 : !llvm.ptr)
2585}
2586
2587func.func @byref_in_private(%arg0: index) {
2588  // expected-error @below {{expected attribute value}}
2589  // expected-error @below {{custom op 'omp.parallel' invalid `private` format}}
2590  omp.parallel private(byref @var1.privatizer %arg0 -> %arg2 : index) {
2591    omp.terminator
2592  }
2593
2594  return
2595}
2596
2597// -----
2598func.func @masked_arg_type_mismatch(%arg0: f32) {
2599  // expected-error @below {{'omp.masked' op operand #0 must be integer or index, but got 'f32'}}
2600  "omp.masked"(%arg0) ({
2601      omp.terminator
2602    }) : (f32) -> ()
2603  return
2604}
2605
2606// -----
2607func.func @masked_arg_count_mismatch(%arg0: i32, %arg1: i32) {
2608  // expected-error @below {{'omp.masked' op operand group starting at #0 requires 0 or 1 element, but found 2}}
2609  "omp.masked"(%arg0, %arg1) ({
2610      omp.terminator
2611    }) : (i32, i32) -> ()
2612  return
2613}
2614
2615// -----
2616func.func @omp_parallel_missing_composite(%lb: index, %ub: index, %step: index) -> () {
2617  // expected-error@+1 {{'omp.composite' attribute missing from composite operation}}
2618  omp.parallel {
2619    omp.distribute {
2620      omp.wsloop {
2621        omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2622          omp.yield
2623        }
2624      } {omp.composite}
2625    } {omp.composite}
2626    omp.terminator
2627  }
2628  return
2629}
2630
2631// -----
2632func.func @omp_parallel_invalid_composite(%lb: index, %ub: index, %step: index) -> () {
2633  // expected-error @below {{'omp.composite' attribute present in non-composite operation}}
2634  omp.parallel {
2635    omp.wsloop {
2636      omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2637        omp.yield
2638      }
2639    }
2640    omp.terminator
2641  } {omp.composite}
2642  return
2643}
2644
2645// -----
2646func.func @omp_parallel_invalid_composite2(%lb: index, %ub: index, %step: index) -> () {
2647  // expected-error @below {{unexpected OpenMP operation inside of composite 'omp.parallel'}}
2648  omp.parallel {
2649    omp.barrier
2650    omp.distribute {
2651      omp.wsloop {
2652        omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2653          omp.yield
2654        }
2655      } {omp.composite}
2656    } {omp.composite}
2657    omp.terminator
2658  } {omp.composite}
2659  return
2660}
2661
2662// -----
2663func.func @omp_wsloop_missing_composite(%lb: index, %ub: index, %step: index) -> () {
2664  // expected-error @below {{'omp.composite' attribute missing from composite wrapper}}
2665  omp.wsloop {
2666    omp.simd {
2667      omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2668        omp.yield
2669      }
2670    } {omp.composite}
2671  }
2672  return
2673}
2674
2675// -----
2676func.func @omp_wsloop_invalid_composite(%lb: index, %ub: index, %step: index) -> () {
2677  // expected-error @below {{'omp.composite' attribute present in non-composite wrapper}}
2678  omp.wsloop {
2679    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2680      omp.yield
2681    }
2682  } {omp.composite}
2683  return
2684}
2685
2686// -----
2687func.func @omp_wsloop_missing_composite_2(%lb: index, %ub: index, %step: index) -> () {
2688  omp.parallel {
2689    omp.distribute {
2690      // expected-error @below {{'omp.composite' attribute missing from composite wrapper}}
2691      omp.wsloop {
2692        omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2693          omp.yield
2694        }
2695      }
2696    } {omp.composite}
2697    omp.terminator
2698  } {omp.composite}
2699  return
2700}
2701
2702// -----
2703func.func @omp_simd_missing_composite(%lb: index, %ub: index, %step: index) -> () {
2704  omp.wsloop {
2705    // expected-error @below {{'omp.composite' attribute missing from composite wrapper}}
2706    omp.simd {
2707      omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2708        omp.yield
2709      }
2710    }
2711  } {omp.composite}
2712  return
2713}
2714
2715// -----
2716func.func @omp_simd_invalid_composite(%lb: index, %ub: index, %step: index) -> () {
2717  // expected-error @below {{'omp.composite' attribute present in non-composite wrapper}}
2718  omp.simd {
2719    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2720      omp.yield
2721    }
2722  } {omp.composite}
2723  return
2724}
2725
2726// -----
2727func.func @omp_distribute_missing_composite(%lb: index, %ub: index, %step: index) -> () {
2728  omp.parallel {
2729    // expected-error @below {{'omp.composite' attribute missing from composite wrapper}}
2730    omp.distribute {
2731      omp.wsloop {
2732        omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2733          omp.yield
2734        }
2735      } {omp.composite}
2736    }
2737    omp.terminator
2738  } {omp.composite}
2739  return
2740}
2741
2742// -----
2743func.func @omp_distribute_invalid_composite(%lb: index, %ub: index, %step: index) -> () {
2744  // expected-error @below {{'omp.composite' attribute present in non-composite wrapper}}
2745  omp.distribute {
2746    omp.loop_nest (%0) : index = (%lb) to (%ub) step (%step) {
2747      omp.yield
2748    }
2749  } {omp.composite}
2750  return
2751}
2752
2753// -----
2754func.func @omp_taskloop_missing_composite(%lb: index, %ub: index, %step: index) -> () {
2755  // expected-error @below {{'omp.composite' attribute missing from composite wrapper}}
2756  omp.taskloop {
2757    omp.simd {
2758      omp.loop_nest (%i) : index = (%lb) to (%ub) step (%step)  {
2759        omp.yield
2760      }
2761    } {omp.composite}
2762  }
2763  return
2764}
2765
2766// -----
2767func.func @omp_taskloop_invalid_composite(%lb: index, %ub: index, %step: index) -> () {
2768  // expected-error @below {{'omp.composite' attribute present in non-composite wrapper}}
2769  omp.taskloop {
2770    omp.loop_nest (%i) : index = (%lb) to (%ub) step (%step)  {
2771      omp.yield
2772    }
2773  } {omp.composite}
2774  return
2775}
2776
2777// -----
2778
2779func.func @omp_loop_invalid_nesting(%lb : index, %ub : index, %step : index) {
2780
2781  // expected-error @below {{`omp.loop` expected to be a standalone loop wrapper}}
2782  omp.loop {
2783    omp.simd {
2784      omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2785        omp.yield
2786      }
2787    } {omp.composite}
2788  }
2789
2790  return
2791}
2792
2793// -----
2794
2795func.func @omp_loop_invalid_nesting2(%lb : index, %ub : index, %step : index) {
2796
2797  omp.simd {
2798    // expected-error @below {{`omp.loop` expected to be a standalone loop wrapper}}
2799    omp.loop {
2800      omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2801        omp.yield
2802      }
2803    } {omp.composite}
2804  }
2805
2806  return
2807}
2808
2809// -----
2810
2811func.func @omp_loop_invalid_binding(%lb : index, %ub : index, %step : index) {
2812
2813  // expected-error @below {{custom op 'omp.loop' invalid clause value: 'dummy_value'}}
2814  omp.loop bind(dummy_value) {
2815    omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2816      omp.yield
2817    }
2818  }
2819  return
2820}
2821
2822// -----
2823func.func @nested_wrapper(%idx : index) {
2824  omp.workshare {
2825    // expected-error @below {{cannot be composite}}
2826    omp.workshare.loop_wrapper {
2827      omp.simd {
2828        omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2829          omp.yield
2830        }
2831      } {omp.composite}
2832    }
2833    omp.terminator
2834  }
2835  return
2836}
2837
2838// -----
2839func.func @not_wrapper() {
2840  omp.workshare {
2841    // expected-error @below {{op nested in loop wrapper is not another loop wrapper or `omp.loop_nest`}}
2842    omp.workshare.loop_wrapper {
2843      %0 = arith.constant 0 : index
2844    }
2845    omp.terminator
2846  }
2847  return
2848}
2849
2850// -----
2851func.func @missing_workshare(%idx : index) {
2852  // expected-error @below {{must be nested in an omp.workshare}}
2853  omp.workshare.loop_wrapper {
2854    omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2855      omp.yield
2856    }
2857  }
2858  return
2859}
2860