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 : i1) if(%n : i1) {
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 @inclusive_not_a_clause(%lb : index, %ub : index, %step : index) {
91  // expected-error @below {{expected 'for'}}
92  omp.wsloop nowait inclusive
93  for (%iv) : index = (%lb) to (%ub) step (%step) {
94    omp.yield
95  }
96}
97
98// -----
99
100func.func @order_value(%lb : index, %ub : index, %step : index) {
101  // expected-error @below {{invalid clause value: 'default'}}
102  omp.wsloop order(default)
103  for (%iv) : index = (%lb) to (%ub) step (%step) {
104    omp.yield
105  }
106}
107
108// -----
109
110func.func @if_not_allowed(%lb : index, %ub : index, %step : index, %bool_var : i1) {
111  // expected-error @below {{expected 'for'}}
112  omp.wsloop if(%bool_var: i1)
113  for (%iv) : index = (%lb) to (%ub) step (%step) {
114    omp.yield
115  }
116}
117
118// -----
119
120func.func @num_threads_not_allowed(%lb : index, %ub : index, %step : index, %int_var : i32) {
121  // expected-error @below {{expected 'for'}}
122  omp.wsloop num_threads(%int_var: i32)
123  for (%iv) : index = (%lb) to (%ub) step (%step) {
124    omp.yield
125  }
126}
127
128// -----
129
130func.func @proc_bind_not_allowed(%lb : index, %ub : index, %step : index) {
131  // expected-error @below {{expected 'for'}}
132  omp.wsloop proc_bind(close)
133  for (%iv) : index = (%lb) to (%ub) step (%step) {
134    omp.yield
135  }
136}
137
138// -----
139
140llvm.func @test_omp_wsloop_dynamic_bad_modifier(%lb : i64, %ub : i64, %step : i64) -> () {
141  // expected-error @+1 {{unknown modifier type: ginandtonic}}
142  omp.wsloop schedule(dynamic, ginandtonic)
143  for (%iv) : i64 = (%lb) to (%ub) step (%step) {
144    omp.yield
145  }
146  llvm.return
147}
148
149// -----
150
151llvm.func @test_omp_wsloop_dynamic_many_modifier(%lb : i64, %ub : i64, %step : i64) -> () {
152  // expected-error @+1 {{unexpected modifier(s)}}
153  omp.wsloop schedule(dynamic, monotonic, monotonic, monotonic)
154  for (%iv) : i64 = (%lb) to (%ub) step (%step) {
155    omp.yield
156  }
157  llvm.return
158}
159
160// -----
161
162llvm.func @test_omp_wsloop_dynamic_wrong_modifier(%lb : i64, %ub : i64, %step : i64) -> () {
163  // expected-error @+1 {{incorrect modifier order}}
164  omp.wsloop schedule(dynamic, simd, monotonic)
165  for (%iv) : i64 = (%lb) to (%ub) step (%step) {
166    omp.yield
167  }
168  llvm.return
169}
170
171// -----
172
173llvm.func @test_omp_wsloop_dynamic_wrong_modifier2(%lb : i64, %ub : i64, %step : i64) -> () {
174  // expected-error @+1 {{incorrect modifier order}}
175  omp.wsloop schedule(dynamic, monotonic, monotonic)
176  for (%iv) : i64 = (%lb) to (%ub) step (%step) {
177    omp.yield
178  }
179  llvm.return
180}
181
182// -----
183
184llvm.func @test_omp_wsloop_dynamic_wrong_modifier3(%lb : i64, %ub : i64, %step : i64) -> () {
185  // expected-error @+1 {{incorrect modifier order}}
186  omp.wsloop schedule(dynamic, simd, simd)
187  for (%iv) : i64 = (%lb) to (%ub) step (%step) {
188    omp.yield
189  }
190  llvm.return
191}
192
193// -----
194
195func.func @omp_simdloop(%lb : index, %ub : index, %step : i32) -> () {
196  // expected-error @below {{op failed to verify that all of {lowerBound, upperBound, step} have same type}}
197  "omp.simdloop" (%lb, %ub, %step) ({
198    ^bb0(%iv: index):
199      omp.yield
200  }) {operand_segment_sizes = dense<[1,1,1]> : vector<3xi32>} :
201    (index, index, i32) -> ()
202
203  return
204}
205
206// -----
207
208// expected-error @below {{op expects initializer region with one argument of the reduction type}}
209omp.reduction.declare @add_f32 : f64
210init {
211^bb0(%arg: f32):
212  %0 = arith.constant 0.0 : f32
213  omp.yield (%0 : f32)
214}
215combiner {
216^bb1(%arg0: f32, %arg1: f32):
217  %1 = arith.addf %arg0, %arg1 : f32
218  omp.yield (%1 : f32)
219}
220
221// -----
222
223// expected-error @below {{expects initializer region to yield a value of the reduction type}}
224omp.reduction.declare @add_f32 : f32
225init {
226^bb0(%arg: f32):
227  %0 = arith.constant 0.0 : f64
228  omp.yield (%0 : f64)
229}
230combiner {
231^bb1(%arg0: f32, %arg1: f32):
232  %1 = arith.addf %arg0, %arg1 : f32
233  omp.yield (%1 : f32)
234}
235
236// -----
237
238// expected-error @below {{expects reduction region with two arguments of the reduction type}}
239omp.reduction.declare @add_f32 : f32
240init {
241^bb0(%arg: f32):
242  %0 = arith.constant 0.0 : f32
243  omp.yield (%0 : f32)
244}
245combiner {
246^bb1(%arg0: f64, %arg1: f64):
247  %1 = arith.addf %arg0, %arg1 : f64
248  omp.yield (%1 : f64)
249}
250
251// -----
252
253// expected-error @below {{expects reduction region to yield a value of the reduction type}}
254omp.reduction.declare @add_f32 : f32
255init {
256^bb0(%arg: f32):
257  %0 = arith.constant 0.0 : f32
258  omp.yield (%0 : f32)
259}
260combiner {
261^bb1(%arg0: f32, %arg1: f32):
262  %1 = arith.addf %arg0, %arg1 : f32
263  %2 = arith.extf %1 : f32 to f64
264  omp.yield (%2 : f64)
265}
266
267// -----
268
269// expected-error @below {{expects atomic reduction region with two arguments of the same type}}
270omp.reduction.declare @add_f32 : f32
271init {
272^bb0(%arg: f32):
273  %0 = arith.constant 0.0 : f32
274  omp.yield (%0 : f32)
275}
276combiner {
277^bb1(%arg0: f32, %arg1: f32):
278  %1 = arith.addf %arg0, %arg1 : f32
279  omp.yield (%1 : f32)
280}
281atomic {
282^bb2(%arg0: memref<f32>, %arg1: memref<f64>):
283  omp.yield
284}
285
286// -----
287
288// expected-error @below {{expects atomic reduction region arguments to be accumulators containing the reduction type}}
289omp.reduction.declare @add_f32 : f32
290init {
291^bb0(%arg: f32):
292  %0 = arith.constant 0.0 : f32
293  omp.yield (%0 : f32)
294}
295combiner {
296^bb1(%arg0: f32, %arg1: f32):
297  %1 = arith.addf %arg0, %arg1 : f32
298  omp.yield (%1 : f32)
299}
300atomic {
301^bb2(%arg0: memref<f64>, %arg1: memref<f64>):
302  omp.yield
303}
304
305// -----
306
307omp.reduction.declare @add_f32 : f32
308init {
309^bb0(%arg: f32):
310  %0 = arith.constant 0.0 : f32
311  omp.yield (%0 : f32)
312}
313combiner {
314^bb1(%arg0: f32, %arg1: f32):
315  %1 = arith.addf %arg0, %arg1 : f32
316  omp.yield (%1 : f32)
317}
318
319func.func @foo(%lb : index, %ub : index, %step : index) {
320  %c1 = arith.constant 1 : i32
321  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
322  %1 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
323
324  omp.wsloop reduction(@add_f32 -> %0 : !llvm.ptr<f32>)
325  for (%iv) : index = (%lb) to (%ub) step (%step) {
326    %2 = arith.constant 2.0 : f32
327    // expected-error @below {{accumulator is not used by the parent}}
328    omp.reduction %2, %1 : !llvm.ptr<f32>
329    omp.yield
330  }
331  return
332}
333
334// -----
335
336func.func @foo(%lb : index, %ub : index, %step : index) {
337  %c1 = arith.constant 1 : i32
338  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
339  %1 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
340
341  // expected-error @below {{expected symbol reference @foo to point to a reduction declaration}}
342  omp.wsloop reduction(@foo -> %0 : !llvm.ptr<f32>)
343  for (%iv) : index = (%lb) to (%ub) step (%step) {
344    %2 = arith.constant 2.0 : f32
345    omp.reduction %2, %1 : !llvm.ptr<f32>
346    omp.yield
347  }
348  return
349}
350
351// -----
352
353omp.reduction.declare @add_f32 : f32
354init {
355^bb0(%arg: f32):
356  %0 = arith.constant 0.0 : f32
357  omp.yield (%0 : f32)
358}
359combiner {
360^bb1(%arg0: f32, %arg1: f32):
361  %1 = arith.addf %arg0, %arg1 : f32
362  omp.yield (%1 : f32)
363}
364
365func.func @foo(%lb : index, %ub : index, %step : index) {
366  %c1 = arith.constant 1 : i32
367  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
368
369  // expected-error @below {{accumulator variable used more than once}}
370  omp.wsloop reduction(@add_f32 -> %0 : !llvm.ptr<f32>, @add_f32 -> %0 : !llvm.ptr<f32>)
371  for (%iv) : index = (%lb) to (%ub) step (%step) {
372    %2 = arith.constant 2.0 : f32
373    omp.reduction %2, %0 : !llvm.ptr<f32>
374    omp.yield
375  }
376  return
377}
378
379// -----
380
381omp.reduction.declare @add_f32 : f32
382init {
383^bb0(%arg: f32):
384  %0 = arith.constant 0.0 : f32
385  omp.yield (%0 : f32)
386}
387combiner {
388^bb1(%arg0: f32, %arg1: f32):
389  %1 = arith.addf %arg0, %arg1 : f32
390  omp.yield (%1 : f32)
391}
392atomic {
393^bb2(%arg2: !llvm.ptr<f32>, %arg3: !llvm.ptr<f32>):
394  %2 = llvm.load %arg3 : !llvm.ptr<f32>
395  llvm.atomicrmw fadd %arg2, %2 monotonic : f32
396  omp.yield
397}
398
399func.func @foo(%lb : index, %ub : index, %step : index, %mem : memref<1xf32>) {
400  %c1 = arith.constant 1 : i32
401
402  // expected-error @below {{expected accumulator ('memref<1xf32>') to be the same type as reduction declaration ('!llvm.ptr<f32>')}}
403  omp.wsloop reduction(@add_f32 -> %mem : memref<1xf32>)
404  for (%iv) : index = (%lb) to (%ub) step (%step) {
405    %2 = arith.constant 2.0 : f32
406    omp.reduction %2, %mem : memref<1xf32>
407    omp.yield
408  }
409  return
410}
411
412// -----
413
414func.func @omp_critical2() -> () {
415  // expected-error @below {{expected symbol reference @excl to point to a critical declaration}}
416  omp.critical(@excl) {
417    omp.terminator
418  }
419  return
420}
421
422// -----
423
424// expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
425omp.critical.declare @mutex hint(uncontended, contended)
426
427// -----
428
429// expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined}}
430omp.critical.declare @mutex hint(nonspeculative, speculative)
431
432// -----
433
434// expected-error @below {{invalid_hint is not a valid hint}}
435omp.critical.declare @mutex hint(invalid_hint)
436
437// -----
438
439func.func @omp_ordered1(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () {
440  omp.wsloop ordered(1)
441  for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
442    // expected-error @below {{ordered region must be closely nested inside a worksharing-loop region with an ordered clause without parameter present}}
443    omp.ordered_region {
444      omp.terminator
445    }
446    omp.yield
447  }
448  return
449}
450
451// -----
452
453func.func @omp_ordered2(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () {
454  omp.wsloop for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
455    // expected-error @below {{ordered region must be closely nested inside a worksharing-loop region with an ordered clause without parameter present}}
456    omp.ordered_region {
457      omp.terminator
458    }
459    omp.yield
460  }
461  return
462}
463
464// -----
465
466func.func @omp_ordered3(%vec0 : i64) -> () {
467  // expected-error @below {{ordered depend directive must be closely nested inside a worksharing-loop with ordered clause with parameter present}}
468  omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {num_loops_val = 1 : i64}
469  return
470}
471
472// -----
473
474func.func @omp_ordered4(%arg1 : i32, %arg2 : i32, %arg3 : i32, %vec0 : i64) -> () {
475  omp.wsloop ordered(0)
476  for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
477    // expected-error @below {{ordered depend directive must be closely nested inside a worksharing-loop with ordered clause with parameter present}}
478    omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {num_loops_val = 1 : i64}
479
480    omp.yield
481  }
482  return
483}
484// -----
485
486func.func @omp_ordered5(%arg1 : i32, %arg2 : i32, %arg3 : i32, %vec0 : i64, %vec1 : i64) -> () {
487  omp.wsloop ordered(1)
488  for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
489    // expected-error @below {{number of variables in depend clause does not match number of iteration variables in the doacross loop}}
490    omp.ordered depend_type(dependsource) depend_vec(%vec0, %vec1 : i64, i64) {num_loops_val = 2 : i64}
491
492    omp.yield
493  }
494  return
495}
496
497// -----
498
499func.func @omp_atomic_read1(%x: memref<i32>, %v: memref<i32>) {
500  // expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined.}}
501  omp.atomic.read %v = %x hint(speculative, nonspeculative) : memref<i32>
502  return
503}
504
505// -----
506
507func.func @omp_atomic_read2(%x: memref<i32>, %v: memref<i32>) {
508  // expected-error @below {{invalid clause value: 'xyz'}}
509  omp.atomic.read %v = %x memory_order(xyz) : memref<i32>
510  return
511}
512
513// -----
514
515func.func @omp_atomic_read3(%x: memref<i32>, %v: memref<i32>) {
516  // expected-error @below {{memory-order must not be acq_rel or release for atomic reads}}
517  omp.atomic.read %v = %x memory_order(acq_rel) : memref<i32>
518  return
519}
520
521// -----
522
523func.func @omp_atomic_read4(%x: memref<i32>, %v: memref<i32>) {
524  // expected-error @below {{memory-order must not be acq_rel or release for atomic reads}}
525  omp.atomic.read %v = %x memory_order(release) : memref<i32>
526  return
527}
528
529// -----
530
531func.func @omp_atomic_read5(%x: memref<i32>, %v: memref<i32>) {
532  // expected-error @below {{`memory_order` clause can appear at most once in the expansion of the oilist directive}}
533  omp.atomic.read %v = %x memory_order(acquire) memory_order(relaxed) : memref<i32>
534  return
535}
536
537// -----
538
539func.func @omp_atomic_read6(%x: memref<i32>, %v: memref<i32>) {
540  // expected-error @below {{`hint` clause can appear at most once in the expansion of the oilist directive}}
541  omp.atomic.read %v =  %x hint(speculative) hint(contended) : memref<i32>
542  return
543}
544
545// -----
546
547func.func @omp_atomic_read6(%x: memref<i32>, %v: memref<i32>) {
548  // expected-error @below {{read and write must not be to the same location for atomic reads}}
549  omp.atomic.read %x =  %x hint(speculative) : memref<i32>
550  return
551}
552
553// -----
554
555func.func @omp_atomic_write1(%addr : memref<i32>, %val : i32) {
556  // expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
557  omp.atomic.write  %addr = %val hint(contended, uncontended) : memref<i32>, i32
558  return
559}
560
561// -----
562
563func.func @omp_atomic_write2(%addr : memref<i32>, %val : i32) {
564  // expected-error @below {{memory-order must not be acq_rel or acquire for atomic writes}}
565  omp.atomic.write  %addr = %val memory_order(acq_rel) : memref<i32>, i32
566  return
567}
568
569// -----
570
571func.func @omp_atomic_write3(%addr : memref<i32>, %val : i32) {
572  // expected-error @below {{memory-order must not be acq_rel or acquire for atomic writes}}
573  omp.atomic.write  %addr = %val memory_order(acquire) : memref<i32>, i32
574  return
575}
576
577// -----
578
579func.func @omp_atomic_write4(%addr : memref<i32>, %val : i32) {
580  // expected-error @below {{`memory_order` clause can appear at most once in the expansion of the oilist directive}}
581  omp.atomic.write  %addr = %val memory_order(release) memory_order(seq_cst) : memref<i32>, i32
582  return
583}
584
585// -----
586
587func.func @omp_atomic_write5(%addr : memref<i32>, %val : i32) {
588  // expected-error @below {{`hint` clause can appear at most once in the expansion of the oilist directive}}
589  omp.atomic.write  %addr = %val hint(contended) hint(speculative) : memref<i32>, i32
590  return
591}
592
593// -----
594
595func.func @omp_atomic_write6(%addr : memref<i32>, %val : i32) {
596  // expected-error @below {{invalid clause value: 'xyz'}}
597  omp.atomic.write  %addr = %val memory_order(xyz) : memref<i32>, i32
598  return
599}
600
601// -----
602
603func.func @omp_atomic_update1(%x: memref<i32>, %expr: f32) {
604  // 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}}
605  omp.atomic.update %x : memref<i32> {
606  ^bb0(%xval: f32):
607    %newval = llvm.fadd %xval, %expr : f32
608    omp.yield (%newval : f32)
609  }
610  return
611}
612
613// -----
614
615func.func @omp_atomic_update2(%x: memref<i32>, %expr: i32) {
616  // expected-error @+2 {{op expects regions to end with 'omp.yield', found 'omp.terminator'}}
617  // expected-note @below {{in custom textual format, the absence of terminator implies 'omp.yield'}}
618  omp.atomic.update %x : memref<i32> {
619  ^bb0(%xval: i32):
620    %newval = llvm.add %xval, %expr : i32
621    omp.terminator
622  }
623  return
624}
625
626// -----
627
628func.func @omp_atomic_update3(%x: memref<i32>, %expr: i32) {
629  // expected-error @below {{memory-order must not be acq_rel or acquire for atomic updates}}
630  omp.atomic.update memory_order(acq_rel) %x : memref<i32> {
631  ^bb0(%xval: i32):
632    %newval = llvm.add %xval, %expr : i32
633    omp.yield (%newval : i32)
634  }
635  return
636}
637
638// -----
639
640func.func @omp_atomic_update4(%x: memref<i32>, %expr: i32) {
641  // expected-error @below {{memory-order must not be acq_rel or acquire for atomic updates}}
642  omp.atomic.update memory_order(acquire) %x : memref<i32> {
643  ^bb0(%xval: i32):
644    %newval = llvm.add %xval, %expr : i32
645    omp.yield (%newval : i32)
646  }
647  return
648}
649
650// -----
651
652func.func @omp_atomic_update5(%x: memref<i32>, %expr: i32) {
653  // expected-error @below {{invalid kind of type specified}}
654  omp.atomic.update %x : i32 {
655  ^bb0(%xval: i32):
656    %newval = llvm.add %xval, %expr : i32
657    omp.yield (%newval : i32)
658  }
659  return
660}
661
662// -----
663
664func.func @omp_atomic_update6(%x: memref<i32>, %expr: i32) {
665  // expected-error @below {{only updated value must be returned}}
666  omp.atomic.update %x : memref<i32> {
667  ^bb0(%xval: i32):
668    %newval = llvm.add %xval, %expr : i32
669    omp.yield (%newval, %expr : i32, i32)
670  }
671  return
672}
673
674// -----
675
676func.func @omp_atomic_update7(%x: memref<i32>, %expr: i32, %y: f32) {
677  // expected-error @below {{input and yielded value must have the same type}}
678  omp.atomic.update %x : memref<i32> {
679  ^bb0(%xval: i32):
680    %newval = llvm.add %xval, %expr : i32
681    omp.yield (%y: f32)
682  }
683  return
684}
685
686// -----
687
688func.func @omp_atomic_update8(%x: memref<i32>, %expr: i32) {
689  // expected-error @below {{the region must accept exactly one argument}}
690  omp.atomic.update %x : memref<i32> {
691  ^bb0(%xval: i32, %tmp: i32):
692    %newval = llvm.add %xval, %expr : i32
693    omp.yield (%newval : i32)
694  }
695  return
696}
697
698// -----
699
700func.func @omp_atomic_update9(%x: memref<i32>, %expr: i32) {
701  // expected-error @below {{the update region must have at least two operations (binop and terminator)}}
702  omp.atomic.update %x : memref<i32> {
703  ^bb0(%xval: i32):
704    omp.yield (%xval : i32)
705  }
706  return
707}
708
709// -----
710
711func.func @omp_atomic_update(%x: memref<i32>, %expr: i32) {
712  // expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
713  omp.atomic.update hint(uncontended, contended) %x : memref<i32> {
714  ^bb0(%xval: i32):
715    %newval = llvm.add %xval, %expr : i32
716    omp.yield (%newval : i32)
717  }
718  return
719}
720
721// -----
722
723func.func @omp_atomic_update(%x: memref<i32>, %expr: i32) {
724  // expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined}}
725  omp.atomic.update hint(nonspeculative, speculative) %x : memref<i32> {
726  ^bb0(%xval: i32):
727    %newval = llvm.add %xval, %expr : i32
728    omp.yield (%newval : i32)
729  }
730  return
731}
732
733// -----
734
735func.func @omp_atomic_update(%x: memref<i32>, %expr: i32) {
736  // expected-error @below {{invalid_hint is not a valid hint}}
737  omp.atomic.update hint(invalid_hint) %x : memref<i32> {
738  ^bb0(%xval: i32):
739    %newval = llvm.add %xval, %expr : i32
740    omp.yield (%newval : i32)
741  }
742  return
743}
744
745// -----
746
747func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
748  // expected-error @below {{expected three operations in omp.atomic.capture region}}
749  omp.atomic.capture {
750    omp.atomic.read %v = %x : memref<i32>
751    omp.terminator
752  }
753  return
754}
755
756// -----
757
758func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
759  omp.atomic.capture {
760    // expected-error @below {{invalid sequence of operations in the capture region}}
761    omp.atomic.read %v = %x : memref<i32>
762    omp.atomic.read %v = %x : memref<i32>
763    omp.terminator
764  }
765  return
766}
767
768// -----
769
770func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
771  omp.atomic.capture {
772    // expected-error @below {{invalid sequence of operations in the capture region}}
773    omp.atomic.update %x : memref<i32> {
774    ^bb0(%xval: i32):
775      %newval = llvm.add %xval, %expr : i32
776      omp.yield (%newval : i32)
777    }
778    omp.atomic.update %x : memref<i32> {
779    ^bb0(%xval: i32):
780      %newval = llvm.add %xval, %expr : i32
781      omp.yield (%newval : i32)
782    }
783    omp.terminator
784  }
785  return
786}
787
788// -----
789
790func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
791  omp.atomic.capture {
792    // expected-error @below {{invalid sequence of operations in the capture region}}
793    omp.atomic.write %x = %expr : memref<i32>, i32
794    omp.atomic.write %x = %expr : memref<i32>, i32
795    omp.terminator
796  }
797  return
798}
799
800// -----
801
802func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
803  omp.atomic.capture {
804    // expected-error @below {{invalid sequence of operations in the capture region}}
805    omp.atomic.write %x = %expr : memref<i32>, i32
806    omp.atomic.update %x : memref<i32> {
807    ^bb0(%xval: i32):
808      %newval = llvm.add %xval, %expr : i32
809      omp.yield (%newval : i32)
810    }
811    omp.terminator
812  }
813  return
814}
815
816// -----
817
818func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
819  omp.atomic.capture {
820    // expected-error @below {{invalid sequence of operations in the capture region}}
821    omp.atomic.update %x : memref<i32> {
822    ^bb0(%xval: i32):
823      %newval = llvm.add %xval, %expr : i32
824      omp.yield (%newval : i32)
825    }
826    omp.atomic.write %x = %expr : memref<i32>, i32
827    omp.terminator
828  }
829  return
830}
831
832// -----
833
834func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
835  omp.atomic.capture {
836    // expected-error @below {{invalid sequence of operations in the capture region}}
837    omp.atomic.write %x = %expr : memref<i32>, i32
838    omp.atomic.read %v = %x : memref<i32>
839    omp.terminator
840  }
841  return
842}
843
844// -----
845
846func.func @omp_atomic_capture(%x: memref<i32>, %y: memref<i32>, %v: memref<i32>, %expr: i32) {
847  omp.atomic.capture {
848    // expected-error @below {{updated variable in omp.atomic.update must be captured in second operation}}
849    omp.atomic.update %x : memref<i32> {
850    ^bb0(%xval: i32):
851      %newval = llvm.add %xval, %expr : i32
852      omp.yield (%newval : i32)
853    }
854    omp.atomic.read %v = %y : memref<i32>
855    omp.terminator
856  }
857}
858
859// -----
860
861func.func @omp_atomic_capture(%x: memref<i32>, %y: memref<i32>, %v: memref<i32>, %expr: i32) {
862  omp.atomic.capture {
863    // expected-error @below {{captured variable in omp.atomic.read must be updated in second operation}}
864    omp.atomic.read %v = %y : memref<i32>
865    omp.atomic.update %x : memref<i32> {
866    ^bb0(%xval: i32):
867      %newval = llvm.add %xval, %expr : i32
868      omp.yield (%newval : i32)
869    }
870    omp.terminator
871  }
872}
873
874// -----
875
876func.func @omp_atomic_capture(%x: memref<i32>, %y: memref<i32>, %v: memref<i32>, %expr: i32) {
877  omp.atomic.capture {
878    // expected-error @below {{captured variable in omp.atomic.read must be updated in second operation}}
879    omp.atomic.read %v = %x : memref<i32>
880    omp.atomic.write %y = %expr : memref<i32>, i32
881    omp.terminator
882  }
883}
884
885// -----
886
887func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
888  // expected-error @below {{the hints omp_sync_hint_uncontended and omp_sync_hint_contended cannot be combined}}
889  omp.atomic.capture hint(contended, uncontended) {
890    omp.atomic.update %x : memref<i32> {
891    ^bb0(%xval: i32):
892      %newval = llvm.add %xval, %expr : i32
893      omp.yield(%newval : i32)
894    }
895    omp.atomic.read %v = %x : memref<i32>
896  }
897  return
898}
899
900// -----
901
902func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
903  // expected-error @below {{the hints omp_sync_hint_nonspeculative and omp_sync_hint_speculative cannot be combined}}
904  omp.atomic.capture hint(nonspeculative, speculative) {
905    omp.atomic.update %x : memref<i32> {
906    ^bb0(%xval: i32):
907      %newval = llvm.add %xval, %expr : i32
908      omp.yield(%newval : i32)
909    }
910    omp.atomic.read %v = %x : memref<i32>
911  }
912  return
913}
914
915// -----
916
917func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
918  // expected-error @below {{invalid_hint is not a valid hint}}
919  omp.atomic.capture hint(invalid_hint) {
920    omp.atomic.update %x : memref<i32> {
921    ^bb0(%xval: i32):
922      %newval = llvm.add %xval, %expr : i32
923      omp.yield(%newval : i32)
924    }
925    omp.atomic.read %v = %x : memref<i32>
926  }
927  return
928}
929
930// -----
931
932func.func @omp_atomic_capture(%x: memref<i32>, %v: memref<i32>, %expr: i32) {
933  // expected-error @below {{operations inside capture region must not have hint clause}}
934  omp.atomic.capture {
935    omp.atomic.update hint(uncontended) %x : memref<i32> {
936    ^bb0(%xval: i32):
937      %newval = llvm.add %xval, %expr : i32
938      omp.yield(%newval : i32)
939    }
940    omp.atomic.read %v = %x : memref<i32>
941  }
942  return
943}
944
945// -----
946
947func.func @omp_sections(%data_var : memref<i32>) -> () {
948  // expected-error @below {{expected equal sizes for allocate and allocator variables}}
949  "omp.sections" (%data_var) ({
950    omp.terminator
951  }) {operand_segment_sizes = dense<[0,1,0]> : vector<3xi32>} : (memref<i32>) -> ()
952  return
953}
954
955// -----
956
957func.func @omp_sections(%data_var : memref<i32>) -> () {
958  // expected-error @below {{expected as many reduction symbol references as reduction variables}}
959  "omp.sections" (%data_var) ({
960    omp.terminator
961  }) {operand_segment_sizes = dense<[1,0,0]> : vector<3xi32>} : (memref<i32>) -> ()
962  return
963}
964
965// -----
966
967func.func @omp_sections(%data_var : memref<i32>) -> () {
968  // expected-error @below {{expected omp.section op or terminator op inside region}}
969  omp.sections {
970    "test.payload" () : () -> ()
971  }
972  return
973}
974
975// -----
976
977func.func @omp_sections(%cond : i1) {
978  // expected-error @below {{expected '{' to begin a region}}
979  omp.sections if(%cond) {
980    omp.terminator
981  }
982  return
983}
984
985// -----
986
987func.func @omp_sections() {
988  // expected-error @below {{expected '{' to begin a region}}
989  omp.sections num_threads(10) {
990    omp.terminator
991  }
992  return
993}
994
995// -----
996
997func.func @omp_sections() {
998  // expected-error @below {{expected '{' to begin a region}}
999  omp.sections proc_bind(close) {
1000    omp.terminator
1001  }
1002  return
1003}
1004
1005// -----
1006
1007func.func @omp_sections(%data_var : memref<i32>, %linear_var : i32) {
1008  // expected-error @below {{expected '{' to begin a region}}
1009  omp.sections linear(%data_var = %linear_var : memref<i32>) {
1010    omp.terminator
1011  }
1012  return
1013}
1014
1015// -----
1016
1017func.func @omp_sections() {
1018  // expected-error @below {{expected '{' to begin a region}}
1019  omp.sections schedule(static, none) {
1020    omp.terminator
1021  }
1022  return
1023}
1024
1025// -----
1026
1027func.func @omp_sections() {
1028  // expected-error @below {{expected '{' to begin a region}}
1029  omp.sections collapse(3) {
1030    omp.terminator
1031  }
1032  return
1033}
1034
1035// -----
1036
1037func.func @omp_sections() {
1038  // expected-error @below {{expected '{' to begin a region}}
1039  omp.sections ordered(2) {
1040    omp.terminator
1041  }
1042  return
1043}
1044
1045// -----
1046
1047func.func @omp_sections() {
1048  // expected-error @below {{expected '{' to begin a region}}
1049  omp.sections order(concurrent) {
1050    omp.terminator
1051  }
1052  return
1053}
1054
1055// -----
1056
1057func.func @omp_sections() {
1058  // expected-error @below {{failed to verify constraint: region with 1 blocks}}
1059  omp.sections {
1060    omp.section {
1061      omp.terminator
1062    }
1063    omp.terminator
1064  ^bb2:
1065    omp.terminator
1066  }
1067  return
1068}
1069
1070// -----
1071
1072func.func @omp_single(%data_var : memref<i32>) -> () {
1073  // expected-error @below {{expected equal sizes for allocate and allocator variables}}
1074  "omp.single" (%data_var) ({
1075    omp.barrier
1076  }) {operand_segment_sizes = dense<[1,0]> : vector<2xi32>} : (memref<i32>) -> ()
1077  return
1078}
1079
1080// -----
1081
1082func.func @omp_task(%ptr: !llvm.ptr<f32>) {
1083  // expected-error @below {{op expected symbol reference @add_f32 to point to a reduction declaration}}
1084  omp.task in_reduction(@add_f32 -> %ptr : !llvm.ptr<f32>) {
1085    // CHECK: "test.foo"() : () -> ()
1086    "test.foo"() : () -> ()
1087    // CHECK: omp.terminator
1088    omp.terminator
1089  }
1090}
1091
1092// -----
1093
1094omp.reduction.declare @add_f32 : f32
1095init {
1096^bb0(%arg: f32):
1097  %0 = arith.constant 0.0 : f32
1098  omp.yield (%0 : f32)
1099}
1100combiner {
1101^bb1(%arg0: f32, %arg1: f32):
1102  %1 = arith.addf %arg0, %arg1 : f32
1103  omp.yield (%1 : f32)
1104}
1105
1106func.func @omp_task(%ptr: !llvm.ptr<f32>) {
1107  // expected-error @below {{op accumulator variable used more than once}}
1108  omp.task in_reduction(@add_f32 -> %ptr : !llvm.ptr<f32>, @add_f32 -> %ptr : !llvm.ptr<f32>) {
1109    // CHECK: "test.foo"() : () -> ()
1110    "test.foo"() : () -> ()
1111    // CHECK: omp.terminator
1112    omp.terminator
1113  }
1114}
1115
1116// -----
1117
1118omp.reduction.declare @add_i32 : i32
1119init {
1120^bb0(%arg: i32):
1121  %0 = arith.constant 0 : i32
1122  omp.yield (%0 : i32)
1123}
1124combiner {
1125^bb1(%arg0: i32, %arg1: i32):
1126  %1 = arith.addi %arg0, %arg1 : i32
1127  omp.yield (%1 : i32)
1128}
1129atomic {
1130^bb2(%arg2: !llvm.ptr<i32>, %arg3: !llvm.ptr<i32>):
1131  %2 = llvm.load %arg3 : !llvm.ptr<i32>
1132  llvm.atomicrmw add %arg2, %2 monotonic : i32
1133  omp.yield
1134}
1135
1136func.func @omp_task(%mem: memref<1xf32>) {
1137  // expected-error @below {{op expected accumulator ('memref<1xf32>') to be the same type as reduction declaration ('!llvm.ptr<i32>')}}
1138  omp.task in_reduction(@add_i32 -> %mem : memref<1xf32>) {
1139    // CHECK: "test.foo"() : () -> ()
1140    "test.foo"() : () -> ()
1141    // CHECK: omp.terminator
1142    omp.terminator
1143  }
1144  return
1145}
1146
1147// -----
1148
1149func.func @omp_cancel() {
1150  omp.sections {
1151    // expected-error @below {{cancel parallel must appear inside a parallel region}}
1152    omp.cancel cancellation_construct_type(parallel)
1153    // CHECK: omp.terminator
1154    omp.terminator
1155  }
1156  return
1157}
1158
1159// -----
1160
1161func.func @omp_cancel1() {
1162  omp.parallel {
1163    // expected-error @below {{cancel sections must appear inside a sections region}}
1164    omp.cancel cancellation_construct_type(sections)
1165    // CHECK: omp.terminator
1166    omp.terminator
1167  }
1168  return
1169}
1170
1171// -----
1172
1173func.func @omp_cancel2() {
1174  omp.sections {
1175    // expected-error @below {{cancel loop must appear inside a worksharing-loop region}}
1176    omp.cancel cancellation_construct_type(loop)
1177    // CHECK: omp.terminator
1178    omp.terminator
1179  }
1180  return
1181}
1182
1183// -----
1184
1185func.func @omp_cancel3(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () {
1186  omp.wsloop nowait
1187    for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
1188    // expected-error @below {{A worksharing construct that is canceled must not have a nowait clause}}
1189    omp.cancel cancellation_construct_type(loop)
1190    // CHECK: omp.terminator
1191    omp.terminator
1192  }
1193  return
1194}
1195
1196// -----
1197
1198func.func @omp_cancel4(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () {
1199  omp.wsloop ordered(1)
1200    for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
1201    // expected-error @below {{A worksharing construct that is canceled must not have an ordered clause}}
1202    omp.cancel cancellation_construct_type(loop)
1203    // CHECK: omp.terminator
1204    omp.terminator
1205  }
1206  return
1207}
1208
1209// -----
1210
1211func.func @omp_cancel5() -> () {
1212  omp.sections nowait {
1213    omp.section {
1214      // expected-error @below {{A sections construct that is canceled must not have a nowait clause}}
1215      omp.cancel cancellation_construct_type(sections)
1216      omp.terminator
1217    }
1218    // CHECK: omp.terminator
1219    omp.terminator
1220  }
1221  return
1222}
1223
1224// -----
1225
1226func.func @omp_cancellationpoint() {
1227  omp.sections {
1228    // expected-error @below {{cancellation point parallel must appear inside a parallel region}}
1229    omp.cancellationpoint cancellation_construct_type(parallel)
1230    // CHECK: omp.terminator
1231    omp.terminator
1232  }
1233  return
1234}
1235
1236// -----
1237
1238func.func @omp_cancellationpoint1() {
1239  omp.parallel {
1240    // expected-error @below {{cancellation point sections must appear inside a sections region}}
1241    omp.cancellationpoint cancellation_construct_type(sections)
1242    // CHECK: omp.terminator
1243    omp.terminator
1244  }
1245  return
1246}
1247
1248// -----
1249
1250func.func @omp_cancellationpoint2() {
1251  omp.sections {
1252    // expected-error @below {{cancellation point loop must appear inside a worksharing-loop region}}
1253    omp.cancellationpoint cancellation_construct_type(loop)
1254    // CHECK: omp.terminator
1255    omp.terminator
1256  }
1257  return
1258}
1259