Reland [OffloadBundler] Compress bundles over 4GB (#122307)
[llvm-project.git] / mlir / test / Dialect / OpenMP / ops.mlir
blobb1901c333ade8dab05a7f26acfb50d3b4b674e9d
1 // RUN: mlir-opt %s | mlir-opt | FileCheck %s
3 func.func @omp_barrier() -> () {
4   // CHECK: omp.barrier
5   omp.barrier
6   return
9 func.func @omp_master() -> () {
10   // CHECK: omp.master
11   omp.master {
12     // CHECK: omp.terminator
13     omp.terminator
14   }
16   return
19 // CHECK-LABEL: omp_masked
20 func.func @omp_masked(%filtered_thread_id : i32) -> () {
21   // CHECK: omp.masked filter(%{{.*}} : i32)
22   "omp.masked" (%filtered_thread_id) ({
23     omp.terminator
24   }) : (i32) -> ()
26   // CHECK: omp.masked
27   "omp.masked" () ({
28     omp.terminator
29   }) : () -> ()
30   return
33 func.func @omp_taskwait() -> () {
34   // CHECK: omp.taskwait
35   omp.taskwait
36   return
39 func.func @omp_taskyield() -> () {
40   // CHECK: omp.taskyield
41   omp.taskyield
42   return
45 // CHECK-LABEL: func @omp_flush
46 // CHECK-SAME: ([[ARG0:%.*]]: memref<i32>) {
47 func.func @omp_flush(%arg0 : memref<i32>) -> () {
48   // Test without data var
49   // CHECK: omp.flush
50   omp.flush
52   // Test with one data var
53   // CHECK: omp.flush([[ARG0]] : memref<i32>)
54   omp.flush(%arg0 : memref<i32>)
56   // Test with two data var
57   // CHECK: omp.flush([[ARG0]], [[ARG0]] : memref<i32>, memref<i32>)
58   omp.flush(%arg0, %arg0: memref<i32>, memref<i32>)
60   return
63 func.func @omp_terminator() -> () {
64   // CHECK: omp.terminator
65   omp.terminator
68 func.func @omp_parallel(%data_var : memref<i32>, %if_cond : i1, %num_threads : i32, %idx : index) -> () {
69   // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) if(%{{.*}}) num_threads(%{{.*}} : i32)
70   "omp.parallel" (%data_var, %data_var, %if_cond, %num_threads) ({
72   // test without if condition
73   // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) num_threads(%{{.*}} : i32)
74     "omp.parallel"(%data_var, %data_var, %num_threads) ({
75       omp.terminator
76     }) {operandSegmentSizes = array<i32: 1,1,0,1,0,0>} : (memref<i32>, memref<i32>, i32) -> ()
78   // CHECK: omp.barrier
79     omp.barrier
81   // test without num_threads
82   // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) if(%{{.*}})
83     "omp.parallel"(%data_var, %data_var, %if_cond) ({
84       omp.terminator
85     }) {operandSegmentSizes = array<i32: 1,1,1,0,0,0>} : (memref<i32>, memref<i32>, i1) -> ()
87   // test without allocate
88   // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32)
89     "omp.parallel"(%if_cond, %num_threads) ({
90       omp.terminator
91     }) {operandSegmentSizes = array<i32: 0,0,1,1,0,0>} : (i1, i32) -> ()
93     omp.terminator
94   }) {operandSegmentSizes = array<i32: 1,1,1,1,0,0>, proc_bind_kind = #omp<procbindkind spread>} : (memref<i32>, memref<i32>, i1, i32) -> ()
96   // test with multiple parameters for single variadic argument
97   // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
98   "omp.parallel" (%data_var, %data_var) ({
99     omp.terminator
100   }) {operandSegmentSizes = array<i32: 1,1,0,0,0,0>} : (memref<i32>, memref<i32>) -> ()
102   // CHECK: omp.parallel
103   omp.parallel {
104     // CHECK-NOT: omp.terminator
105     // CHECK: omp.distribute
106     omp.distribute {
107       // CHECK-NEXT: omp.wsloop
108       omp.wsloop {
109         // CHECK-NEXT: omp.loop_nest
110         omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
111           omp.yield
112         }
113       } {omp.composite}
114     } {omp.composite}
115     omp.terminator
116   } {omp.composite}
118   // CHECK: omp.parallel
119   omp.parallel {
120     // CHECK-NOT: omp.terminator
121     // CHECK: omp.distribute
122     omp.distribute {
123       // CHECK-NEXT: omp.wsloop
124       omp.wsloop {
125         // CHECK-NEXT: omp.simd
126         omp.simd {
127           // CHECK-NEXT: omp.loop_nest
128           omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
129             omp.yield
130           }
131         } {omp.composite}
132       } {omp.composite}
133     } {omp.composite}
134     omp.terminator
135   } {omp.composite}
137   return
140 func.func @omp_parallel_pretty(%data_var : memref<i32>, %if_cond : i1, %num_threads : i32, %allocator : si32) -> () {
141  // CHECK: omp.parallel
142  omp.parallel {
143   omp.terminator
146  // CHECK: omp.parallel num_threads(%{{.*}} : i32)
147  omp.parallel num_threads(%num_threads : i32) {
148    omp.terminator
151  %n_index = arith.constant 2 : index
152  // CHECK: omp.parallel num_threads(%{{.*}} : index)
153  omp.parallel num_threads(%n_index : index) {
154    omp.terminator
157  %n_i64 = arith.constant 4 : i64
158  // CHECK: omp.parallel num_threads(%{{.*}} : i64)
159  omp.parallel num_threads(%n_i64 : i64) {
160    omp.terminator
163  // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
164  omp.parallel allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
165    omp.terminator
168  // CHECK: omp.parallel
169  // CHECK-NEXT: omp.parallel if(%{{.*}})
170  omp.parallel {
171    omp.parallel if(%if_cond) {
172      omp.terminator
173    }
174    omp.terminator
177  // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) proc_bind(close)
178  omp.parallel num_threads(%num_threads : i32) if(%if_cond) proc_bind(close) {
179    omp.terminator
182   return
185 // CHECK-LABEL: omp_loop_nest
186 func.func @omp_loop_nest(%lb : index, %ub : index, %step : index) -> () {
187   omp.wsloop {
188     // CHECK: omp.loop_nest
189     // CHECK-SAME: (%{{.*}}) : index =
190     // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}})
191     "omp.loop_nest" (%lb, %ub, %step) ({
192     ^bb0(%iv: index):
193       omp.yield
194     }) : (index, index, index) -> ()
195   }
197   omp.wsloop {
198     // CHECK: omp.loop_nest
199     // CHECK-SAME: (%{{.*}}) : index =
200     // CHECK-SAME: (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}})
201     "omp.loop_nest" (%lb, %ub, %step) ({
202     ^bb0(%iv: index):
203       omp.yield
204     }) {loop_inclusive} : (index, index, index) -> ()
205   }
207   omp.wsloop {
208     // CHECK: omp.loop_nest
209     // CHECK-SAME: (%{{.*}}, %{{.*}}) : index =
210     // CHECK-SAME: (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}})
211     "omp.loop_nest" (%lb, %lb, %ub, %ub, %step, %step) ({
212     ^bb0(%iv: index, %iv3: index):
213       omp.yield
214     }) : (index, index, index, index, index, index) -> ()
215   }
217   omp.wsloop {
218     // CHECK: omp.loop_nest
219     // CHECK-SAME: (%{{.*}}) : index =
220     // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}})
221     "omp.loop_nest" (%lb, %ub, %step) ({
222     ^bb0(%iv: index):
223       // CHECK: test.op1
224       "test.op1"(%lb) : (index) -> ()
225       // CHECK: test.op2
226       "test.op2"() : () -> ()
227       // CHECK: omp.yield
228       omp.yield
229     }) : (index, index, index) -> ()
230   }
232   return
235 // CHECK-LABEL: omp_loop_nest_pretty
236 func.func @omp_loop_nest_pretty(%lb : index, %ub : index, %step : index) -> () {
237   omp.wsloop {
238     // CHECK: omp.loop_nest
239     // CHECK-SAME: (%{{.*}}) : index =
240     // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}})
241     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
242       omp.yield
243     }
244   }
246   omp.wsloop {
247     // CHECK: omp.loop_nest
248     // CHECK-SAME: (%{{.*}}) : index =
249     // CHECK-SAME: (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}})
250     omp.loop_nest (%iv) : index = (%lb) to (%ub) inclusive step (%step) {
251       omp.yield
252     }
253   }
255   omp.wsloop {
256     // CHECK: omp.loop_nest
257     // CHECK-SAME: (%{{.*}}) : index =
258     // CHECK-SAME: (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}})
259     omp.loop_nest (%iv1, %iv2) : index = (%lb, %lb) to (%ub, %ub) step (%step, %step) {
260       omp.yield
261     }
262   }
264   omp.wsloop {
265     // CHECK: omp.loop_nest
266     // CHECK-SAME: (%{{.*}}) : index =
267     // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}})
268     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step)  {
269       // CHECK: test.op1
270       "test.op1"(%lb) : (index) -> ()
271       // CHECK: test.op2
272       "test.op2"() : () -> ()
273       // CHECK: omp.yield
274       omp.yield
275     }
276   }
278   return
281 // CHECK-LABEL: omp_loop_nest_pretty_multi_block
282 func.func @omp_loop_nest_pretty_multi_block(%lb : index, %ub : index,
283     %step : index, %data1 : memref<?xi32>, %data2 : memref<?xi32>) -> () {
285   omp.wsloop {
286     // CHECK: omp.loop_nest (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
287     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
288       %1 = "test.payload"(%iv) : (index) -> (i32)
289       cf.br ^bb1(%1: i32)
290     ^bb1(%arg: i32):
291       memref.store %arg, %data1[%iv] : memref<?xi32>
292       omp.yield
293     }
294   }
296   omp.wsloop {
297     // CHECK: omp.loop_nest (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
298     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
299       %c = "test.condition"(%iv) : (index) -> (i1)
300       %v1 = "test.payload"(%iv) : (index) -> (i32)
301       cf.cond_br %c, ^bb1(%v1: i32), ^bb2(%v1: i32)
302     ^bb1(%arg0: i32):
303       memref.store %arg0, %data1[%iv] : memref<?xi32>
304       cf.br ^bb3
305     ^bb2(%arg1: i32):
306       memref.store %arg1, %data2[%iv] : memref<?xi32>
307       cf.br ^bb3
308     ^bb3:
309       omp.yield
310     }
311   }
313   omp.wsloop {
314     // CHECK: omp.loop_nest (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
315     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
316       %c = "test.condition"(%iv) : (index) -> (i1)
317       %v1 = "test.payload"(%iv) : (index) -> (i32)
318       cf.cond_br %c, ^bb1(%v1: i32), ^bb2(%v1: i32)
319     ^bb1(%arg0: i32):
320       memref.store %arg0, %data1[%iv] : memref<?xi32>
321       omp.yield
322     ^bb2(%arg1: i32):
323       memref.store %arg1, %data2[%iv] : memref<?xi32>
324       omp.yield
325     }
326   }
328   return
331 // CHECK-LABEL: omp_loop_nest_pretty_non_index
332 func.func @omp_loop_nest_pretty_non_index(%lb1 : i32, %ub1 : i32, %step1 : i32,
333     %lb2 : i64, %ub2 : i64, %step2 : i64, %data1 : memref<?xi32>,
334     %data2 : memref<?xi64>) -> () {
336   omp.wsloop {
337     // CHECK: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
338     omp.loop_nest (%iv1) : i32 = (%lb1) to (%ub1) step (%step1) {
339       %1 = "test.payload"(%iv1) : (i32) -> (index)
340       cf.br ^bb1(%1: index)
341     ^bb1(%arg1: index):
342       memref.store %iv1, %data1[%arg1] : memref<?xi32>
343       omp.yield
344     }
345   }
347   omp.wsloop {
348     // CHECK: omp.loop_nest (%{{.*}}) : i64 = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
349     omp.loop_nest (%iv) : i64 = (%lb2) to (%ub2) step (%step2) {
350       %2 = "test.payload"(%iv) : (i64) -> (index)
351       cf.br ^bb1(%2: index)
352     ^bb1(%arg2: index):
353       memref.store %iv, %data2[%arg2] : memref<?xi64>
354       omp.yield
355     }
356   }
358   return
361 // CHECK-LABEL: omp_loop_nest_pretty_multiple
362 func.func @omp_loop_nest_pretty_multiple(%lb1 : i32, %ub1 : i32, %step1 : i32,
363     %lb2 : i32, %ub2 : i32, %step2 : i32, %data1 : memref<?xi32>) -> () {
365   omp.wsloop {
366     // CHECK: omp.loop_nest (%{{.*}}, %{{.*}}) : i32 = (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}})
367     omp.loop_nest (%iv1, %iv2) : i32 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
368       %1 = "test.payload"(%iv1) : (i32) -> (index)
369       %2 = "test.payload"(%iv2) : (i32) -> (index)
370       memref.store %iv1, %data1[%1] : memref<?xi32>
371       memref.store %iv2, %data1[%2] : memref<?xi32>
372       omp.yield
373     }
374   }
376   return
379 // CHECK-LABEL: omp_wsloop
380 func.func @omp_wsloop(%lb : index, %ub : index, %step : index, %data_var : memref<i32>, %linear_var : i32, %chunk_var : i32) -> () {
382   // CHECK: omp.wsloop ordered(1) {
383   // CHECK-NEXT: omp.loop_nest
384   "omp.wsloop" () ({
385     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
386       omp.yield
387     }
388   }) {operandSegmentSizes = array<i32: 0,0,0,0,0,0,0>, ordered = 1} :
389     () -> ()
391   // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static) {
392   // CHECK-NEXT: omp.loop_nest
393   "omp.wsloop" (%data_var, %linear_var) ({
394     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
395       omp.yield
396     }
397   }) {operandSegmentSizes = array<i32: 0,0,1,1,0,0,0>, schedule_kind = #omp<schedulekind static>} :
398     (memref<i32>, i32) -> ()
400   // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>, %{{.*}} = %{{.*}} : memref<i32>) schedule(static) {
401   // CHECK-NEXT: omp.loop_nest
402   "omp.wsloop" (%data_var, %data_var, %linear_var, %linear_var) ({
403     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
404       omp.yield
405     }
406   }) {operandSegmentSizes = array<i32: 0,0,2,2,0,0,0>, schedule_kind = #omp<schedulekind static>} :
407     (memref<i32>, memref<i32>, i32, i32) -> ()
409   // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(dynamic = %{{.*}}) {
410   // CHECK-NEXT: omp.loop_nest
411   "omp.wsloop" (%data_var, %linear_var, %chunk_var) ({
412     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
413       omp.yield
414     }
415   }) {operandSegmentSizes = array<i32: 0,0,1,1,0,0,1>, schedule_kind = #omp<schedulekind dynamic>, ordered = 2} :
416     (memref<i32>, i32, i32) -> ()
418   // CHECK: omp.wsloop nowait schedule(auto) {
419   // CHECK-NEXT: omp.loop_nest
420   "omp.wsloop" () ({
421     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
422       omp.yield
423     }
424   }) {operandSegmentSizes = array<i32: 0,0,0,0,0,0,0>, nowait, schedule_kind = #omp<schedulekind auto>} :
425     () -> ()
427   // CHECK: omp.wsloop {
428   // CHECK-NEXT: omp.simd
429   // CHECK-NEXT: omp.loop_nest
430   "omp.wsloop" () ({
431     omp.simd {
432       omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
433         omp.yield
434       }
435     } {omp.composite}
436   }) {omp.composite} : () -> ()
438   return
441 // CHECK-LABEL: omp_wsloop_pretty
442 func.func @omp_wsloop_pretty(%lb : index, %ub : index, %step : index, %data_var : memref<i32>, %linear_var : i32, %chunk_var : i32, %chunk_var2 : i16) -> () {
444   // CHECK: omp.wsloop ordered(2) {
445   // CHECK-NEXT: omp.loop_nest
446   omp.wsloop ordered(2) {
447     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
448       omp.yield
449     }
450   }
452   // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static) {
453   // CHECK-NEXT: omp.loop_nest
454   omp.wsloop schedule(static) linear(%data_var = %linear_var : memref<i32>) {
455     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
456       omp.yield
457     }
458   }
460   // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(static = %{{.*}} : i32) {
461   // CHECK-NEXT: omp.loop_nest
462   omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(static = %chunk_var : i32) {
463     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
464       omp.yield
465     }
466   }
468   // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(dynamic = %{{.*}} : i32, nonmonotonic) {
469   // CHECK-NEXT: omp.loop_nest
470   omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var : i32, nonmonotonic) {
471     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step)  {
472       omp.yield
473     }
474   }
476   // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(dynamic = %{{.*}} : i16, monotonic) {
477   // CHECK-NEXT: omp.loop_nest
478   omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var2 : i16, monotonic) {
479     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
480       omp.yield
481     }
482   }
484   // CHECK: omp.wsloop {
485   // CHECK-NEXT: omp.loop_nest
486   omp.wsloop {
487     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
488       omp.yield
489     }
490   }
492   // CHECK: omp.wsloop nowait {
493   // CHECK-NEXT: omp.loop_nest
494   omp.wsloop nowait {
495     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
496       omp.yield
497     }
498   }
500   // CHECK: omp.wsloop nowait order(concurrent) {
501   // CHECK-NEXT: omp.loop_nest
502   omp.wsloop order(concurrent) nowait {
503     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
504       omp.yield
505     }
506   }
508   // CHECK: omp.wsloop nowait order(reproducible:concurrent) {
509   // CHECK-NEXT: omp.loop_nest
510   omp.wsloop order(reproducible:concurrent) nowait {
511     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
512       omp.yield
513     }
514   }
515   // CHECK: omp.wsloop nowait order(unconstrained:concurrent) {
516   // CHECK-NEXT: omp.loop_nest
517   omp.wsloop order(unconstrained:concurrent) nowait {
518     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
519       omp.yield
520     }
521   }
522   // CHECK: omp.wsloop {
523   // CHECK-NEXT: omp.simd
524   // CHECK-NEXT: omp.loop_nest
525   omp.wsloop {
526     omp.simd {
527       omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
528         omp.yield
529       }
530     } {omp.composite}
531   } {omp.composite}
533   return
536 // CHECK-LABEL: omp_simd
537 func.func @omp_simd(%lb : index, %ub : index, %step : index) -> () {
538   // CHECK: omp.simd
539   omp.simd {
540     "omp.loop_nest" (%lb, %ub, %step) ({
541     ^bb1(%iv2: index):
542       "omp.yield"() : () -> ()
543     }) : (index, index, index) -> ()
544   }
546   return
549 // CHECK-LABEL: omp_simd_aligned_list
550 func.func @omp_simd_aligned_list(%arg0 : index, %arg1 : index, %arg2 : index,
551                                  %arg3 : memref<i32>, %arg4 : memref<i32>) -> () {
552   // CHECK:      omp.simd aligned(
553   // CHECK-SAME: %{{.*}} : memref<i32> -> 32 : i64,
554   // CHECK-SAME: %{{.*}} : memref<i32> -> 128 : i64)
555   "omp.simd"(%arg3, %arg4) ({
556     "omp.loop_nest" (%arg0, %arg1, %arg2) ({
557     ^bb1(%iv2: index):
558       "omp.yield"() : () -> ()
559     }) : (index, index, index) -> ()
560   }) {alignments = [32, 128],
561       operandSegmentSizes = array<i32: 2, 0, 0, 0, 0, 0, 0>} : (memref<i32>, memref<i32>) -> ()
562   return
565 // CHECK-LABEL: omp_simd_aligned_single
566 func.func @omp_simd_aligned_single(%arg0 : index, %arg1 : index, %arg2 : index,
567                                    %arg3 : memref<i32>, %arg4 : memref<i32>) -> () {
568   // CHECK: omp.simd aligned(%{{.*}} : memref<i32> -> 32 : i64)
569   "omp.simd"(%arg3) ({
570     "omp.loop_nest" (%arg0, %arg1, %arg2) ({
571     ^bb1(%iv2: index):
572       "omp.yield"() : () -> ()
573     }) : (index, index, index) -> ()
574   }) {alignments = [32],
575       operandSegmentSizes = array<i32: 1, 0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
576   return
579 // CHECK-LABEL: omp_simd_nontemporal_list
580 func.func @omp_simd_nontemporal_list(%arg0 : index, %arg1 : index,
581                                      %arg2 : index, %arg3 : memref<i32>,
582                                      %arg4 : memref<i64>) -> () {
583   // CHECK: omp.simd nontemporal(%{{.*}}, %{{.*}} : memref<i32>, memref<i64>)
584   "omp.simd"(%arg3, %arg4) ({
585     "omp.loop_nest" (%arg0, %arg1, %arg2) ({
586     ^bb1(%iv2: index):
587       "omp.yield"() : () -> ()
588     }) : (index, index, index) -> ()
589   }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 2, 0, 0>} : (memref<i32>, memref<i64>) -> ()
590   return
593 // CHECK-LABEL: omp_simd_nontemporal_single
594 func.func @omp_simd_nontemporal_single(%arg0 : index, %arg1 : index,
595                                        %arg2 : index, %arg3 : memref<i32>,
596                                        %arg4 : memref<i64>) -> () {
597   // CHECK: omp.simd nontemporal(%{{.*}} : memref<i32>)
598   "omp.simd"(%arg3) ({
599     "omp.loop_nest" (%arg0, %arg1, %arg2) ({
600     ^bb1(%iv2: index):
601       "omp.yield"() : () -> ()
602     }) : (index, index, index) -> ()
603   }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 1, 0, 0>} : (memref<i32>) -> ()
604   return
607 // CHECK-LABEL: omp_simd_pretty
608 func.func @omp_simd_pretty(%lb : index, %ub : index, %step : index) -> () {
609   // CHECK: omp.simd {
610   omp.simd {
611     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
612       omp.yield
613     }
614   }
615   return
618 // CHECK-LABEL:   func.func @omp_simd_pretty_aligned(
619 func.func @omp_simd_pretty_aligned(%lb : index, %ub : index, %step : index,
620                                    %data_var : memref<i32>,
621                                    %data_var1 : memref<i32>) -> () {
622   // CHECK:      omp.simd aligned(
623   // CHECK-SAME: %{{.*}} : memref<i32> -> 32 : i64,
624   // CHECK-SAME: %{{.*}} : memref<i32> -> 128 : i64)
625   omp.simd aligned(%data_var :  memref<i32> -> 32, %data_var1 : memref<i32> -> 128) {
626     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
627       omp.yield
628     }
629   }
630   return
633 // CHECK-LABEL: omp_simd_pretty_if
634 func.func @omp_simd_pretty_if(%lb : index, %ub : index, %step : index, %if_cond : i1) -> () {
635   // CHECK: omp.simd if(%{{.*}})
636   omp.simd if(%if_cond) {
637     omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
638       omp.yield
639     }
640   }
641   return
644 // CHECK-LABEL: func.func @omp_simd_pretty_nontemporal
645 func.func @omp_simd_pretty_nontemporal(%lb : index, %ub : index, %step : index,
646                                        %data_var : memref<i32>,
647                                        %data_var1 : memref<i32>) -> () {
648   // CHECK: omp.simd nontemporal(%{{.*}}, %{{.*}} : memref<i32>, memref<i32>)
649   omp.simd nontemporal(%data_var, %data_var1 : memref<i32>, memref<i32>) {
650     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
651       omp.yield
652     }
653   }
654   return
657 // CHECK-LABEL: omp_simd_pretty_order
658 func.func @omp_simd_pretty_order(%lb : index, %ub : index, %step : index) -> () {
659   // CHECK: omp.simd order(concurrent)
660   omp.simd order(concurrent) {
661     omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
662       omp.yield
663     }
664   }
665   // CHECK: omp.simd order(reproducible:concurrent)
666   omp.simd order(reproducible:concurrent) {
667     omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
668       omp.yield
669     }
670   }
671   // CHECK: omp.simd order(unconstrained:concurrent)
672   omp.simd order(unconstrained:concurrent) {
673     omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
674       omp.yield
675     }
676   }
677   return
680 // CHECK-LABEL: omp_simd_pretty_simdlen
681 func.func @omp_simd_pretty_simdlen(%lb : index, %ub : index, %step : index) -> () {
682   // CHECK: omp.simd simdlen(2)
683   omp.simd simdlen(2) {
684     omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
685       omp.yield
686     }
687   }
688   return
691 // CHECK-LABEL: omp_simd_pretty_safelen
692 func.func @omp_simd_pretty_safelen(%lb : index, %ub : index, %step : index) -> () {
693   // CHECK: omp.simd safelen(2)
694   omp.simd safelen(2) {
695     omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
696       omp.yield
697     }
698   }
699   return
702 // CHECK-LABEL: omp_distribute
703 func.func @omp_distribute(%chunk_size : i32, %data_var : memref<i32>, %arg0 : i32) -> () {
704   // CHECK: omp.distribute
705   "omp.distribute" () ({
706     "omp.loop_nest" (%arg0, %arg0, %arg0) ({
707     ^bb0(%iv: i32):
708       "omp.yield"() : () -> ()
709     }) : (i32, i32, i32) -> ()
710   }) {} : () -> ()
711   // CHECK: omp.distribute
712   omp.distribute {
713     omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
714       omp.yield
715     }
716   }
717   // CHECK: omp.distribute dist_schedule_static
718   omp.distribute dist_schedule_static {
719     omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
720       omp.yield
721     }
722   }
723   // CHECK: omp.distribute dist_schedule_static dist_schedule_chunk_size(%{{.+}} : i32)
724   omp.distribute dist_schedule_static dist_schedule_chunk_size(%chunk_size : i32) {
725     omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
726       omp.yield
727     }
728   }
729   // CHECK: omp.distribute order(concurrent)
730   omp.distribute order(concurrent) {
731     omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
732       omp.yield
733     }
734   }
735   // CHECK: omp.distribute order(reproducible:concurrent)
736   omp.distribute order(reproducible:concurrent) {
737     omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
738       omp.yield
739     }
740   }
741   // CHECK: omp.distribute order(unconstrained:concurrent)
742   omp.distribute order(unconstrained:concurrent) {
743     omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
744       omp.yield
745     }
746   }
747   // CHECK: omp.distribute allocate(%{{.+}} : memref<i32> -> %{{.+}} : memref<i32>)
748   omp.distribute allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
749     omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
750       omp.yield
751     }
752   }
753   // CHECK: omp.distribute
754   omp.distribute {
755     omp.simd {
756       omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
757         omp.yield
758       }
759     } {omp.composite}
760   } {omp.composite}
761   return
765 // CHECK-LABEL: omp_target
766 func.func @omp_target(%if_cond : i1, %device : si32,  %num_threads : i32, %device_ptr: memref<i32>, %device_addr: memref<?xi32>, %map1: memref<?xi32>, %map2: memref<?xi32>) -> () {
768     // Test with optional operands; if_expr, device, thread_limit, private, firstprivate and nowait.
769     // CHECK: omp.target device({{.*}}) if({{.*}}) nowait thread_limit({{.*}})
770     "omp.target"(%device, %if_cond, %num_threads) ({
771        // CHECK: omp.terminator
772        omp.terminator
773     }) {nowait, operandSegmentSizes = array<i32: 0,0,0,1,0,0,1,0,0,0,0,1>} : ( si32, i1, i32 ) -> ()
775     // Test with optional map clause.
776     // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
777     // CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
778     // CHECK: omp.target has_device_addr(%[[VAL_5:.*]] : memref<?xi32>) is_device_ptr(%[[VAL_4:.*]] : memref<i32>) map_entries(%[[MAP_A]] -> {{.*}}, %[[MAP_B]] -> {{.*}} : memref<?xi32>, memref<?xi32>) {
779     %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)   map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
780     %mapv2 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
781     omp.target is_device_ptr(%device_ptr : memref<i32>) has_device_addr(%device_addr : memref<?xi32>) map_entries(%mapv1 -> %arg0, %mapv2 -> %arg1 : memref<?xi32>, memref<?xi32>) {
782       omp.terminator
783     }
784     // CHECK: %[[MAP_C:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""}
785     // CHECK: %[[MAP_D:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
786     // CHECK: omp.target map_entries(%[[MAP_C]] -> {{.*}}, %[[MAP_D]] -> {{.*}} : memref<?xi32>, memref<?xi32>) {
787     %mapv3 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)   map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""}
788     %mapv4 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>)   map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
789     omp.target map_entries(%mapv3 -> %arg0, %mapv4 -> %arg1 : memref<?xi32>, memref<?xi32>) {
790       omp.terminator
791     }
792     // CHECK: omp.barrier
793     omp.barrier
795     return
798 func.func @omp_target_data (%if_cond : i1, %device : si32, %device_ptr: memref<i32>, %device_addr: memref<?xi32>, %map1: memref<?xi32>, %map2: memref<?xi32>) -> () {
799     // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
800     // CHECK: omp.target_data device(%[[VAL_1:.*]] : si32) if(%[[VAL_0:.*]]) map_entries(%[[MAP_A]] : memref<?xi32>)
801     %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)   map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
802     omp.target_data if(%if_cond) device(%device : si32) map_entries(%mapv1 : memref<?xi32>){}
804     // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(close, present, to) capture(ByRef) -> memref<?xi32> {name = ""}
805     // CHECK: omp.target_data map_entries(%[[MAP_A]] : memref<?xi32>) use_device_addr(%[[VAL_3:.*]] -> %{{.*}} : memref<?xi32>) use_device_ptr(%[[VAL_4:.*]] -> %{{.*}} : memref<i32>)
806     %mapv2 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)   map_clauses(close, present, to) capture(ByRef) -> memref<?xi32> {name = ""}
807     omp.target_data map_entries(%mapv2 : memref<?xi32>) use_device_addr(%device_addr -> %arg0 : memref<?xi32>) use_device_ptr(%device_ptr -> %arg1 : memref<i32>) {
808       omp.terminator
809     }
811     // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
812     // CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
813     // CHECK: omp.target_data map_entries(%[[MAP_A]], %[[MAP_B]] : memref<?xi32>, memref<?xi32>)
814     %mapv3 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)   map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
815     %mapv4 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
816     omp.target_data map_entries(%mapv3, %mapv4 : memref<?xi32>, memref<?xi32>) {}
818     // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_3:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
819     // CHECK: omp.target_enter_data device(%[[VAL_1:.*]] : si32) if(%[[VAL_0:.*]]) map_entries(%[[MAP_A]] : memref<?xi32>) nowait
820     %mapv5 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
821     omp.target_enter_data if(%if_cond) device(%device : si32) nowait map_entries(%mapv5 : memref<?xi32>)
823     // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_3:.*]] : memref<?xi32>, tensor<?xi32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
824     // CHECK: omp.target_exit_data device(%[[VAL_1:.*]] : si32) if(%[[VAL_0:.*]]) map_entries(%[[MAP_A]] : memref<?xi32>) nowait
825     %mapv6 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>)   map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
826     omp.target_exit_data if(%if_cond) device(%device : si32) nowait map_entries(%mapv6 : memref<?xi32>)
828     return
831 // CHECK-LABEL: omp_target_pretty
832 func.func @omp_target_pretty(%if_cond : i1, %device : si32,  %num_threads : i32) -> () {
833     // CHECK: omp.target device({{.*}}) if({{.*}})
834     omp.target if(%if_cond) device(%device : si32) {
835       omp.terminator
836     }
838     // CHECK: omp.target device({{.*}}) if({{.*}}) nowait
839     omp.target if(%if_cond) device(%device : si32) thread_limit(%num_threads : i32) nowait {
840       omp.terminator
841     }
843     return
846 // CHECK: omp.declare_reduction
847 // CHECK-LABEL: @add_f32
848 // CHECK: : f32
849 // CHECK: init
850 // CHECK: ^{{.+}}(%{{.+}}: f32):
851 // CHECK:   omp.yield
852 // CHECK: combiner
853 // CHECK: ^{{.+}}(%{{.+}}: f32, %{{.+}}: f32):
854 // CHECK:   omp.yield
855 // CHECK: atomic
856 // CHECK: ^{{.+}}(%{{.+}}: !llvm.ptr, %{{.+}}: !llvm.ptr):
857 // CHECK:  omp.yield
858 // CHECK: cleanup
859 // CHECK:  omp.yield
860 omp.declare_reduction @add_f32 : f32
861 init {
862 ^bb0(%arg: f32):
863   %0 = arith.constant 0.0 : f32
864   omp.yield (%0 : f32)
866 combiner {
867 ^bb1(%arg0: f32, %arg1: f32):
868   %1 = arith.addf %arg0, %arg1 : f32
869   omp.yield (%1 : f32)
871 atomic {
872 ^bb2(%arg2: !llvm.ptr, %arg3: !llvm.ptr):
873   %2 = llvm.load %arg3 : !llvm.ptr -> f32
874   llvm.atomicrmw fadd %arg2, %2 monotonic : !llvm.ptr, f32
875   omp.yield
877 cleanup {
878 ^bb0(%arg: f32):
879   omp.yield
882 // CHECK-LABEL: func @wsloop_reduction
883 func.func @wsloop_reduction(%lb : index, %ub : index, %step : index) {
884   %c1 = arith.constant 1 : i32
885   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
886   // CHECK: reduction(@add_f32 %{{.+}} -> %[[PRV:.+]] : !llvm.ptr)
887   omp.wsloop reduction(@add_f32 %0 -> %prv : !llvm.ptr) {
888     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
889       // CHECK: %[[CST:.+]] = arith.constant 2.0{{.*}} : f32
890       %cst = arith.constant 2.0 : f32
891       // CHECK: %[[LPRV:.+]] = llvm.load %[[PRV]] : !llvm.ptr -> f32
892       %lprv = llvm.load %prv : !llvm.ptr -> f32
893       // CHECK: %[[RES:.+]] = llvm.fadd %[[LPRV]], %[[CST]] : f32
894       %res = llvm.fadd %lprv, %cst: f32
895       // CHECK: llvm.store %[[RES]], %[[PRV]] :  f32, !llvm.ptr
896       llvm.store %res, %prv :  f32, !llvm.ptr
897       omp.yield
898     }
899   }
900   return
903 // CHECK-LABEL: func @wsloop_reduction_byref
904 func.func @wsloop_reduction_byref(%lb : index, %ub : index, %step : index) {
905   %c1 = arith.constant 1 : i32
906   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
907   // CHECK: reduction(byref @add_f32 %{{.+}} -> %[[PRV:.+]] : !llvm.ptr)
908   omp.wsloop reduction(byref @add_f32 %0 -> %prv : !llvm.ptr) {
909     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
910       // CHECK: %[[CST:.+]] = arith.constant 2.0{{.*}} : f32
911       %cst = arith.constant 2.0 : f32
912       // CHECK: %[[LPRV:.+]] = llvm.load %[[PRV]] : !llvm.ptr -> f32
913       %lprv = llvm.load %prv : !llvm.ptr -> f32
914       // CHECK: %[[RES:.+]] = llvm.fadd %[[LPRV]], %[[CST]] : f32
915       %res = llvm.fadd %lprv, %cst: f32
916       // CHECK: llvm.store %[[RES]], %[[PRV]] :  f32, !llvm.ptr
917       llvm.store %res, %prv :  f32, !llvm.ptr
918       omp.yield
919     }
920   }
921   return
924 // CHECK-LABEL: func @parallel_reduction
925 func.func @parallel_reduction() {
926   %c1 = arith.constant 1 : i32
927   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
928   // CHECK: omp.parallel reduction(@add_f32 {{.+}} -> {{.+}} : !llvm.ptr)
929   omp.parallel reduction(@add_f32 %0 -> %prv : !llvm.ptr) {
930     %1 = arith.constant 2.0 : f32
931     %2 = llvm.load %prv : !llvm.ptr -> f32
932     // CHECK: llvm.fadd %{{.*}}, %{{.*}} : f32
933     %3 = llvm.fadd %1, %2 : f32
934     llvm.store %3, %prv : f32, !llvm.ptr
935     omp.terminator
936   }
937   return
940 // CHECK-LABEL: func @parallel_reduction_byref
941 func.func @parallel_reduction_byref() {
942   %c1 = arith.constant 1 : i32
943   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
944   // CHECK: omp.parallel reduction(byref @add_f32 {{.+}} -> {{.+}} : !llvm.ptr)
945   omp.parallel reduction(byref @add_f32 %0 -> %prv : !llvm.ptr) {
946     %1 = arith.constant 2.0 : f32
947     %2 = llvm.load %prv : !llvm.ptr -> f32
948     // CHECK: llvm.fadd %{{.*}}, %{{.*}} : f32
949     %3 = llvm.fadd %1, %2 : f32
950     llvm.store %3, %prv : f32, !llvm.ptr
951     omp.terminator
952   }
953   return
956 // CHECK: func @parallel_wsloop_reduction
957 func.func @parallel_wsloop_reduction(%lb : index, %ub : index, %step : index) {
958   %c1 = arith.constant 1 : i32
959   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
960   // CHECK: omp.parallel {
961   omp.parallel {
962     // CHECK: omp.wsloop reduction(@add_f32 %{{.*}} -> %{{.+}} : !llvm.ptr) {
963     omp.wsloop reduction(@add_f32 %0 -> %prv : !llvm.ptr) {
964       // CHECK: omp.loop_nest (%{{.+}}) : index = (%{{.+}}) to (%{{.+}}) step (%{{.+}}) {
965       omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
966         %1 = arith.constant 2.0 : f32
967         %2 = llvm.load %prv : !llvm.ptr -> f32
968         // CHECK: llvm.fadd %{{.+}}, %{{.+}} : f32
969         llvm.fadd %1, %2 : f32
970         // CHECK: omp.yield
971         omp.yield
972       }
973     }
974     // CHECK: omp.terminator
975     omp.terminator
976   }
977   return
980 // CHECK-LABEL: omp_teams
981 func.func @omp_teams(%lb : i32, %ub : i32, %if_cond : i1, %num_threads : i32,
982                      %data_var : memref<i32>) -> () {
983   // Test nesting inside of omp.target
984   omp.target {
985     // CHECK: omp.teams
986     omp.teams {
987       // CHECK: omp.terminator
988       omp.terminator
989     }
990     // CHECK: omp.terminator
991     omp.terminator
992   }
994   // CHECK: omp.teams
995   omp.teams {
996     %0 = arith.constant 1 : i32
997     // CHECK: omp.terminator
998     omp.terminator
999   }
1001   // Test num teams.
1002   // CHECK: omp.teams num_teams(%{{.+}} : i32 to %{{.+}} : i32)
1003   omp.teams num_teams(%lb : i32 to %ub : i32) {
1004     // CHECK: omp.terminator
1005     omp.terminator
1006   }
1008   // CHECK: omp.teams num_teams( to %{{.+}} : i32)
1009   omp.teams num_teams(to %ub : i32) {
1010     // CHECK: omp.terminator
1011     omp.terminator
1012   }
1014   // Test if.
1015   // CHECK: omp.teams if(%{{.+}})
1016   omp.teams if(%if_cond) {
1017     // CHECK: omp.terminator
1018     omp.terminator
1019   }
1021   // Test thread limit.
1022   // CHECK: omp.teams thread_limit(%{{.+}} : i32)
1023   omp.teams thread_limit(%num_threads : i32) {
1024     // CHECK: omp.terminator
1025     omp.terminator
1026   }
1028   // Test reduction.
1029   %c1 = arith.constant 1 : i32
1030   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
1031   // CHECK: omp.teams reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) {
1032   omp.teams reduction(@add_f32 %0 -> %arg0 : !llvm.ptr) {
1033     %1 = arith.constant 2.0 : f32
1034     // CHECK: omp.terminator
1035     omp.terminator
1036   }
1038   // Test reduction byref
1039   // CHECK: omp.teams reduction(byref @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) {
1040   omp.teams reduction(byref @add_f32 %0 -> %arg0 : !llvm.ptr) {
1041     %1 = arith.constant 2.0 : f32
1042     // CHECK: omp.terminator
1043     omp.terminator
1044   }
1046   // Test allocate.
1047   // CHECK: omp.teams allocate(%{{.+}} : memref<i32> -> %{{.+}} : memref<i32>)
1048   omp.teams allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
1049     // CHECK: omp.terminator
1050     omp.terminator
1051   }
1053   return
1056 // CHECK-LABEL: func @sections_reduction
1057 func.func @sections_reduction() {
1058   %c1 = arith.constant 1 : i32
1059   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
1060   // CHECK: omp.sections reduction(@add_f32 %{{.+}} -> {{.+}} : !llvm.ptr)
1061   omp.sections reduction(@add_f32 %0 -> %arg0 : !llvm.ptr) {
1062     // CHECK: omp.section
1063     omp.section {
1064     ^bb0(%arg1 : !llvm.ptr):
1065       %1 = arith.constant 2.0 : f32
1066       omp.terminator
1067     }
1068     // CHECK: omp.section
1069     omp.section {
1070     ^bb0(%arg1 : !llvm.ptr):
1071       %1 = arith.constant 3.0 : f32
1072       omp.terminator
1073     }
1074     omp.terminator
1075   }
1076   return
1079 // CHECK-LABEL: func @sections_reduction_byref
1080 func.func @sections_reduction_byref() {
1081   %c1 = arith.constant 1 : i32
1082   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
1083   // CHECK: omp.sections reduction(byref @add_f32 %{{.+}} -> {{.+}} : !llvm.ptr)
1084   omp.sections reduction(byref @add_f32 %0 -> %arg0 : !llvm.ptr) {
1085     // CHECK: omp.section
1086     omp.section {
1087     ^bb0(%arg1 : !llvm.ptr):
1088       %1 = arith.constant 2.0 : f32
1089       omp.terminator
1090     }
1091     // CHECK: omp.section
1092     omp.section {
1093     ^bb0(%arg1 : !llvm.ptr):
1094       %1 = arith.constant 3.0 : f32
1095       omp.terminator
1096     }
1097     omp.terminator
1098   }
1099   return
1102 // CHECK: omp.declare_reduction
1103 // CHECK-LABEL: @add2_f32
1104 omp.declare_reduction @add2_f32 : f32
1105 // CHECK: init
1106 init {
1107 ^bb0(%arg: f32):
1108   %0 = arith.constant 0.0 : f32
1109   omp.yield (%0 : f32)
1111 // CHECK: combiner
1112 combiner {
1113 ^bb1(%arg0: f32, %arg1: f32):
1114   %1 = arith.addf %arg0, %arg1 : f32
1115   omp.yield (%1 : f32)
1117 // CHECK-NOT: atomic
1118 // CHECK-NOT: cleanup
1120 // CHECK-LABEL: func @wsloop_reduction2
1121 func.func @wsloop_reduction2(%lb : index, %ub : index, %step : index) {
1122   %0 = memref.alloca() : memref<1xf32>
1123   // CHECK: omp.wsloop reduction(@add2_f32 %{{.+}} -> %{{.+}} : memref<1xf32>) {
1124   omp.wsloop reduction(@add2_f32 %0 -> %prv : memref<1xf32>) {
1125     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
1126       %1 = arith.constant 2.0 : f32
1127       %2 = arith.constant 0 : index
1128       %3 = memref.load %prv[%2] : memref<1xf32>
1129       // CHECK: llvm.fadd
1130       %4 = llvm.fadd %1, %3 : f32
1131       memref.store %4, %prv[%2] : memref<1xf32>
1132       omp.yield
1133     }
1134   }
1135   return
1138 // CHECK-LABEL: func @parallel_reduction2
1139 func.func @parallel_reduction2() {
1140   %0 = memref.alloca() : memref<1xf32>
1141   // CHECK: omp.parallel reduction(@add2_f32 %{{.+}} -> %{{.+}} : memref<1xf32>)
1142   omp.parallel reduction(@add2_f32 %0 -> %prv : memref<1xf32>) {
1143     %1 = arith.constant 2.0 : f32
1144     %2 = arith.constant 0 : index
1145     %3 = memref.load %prv[%2] : memref<1xf32>
1146     // CHECK: llvm.fadd
1147     %4 = llvm.fadd %1, %3 : f32
1148     memref.store %4, %prv[%2] : memref<1xf32>
1149     omp.terminator
1150   }
1151   return
1154 // CHECK: func @parallel_wsloop_reduction2
1155 func.func @parallel_wsloop_reduction2(%lb : index, %ub : index, %step : index) {
1156   %c1 = arith.constant 1 : i32
1157   %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
1158   // CHECK: omp.parallel {
1159   omp.parallel {
1160     // CHECK: omp.wsloop reduction(@add2_f32 %{{.*}} -> %{{.+}} : !llvm.ptr) {
1161     omp.wsloop reduction(@add2_f32 %0 -> %prv : !llvm.ptr) {
1162       // CHECK: omp.loop_nest (%{{.+}}) : index = (%{{.+}}) to (%{{.+}}) step (%{{.+}}) {
1163       omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
1164         %1 = arith.constant 2.0 : f32
1165         %2 = llvm.load %prv : !llvm.ptr -> f32
1166         // CHECK: llvm.fadd %{{.+}}, %{{.+}} : f32
1167         %3 = llvm.fadd %1, %2 : f32
1168         // CHECK: omp.yield
1169         omp.yield
1170       }
1171     }
1172     // CHECK: omp.terminator
1173     omp.terminator
1174   }
1175   return
1178 // CHECK-LABEL: func @sections_reduction2
1179 func.func @sections_reduction2() {
1180   %0 = memref.alloca() : memref<1xf32>
1181   // CHECK: omp.sections reduction(@add2_f32 %{{.+}} -> %{{.+}} : memref<1xf32>)
1182   omp.sections reduction(@add2_f32 %0 -> %arg0 : memref<1xf32>) {
1183     omp.section {
1184     ^bb0(%arg1 : !llvm.ptr):
1185       %1 = arith.constant 2.0 : f32
1186       omp.terminator
1187     }
1188     omp.section {
1189     ^bb0(%arg1 : !llvm.ptr):
1190       %1 = arith.constant 2.0 : f32
1191       omp.terminator
1192     }
1193     omp.terminator
1194   }
1195   return
1198 // CHECK: omp.critical.declare @mutex1 hint(uncontended)
1199 omp.critical.declare @mutex1 hint(uncontended)
1200 // CHECK: omp.critical.declare @mutex2 hint(contended)
1201 omp.critical.declare @mutex2 hint(contended)
1202 // CHECK: omp.critical.declare @mutex3 hint(nonspeculative)
1203 omp.critical.declare @mutex3 hint(nonspeculative)
1204 // CHECK: omp.critical.declare @mutex4 hint(speculative)
1205 omp.critical.declare @mutex4 hint(speculative)
1206 // CHECK: omp.critical.declare @mutex5 hint(uncontended, nonspeculative)
1207 omp.critical.declare @mutex5 hint(uncontended, nonspeculative)
1208 // CHECK: omp.critical.declare @mutex6 hint(contended, nonspeculative)
1209 omp.critical.declare @mutex6 hint(contended, nonspeculative)
1210 // CHECK: omp.critical.declare @mutex7 hint(uncontended, speculative)
1211 omp.critical.declare @mutex7 hint(uncontended, speculative)
1212 // CHECK: omp.critical.declare @mutex8 hint(contended, speculative)
1213 omp.critical.declare @mutex8 hint(contended, speculative)
1214 // CHECK: omp.critical.declare @mutex9
1215 omp.critical.declare @mutex9 hint(none)
1216 // CHECK: omp.critical.declare @mutex10
1217 omp.critical.declare @mutex10
1220 // CHECK-LABEL: omp_critical
1221 func.func @omp_critical() -> () {
1222   // CHECK: omp.critical
1223   omp.critical {
1224     omp.terminator
1225   }
1227   // CHECK: omp.critical(@{{.*}})
1228   omp.critical(@mutex1) {
1229     omp.terminator
1230   }
1231   return
1234 func.func @omp_ordered(%arg1 : i32, %arg2 : i32, %arg3 : i32,
1235     %vec0 : i64, %vec1 : i64, %vec2 : i64, %vec3 : i64) -> () {
1236   // CHECK: omp.ordered.region
1237   omp.ordered.region {
1238     // CHECK: omp.terminator
1239     omp.terminator
1240   }
1242   omp.wsloop ordered(0) {
1243     omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3)  {
1244       // CHECK: omp.ordered.region
1245       omp.ordered.region {
1246         // CHECK: omp.terminator
1247         omp.terminator
1248       }
1249       omp.yield
1250     }
1251   }
1253   omp.wsloop ordered(1) {
1254     omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
1255       // Only one DEPEND(SINK: vec) clause
1256       // CHECK: omp.ordered depend_type(dependsink) depend_vec(%{{.*}} : i64) {doacross_num_loops = 1 : i64}
1257       omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {doacross_num_loops = 1 : i64}
1259       // CHECK: omp.ordered depend_type(dependsource) depend_vec(%{{.*}} : i64) {doacross_num_loops = 1 : i64}
1260       omp.ordered depend_type(dependsource) depend_vec(%vec0 : i64) {doacross_num_loops = 1 : i64}
1262       omp.yield
1263     }
1264   }
1266   omp.wsloop ordered(2) {
1267     omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
1268       // Multiple DEPEND(SINK: vec) clauses
1269       // CHECK: omp.ordered depend_type(dependsink) depend_vec(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : i64, i64, i64, i64) {doacross_num_loops = 2 : i64}
1270       omp.ordered depend_type(dependsink) depend_vec(%vec0, %vec1, %vec2, %vec3 : i64, i64, i64, i64) {doacross_num_loops = 2 : i64}
1272       // CHECK: omp.ordered depend_type(dependsource) depend_vec(%{{.*}}, %{{.*}} : i64, i64) {doacross_num_loops = 2 : i64}
1273       omp.ordered depend_type(dependsource) depend_vec(%vec0, %vec1 : i64, i64) {doacross_num_loops = 2 : i64}
1275       omp.yield
1276     }
1277   }
1279   return
1282 // CHECK-LABEL: omp_atomic_read
1283 // CHECK-SAME: (%[[v:.*]]: memref<i32>, %[[x:.*]]: memref<i32>)
1284 func.func @omp_atomic_read(%v: memref<i32>, %x: memref<i32>) {
1285   // CHECK: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1286   omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1287   // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1288   omp.atomic.read %v = %x memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1289   // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(acquire) : memref<i32>, memref<i32>, i32
1290   omp.atomic.read %v = %x memory_order(acquire) : memref<i32>, memref<i32>, i32
1291   // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(relaxed) : memref<i32>, memref<i32>, i32
1292   omp.atomic.read %v = %x memory_order(relaxed) : memref<i32>, memref<i32>, i32
1293   // CHECK: omp.atomic.read %[[v]] = %[[x]] hint(contended, nonspeculative) : memref<i32>, memref<i32>, i32
1294   omp.atomic.read %v = %x hint(nonspeculative, contended) : memref<i32>, memref<i32>, i32
1295   // CHECK: omp.atomic.read %[[v]] = %[[x]] hint(contended, speculative) memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1296   omp.atomic.read %v = %x hint(speculative, contended) memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1297   // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1298   omp.atomic.read %v = %x hint(none) memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1299   return
1302 // CHECK-LABEL: omp_atomic_write
1303 // CHECK-SAME: (%[[ADDR:.*]]: memref<i32>, %[[VAL:.*]]: i32)
1304 func.func @omp_atomic_write(%addr : memref<i32>, %val : i32) {
1305   // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] : memref<i32>, i32
1306   omp.atomic.write %addr = %val : memref<i32>, i32
1307   // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(seq_cst) : memref<i32>, i32
1308   omp.atomic.write %addr = %val memory_order(seq_cst) : memref<i32>, i32
1309   // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(release) : memref<i32>, i32
1310   omp.atomic.write %addr = %val memory_order(release) : memref<i32>, i32
1311   // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(relaxed) : memref<i32>, i32
1312   omp.atomic.write %addr = %val memory_order(relaxed) : memref<i32>, i32
1313   // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(uncontended, speculative) : memref<i32>, i32
1314   omp.atomic.write %addr = %val hint(speculative, uncontended) : memref<i32>, i32
1315   // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] : memref<i32>, i32
1316   omp.atomic.write %addr = %val hint(none) : memref<i32>, i32
1317   return
1320 // CHECK-LABEL: omp_atomic_update
1321 // CHECK-SAME: (%[[X:.*]]: memref<i32>, %[[EXPR:.*]]: i32, %[[XBOOL:.*]]: memref<i1>, %[[EXPRBOOL:.*]]: i1)
1322 func.func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>, %exprBool : i1) {
1323   // CHECK: omp.atomic.update %[[X]] : memref<i32>
1324   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1325   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1326   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1327   omp.atomic.update %x : memref<i32> {
1328   ^bb0(%xval: i32):
1329     %newval = llvm.add %xval, %expr : i32
1330     omp.yield(%newval : i32)
1331   }
1332   // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
1333   // CHECK-NEXT: (%[[XVAL:.*]]: i1):
1334   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.and %[[XVAL]], %[[EXPRBOOL]] : i1
1335   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i1)
1336   omp.atomic.update %xBool : memref<i1> {
1337   ^bb0(%xval: i1):
1338     %newval = llvm.and %xval, %exprBool : i1
1339     omp.yield(%newval : i1)
1340   }
1341   // CHECK: omp.atomic.update %[[X]] : memref<i32>
1342   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1343   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.shl %[[XVAL]], %[[EXPR]] : i32
1344   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1345   // CHECK-NEXT: }
1346   omp.atomic.update %x : memref<i32> {
1347   ^bb0(%xval: i32):
1348     %newval = llvm.shl %xval, %expr : i32
1349     omp.yield(%newval : i32)
1350   }
1351   // CHECK: omp.atomic.update %[[X]] : memref<i32>
1352   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1353   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.intr.smax(%[[XVAL]], %[[EXPR]]) : (i32, i32) -> i32
1354   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1355   // CHECK-NEXT: }
1356   omp.atomic.update %x : memref<i32> {
1357   ^bb0(%xval: i32):
1358     %newval = llvm.intr.smax(%xval, %expr) : (i32, i32) -> i32
1359     omp.yield(%newval : i32)
1360   }
1362   // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
1363   // CHECK-NEXT: (%[[XVAL:.*]]: i1):
1364   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.icmp "eq" %[[XVAL]], %[[EXPRBOOL]] : i1
1365   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i1)
1366   // }
1367   omp.atomic.update %xBool : memref<i1> {
1368   ^bb0(%xval: i1):
1369     %newval = llvm.icmp "eq" %xval, %exprBool : i1
1370     omp.yield(%newval : i1)
1371   }
1373   // CHECK: omp.atomic.update %[[X]] : memref<i32> {
1374   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1375   // CHECK-NEXT:   omp.yield(%[[XVAL]] : i32)
1376   // CHECK-NEXT: }
1377   omp.atomic.update %x : memref<i32> {
1378   ^bb0(%xval:i32):
1379     omp.yield(%xval:i32)
1380   }
1382   // CHECK: omp.atomic.update %[[X]] : memref<i32> {
1383   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1384   // CHECK-NEXT:   omp.yield(%{{.+}} : i32)
1385   // CHECK-NEXT: }
1386   %const = arith.constant 42 : i32
1387   omp.atomic.update %x : memref<i32> {
1388   ^bb0(%xval:i32):
1389     omp.yield(%const:i32)
1390   }
1392   // CHECK: omp.atomic.update %[[X]] : memref<i32>
1393   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1394   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1395   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1396   omp.atomic.update hint(none) %x : memref<i32> {
1397   ^bb0(%xval: i32):
1398     %newval = llvm.add %xval, %expr : i32
1399     omp.yield(%newval : i32)
1400   }
1402   // CHECK: omp.atomic.update hint(uncontended) %[[X]] : memref<i32>
1403   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1404   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1405   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1406   omp.atomic.update hint(uncontended) %x : memref<i32> {
1407   ^bb0(%xval: i32):
1408     %newval = llvm.add %xval, %expr : i32
1409     omp.yield(%newval : i32)
1410   }
1412   // CHECK: omp.atomic.update hint(contended) %[[X]] : memref<i32>
1413   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1414   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1415   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1416   omp.atomic.update hint(contended) %x : memref<i32> {
1417   ^bb0(%xval: i32):
1418     %newval = llvm.add %xval, %expr : i32
1419     omp.yield(%newval : i32)
1420   }
1422   // CHECK: omp.atomic.update hint(nonspeculative) %[[X]] : memref<i32>
1423   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1424   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1425   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1426   omp.atomic.update hint(nonspeculative) %x : memref<i32> {
1427   ^bb0(%xval: i32):
1428     %newval = llvm.add %xval, %expr : i32
1429     omp.yield(%newval : i32)
1430   }
1432   // CHECK: omp.atomic.update hint(speculative) %[[X]] : memref<i32>
1433   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1434   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1435   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1436   omp.atomic.update hint(speculative) %x : memref<i32> {
1437   ^bb0(%xval: i32):
1438     %newval = llvm.add %xval, %expr : i32
1439     omp.yield(%newval : i32)
1440   }
1442   // CHECK: omp.atomic.update hint(uncontended, nonspeculative) %[[X]] : memref<i32>
1443   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1444   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1445   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1446   omp.atomic.update hint(uncontended, nonspeculative) %x : memref<i32> {
1447   ^bb0(%xval: i32):
1448     %newval = llvm.add %xval, %expr : i32
1449     omp.yield(%newval : i32)
1450   }
1452   // CHECK: omp.atomic.update hint(contended, nonspeculative) %[[X]] : memref<i32>
1453   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1454   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1455   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1456   omp.atomic.update hint(contended, nonspeculative) %x : memref<i32> {
1457   ^bb0(%xval: i32):
1458     %newval = llvm.add %xval, %expr : i32
1459     omp.yield(%newval : i32)
1460   }
1462   // CHECK: omp.atomic.update hint(uncontended, speculative) %[[X]] : memref<i32>
1463   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1464   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1465   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1466   omp.atomic.update hint(uncontended, speculative) %x : memref<i32> {
1467   ^bb0(%xval: i32):
1468     %newval = llvm.add %xval, %expr : i32
1469     omp.yield(%newval : i32)
1470   }
1472   // CHECK: omp.atomic.update hint(contended, speculative) %[[X]] : memref<i32>
1473   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1474   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1475   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1476   omp.atomic.update hint(contended, speculative) %x : memref<i32> {
1477   ^bb0(%xval: i32):
1478     %newval = llvm.add %xval, %expr : i32
1479     omp.yield(%newval : i32)
1480   }
1482   // CHECK: omp.atomic.update memory_order(seq_cst) %[[X]] : memref<i32>
1483   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1484   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1485   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1486   omp.atomic.update memory_order(seq_cst) %x : memref<i32> {
1487   ^bb0(%xval: i32):
1488     %newval = llvm.add %xval, %expr : i32
1489     omp.yield(%newval : i32)
1490   }
1492   // CHECK: omp.atomic.update memory_order(release) %[[X]] : memref<i32>
1493   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1494   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1495   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1496   omp.atomic.update memory_order(release) %x : memref<i32> {
1497   ^bb0(%xval: i32):
1498     %newval = llvm.add %xval, %expr : i32
1499     omp.yield(%newval : i32)
1500   }
1502   // CHECK: omp.atomic.update memory_order(relaxed) %[[X]] : memref<i32>
1503   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1504   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1505   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1506   omp.atomic.update memory_order(relaxed) %x : memref<i32> {
1507   ^bb0(%xval: i32):
1508     %newval = llvm.add %xval, %expr : i32
1509     omp.yield(%newval : i32)
1510   }
1512   // CHECK: omp.atomic.update hint(uncontended, speculative) memory_order(seq_cst) %[[X]] : memref<i32>
1513   // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1514   // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1515   // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
1516   omp.atomic.update memory_order(seq_cst) hint(uncontended, speculative) %x : memref<i32> {
1517   ^bb0(%xval: i32):
1518     %newval = llvm.add %xval, %expr : i32
1519     omp.yield(%newval : i32)
1520   }
1522   return
1525 // CHECK-LABEL: omp_atomic_capture
1526 // CHECK-SAME: (%[[v:.*]]: memref<i32>, %[[x:.*]]: memref<i32>, %[[expr:.*]]: i32)
1527 func.func @omp_atomic_capture(%v: memref<i32>, %x: memref<i32>, %expr: i32) {
1528   // CHECK: omp.atomic.capture {
1529   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1530   // CHECK-NEXT: (%[[xval:.*]]: i32):
1531   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1532   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1533   // CHECK-NEXT: }
1534   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1535   // CHECK-NEXT: }
1536   omp.atomic.capture{
1537     omp.atomic.update %x : memref<i32> {
1538     ^bb0(%xval: i32):
1539       %newval = llvm.add %xval, %expr : i32
1540       omp.yield(%newval : i32)
1541     }
1542     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1543   }
1544   // CHECK: omp.atomic.capture {
1545   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1546   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1547   // CHECK-NEXT: (%[[xval:.*]]: i32):
1548   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1549   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1550   // CHECK-NEXT: }
1551   // CHECK-NEXT: }
1552   omp.atomic.capture{
1553     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1554     omp.atomic.update %x : memref<i32> {
1555     ^bb0(%xval: i32):
1556       %newval = llvm.add %xval, %expr : i32
1557       omp.yield(%newval : i32)
1558     }
1559   }
1560   // CHECK: omp.atomic.capture {
1561   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1562   // CHECK-NEXT: omp.atomic.write %[[x]] = %[[expr]] : memref<i32>, i32
1563   // CHECK-NEXT: }
1564   omp.atomic.capture{
1565     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1566     omp.atomic.write %x = %expr : memref<i32>, i32
1567   }
1569   // CHECK: omp.atomic.capture {
1570   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1571   // CHECK-NEXT: (%[[xval:.*]]: i32):
1572   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1573   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1574   // CHECK-NEXT: }
1575   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1576   // CHECK-NEXT: }
1577   omp.atomic.capture hint(none) {
1578     omp.atomic.update %x : memref<i32> {
1579     ^bb0(%xval: i32):
1580       %newval = llvm.add %xval, %expr : i32
1581       omp.yield(%newval : i32)
1582     }
1583     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1584   }
1586   // CHECK: omp.atomic.capture hint(uncontended) {
1587   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1588   // CHECK-NEXT: (%[[xval:.*]]: i32):
1589   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1590   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1591   // CHECK-NEXT: }
1592   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1593   // CHECK-NEXT: }
1594   omp.atomic.capture hint(uncontended) {
1595     omp.atomic.update %x : memref<i32> {
1596     ^bb0(%xval: i32):
1597       %newval = llvm.add %xval, %expr : i32
1598       omp.yield(%newval : i32)
1599     }
1600     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1601   }
1603   // CHECK: omp.atomic.capture hint(contended) {
1604   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1605   // CHECK-NEXT: (%[[xval:.*]]: i32):
1606   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1607   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1608   // CHECK-NEXT: }
1609   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1610   // CHECK-NEXT: }
1611   omp.atomic.capture hint(contended) {
1612     omp.atomic.update %x : memref<i32> {
1613     ^bb0(%xval: i32):
1614       %newval = llvm.add %xval, %expr : i32
1615       omp.yield(%newval : i32)
1616     }
1617     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1618   }
1620   // CHECK: omp.atomic.capture hint(nonspeculative) {
1621   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1622   // CHECK-NEXT: (%[[xval:.*]]: i32):
1623   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1624   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1625   // CHECK-NEXT: }
1626   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1627   // CHECK-NEXT: }
1628   omp.atomic.capture hint(nonspeculative) {
1629     omp.atomic.update %x : memref<i32> {
1630     ^bb0(%xval: i32):
1631       %newval = llvm.add %xval, %expr : i32
1632       omp.yield(%newval : i32)
1633     }
1634     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1635   }
1637   // CHECK: omp.atomic.capture hint(speculative) {
1638   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1639   // CHECK-NEXT: (%[[xval:.*]]: i32):
1640   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1641   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1642   // CHECK-NEXT: }
1643   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1644   // CHECK-NEXT: }
1645   omp.atomic.capture hint(speculative) {
1646     omp.atomic.update %x : memref<i32> {
1647     ^bb0(%xval: i32):
1648       %newval = llvm.add %xval, %expr : i32
1649       omp.yield(%newval : i32)
1650     }
1651     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1652   }
1654   // CHECK: omp.atomic.capture hint(uncontended, nonspeculative) {
1655   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1656   // CHECK-NEXT: (%[[xval:.*]]: i32):
1657   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1658   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1659   // CHECK-NEXT: }
1660   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1661   // CHECK-NEXT: }
1662   omp.atomic.capture hint(uncontended, nonspeculative) {
1663     omp.atomic.update %x : memref<i32> {
1664     ^bb0(%xval: i32):
1665       %newval = llvm.add %xval, %expr : i32
1666       omp.yield(%newval : i32)
1667     }
1668     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1669   }
1671   // CHECK: omp.atomic.capture hint(contended, nonspeculative) {
1672   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1673   // CHECK-NEXT: (%[[xval:.*]]: i32):
1674   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1675   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1676   // CHECK-NEXT: }
1677   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1678   // CHECK-NEXT: }
1679   omp.atomic.capture hint(contended, nonspeculative) {
1680     omp.atomic.update %x : memref<i32> {
1681     ^bb0(%xval: i32):
1682       %newval = llvm.add %xval, %expr : i32
1683       omp.yield(%newval : i32)
1684     }
1685     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1686   }
1688   // CHECK: omp.atomic.capture hint(uncontended, speculative) {
1689   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1690   // CHECK-NEXT: (%[[xval:.*]]: i32):
1691   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1692   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1693   // CHECK-NEXT: }
1694   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1695   // CHECK-NEXT: }
1696   omp.atomic.capture hint(uncontended, speculative) {
1697     omp.atomic.update %x : memref<i32> {
1698     ^bb0(%xval: i32):
1699       %newval = llvm.add %xval, %expr : i32
1700       omp.yield(%newval : i32)
1701     }
1702     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1703   }
1705   // CHECK: omp.atomic.capture hint(contended, speculative) {
1706   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1707   // CHECK-NEXT: (%[[xval:.*]]: i32):
1708   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1709   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1710   // CHECK-NEXT: }
1711   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1712   // CHECK-NEXT: }
1713   omp.atomic.capture hint(contended, speculative) {
1714     omp.atomic.update %x : memref<i32> {
1715     ^bb0(%xval: i32):
1716       %newval = llvm.add %xval, %expr : i32
1717       omp.yield(%newval : i32)
1718     }
1719     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1720   }
1722   // CHECK: omp.atomic.capture memory_order(seq_cst) {
1723   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1724   // CHECK-NEXT: (%[[xval:.*]]: i32):
1725   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1726   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1727   // CHECK-NEXT: }
1728   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1729   // CHECK-NEXT: }
1730   omp.atomic.capture memory_order(seq_cst) {
1731     omp.atomic.update %x : memref<i32> {
1732     ^bb0(%xval: i32):
1733       %newval = llvm.add %xval, %expr : i32
1734       omp.yield(%newval : i32)
1735     }
1736     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1737   }
1739   // CHECK: omp.atomic.capture memory_order(acq_rel) {
1740   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1741   // CHECK-NEXT: (%[[xval:.*]]: i32):
1742   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1743   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1744   // CHECK-NEXT: }
1745   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1746   // CHECK-NEXT: }
1747   omp.atomic.capture memory_order(acq_rel) {
1748     omp.atomic.update %x : memref<i32> {
1749     ^bb0(%xval: i32):
1750       %newval = llvm.add %xval, %expr : i32
1751       omp.yield(%newval : i32)
1752     }
1753     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1754   }
1756   // CHECK: omp.atomic.capture memory_order(acquire) {
1757   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1758   // CHECK-NEXT: (%[[xval:.*]]: i32):
1759   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1760   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1761   // CHECK-NEXT: }
1762   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1763   // CHECK-NEXT: }
1764   omp.atomic.capture memory_order(acquire) {
1765     omp.atomic.update %x : memref<i32> {
1766     ^bb0(%xval: i32):
1767       %newval = llvm.add %xval, %expr : i32
1768       omp.yield(%newval : i32)
1769     }
1770     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1771   }
1773   // CHECK: omp.atomic.capture memory_order(release) {
1774   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1775   // CHECK-NEXT: (%[[xval:.*]]: i32):
1776   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1777   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1778   // CHECK-NEXT: }
1779   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1780   // CHECK-NEXT: }
1781   omp.atomic.capture memory_order(release) {
1782     omp.atomic.update %x : memref<i32> {
1783     ^bb0(%xval: i32):
1784       %newval = llvm.add %xval, %expr : i32
1785       omp.yield(%newval : i32)
1786     }
1787     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1788   }
1790   // CHECK: omp.atomic.capture memory_order(relaxed) {
1791   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1792   // CHECK-NEXT: (%[[xval:.*]]: i32):
1793   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1794   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1795   // CHECK-NEXT: }
1796   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1797   // CHECK-NEXT: }
1798   omp.atomic.capture memory_order(relaxed) {
1799     omp.atomic.update %x : memref<i32> {
1800     ^bb0(%xval: i32):
1801       %newval = llvm.add %xval, %expr : i32
1802       omp.yield(%newval : i32)
1803     }
1804     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1805   }
1807   // CHECK: omp.atomic.capture hint(contended, speculative) memory_order(seq_cst) {
1808   // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1809   // CHECK-NEXT: (%[[xval:.*]]: i32):
1810   // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1811   // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1812   // CHECK-NEXT: }
1813   // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1814   // CHECK-NEXT: }
1815   omp.atomic.capture hint(contended, speculative) memory_order(seq_cst) {
1816     omp.atomic.update %x : memref<i32> {
1817     ^bb0(%xval: i32):
1818       %newval = llvm.add %xval, %expr : i32
1819       omp.yield(%newval : i32)
1820     }
1821     omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1822   }
1824   return
1827 // CHECK-LABEL: omp_sectionsop
1828 func.func @omp_sectionsop(%data_var1 : memref<i32>, %data_var2 : memref<i32>,
1829                      %data_var3 : memref<i32>, %redn_var : !llvm.ptr) {
1830   // CHECK: omp.sections allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
1831   "omp.sections" (%data_var1, %data_var1) ({
1832     // CHECK: omp.terminator
1833     omp.terminator
1834   }) {operandSegmentSizes = array<i32: 1,1,0,0>} : (memref<i32>, memref<i32>) -> ()
1836     // CHECK: omp.sections reduction(@add_f32 %{{.*}} -> %{{.*}} : !llvm.ptr)
1837   "omp.sections" (%redn_var) ({
1838   ^bb0(%arg0: !llvm.ptr):
1839     // CHECK: omp.terminator
1840     omp.terminator
1841   }) {operandSegmentSizes = array<i32: 0,0,0,1>, reduction_byref = array<i1: false>, reduction_syms=[@add_f32]} : (!llvm.ptr) -> ()
1843   // CHECK: omp.sections nowait {
1844   omp.sections nowait {
1845     // CHECK: omp.terminator
1846     omp.terminator
1847   }
1849   // CHECK: omp.sections reduction(@add_f32 %{{.*}} -> %{{.*}} : !llvm.ptr) {
1850   omp.sections reduction(@add_f32 %redn_var -> %arg0 : !llvm.ptr) {
1851     // CHECK: omp.terminator
1852     omp.terminator
1853   }
1855   // CHECK: omp.sections allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
1856   omp.sections allocate(%data_var1 : memref<i32> -> %data_var1 : memref<i32>) {
1857     // CHECK: omp.terminator
1858     omp.terminator
1859   }
1861   // CHECK: omp.sections nowait
1862   omp.sections nowait {
1863     // CHECK: omp.section
1864     omp.section {
1865       // CHECK: %{{.*}} = "test.payload"() : () -> i32
1866       %1 = "test.payload"() : () -> i32
1867       // CHECK: %{{.*}} = "test.payload"() : () -> i32
1868       %2 = "test.payload"() : () -> i32
1869       // CHECK: %{{.*}} = "test.payload"(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
1870       %3 = "test.payload"(%1, %2) : (i32, i32) -> i32
1871     }
1872     // CHECK: omp.section
1873     omp.section {
1874       // CHECK: %{{.*}} = "test.payload"(%{{.*}}) : (!llvm.ptr) -> i32
1875       %1 = "test.payload"(%redn_var) : (!llvm.ptr) -> i32
1876     }
1877     // CHECK: omp.section
1878     omp.section {
1879       // CHECK: "test.payload"(%{{.*}}) : (!llvm.ptr) -> ()
1880       "test.payload"(%redn_var) : (!llvm.ptr) -> ()
1881     }
1882     // CHECK: omp.terminator
1883     omp.terminator
1884   }
1885   return
1888 // CHECK-LABEL: func @omp_single
1889 func.func @omp_single() {
1890   omp.parallel {
1891     // CHECK: omp.single {
1892     omp.single {
1893       "test.payload"() : () -> ()
1894       // CHECK: omp.terminator
1895       omp.terminator
1896     }
1897     // CHECK: omp.terminator
1898     omp.terminator
1899   }
1900   return
1903 // CHECK-LABEL: func @omp_single_nowait
1904 func.func @omp_single_nowait() {
1905   omp.parallel {
1906     // CHECK: omp.single nowait {
1907     omp.single nowait {
1908       "test.payload"() : () -> ()
1909       // CHECK: omp.terminator
1910       omp.terminator
1911     }
1912     // CHECK: omp.terminator
1913     omp.terminator
1914   }
1915   return
1918 // CHECK-LABEL: func @omp_single_allocate
1919 func.func @omp_single_allocate(%data_var: memref<i32>) {
1920   omp.parallel {
1921     // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) {
1922     omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
1923       "test.payload"() : () -> ()
1924       // CHECK: omp.terminator
1925       omp.terminator
1926     }
1927     // CHECK: omp.terminator
1928     omp.terminator
1929   }
1930   return
1933 // CHECK-LABEL: func @omp_single_allocate_nowait
1934 func.func @omp_single_allocate_nowait(%data_var: memref<i32>) {
1935   omp.parallel {
1936     // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) nowait {
1937     omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) nowait {
1938       "test.payload"() : () -> ()
1939       // CHECK: omp.terminator
1940       omp.terminator
1941     }
1942     // CHECK: omp.terminator
1943     omp.terminator
1944   }
1945   return
1948 // CHECK-LABEL: func @omp_single_multiple_blocks
1949 func.func @omp_single_multiple_blocks() {
1950   // CHECK: omp.single {
1951   omp.single {
1952     cf.br ^bb2
1953     ^bb2:
1954     // CHECK: omp.terminator
1955     omp.terminator
1956   }
1957   return
1960 func.func private @copy_i32(memref<i32>, memref<i32>)
1962 // CHECK-LABEL: func @omp_single_copyprivate
1963 func.func @omp_single_copyprivate(%data_var: memref<i32>) {
1964   omp.parallel {
1965     // CHECK: omp.single copyprivate(%{{.*}} -> @copy_i32 : memref<i32>) {
1966     omp.single copyprivate(%data_var -> @copy_i32 : memref<i32>) {
1967       "test.payload"() : () -> ()
1968       // CHECK: omp.terminator
1969       omp.terminator
1970     }
1971     // CHECK: omp.terminator
1972     omp.terminator
1973   }
1974   return
1977 // CHECK-LABEL: @omp_task
1978 // CHECK-SAME: (%[[bool_var:.*]]: i1, %[[i64_var:.*]]: i64, %[[i32_var:.*]]: i32, %[[data_var:.*]]: memref<i32>, %[[event_handle:.*]]: !llvm.ptr)
1979 func.func @omp_task(%bool_var: i1, %i64_var: i64, %i32_var: i32, %data_var: memref<i32>, %event_handle : !llvm.ptr) {
1981   // Checking simple task
1982   // CHECK: omp.task {
1983   omp.task {
1984     // CHECK: "test.foo"() : () -> ()
1985     "test.foo"() : () -> ()
1986     // CHECK: omp.terminator
1987     omp.terminator
1988   }
1990   // Checking `if` clause
1991   // CHECK: omp.task if(%[[bool_var]]) {
1992   omp.task if(%bool_var) {
1993     // CHECK: "test.foo"() : () -> ()
1994     "test.foo"() : () -> ()
1995     // CHECK: omp.terminator
1996     omp.terminator
1997   }
1999   // Checking `final` clause
2000   // CHECK: omp.task final(%[[bool_var]]) {
2001   omp.task final(%bool_var) {
2002     // CHECK: "test.foo"() : () -> ()
2003     "test.foo"() : () -> ()
2004     // CHECK: omp.terminator
2005     omp.terminator
2006   }
2008   // Checking `untied` clause
2009   // CHECK: omp.task untied {
2010   omp.task untied {
2011     // CHECK: "test.foo"() : () -> ()
2012     "test.foo"() : () -> ()
2013     // CHECK: omp.terminator
2014     omp.terminator
2015   }
2017   // Checking `in_reduction` clause
2018   %c1 = arith.constant 1 : i32
2019   // CHECK: %[[redn_var1:.*]] = llvm.alloca %{{.*}} x f32 : (i32) -> !llvm.ptr
2020   %0 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr
2021   // CHECK: %[[redn_var2:.*]] = llvm.alloca %{{.*}} x f32 : (i32) -> !llvm.ptr
2022   %1 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr
2023   // CHECK: omp.task in_reduction(@add_f32 %[[redn_var1]] -> %{{.+}}, @add_f32 %[[redn_var2]] -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2024   omp.task in_reduction(@add_f32 %0 -> %arg0, @add_f32 %1 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2025     // CHECK: "test.foo"() : () -> ()
2026     "test.foo"() : () -> ()
2027     // CHECK: omp.terminator
2028     omp.terminator
2029   }
2031   // Checking `in_reduction` clause (mixed) byref
2032   // CHECK: omp.task in_reduction(byref @add_f32 %[[redn_var1]] -> %{{.+}}, @add_f32 %[[redn_var2]] -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2033   omp.task in_reduction(byref @add_f32 %0 -> %arg0, @add_f32 %1 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2034     // CHECK: "test.foo"() : () -> ()
2035     "test.foo"() : () -> ()
2036     // CHECK: omp.terminator
2037     omp.terminator
2038   }
2040   // Checking priority clause
2041   // CHECK: omp.task priority(%[[i32_var]] : i32) {
2042   omp.task priority(%i32_var : i32) {
2043     // CHECK: "test.foo"() : () -> ()
2044     "test.foo"() : () -> ()
2045     // CHECK: omp.terminator
2046     omp.terminator
2047   }
2049   // Checking allocate clause
2050   // CHECK: omp.task allocate(%[[data_var]] : memref<i32> -> %[[data_var]] : memref<i32>) {
2051   omp.task allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
2052     // CHECK: "test.foo"() : () -> ()
2053     "test.foo"() : () -> ()
2054     // CHECK: omp.terminator
2055     omp.terminator
2056   }
2057   // Checking detach clause
2058   // CHECK: omp.task detach(%[[event_handle]] : !llvm.ptr)
2059   omp.task detach(%event_handle : !llvm.ptr){
2060      omp.terminator
2061   }
2062   // Checking multiple clauses
2063   // CHECK: omp.task allocate(%[[data_var]] : memref<i32> -> %[[data_var]] : memref<i32>)
2064   omp.task allocate(%data_var : memref<i32> -> %data_var : memref<i32>)
2065       // CHECK-SAME: final(%[[bool_var]]) if(%[[bool_var]])
2066       final(%bool_var) if(%bool_var)
2067       // CHECK-SAME: priority(%[[i32_var]] : i32) untied
2068       priority(%i32_var : i32) untied
2069       // CHECK-SAME: in_reduction(@add_f32 %[[redn_var1]] -> %{{.+}}, byref @add_f32 %[[redn_var2]] -> %{{.+}} : !llvm.ptr, !llvm.ptr)
2070       in_reduction(@add_f32 %0 -> %arg0, byref @add_f32 %1 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2071     // CHECK: "test.foo"() : () -> ()
2072     "test.foo"() : () -> ()
2073     // CHECK: omp.terminator
2074     omp.terminator
2075   }
2077   return
2080 // CHECK-LABEL: @omp_task_depend
2081 // CHECK-SAME: (%arg0: memref<i32>, %arg1: memref<i32>) {
2082 func.func @omp_task_depend(%arg0: memref<i32>, %arg1: memref<i32>) {
2083   // CHECK:  omp.task   depend(taskdependin -> %arg0 : memref<i32>, taskdependin -> %arg1 : memref<i32>, taskdependinout -> %arg0 : memref<i32>) {
2084   omp.task   depend(taskdependin -> %arg0 : memref<i32>, taskdependin -> %arg1 : memref<i32>, taskdependinout -> %arg0 : memref<i32>) {
2085     // CHECK: "test.foo"() : () -> ()
2086     "test.foo"() : () -> ()
2087     // CHECK: omp.terminator
2088     omp.terminator
2089   }
2090   return
2094 // CHECK-LABEL: @omp_target_depend
2095 // CHECK-SAME: (%arg0: memref<i32>, %arg1: memref<i32>) {
2096 func.func @omp_target_depend(%arg0: memref<i32>, %arg1: memref<i32>) {
2097   // CHECK:  omp.target depend(taskdependin -> %arg0 : memref<i32>, taskdependin -> %arg1 : memref<i32>, taskdependinout -> %arg0 : memref<i32>) {
2098   omp.target depend(taskdependin -> %arg0 : memref<i32>, taskdependin -> %arg1 : memref<i32>, taskdependinout -> %arg0 : memref<i32>) {
2099     // CHECK: omp.terminator
2100     omp.terminator
2101   } {operandSegmentSizes = array<i32: 0,0,0,3,0,0,0,0>}
2102   return
2105 func.func @omp_threadprivate() {
2106   %0 = arith.constant 1 : i32
2107   %1 = arith.constant 2 : i32
2108   %2 = arith.constant 3 : i32
2110   // CHECK: [[ARG0:%.*]] = llvm.mlir.addressof @_QFsubEx : !llvm.ptr
2111   // CHECK: {{.*}} = omp.threadprivate [[ARG0]] : !llvm.ptr -> !llvm.ptr
2112   %3 = llvm.mlir.addressof @_QFsubEx : !llvm.ptr
2113   %4 = omp.threadprivate %3 : !llvm.ptr -> !llvm.ptr
2114   llvm.store %0, %4 : i32, !llvm.ptr
2116   // CHECK:  omp.parallel
2117   // CHECK:    {{.*}} = omp.threadprivate [[ARG0]] : !llvm.ptr -> !llvm.ptr
2118   omp.parallel  {
2119     %5 = omp.threadprivate %3 : !llvm.ptr -> !llvm.ptr
2120     llvm.store %1, %5 : i32, !llvm.ptr
2121     omp.terminator
2122   }
2123   llvm.store %2, %4 : i32, !llvm.ptr
2124   return
2127 llvm.mlir.global internal @_QFsubEx() : i32
2129 func.func @omp_cancel_parallel(%if_cond : i1) -> () {
2130   // Test with optional operand; if_expr.
2131   omp.parallel {
2132     // CHECK: omp.cancel cancellation_construct_type(parallel) if(%{{.*}})
2133     omp.cancel cancellation_construct_type(parallel) if(%if_cond)
2134     // CHECK: omp.terminator
2135     omp.terminator
2136   }
2137   return
2140 func.func @omp_cancel_wsloop(%lb : index, %ub : index, %step : index) {
2141   omp.wsloop {
2142     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2143       // CHECK: omp.cancel cancellation_construct_type(loop)
2144       omp.cancel cancellation_construct_type(loop)
2145       // CHECK: omp.yield
2146       omp.yield
2147     }
2148   }
2149   return
2152 func.func @omp_cancel_sections() -> () {
2153   omp.sections {
2154     omp.section {
2155       // CHECK: omp.cancel cancellation_construct_type(sections)
2156       omp.cancel cancellation_construct_type(sections)
2157       omp.terminator
2158     }
2159     // CHECK: omp.terminator
2160     omp.terminator
2161   }
2162   return
2165 func.func @omp_cancellationpoint_parallel() -> () {
2166   omp.parallel {
2167     // CHECK: omp.cancellation_point cancellation_construct_type(parallel)
2168     omp.cancellation_point cancellation_construct_type(parallel)
2169     // CHECK: omp.cancel cancellation_construct_type(parallel)
2170     omp.cancel cancellation_construct_type(parallel)
2171     omp.terminator
2172   }
2173   return
2176 func.func @omp_cancellationpoint_wsloop(%lb : index, %ub : index, %step : index) {
2177   omp.wsloop {
2178     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2179       // CHECK: omp.cancellation_point cancellation_construct_type(loop)
2180       omp.cancellation_point cancellation_construct_type(loop)
2181       // CHECK: omp.cancel cancellation_construct_type(loop)
2182       omp.cancel cancellation_construct_type(loop)
2183       // CHECK: omp.yield
2184       omp.yield
2185     }
2186   }
2187   return
2190 func.func @omp_cancellationpoint_sections() -> () {
2191   omp.sections {
2192     omp.section {
2193       // CHECK: omp.cancellation_point cancellation_construct_type(sections)
2194       omp.cancellation_point cancellation_construct_type(sections)
2195       // CHECK: omp.cancel cancellation_construct_type(sections)
2196       omp.cancel cancellation_construct_type(sections)
2197       omp.terminator
2198     }
2199     // CHECK: omp.terminator
2200     omp.terminator
2201   }
2202   return
2205 // CHECK-LABEL: @omp_taskgroup_no_tasks
2206 func.func @omp_taskgroup_no_tasks() -> () {
2208   // CHECK: omp.taskgroup
2209   omp.taskgroup {
2210     // CHECK: "test.foo"() : () -> ()
2211     "test.foo"() : () -> ()
2212     // CHECK: omp.terminator
2213     omp.terminator
2214   }
2215   return
2218 // CHECK-LABEL: @omp_taskgroup_multiple_tasks
2219 func.func @omp_taskgroup_multiple_tasks() -> () {
2220   // CHECK: omp.taskgroup
2221   omp.taskgroup {
2222     // CHECK: omp.task
2223     omp.task {
2224       "test.foo"() : () -> ()
2225       // CHECK: omp.terminator
2226       omp.terminator
2227     }
2228     // CHECK: omp.task
2229     omp.task {
2230       "test.foo"() : () -> ()
2231       // CHECK: omp.terminator
2232       omp.terminator
2233     }
2234     // CHECK: omp.terminator
2235     omp.terminator
2236   }
2237   return
2240 // CHECK-LABEL: @omp_taskgroup_clauses
2241 func.func @omp_taskgroup_clauses() -> () {
2242   %testmemref = "test.memref"() : () -> (memref<i32>)
2243   %testf32 = "test.f32"() : () -> (!llvm.ptr)
2244   // CHECK: omp.taskgroup allocate(%{{.+}}: memref<i32> -> %{{.+}} : memref<i32>) task_reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr)
2245   omp.taskgroup allocate(%testmemref : memref<i32> -> %testmemref : memref<i32>) task_reduction(@add_f32 %testf32 -> %arg0 : !llvm.ptr) {
2246     // CHECK: omp.task
2247     omp.task {
2248       "test.foo"() : () -> ()
2249       // CHECK: omp.terminator
2250       omp.terminator
2251     }
2252     // CHECK: omp.task
2253     omp.task {
2254       "test.foo"() : () -> ()
2255       // CHECK: omp.terminator
2256       omp.terminator
2257     }
2258     // CHECK: omp.terminator
2259     omp.terminator
2260   }
2261   return
2264 // CHECK-LABEL: @omp_taskloop
2265 func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
2267   // CHECK: omp.taskloop {
2268   omp.taskloop {
2269     omp.loop_nest (%i) : i32 = (%lb) to (%ub) step (%step)  {
2270       // CHECK: omp.yield
2271       omp.yield
2272     }
2273   }
2275   %testbool = "test.bool"() : () -> (i1)
2277   // CHECK: omp.taskloop if(%{{[^)]+}}) {
2278   omp.taskloop if(%testbool) {
2279     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2280       // CHECK: omp.yield
2281       omp.yield
2282     }
2283   }
2285   // CHECK: omp.taskloop final(%{{[^)]+}}) {
2286   omp.taskloop final(%testbool) {
2287     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2288       // CHECK: omp.yield
2289       omp.yield
2290     }
2291   }
2293   // CHECK: omp.taskloop untied {
2294   omp.taskloop untied {
2295     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2296       // CHECK: omp.yield
2297       omp.yield
2298     }
2299   }
2301   // CHECK: omp.taskloop mergeable {
2302   omp.taskloop mergeable {
2303     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2304       // CHECK: omp.yield
2305       omp.yield
2306     }
2307   }
2309   %testf32 = "test.f32"() : () -> (!llvm.ptr)
2310   %testf32_2 = "test.f32"() : () -> (!llvm.ptr)
2311   // CHECK: omp.taskloop in_reduction(@add_f32 %{{.+}} -> %{{.+}}, @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2312   omp.taskloop in_reduction(@add_f32 %testf32 -> %arg0, @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2313     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2314       // CHECK: omp.yield
2315       omp.yield
2316     }
2317   }
2319   // Checking byref attribute for in_reduction
2320   // CHECK: omp.taskloop in_reduction(byref @add_f32 %{{.+}} -> %{{.+}}, @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2321   omp.taskloop in_reduction(byref @add_f32 %testf32 -> %arg0, @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2322     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2323       // CHECK: omp.yield
2324       omp.yield
2325     }
2326   }
2328   // CHECK: omp.taskloop reduction(byref @add_f32 %{{.+}} -> %{{.+}}, @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2329   omp.taskloop reduction(byref @add_f32 %testf32 -> %arg0, @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2330     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2331       // CHECK: omp.yield
2332       omp.yield
2333     }
2334   }
2336   // check byref attrbute for reduction
2337   // CHECK: omp.taskloop reduction(byref @add_f32 %{{.+}} -> %{{.+}}, byref @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2338   omp.taskloop reduction(byref @add_f32 %testf32 -> %arg0, byref @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2339     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2340       // CHECK: omp.yield
2341       omp.yield
2342     }
2343   }
2345   // CHECK: omp.taskloop in_reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) {
2346   omp.taskloop in_reduction(@add_f32 %testf32 -> %arg0 : !llvm.ptr) reduction(@add_f32 %testf32_2 -> %arg1 : !llvm.ptr) {
2347     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2348       // CHECK: omp.yield
2349       omp.yield
2350     }
2351   }
2353   %testi32 = "test.i32"() : () -> (i32)
2354   // CHECK: omp.taskloop priority(%{{[^:]+}}: i32) {
2355   omp.taskloop priority(%testi32 : i32) {
2356     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2357       // CHECK: omp.yield
2358       omp.yield
2359     }
2360   }
2362   %testmemref = "test.memref"() : () -> (memref<i32>)
2363   // CHECK: omp.taskloop allocate(%{{.+}} : memref<i32> -> %{{.+}} : memref<i32>) {
2364   omp.taskloop allocate(%testmemref : memref<i32> -> %testmemref : memref<i32>) {
2365     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2366       // CHECK: omp.yield
2367       omp.yield
2368     }
2369   }
2371   %testi64 = "test.i64"() : () -> (i64)
2372   // CHECK: omp.taskloop grainsize(%{{[^:]+}}: i64) {
2373   omp.taskloop grainsize(%testi64: i64) {
2374     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2375       // CHECK: omp.yield
2376       omp.yield
2377     }
2378   }
2380   // CHECK: omp.taskloop num_tasks(%{{[^:]+}}: i64) {
2381   omp.taskloop num_tasks(%testi64: i64) {
2382     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2383       // CHECK: omp.yield
2384       omp.yield
2385     }
2386   }
2388   // CHECK: omp.taskloop nogroup {
2389   omp.taskloop nogroup {
2390     omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2391       // CHECK: omp.yield
2392       omp.yield
2393     }
2394   }
2396   // CHECK: omp.taskloop {
2397   omp.taskloop {
2398     omp.simd {
2399       omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2400         // CHECK: omp.yield
2401         omp.yield
2402       }
2403     } {omp.composite}
2404   } {omp.composite}
2406   // CHECK: return
2407   return
2410 // CHECK: func.func @omp_requires_one
2411 // CHECK-SAME: omp.requires = #omp<clause_requires reverse_offload>
2412 func.func @omp_requires_one() -> ()
2413     attributes {omp.requires = #omp<clause_requires reverse_offload>} {
2414   return
2417 // CHECK: func.func @omp_requires_multiple
2418 // CHECK-SAME: omp.requires = #omp<clause_requires unified_address|dynamic_allocators>
2419 func.func @omp_requires_multiple() -> ()
2420     attributes {omp.requires = #omp<clause_requires unified_address|dynamic_allocators>} {
2421   return
2424 // CHECK-LABEL: @opaque_pointers_atomic_rwu
2425 // CHECK-SAME: (%[[v:.*]]: !llvm.ptr, %[[x:.*]]: !llvm.ptr)
2426 func.func @opaque_pointers_atomic_rwu(%v: !llvm.ptr, %x: !llvm.ptr) {
2427   // CHECK: omp.atomic.read %[[v]] = %[[x]] : !llvm.ptr, !llvm.ptr, i32
2428   // CHECK: %[[VAL:.*]] = llvm.load %[[x]] : !llvm.ptr -> i32
2429   // CHECK: omp.atomic.write %[[v]] = %[[VAL]] : !llvm.ptr, i32
2430   // CHECK: omp.atomic.update %[[x]] : !llvm.ptr {
2431   // CHECK-NEXT: ^{{[[:alnum:]]+}}(%[[XVAL:.*]]: i32):
2432   // CHECK-NEXT:   omp.yield(%[[XVAL]] : i32)
2433   // CHECK-NEXT: }
2434   omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2435   %val = llvm.load %x : !llvm.ptr -> i32
2436   omp.atomic.write %v = %val : !llvm.ptr, i32
2437   omp.atomic.update %x : !llvm.ptr {
2438     ^bb0(%xval: i32):
2439       omp.yield(%xval : i32)
2440   }
2441   return
2444 // CHECK-LABEL: @opaque_pointers_reduction
2445 // CHECK: atomic {
2446 // CHECK-NEXT: ^{{[[:alnum:]]+}}(%{{.*}}: !llvm.ptr, %{{.*}}: !llvm.ptr):
2447 // CHECK-NOT: cleanup
2448 omp.declare_reduction @opaque_pointers_reduction : f32
2449 init {
2450 ^bb0(%arg: f32):
2451   %0 = arith.constant 0.0 : f32
2452   omp.yield (%0 : f32)
2454 combiner {
2455 ^bb1(%arg0: f32, %arg1: f32):
2456   %1 = arith.addf %arg0, %arg1 : f32
2457   omp.yield (%1 : f32)
2459 atomic {
2460 ^bb2(%arg2: !llvm.ptr, %arg3: !llvm.ptr):
2461   %2 = llvm.load %arg3 : !llvm.ptr -> f32
2462   llvm.atomicrmw fadd %arg2, %2 monotonic : !llvm.ptr, f32
2463   omp.yield
2466 // CHECK-LABEL: @alloc_reduction
2467 // CHECK-SAME:  alloc {
2468 // CHECK-NEXT:  ^bb0(%[[ARG0:.*]]: !llvm.ptr):
2469 // ...
2470 // CHECK:         omp.yield
2471 // CHECK-NEXT:  } init {
2472 // CHECK:       } combiner {
2473 // CHECK:       }
2474 omp.declare_reduction @alloc_reduction : !llvm.ptr
2475 alloc {
2476 ^bb0(%arg: !llvm.ptr):
2477   %c1 = arith.constant 1 : i32
2478   %0 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr
2479   omp.yield (%0 : !llvm.ptr)
2481 init {
2482 ^bb0(%mold: !llvm.ptr, %alloc: !llvm.ptr):
2483   %cst = arith.constant 1.0 : f32
2484   llvm.store %cst, %alloc : f32, !llvm.ptr
2485   omp.yield (%alloc : !llvm.ptr)
2487 combiner {
2488 ^bb1(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
2489   %0 = llvm.load %arg0 : !llvm.ptr -> f32
2490   %1 = llvm.load %arg1 : !llvm.ptr -> f32
2491   %2 = arith.addf %0, %1 : f32
2492   llvm.store %2, %arg0 : f32, !llvm.ptr
2493   omp.yield (%arg0 : !llvm.ptr)
2496 // CHECK-LABEL: omp_targets_with_map_bounds
2497 // CHECK-SAME: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr)
2498 func.func @omp_targets_with_map_bounds(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () {
2499   // CHECK: %[[C_00:.*]] = llvm.mlir.constant(4 : index) : i64
2500   // CHECK: %[[C_01:.*]] = llvm.mlir.constant(1 : index) : i64
2501   // CHECK: %[[C_02:.*]] = llvm.mlir.constant(1 : index) : i64
2502   // CHECK: %[[C_03:.*]] = llvm.mlir.constant(1 : index) : i64
2503   // CHECK: %[[BOUNDS0:.*]] = omp.map.bounds   lower_bound(%[[C_01]] : i64) upper_bound(%[[C_00]] : i64) stride(%[[C_02]] : i64) start_idx(%[[C_03]] : i64)
2504   // CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<10 x i32>)   map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""}
2505     %0 = llvm.mlir.constant(4 : index) : i64
2506     %1 = llvm.mlir.constant(1 : index) : i64
2507     %2 = llvm.mlir.constant(1 : index) : i64
2508     %3 = llvm.mlir.constant(1 : index) : i64
2509     %4 = omp.map.bounds   lower_bound(%1 : i64) upper_bound(%0 : i64) stride(%2 : i64) start_idx(%3 : i64)
2511     %mapv1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.array<10 x i32>)   map_clauses(tofrom) capture(ByRef) bounds(%4) -> !llvm.ptr {name = ""}
2512   // CHECK: %[[C_10:.*]] = llvm.mlir.constant(9 : index) : i64
2513   // CHECK: %[[C_11:.*]] = llvm.mlir.constant(1 : index) : i64
2514   // CHECK: %[[C_12:.*]] = llvm.mlir.constant(2 : index) : i64
2515   // CHECK: %[[C_13:.*]] = llvm.mlir.constant(2 : index) : i64
2516   // CHECK: %[[BOUNDS1:.*]] = omp.map.bounds   lower_bound(%[[C_11]] : i64) upper_bound(%[[C_10]] : i64) stride(%[[C_12]] : i64) start_idx(%[[C_13]] : i64)
2517   // CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.array<10 x i32>)   map_clauses(exit_release_or_enter_alloc) capture(ByCopy) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""}
2518     %6 = llvm.mlir.constant(9 : index) : i64
2519     %7 = llvm.mlir.constant(1 : index) : i64
2520     %8 = llvm.mlir.constant(2 : index) : i64
2521     %9 = llvm.mlir.constant(2 : index) : i64
2522     %10 = omp.map.bounds   lower_bound(%7 : i64) upper_bound(%6 : i64) stride(%8 : i64) start_idx(%9 : i64)
2523     %mapv2 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>)   map_clauses(exit_release_or_enter_alloc) capture(ByCopy) bounds(%10) -> !llvm.ptr {name = ""}
2525     // CHECK: omp.target map_entries(%[[MAP0]] -> {{.*}}, %[[MAP1]] -> {{.*}} : !llvm.ptr, !llvm.ptr)
2526     omp.target map_entries(%mapv1 -> %arg2, %mapv2 -> %arg3 : !llvm.ptr, !llvm.ptr) {
2527       omp.terminator
2528     }
2530     // CHECK: omp.target_data map_entries(%[[MAP0]], %[[MAP1]] : !llvm.ptr, !llvm.ptr)
2531     omp.target_data map_entries(%mapv1, %mapv2 : !llvm.ptr, !llvm.ptr){}
2533     // CHECK: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<10 x i32>)   map_clauses(exit_release_or_enter_alloc) capture(VLAType) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""}
2534     // CHECK: omp.target_enter_data map_entries(%[[MAP2]] : !llvm.ptr)
2535     %mapv3 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.array<10 x i32>)   map_clauses(exit_release_or_enter_alloc) capture(VLAType) bounds(%4) -> !llvm.ptr {name = ""}
2536     omp.target_enter_data map_entries(%mapv3 : !llvm.ptr){}
2538     // CHECK: %[[MAP3:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.array<10 x i32>)   map_clauses(exit_release_or_enter_alloc) capture(This) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""}
2539     // CHECK: omp.target_exit_data map_entries(%[[MAP3]] : !llvm.ptr)
2540     %mapv4 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>)   map_clauses(exit_release_or_enter_alloc) capture(This) bounds(%10) -> !llvm.ptr {name = ""}
2541     omp.target_exit_data map_entries(%mapv4 : !llvm.ptr){}
2543     return
2546 // CHECK-LABEL: omp_target_update_data
2547 func.func @omp_target_update_data (%if_cond : i1, %device : si32, %map1: memref<?xi32>, %map2: memref<?xi32>) -> () {
2548     %mapv_from = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""}
2550     %mapv_to = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(present, to) capture(ByRef) -> memref<?xi32> {name = ""}
2552     // CHECK: omp.target_update device(%[[VAL_1:.*]] : si32) if(%[[VAL_0:.*]]) map_entries(%{{.*}}, %{{.*}} : memref<?xi32>, memref<?xi32>) nowait
2553     omp.target_update if(%if_cond) device(%device : si32) nowait map_entries(%mapv_from , %mapv_to : memref<?xi32>, memref<?xi32>)
2554     return
2557 // CHECK-LABEL: omp_targets_is_allocatable
2558 // CHECK-SAME: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr)
2559 func.func @omp_targets_is_allocatable(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () {
2560   // CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
2561   %mapv1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
2562   // CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%[[MAP0]] : [0] : !llvm.ptr) -> !llvm.ptr {name = ""}
2563   %mapv2 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>)   map_clauses(tofrom) capture(ByRef) members(%mapv1 : [0] : !llvm.ptr) -> !llvm.ptr {name = ""}
2564   // CHECK: omp.target map_entries(%[[MAP0]] -> {{.*}}, %[[MAP1]] -> {{.*}} : !llvm.ptr, !llvm.ptr)
2565   omp.target map_entries(%mapv1 -> %arg2, %mapv2 -> %arg3 : !llvm.ptr, !llvm.ptr) {
2566     omp.terminator
2567   }
2568   return
2571 // CHECK-LABEL: func @omp_target_enter_update_exit_data_depend
2572 // CHECK-SAME:([[ARG0:%.*]]: memref<?xi32>, [[ARG1:%.*]]: memref<?xi32>, [[ARG2:%.*]]: memref<?xi32>) {
2573 func.func @omp_target_enter_update_exit_data_depend(%a: memref<?xi32>, %b: memref<?xi32>, %c: memref<?xi32>) {
2574 // CHECK-NEXT: [[MAP0:%.*]] = omp.map.info
2575 // CHECK-NEXT: [[MAP1:%.*]] = omp.map.info
2576 // CHECK-NEXT: [[MAP2:%.*]] = omp.map.info
2577   %map_a = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32>
2578   %map_b = omp.map.info var_ptr(%b: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32>
2579   %map_c = omp.map.info var_ptr(%c: memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32>
2581   // Do some work on the host that writes to 'a'
2582   omp.task depend(taskdependout -> %a : memref<?xi32>) {
2583     "test.foo"(%a) : (memref<?xi32>) -> ()
2584     omp.terminator
2585   }
2587   // Then map that over to the target
2588   // CHECK: omp.target_enter_data depend(taskdependin -> [[ARG0]] : memref<?xi32>) map_entries([[MAP0]], [[MAP2]] : memref<?xi32>, memref<?xi32>) nowait
2589   omp.target_enter_data depend(taskdependin ->  %a: memref<?xi32>) nowait map_entries(%map_a, %map_c: memref<?xi32>, memref<?xi32>)
2591   // Compute 'b' on the target and copy it back
2592   // CHECK: omp.target map_entries([[MAP1]] -> {{%.*}} : memref<?xi32>) {
2593   omp.target map_entries(%map_b -> %arg0 : memref<?xi32>) {
2594     "test.foo"(%arg0) : (memref<?xi32>) -> ()
2595     omp.terminator
2596   }
2598   // Update 'a' on the host using 'b'
2599   omp.task depend(taskdependout -> %a: memref<?xi32>){
2600     "test.bar"(%a, %b) : (memref<?xi32>, memref<?xi32>) -> ()
2601   }
2603   // Copy the updated 'a' onto the target
2604   // CHECK: omp.target_update depend(taskdependin -> [[ARG0]] : memref<?xi32>) map_entries([[MAP0]] : memref<?xi32>) nowait
2605   omp.target_update depend(taskdependin -> %a : memref<?xi32>) nowait map_entries(%map_a :  memref<?xi32>)
2607   // Compute 'c' on the target and copy it back
2608   %map_c_from = omp.map.info var_ptr(%c: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32>
2609   omp.target depend(taskdependout -> %c : memref<?xi32>) map_entries(%map_a -> %arg0, %map_c_from -> %arg1 : memref<?xi32>, memref<?xi32>) {
2610     "test.foobar"() : ()->()
2611     omp.terminator
2612   }
2613   // CHECK: omp.target_exit_data depend(taskdependin -> [[ARG2]] : memref<?xi32>) map_entries([[MAP2]] : memref<?xi32>)
2614   omp.target_exit_data depend(taskdependin -> %c : memref<?xi32>) map_entries(%map_c : memref<?xi32>)
2616   return
2619 // CHECK-LABEL: omp_map_with_members
2620 // CHECK-SAME: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr, %[[ARG2:.*]]: !llvm.ptr, %[[ARG3:.*]]: !llvm.ptr, %[[ARG4:.*]]: !llvm.ptr, %[[ARG5:.*]]: !llvm.ptr)
2621 func.func @omp_map_with_members(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: !llvm.ptr) -> () {
2622   // CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
2623   %mapv1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
2625   // CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, f32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
2626   %mapv2 = omp.map.info var_ptr(%arg1 : !llvm.ptr, f32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
2628   // CHECK: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ARG2]] : !llvm.ptr, !llvm.struct<(i32, f32)>) map_clauses(to) capture(ByRef) members(%[[MAP0]], %[[MAP1]] : [0], [1] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {name = "", partial_map = true}
2629   %mapv3 = omp.map.info var_ptr(%arg2 : !llvm.ptr, !llvm.struct<(i32, f32)>)   map_clauses(to) capture(ByRef) members(%mapv1, %mapv2 : [0], [1] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {name = "", partial_map = true}
2631   // CHECK: omp.target_enter_data map_entries(%[[MAP0]], %[[MAP1]], %[[MAP2]] : !llvm.ptr, !llvm.ptr, !llvm.ptr)
2632   omp.target_enter_data map_entries(%mapv1, %mapv2, %mapv3 : !llvm.ptr, !llvm.ptr, !llvm.ptr){}
2634   // CHECK: %[[MAP3:.*]] = omp.map.info var_ptr(%[[ARG3]] : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
2635   %mapv4 = omp.map.info var_ptr(%arg3 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
2637   // CHECK: %[[MAP4:.*]] = omp.map.info var_ptr(%[[ARG4]] : !llvm.ptr, f32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
2638   %mapv5 = omp.map.info var_ptr(%arg4 : !llvm.ptr, f32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
2640   // CHECK: %[[MAP5:.*]] = omp.map.info var_ptr(%[[ARG5]] : !llvm.ptr, !llvm.struct<(i32, struct<(i32, f32)>)>) map_clauses(from) capture(ByRef) members(%[[MAP3]], %[[MAP4]] : [1, 0], [1, 1] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {name = "", partial_map = true}
2641   %mapv6 = omp.map.info var_ptr(%arg5 : !llvm.ptr, !llvm.struct<(i32, struct<(i32, f32)>)>) map_clauses(from) capture(ByRef) members(%mapv4, %mapv5 : [1, 0], [1, 1] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {name = "", partial_map = true}
2643   // CHECK: omp.target_exit_data map_entries(%[[MAP3]], %[[MAP4]], %[[MAP5]] : !llvm.ptr, !llvm.ptr, !llvm.ptr)
2644   omp.target_exit_data map_entries(%mapv4, %mapv5, %mapv6 : !llvm.ptr, !llvm.ptr, !llvm.ptr){}
2646   return
2649 // CHECK-LABEL: parallel_op_privatizers
2650 // CHECK-SAME: (%[[ARG0:[^[:space:]]+]]: !llvm.ptr, %[[ARG1:[^[:space:]]+]]: !llvm.ptr)
2651 func.func @parallel_op_privatizers(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {
2652   // CHECK: omp.parallel private(
2653   // CHECK-SAME: @x.privatizer %[[ARG0]] -> %[[ARG0_PRIV:[^[:space:]]+]],
2654   // CHECK-SAME: @y.privatizer %[[ARG1]] -> %[[ARG1_PRIV:[^[:space:]]+]] : !llvm.ptr, !llvm.ptr)
2655   omp.parallel private(@x.privatizer %arg0 -> %arg2, @y.privatizer %arg1 -> %arg3 : !llvm.ptr, !llvm.ptr) {
2656     // CHECK: llvm.load %[[ARG0_PRIV]]
2657     %0 = llvm.load %arg2 : !llvm.ptr -> i32
2658     // CHECK: llvm.load %[[ARG1_PRIV]]
2659     %1 = llvm.load %arg3 : !llvm.ptr -> i32
2660     omp.terminator
2661   }
2662   return
2665 // CHECK-LABEL: omp.private {type = private} @a.privatizer : !llvm.ptr alloc {
2666 omp.private {type = private} @a.privatizer : !llvm.ptr alloc {
2667 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2668 ^bb0(%arg0: !llvm.ptr):
2669   omp.yield(%arg0 : !llvm.ptr)
2672 // CHECK-LABEL: omp.private {type = private} @x.privatizer : !llvm.ptr alloc {
2673 omp.private {type = private} @x.privatizer : !llvm.ptr alloc {
2674 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2675 ^bb0(%arg0: !llvm.ptr):
2676   omp.yield(%arg0 : !llvm.ptr)
2677 } dealloc {
2678 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2679 ^bb0(%arg0: !llvm.ptr):
2680   omp.yield
2683 // CHECK-LABEL: omp.private {type = firstprivate} @y.privatizer : !llvm.ptr alloc {
2684 omp.private {type = firstprivate} @y.privatizer : !llvm.ptr alloc {
2685 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2686 ^bb0(%arg0: !llvm.ptr):
2687   omp.yield(%arg0 : !llvm.ptr)
2688 // CHECK: } copy {
2689 } copy {
2690 // CHECK: ^bb0(%{{.*}}: {{.*}}, %{{.*}}: {{.*}}):
2691 ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
2692   omp.yield(%arg0 : !llvm.ptr)
2693 } dealloc {
2694 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2695 ^bb0(%arg0: !llvm.ptr):
2696   omp.yield
2699 // CHECK-LABEL: parallel_op_reduction_and_private
2700 func.func @parallel_op_reduction_and_private(%priv_var: !llvm.ptr, %priv_var2: !llvm.ptr, %reduc_var: !llvm.ptr, %reduc_var2: !llvm.ptr) {
2701   // CHECK: omp.parallel
2702   // CHECK-SAME: private(
2703   // CHECK-SAME: @x.privatizer %[[PRIV_VAR:[^[:space:]]+]] -> %[[PRIV_ARG:[^[:space:]]+]],
2704   // CHECK-SAME: @y.privatizer %[[PRIV_VAR2:[^[:space:]]+]] -> %[[PRIV_ARG2:[^[:space:]]+]] : !llvm.ptr, !llvm.ptr)
2705   //
2706   // CHECK-SAME: reduction(
2707   // CHECK-SAME: @add_f32 %[[REDUC_VAR:[^[:space:]]+]] -> %[[REDUC_ARG:[^[:space:]]+]],
2708   // CHECK-SAME: @add_f32 %[[REDUC_VAR2:[^[:space:]]+]] -> %[[REDUC_ARG2:[^[:space:]]+]] : !llvm.ptr, !llvm.ptr)
2709   omp.parallel private(@x.privatizer %priv_var -> %priv_arg, @y.privatizer %priv_var2 -> %priv_arg2 : !llvm.ptr, !llvm.ptr)
2710                reduction(@add_f32 %reduc_var -> %reduc_arg, @add_f32 %reduc_var2 -> %reduc_arg2 : !llvm.ptr, !llvm.ptr) {
2711     // CHECK: llvm.load %[[PRIV_ARG]]
2712     %0 = llvm.load %priv_arg : !llvm.ptr -> f32
2713     // CHECK: llvm.load %[[PRIV_ARG2]]
2714     %1 = llvm.load %priv_arg2 : !llvm.ptr -> f32
2715     // CHECK: llvm.load %[[REDUC_ARG]]
2716     %2 = llvm.load %reduc_arg : !llvm.ptr -> f32
2717     // CHECK: llvm.load %[[REDUC_ARG2]]
2718     %3 = llvm.load %reduc_arg2 : !llvm.ptr -> f32
2719     omp.terminator
2720   }
2721   return
2724 // CHECK-LABEL: omp_target_private
2725 func.func @omp_target_private(%map1: memref<?xi32>, %map2: memref<?xi32>, %priv_var: !llvm.ptr) -> () {
2726   %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
2727   %mapv2 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
2729   // CHECK: omp.target
2730   // CHECK-SAME: private(
2731   // CHECK-SAME:   @x.privatizer %{{[^[:space:]]+}} -> %[[PRIV_ARG:[^[:space:]]+]]
2732   // CHECK-SAME:   : !llvm.ptr
2733   // CHECK-SAME: )
2734   omp.target private(@x.privatizer %priv_var -> %priv_arg : !llvm.ptr) {
2735     omp.terminator
2736   }
2738   // CHECK: omp.target
2740   // CHECK-SAME: map_entries(
2741   // CHECK-SAME:   %{{[^[:space:]]+}} -> %[[MAP1_ARG:[^[:space:]]+]],
2742   // CHECK-SAME:   %{{[^[:space:]]+}} -> %[[MAP2_ARG:[^[:space:]]+]]
2743   // CHECK-SAME:   : memref<?xi32>, memref<?xi32>
2744   // CHECK-SAME: )
2746   // CHECK-SAME: private(
2747   // CHECK-SAME:   @x.privatizer %{{[^[:space:]]+}} -> %[[PRIV_ARG:[^[:space:]]+]]
2748   // CHECK-SAME:   : !llvm.ptr
2749   // CHECK-SAME: )
2750   omp.target map_entries(%mapv1 -> %arg0, %mapv2 -> %arg1 : memref<?xi32>, memref<?xi32>) private(@x.privatizer %priv_var -> %priv_arg : !llvm.ptr) {
2751     omp.terminator
2752   }
2754   return
2757 // CHECK-LABEL: omp_target_private_with_map_idx
2758 func.func @omp_target_private_with_map_idx(%map1: memref<?xi32>, %map2: memref<?xi32>, %priv_var: !llvm.ptr) -> () {
2759   %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
2760   %mapv2 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
2762   // CHECK: omp.target
2764   // CHECK-SAME: map_entries(
2765   // CHECK-SAME:   %{{[^[:space:]]+}} -> %[[MAP1_ARG:[^[:space:]]+]],
2766   // CHECK-SAME:   %{{[^[:space:]]+}} -> %[[MAP2_ARG:[^[:space:]]+]]
2767   // CHECK-SAME:   : memref<?xi32>, memref<?xi32>
2768   // CHECK-SAME: )
2770   // CHECK-SAME: private(
2771   // CHECK-SAME:   @x.privatizer %{{[^[:space:]]+}} -> %[[PRIV_ARG:[^[:space:]]+]] [map_idx=1]
2772   // CHECK-SAME:   : !llvm.ptr
2773   // CHECK-SAME: )
2774   omp.target map_entries(%mapv1 -> %arg0, %mapv2 -> %arg1 : memref<?xi32>, memref<?xi32>) private(@x.privatizer %priv_var -> %priv_arg [map_idx=1] : !llvm.ptr) {
2775     omp.terminator
2776   }
2778   return
2781 func.func @omp_target_host_eval(%x : i32) {
2782   // CHECK: omp.target host_eval(%{{.*}} -> %[[HOST_ARG:.*]] : i32) {
2783   // CHECK: omp.teams num_teams( to %[[HOST_ARG]] : i32)
2784   // CHECK-SAME: thread_limit(%[[HOST_ARG]] : i32)
2785   omp.target host_eval(%x -> %arg0 : i32) {
2786     omp.teams num_teams(to %arg0 : i32) thread_limit(%arg0 : i32) {
2787       omp.terminator
2788     }
2789     omp.terminator
2790   }
2792   // CHECK: omp.target host_eval(%{{.*}} -> %[[HOST_ARG:.*]] : i32) {
2793   // CHECK: omp.teams {
2794   // CHECK: omp.parallel num_threads(%[[HOST_ARG]] : i32) {
2795   // CHECK: omp.distribute {
2796   // CHECK: omp.wsloop {
2797   // CHECK: omp.loop_nest (%{{.*}}) : i32 = (%[[HOST_ARG]]) to (%[[HOST_ARG]]) step (%[[HOST_ARG]]) {
2798   omp.target host_eval(%x -> %arg0 : i32) {
2799     omp.teams {
2800       omp.parallel num_threads(%arg0 : i32) {
2801         omp.distribute {
2802           omp.wsloop {
2803             omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
2804               omp.yield
2805             }
2806           } {omp.composite}
2807         } {omp.composite}
2808         omp.terminator
2809       } {omp.composite}
2810       omp.terminator
2811     }
2812     omp.terminator
2813   }
2815   // CHECK: omp.target host_eval(%{{.*}} -> %[[HOST_ARG:.*]] : i32) {
2816   // CHECK: omp.teams {
2817   // CHECK: omp.distribute {
2818   // CHECK: omp.loop_nest (%{{.*}}) : i32 = (%[[HOST_ARG]]) to (%[[HOST_ARG]]) step (%[[HOST_ARG]]) {
2819   omp.target host_eval(%x -> %arg0 : i32) {
2820     omp.teams {
2821       omp.distribute {
2822         omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
2823           omp.yield
2824         }
2825       }
2826       omp.terminator
2827     }
2828     omp.terminator
2829   }
2830   return
2833 // CHECK-LABEL: omp_loop
2834 func.func @omp_loop(%lb : index, %ub : index, %step : index) {
2835   // CHECK: omp.loop {
2836   omp.loop {
2837     // CHECK: omp.loop_nest {{.*}} {
2838     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2839       // CHECK: omp.yield
2840       omp.yield
2841     }
2842     // CHECK: }
2843   }
2844   // CHECK: }
2846   // CHECK: omp.loop bind(teams) {
2847   omp.loop bind(teams) {
2848     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2849       omp.yield
2850     }
2851   }
2852   // CHECK: }
2854   // CHECK: omp.loop bind(parallel) {
2855   omp.loop bind(parallel) {
2856     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2857       omp.yield
2858     }
2859   }
2860   // CHECK: }
2862   // CHECK: omp.loop bind(thread) {
2863   omp.loop bind(thread) {
2864     omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2865       omp.yield
2866     }
2867   }
2868   // CHECK: }
2870   return
2873 // CHECK-LABEL: func @omp_workshare
2874 func.func @omp_workshare() {
2875   // CHECK: omp.workshare {
2876   omp.workshare {
2877     "test.payload"() : () -> ()
2878     // CHECK: omp.terminator
2879     omp.terminator
2880   }
2881   return
2884 // CHECK-LABEL: func @omp_workshare_nowait
2885 func.func @omp_workshare_nowait() {
2886   // CHECK: omp.workshare nowait {
2887   omp.workshare nowait {
2888     "test.payload"() : () -> ()
2889     // CHECK: omp.terminator
2890     omp.terminator
2891   }
2892   return
2895 // CHECK-LABEL: func @omp_workshare_multiple_blocks
2896 func.func @omp_workshare_multiple_blocks() {
2897   // CHECK: omp.workshare {
2898   omp.workshare {
2899     cf.br ^bb2
2900     ^bb2:
2901     // CHECK: omp.terminator
2902     omp.terminator
2903   }
2904   return
2907 // CHECK-LABEL: func @omp_workshare_loop_wrapper
2908 func.func @omp_workshare_loop_wrapper(%idx : index) {
2909   // CHECK-NEXT: omp.workshare {
2910   omp.workshare {
2911     // CHECK-NEXT: omp.workshare.loop_wrapper
2912     omp.workshare.loop_wrapper {
2913       // CHECK-NEXT: omp.loop_nest
2914       omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2915         omp.yield
2916       }
2917     }
2918     omp.terminator
2919   }
2920   return
2923 // CHECK-LABEL: func @omp_workshare_loop_wrapper_attrs
2924 func.func @omp_workshare_loop_wrapper_attrs(%idx : index) {
2925   // CHECK-NEXT: omp.workshare {
2926   omp.workshare {
2927     // CHECK-NEXT: omp.workshare.loop_wrapper {
2928     omp.workshare.loop_wrapper {
2929       // CHECK-NEXT: omp.loop_nest
2930       omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2931         omp.yield
2932       }
2933     // CHECK: } {attr_in_dict}
2934     } {attr_in_dict}
2935     omp.terminator
2936   }
2937   return