1// RUN: mlir-opt -split-input-file %s | mlir-opt | FileCheck %s
2
3func.func @omp_barrier() -> () {
4  // CHECK: omp.barrier
5  omp.barrier
6  return
7}
8
9func.func @omp_master() -> () {
10  // CHECK: omp.master
11  omp.master {
12    // CHECK: omp.terminator
13    omp.terminator
14  }
15
16  return
17}
18
19func.func @omp_taskwait() -> () {
20  // CHECK: omp.taskwait
21  omp.taskwait
22  return
23}
24
25func.func @omp_taskyield() -> () {
26  // CHECK: omp.taskyield
27  omp.taskyield
28  return
29}
30
31// CHECK-LABEL: func @omp_flush
32// CHECK-SAME: ([[ARG0:%.*]]: i32) {
33func.func @omp_flush(%arg0 : i32) -> () {
34  // Test without data var
35  // CHECK: omp.flush
36  omp.flush
37
38  // Test with one data var
39  // CHECK: omp.flush([[ARG0]] : i32)
40  omp.flush(%arg0 : i32)
41
42  // Test with two data var
43  // CHECK: omp.flush([[ARG0]], [[ARG0]] : i32, i32)
44  omp.flush(%arg0, %arg0: i32, i32)
45
46  return
47}
48
49func.func @omp_terminator() -> () {
50  // CHECK: omp.terminator
51  omp.terminator
52}
53
54func.func @omp_parallel(%data_var : memref<i32>, %if_cond : i1, %num_threads : i32) -> () {
55  // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
56  "omp.parallel" (%if_cond, %num_threads, %data_var, %data_var) ({
57
58  // test without if condition
59  // CHECK: omp.parallel num_threads(%{{.*}} : i32) allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
60    "omp.parallel"(%num_threads, %data_var, %data_var) ({
61      omp.terminator
62    }) {operand_segment_sizes = dense<[0,1,1,1,0]> : vector<5xi32>} : (i32, memref<i32>, memref<i32>) -> ()
63
64  // CHECK: omp.barrier
65    omp.barrier
66
67  // test without num_threads
68  // CHECK: omp.parallel if(%{{.*}}) allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
69    "omp.parallel"(%if_cond, %data_var, %data_var) ({
70      omp.terminator
71    }) {operand_segment_sizes = dense<[1,0,1,1,0]> : vector<5xi32>} : (i1, memref<i32>, memref<i32>) -> ()
72
73  // test without allocate
74  // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32)
75    "omp.parallel"(%if_cond, %num_threads) ({
76      omp.terminator
77    }) {operand_segment_sizes = dense<[1,1,0,0,0]> : vector<5xi32>} : (i1, i32) -> ()
78
79    omp.terminator
80  }) {operand_segment_sizes = dense<[1,1,1,1,0]> : vector<5xi32>, proc_bind_val = #omp<"procbindkind spread">} : (i1, i32, memref<i32>, memref<i32>) -> ()
81
82  // test with multiple parameters for single variadic argument
83  // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
84  "omp.parallel" (%data_var, %data_var) ({
85    omp.terminator
86  }) {operand_segment_sizes = dense<[0,0,1,1,0]> : vector<5xi32>} : (memref<i32>, memref<i32>) -> ()
87
88  return
89}
90
91func.func @omp_parallel_pretty(%data_var : memref<i32>, %if_cond : i1, %num_threads : i32, %allocator : si32) -> () {
92 // CHECK: omp.parallel
93 omp.parallel {
94  omp.terminator
95 }
96
97 // CHECK: omp.parallel num_threads(%{{.*}} : i32)
98 omp.parallel num_threads(%num_threads : i32) {
99   omp.terminator
100 }
101
102 %n_index = arith.constant 2 : index
103 // CHECK: omp.parallel num_threads(%{{.*}} : index)
104 omp.parallel num_threads(%n_index : index) {
105   omp.terminator
106 }
107
108 %n_i64 = arith.constant 4 : i64
109 // CHECK: omp.parallel num_threads(%{{.*}} : i64)
110 omp.parallel num_threads(%n_i64 : i64) {
111   omp.terminator
112 }
113
114 // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
115 omp.parallel allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
116   omp.terminator
117 }
118
119 // CHECK: omp.parallel
120 // CHECK-NEXT: omp.parallel if(%{{.*}} : i1)
121 omp.parallel {
122   omp.parallel if(%if_cond: i1) {
123     omp.terminator
124   }
125   omp.terminator
126 }
127
128 // CHECK omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) private(%{{.*}} : memref<i32>) proc_bind(close)
129 omp.parallel num_threads(%num_threads : i32) if(%if_cond: i1) proc_bind(close) {
130   omp.terminator
131 }
132
133  return
134}
135
136// CHECK-LABEL: omp_wsloop
137func.func @omp_wsloop(%lb : index, %ub : index, %step : index, %data_var : memref<i32>, %linear_var : i32, %chunk_var : i32) -> () {
138
139  // CHECK: omp.wsloop collapse(2) ordered(1)
140  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
141  "omp.wsloop" (%lb, %ub, %step) ({
142    ^bb0(%iv: index):
143      omp.yield
144  }) {operand_segment_sizes = dense<[1,1,1,0,0,0,0]> : vector<7xi32>, collapse_val = 2, ordered_val = 1} :
145    (index, index, index) -> ()
146
147  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static)
148  // CHECK-SAMe: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
149  "omp.wsloop" (%lb, %ub, %step, %data_var, %linear_var) ({
150    ^bb0(%iv: index):
151      omp.yield
152  }) {operand_segment_sizes = dense<[1,1,1,1,1,0,0]> : vector<7xi32>, schedule_val = #omp<"schedulekind static">} :
153    (index, index, index, memref<i32>, i32) -> ()
154
155  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>, %{{.*}} = %{{.*}} : memref<i32>) schedule(static)
156  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
157  "omp.wsloop" (%lb, %ub, %step, %data_var, %data_var, %linear_var, %linear_var) ({
158    ^bb0(%iv: index):
159      omp.yield
160  }) {operand_segment_sizes = dense<[1,1,1,2,2,0,0]> : vector<7xi32>, schedule_val = #omp<"schedulekind static">} :
161    (index, index, index, memref<i32>, memref<i32>, i32, i32) -> ()
162
163  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(dynamic = %{{.*}}) collapse(3) ordered(2)
164  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
165  "omp.wsloop" (%lb, %ub, %step, %data_var, %linear_var, %chunk_var) ({
166    ^bb0(%iv: index):
167      omp.yield
168  }) {operand_segment_sizes = dense<[1,1,1,1,1,0,1]> : vector<7xi32>, schedule_val = #omp<"schedulekind dynamic">, collapse_val = 3, ordered_val = 2} :
169    (index, index, index, memref<i32>, i32, i32) -> ()
170
171  // CHECK: omp.wsloop schedule(auto) nowait
172  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
173  "omp.wsloop" (%lb, %ub, %step) ({
174    ^bb0(%iv: index):
175      omp.yield
176  }) {operand_segment_sizes = dense<[1,1,1,0,0,0,0]> : vector<7xi32>, nowait, schedule_val = #omp<"schedulekind auto">} :
177    (index, index, index) -> ()
178
179  return
180}
181
182// CHECK-LABEL: omp_wsloop_pretty
183func.func @omp_wsloop_pretty(%lb : index, %ub : index, %step : index, %data_var : memref<i32>, %linear_var : i32, %chunk_var : i32, %chunk_var2 : i16) -> () {
184
185  // CHECK: omp.wsloop collapse(2) ordered(2)
186  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
187  omp.wsloop collapse(2) ordered(2)
188  for (%iv) : index = (%lb) to (%ub) step (%step) {
189    omp.yield
190  }
191
192  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static)
193  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
194  omp.wsloop schedule(static) linear(%data_var = %linear_var : memref<i32>)
195  for (%iv) : index = (%lb) to (%ub) step (%step) {
196    omp.yield
197  }
198
199  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static = %{{.*}} : i32) collapse(3) ordered(2)
200  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
201  omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(static = %chunk_var : i32) collapse(3)
202  for (%iv) : index = (%lb) to (%ub) step (%step) {
203    omp.yield
204  }
205
206  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(dynamic = %{{.*}} : i32, nonmonotonic) collapse(3) ordered(2)
207  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
208  omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var : i32, nonmonotonic) collapse(3)
209  for (%iv) : index = (%lb) to (%ub) step (%step)  {
210    omp.yield
211  }
212
213  // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(dynamic = %{{.*}} : i16, monotonic) collapse(3) ordered(2)
214  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
215  omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var2 : i16, monotonic) collapse(3)
216  for (%iv) : index = (%lb) to (%ub) step (%step) {
217    omp.yield
218  }
219
220  // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
221  omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) {
222    omp.yield
223  }
224
225  // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}})
226  omp.wsloop for (%iv) : index = (%lb) to (%ub) inclusive step (%step) {
227    omp.yield
228  }
229
230  // CHECK: omp.wsloop nowait
231  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
232  omp.wsloop nowait
233  for (%iv) : index = (%lb) to (%ub) step (%step) {
234    omp.yield
235  }
236
237  // CHECK: omp.wsloop nowait order(concurrent)
238  // CHECK-SAME: for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
239  omp.wsloop order(concurrent) nowait
240  for (%iv) : index = (%lb) to (%ub) step (%step) {
241    omp.yield
242  }
243
244  return
245}
246
247// CHECK-LABEL: omp_wsloop_pretty_multi_block
248func.func @omp_wsloop_pretty_multi_block(%lb : index, %ub : index, %step : index, %data1 : memref<?xi32>, %data2 : memref<?xi32>) -> () {
249
250  // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
251  omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) {
252    %1 = "test.payload"(%iv) : (index) -> (i32)
253    cf.br ^bb1(%1: i32)
254  ^bb1(%arg: i32):
255    memref.store %arg, %data1[%iv] : memref<?xi32>
256    omp.yield
257  }
258
259  // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
260  omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) {
261    %c = "test.condition"(%iv) : (index) -> (i1)
262    %v1 = "test.payload"(%iv) : (index) -> (i32)
263    cf.cond_br %c, ^bb1(%v1: i32), ^bb2(%v1: i32)
264  ^bb1(%arg0: i32):
265    memref.store %arg0, %data1[%iv] : memref<?xi32>
266    cf.br ^bb3
267  ^bb2(%arg1: i32):
268    memref.store %arg1, %data2[%iv] : memref<?xi32>
269    cf.br ^bb3
270  ^bb3:
271    omp.yield
272  }
273
274  // CHECK: omp.wsloop for (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
275  omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) {
276    %c = "test.condition"(%iv) : (index) -> (i1)
277    %v1 = "test.payload"(%iv) : (index) -> (i32)
278    cf.cond_br %c, ^bb1(%v1: i32), ^bb2(%v1: i32)
279  ^bb1(%arg0: i32):
280    memref.store %arg0, %data1[%iv] : memref<?xi32>
281    omp.yield
282  ^bb2(%arg1: i32):
283    memref.store %arg1, %data2[%iv] : memref<?xi32>
284    omp.yield
285  }
286
287  return
288}
289
290// CHECK-LABEL: omp_wsloop_pretty_non_index
291func.func @omp_wsloop_pretty_non_index(%lb1 : i32, %ub1 : i32, %step1 : i32, %lb2 : i64, %ub2 : i64, %step2 : i64,
292                           %data1 : memref<?xi32>, %data2 : memref<?xi64>) -> () {
293
294  // CHECK: omp.wsloop for (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
295  omp.wsloop for (%iv1) : i32 = (%lb1) to (%ub1) step (%step1) {
296    %1 = "test.payload"(%iv1) : (i32) -> (index)
297    cf.br ^bb1(%1: index)
298  ^bb1(%arg1: index):
299    memref.store %iv1, %data1[%arg1] : memref<?xi32>
300    omp.yield
301  }
302
303  // CHECK: omp.wsloop for (%{{.*}}) : i64 = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
304  omp.wsloop for (%iv2) : i64 = (%lb2) to (%ub2) step (%step2) {
305    %2 = "test.payload"(%iv2) : (i64) -> (index)
306    cf.br ^bb1(%2: index)
307  ^bb1(%arg2: index):
308    memref.store %iv2, %data2[%arg2] : memref<?xi64>
309    omp.yield
310  }
311
312  return
313}
314
315// CHECK-LABEL: omp_wsloop_pretty_multiple
316func.func @omp_wsloop_pretty_multiple(%lb1 : i32, %ub1 : i32, %step1 : i32, %lb2 : i32, %ub2 : i32, %step2 : i32, %data1 : memref<?xi32>) -> () {
317
318  // CHECK: omp.wsloop for (%{{.*}}, %{{.*}}) : i32 = (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}})
319  omp.wsloop for (%iv1, %iv2) : i32 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
320    %1 = "test.payload"(%iv1) : (i32) -> (index)
321    %2 = "test.payload"(%iv2) : (i32) -> (index)
322    memref.store %iv1, %data1[%1] : memref<?xi32>
323    memref.store %iv2, %data1[%2] : memref<?xi32>
324    omp.yield
325  }
326
327  return
328}
329
330// CHECK-LABEL: omp_simdloop
331func.func @omp_simdloop(%lb : index, %ub : index, %step : index) -> () {
332  // CHECK: omp.simdloop (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
333  "omp.simdloop" (%lb, %ub, %step) ({
334    ^bb0(%iv: index):
335      omp.yield
336  }) {operand_segment_sizes = dense<[1,1,1]> : vector<3xi32>} :
337    (index, index, index) -> ()
338
339  return
340}
341
342
343// CHECK-LABEL: omp_simdloop_pretty
344func.func @omp_simdloop_pretty(%lb : index, %ub : index, %step : index) -> () {
345  // CHECK: omp.simdloop (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
346  omp.simdloop (%iv) : index = (%lb) to (%ub) step (%step) {
347    omp.yield
348  }
349  return
350}
351
352// CHECK-LABEL: omp_simdloop_pretty_multiple
353func.func @omp_simdloop_pretty_multiple(%lb1 : index, %ub1 : index, %step1 : index, %lb2 : index, %ub2 : index, %step2 : index) -> () {
354  // CHECK: omp.simdloop (%{{.*}}, %{{.*}}) : index = (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}})
355  omp.simdloop (%iv1, %iv2) : index = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
356    omp.yield
357  }
358  return
359}
360
361// CHECK-LABEL: omp_target
362func.func @omp_target(%if_cond : i1, %device : si32,  %num_threads : i32) -> () {
363
364    // Test with optional operands; if_expr, device, thread_limit, private, firstprivate and nowait.
365    // CHECK: omp.target if({{.*}}) device({{.*}}) thread_limit({{.*}}) nowait
366    "omp.target"(%if_cond, %device, %num_threads) ({
367       // CHECK: omp.terminator
368       omp.terminator
369    }) {nowait, operand_segment_sizes = dense<[1,1,1]>: vector<3xi32>} : ( i1, si32, i32 ) -> ()
370
371    // CHECK: omp.barrier
372    omp.barrier
373
374    return
375}
376
377// CHECK-LABEL: omp_target_pretty
378func.func @omp_target_pretty(%if_cond : i1, %device : si32,  %num_threads : i32) -> () {
379    // CHECK: omp.target if({{.*}}) device({{.*}})
380    omp.target if(%if_cond) device(%device : si32) {
381      omp.terminator
382    }
383
384    // CHECK: omp.target if({{.*}}) device({{.*}}) nowait
385    omp.target if(%if_cond) device(%device : si32) thread_limit(%num_threads : i32) nowait {
386      omp.terminator
387    }
388
389    return
390}
391
392// CHECK: omp.reduction.declare
393// CHECK-LABEL: @add_f32
394// CHECK: : f32
395// CHECK: init
396// CHECK: ^{{.+}}(%{{.+}}: f32):
397// CHECK:   omp.yield
398// CHECK: combiner
399// CHECK: ^{{.+}}(%{{.+}}: f32, %{{.+}}: f32):
400// CHECK:   omp.yield
401// CHECK: atomic
402// CHECK: ^{{.+}}(%{{.+}}: !llvm.ptr<f32>, %{{.+}}: !llvm.ptr<f32>):
403// CHECK:  omp.yield
404omp.reduction.declare @add_f32 : f32
405init {
406^bb0(%arg: f32):
407  %0 = arith.constant 0.0 : f32
408  omp.yield (%0 : f32)
409}
410combiner {
411^bb1(%arg0: f32, %arg1: f32):
412  %1 = arith.addf %arg0, %arg1 : f32
413  omp.yield (%1 : f32)
414}
415atomic {
416^bb2(%arg2: !llvm.ptr<f32>, %arg3: !llvm.ptr<f32>):
417  %2 = llvm.load %arg3 : !llvm.ptr<f32>
418  llvm.atomicrmw fadd %arg2, %2 monotonic : f32
419  omp.yield
420}
421
422// CHECK-LABEL: func @wsloop_reduction
423func.func @wsloop_reduction(%lb : index, %ub : index, %step : index) {
424  %c1 = arith.constant 1 : i32
425  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
426  // CHECK: reduction(@add_f32 -> %{{.+}} : !llvm.ptr<f32>)
427  omp.wsloop reduction(@add_f32 -> %0 : !llvm.ptr<f32>)
428  for (%iv) : index = (%lb) to (%ub) step (%step) {
429    %1 = arith.constant 2.0 : f32
430    // CHECK: omp.reduction %{{.+}}, %{{.+}}
431    omp.reduction %1, %0 : !llvm.ptr<f32>
432    omp.yield
433  }
434  return
435}
436
437// CHECK-LABEL: func @parallel_reduction
438func.func @parallel_reduction() {
439  %c1 = arith.constant 1 : i32
440  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
441  // CHECK: omp.parallel reduction(@add_f32 -> {{.+}} : !llvm.ptr<f32>)
442  omp.parallel reduction(@add_f32 -> %0 : !llvm.ptr<f32>) {
443    %1 = arith.constant 2.0 : f32
444    // CHECK: omp.reduction %{{.+}}, %{{.+}}
445    omp.reduction %1, %0 : !llvm.ptr<f32>
446    omp.terminator
447  }
448  return
449}
450
451// CHECK: func @parallel_wsloop_reduction
452func.func @parallel_wsloop_reduction(%lb : index, %ub : index, %step : index) {
453  %c1 = arith.constant 1 : i32
454  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
455  // CHECK: omp.parallel reduction(@add_f32 -> %{{.+}} : !llvm.ptr<f32>) {
456  omp.parallel reduction(@add_f32 -> %0 : !llvm.ptr<f32>) {
457    // CHECK: omp.wsloop for (%{{.+}}) : index = (%{{.+}}) to (%{{.+}}) step (%{{.+}})
458    omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) {
459      %1 = arith.constant 2.0 : f32
460      // CHECK: omp.reduction %{{.+}}, %{{.+}} : !llvm.ptr<f32>
461      omp.reduction %1, %0 : !llvm.ptr<f32>
462      // CHECK: omp.yield
463      omp.yield
464    }
465    // CHECK: omp.terminator
466    omp.terminator
467  }
468  return
469}
470
471// CHECK-LABEL: func @sections_reduction
472func.func @sections_reduction() {
473  %c1 = arith.constant 1 : i32
474  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
475  // CHECK: omp.sections reduction(@add_f32 -> {{.+}} : !llvm.ptr<f32>)
476  omp.sections reduction(@add_f32 -> %0 : !llvm.ptr<f32>) {
477    // CHECK: omp.section
478    omp.section {
479      %1 = arith.constant 2.0 : f32
480      // CHECK: omp.reduction %{{.+}}, %{{.+}}
481      omp.reduction %1, %0 : !llvm.ptr<f32>
482      omp.terminator
483    }
484    // CHECK: omp.section
485    omp.section {
486      %1 = arith.constant 3.0 : f32
487      // CHECK: omp.reduction %{{.+}}, %{{.+}}
488      omp.reduction %1, %0 : !llvm.ptr<f32>
489      omp.terminator
490    }
491    omp.terminator
492  }
493  return
494}
495
496// CHECK: omp.reduction.declare
497// CHECK-LABEL: @add2_f32
498omp.reduction.declare @add2_f32 : f32
499// CHECK: init
500init {
501^bb0(%arg: f32):
502  %0 = arith.constant 0.0 : f32
503  omp.yield (%0 : f32)
504}
505// CHECK: combiner
506combiner {
507^bb1(%arg0: f32, %arg1: f32):
508  %1 = arith.addf %arg0, %arg1 : f32
509  omp.yield (%1 : f32)
510}
511// CHECK-NOT: atomic
512
513// CHECK-LABEL: func @wsloop_reduction2
514func.func @wsloop_reduction2(%lb : index, %ub : index, %step : index) {
515  %0 = memref.alloca() : memref<1xf32>
516  // CHECK: omp.wsloop reduction(@add2_f32 -> %{{.+}} : memref<1xf32>)
517  omp.wsloop reduction(@add2_f32 -> %0 : memref<1xf32>)
518  for (%iv) : index = (%lb) to (%ub) step (%step) {
519    %1 = arith.constant 2.0 : f32
520    // CHECK: omp.reduction
521    omp.reduction %1, %0 : memref<1xf32>
522    omp.yield
523  }
524  return
525}
526
527// CHECK-LABEL: func @parallel_reduction2
528func.func @parallel_reduction2() {
529  %0 = memref.alloca() : memref<1xf32>
530  // CHECK: omp.parallel reduction(@add2_f32 -> %{{.+}} : memref<1xf32>)
531  omp.parallel reduction(@add2_f32 -> %0 : memref<1xf32>) {
532    %1 = arith.constant 2.0 : f32
533    // CHECK: omp.reduction
534    omp.reduction %1, %0 : memref<1xf32>
535    omp.terminator
536  }
537  return
538}
539
540// CHECK: func @parallel_wsloop_reduction2
541func.func @parallel_wsloop_reduction2(%lb : index, %ub : index, %step : index) {
542  %c1 = arith.constant 1 : i32
543  %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr<f32>
544  // CHECK: omp.parallel reduction(@add2_f32 -> %{{.+}} : !llvm.ptr<f32>) {
545  omp.parallel reduction(@add2_f32 -> %0 : !llvm.ptr<f32>) {
546    // CHECK: omp.wsloop for (%{{.+}}) : index = (%{{.+}}) to (%{{.+}}) step (%{{.+}})
547    omp.wsloop for (%iv) : index = (%lb) to (%ub) step (%step) {
548      %1 = arith.constant 2.0 : f32
549      // CHECK: omp.reduction %{{.+}}, %{{.+}} : !llvm.ptr<f32>
550      omp.reduction %1, %0 : !llvm.ptr<f32>
551      // CHECK: omp.yield
552      omp.yield
553    }
554    // CHECK: omp.terminator
555    omp.terminator
556  }
557  return
558}
559
560// CHECK-LABEL: func @sections_reduction2
561func.func @sections_reduction2() {
562  %0 = memref.alloca() : memref<1xf32>
563  // CHECK: omp.sections reduction(@add2_f32 -> %{{.+}} : memref<1xf32>)
564  omp.sections reduction(@add2_f32 -> %0 : memref<1xf32>) {
565    omp.section {
566      %1 = arith.constant 2.0 : f32
567      // CHECK: omp.reduction
568      omp.reduction %1, %0 : memref<1xf32>
569      omp.terminator
570    }
571    omp.section {
572      %1 = arith.constant 2.0 : f32
573      // CHECK: omp.reduction
574      omp.reduction %1, %0 : memref<1xf32>
575      omp.terminator
576    }
577    omp.terminator
578  }
579  return
580}
581
582// CHECK: omp.critical.declare @mutex1 hint(uncontended)
583omp.critical.declare @mutex1 hint(uncontended)
584// CHECK: omp.critical.declare @mutex2 hint(contended)
585omp.critical.declare @mutex2 hint(contended)
586// CHECK: omp.critical.declare @mutex3 hint(nonspeculative)
587omp.critical.declare @mutex3 hint(nonspeculative)
588// CHECK: omp.critical.declare @mutex4 hint(speculative)
589omp.critical.declare @mutex4 hint(speculative)
590// CHECK: omp.critical.declare @mutex5 hint(uncontended, nonspeculative)
591omp.critical.declare @mutex5 hint(uncontended, nonspeculative)
592// CHECK: omp.critical.declare @mutex6 hint(contended, nonspeculative)
593omp.critical.declare @mutex6 hint(contended, nonspeculative)
594// CHECK: omp.critical.declare @mutex7 hint(uncontended, speculative)
595omp.critical.declare @mutex7 hint(uncontended, speculative)
596// CHECK: omp.critical.declare @mutex8 hint(contended, speculative)
597omp.critical.declare @mutex8 hint(contended, speculative)
598// CHECK: omp.critical.declare @mutex9 hint(none)
599omp.critical.declare @mutex9 hint(none)
600// CHECK: omp.critical.declare @mutex10
601omp.critical.declare @mutex10
602
603
604// CHECK-LABEL: omp_critical
605func.func @omp_critical() -> () {
606  // CHECK: omp.critical
607  omp.critical {
608    omp.terminator
609  }
610
611  // CHECK: omp.critical(@{{.*}})
612  omp.critical(@mutex1) {
613    omp.terminator
614  }
615  return
616}
617
618func.func @omp_ordered(%arg1 : i32, %arg2 : i32, %arg3 : i32,
619    %vec0 : i64, %vec1 : i64, %vec2 : i64, %vec3 : i64) -> () {
620  // CHECK: omp.ordered_region
621  omp.ordered_region {
622    // CHECK: omp.terminator
623    omp.terminator
624  }
625
626  omp.wsloop ordered(0)
627  for (%0) : i32 = (%arg1) to (%arg2) step (%arg3)  {
628    omp.ordered_region {
629      omp.terminator
630    }
631    omp.yield
632  }
633
634  omp.wsloop ordered(1)
635  for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
636    // Only one DEPEND(SINK: vec) clause
637    // CHECK: omp.ordered depend_type(dependsink) depend_vec(%{{.*}} : i64) {num_loops_val = 1 : i64}
638    omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {num_loops_val = 1 : i64}
639
640    // CHECK: omp.ordered depend_type(dependsource) depend_vec(%{{.*}} : i64) {num_loops_val = 1 : i64}
641    omp.ordered depend_type(dependsource) depend_vec(%vec0 : i64) {num_loops_val = 1 : i64}
642
643    omp.yield
644  }
645
646  omp.wsloop ordered(2)
647  for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
648    // Multiple DEPEND(SINK: vec) clauses
649    // CHECK: omp.ordered depend_type(dependsink) depend_vec(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : i64, i64, i64, i64) {num_loops_val = 2 : i64}
650    omp.ordered depend_type(dependsink) depend_vec(%vec0, %vec1, %vec2, %vec3 : i64, i64, i64, i64) {num_loops_val = 2 : i64}
651
652    // CHECK: omp.ordered depend_type(dependsource) depend_vec(%{{.*}}, %{{.*}} : i64, i64) {num_loops_val = 2 : i64}
653    omp.ordered depend_type(dependsource) depend_vec(%vec0, %vec1 : i64, i64) {num_loops_val = 2 : i64}
654
655    omp.yield
656  }
657
658  return
659}
660
661// CHECK-LABEL: omp_atomic_read
662// CHECK-SAME: (%[[v:.*]]: memref<i32>, %[[x:.*]]: memref<i32>)
663func.func @omp_atomic_read(%v: memref<i32>, %x: memref<i32>) {
664  // CHECK: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
665  omp.atomic.read %v = %x : memref<i32>
666  // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) : memref<i32>
667  omp.atomic.read %v = %x memory_order(seq_cst) : memref<i32>
668  // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(acquire) : memref<i32>
669  omp.atomic.read %v = %x memory_order(acquire) : memref<i32>
670  // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(relaxed) : memref<i32>
671  omp.atomic.read %v = %x memory_order(relaxed) : memref<i32>
672  // CHECK: omp.atomic.read %[[v]] = %[[x]] hint(contended, nonspeculative) : memref<i32>
673  omp.atomic.read %v = %x hint(nonspeculative, contended) : memref<i32>
674  // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) hint(contended, speculative) : memref<i32>
675  omp.atomic.read %v = %x hint(speculative, contended) memory_order(seq_cst) : memref<i32>
676  // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) hint(none) : memref<i32>
677  omp.atomic.read %v = %x hint(none) memory_order(seq_cst) : memref<i32>
678  return
679}
680
681// CHECK-LABEL: omp_atomic_write
682// CHECK-SAME: (%[[ADDR:.*]]: memref<i32>, %[[VAL:.*]]: i32)
683func.func @omp_atomic_write(%addr : memref<i32>, %val : i32) {
684  // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] : memref<i32>, i32
685  omp.atomic.write %addr = %val : memref<i32>, i32
686  // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(seq_cst) : memref<i32>, i32
687  omp.atomic.write %addr = %val memory_order(seq_cst) : memref<i32>, i32
688  // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(release) : memref<i32>, i32
689  omp.atomic.write %addr = %val memory_order(release) : memref<i32>, i32
690  // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(relaxed) : memref<i32>, i32
691  omp.atomic.write %addr = %val memory_order(relaxed) : memref<i32>, i32
692  // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(uncontended, speculative) : memref<i32>, i32
693  omp.atomic.write %addr = %val hint(speculative, uncontended) : memref<i32>, i32
694  // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(none) : memref<i32>, i32
695  omp.atomic.write %addr = %val hint(none) : memref<i32>, i32
696  return
697}
698
699// CHECK-LABEL: omp_atomic_update
700// CHECK-SAME: (%[[X:.*]]: memref<i32>, %[[EXPR:.*]]: i32, %[[XBOOL:.*]]: memref<i1>, %[[EXPRBOOL:.*]]: i1)
701func.func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>, %exprBool : i1) {
702  // CHECK: omp.atomic.update %[[X]] : memref<i32>
703  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
704  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
705  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
706  omp.atomic.update %x : memref<i32> {
707  ^bb0(%xval: i32):
708    %newval = llvm.add %xval, %expr : i32
709    omp.yield(%newval : i32)
710  }
711  // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
712  // CHECK-NEXT: (%[[XVAL:.*]]: i1):
713  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.and %[[XVAL]], %[[EXPRBOOL]] : i1
714  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i1)
715  omp.atomic.update %xBool : memref<i1> {
716  ^bb0(%xval: i1):
717    %newval = llvm.and %xval, %exprBool : i1
718    omp.yield(%newval : i1)
719  }
720  // CHECK: omp.atomic.update %[[X]] : memref<i32>
721  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
722  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.shl %[[XVAL]], %[[EXPR]] : i32
723  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
724  // CHECK-NEXT: }
725  omp.atomic.update %x : memref<i32> {
726  ^bb0(%xval: i32):
727    %newval = llvm.shl %xval, %expr : i32
728    omp.yield(%newval : i32)
729  }
730  // CHECK: omp.atomic.update %[[X]] : memref<i32>
731  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
732  // CHECK-NEXT:   %[[NEWVAL:.*]] = "llvm.intr.smax"(%[[XVAL]], %[[EXPR]]) : (i32, i32) -> i32
733  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
734  // CHECK-NEXT: }
735  omp.atomic.update %x : memref<i32> {
736  ^bb0(%xval: i32):
737    %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i32
738    omp.yield(%newval : i32)
739  }
740
741  // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
742  // CHECK-NEXT: (%[[XVAL:.*]]: i1):
743  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.icmp "eq" %[[XVAL]], %[[EXPRBOOL]] : i1
744  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i1)
745  // }
746  omp.atomic.update %xBool : memref<i1> {
747  ^bb0(%xval: i1):
748    %newval = llvm.icmp "eq" %xval, %exprBool : i1
749    omp.yield(%newval : i1)
750  }
751
752  // CHECK: omp.atomic.update hint(none) %[[X]] : memref<i32>
753  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
754  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
755  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
756  omp.atomic.update hint(none) %x : memref<i32> {
757  ^bb0(%xval: i32):
758    %newval = llvm.add %xval, %expr : i32
759    omp.yield(%newval : i32)
760  }
761
762  // CHECK: omp.atomic.update hint(uncontended) %[[X]] : memref<i32>
763  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
764  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
765  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
766  omp.atomic.update hint(uncontended) %x : memref<i32> {
767  ^bb0(%xval: i32):
768    %newval = llvm.add %xval, %expr : i32
769    omp.yield(%newval : i32)
770  }
771
772  // CHECK: omp.atomic.update hint(contended) %[[X]] : memref<i32>
773  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
774  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
775  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
776  omp.atomic.update hint(contended) %x : memref<i32> {
777  ^bb0(%xval: i32):
778    %newval = llvm.add %xval, %expr : i32
779    omp.yield(%newval : i32)
780  }
781
782  // CHECK: omp.atomic.update hint(nonspeculative) %[[X]] : memref<i32>
783  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
784  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
785  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
786  omp.atomic.update hint(nonspeculative) %x : memref<i32> {
787  ^bb0(%xval: i32):
788    %newval = llvm.add %xval, %expr : i32
789    omp.yield(%newval : i32)
790  }
791
792  // CHECK: omp.atomic.update hint(speculative) %[[X]] : memref<i32>
793  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
794  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
795  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
796  omp.atomic.update hint(speculative) %x : memref<i32> {
797  ^bb0(%xval: i32):
798    %newval = llvm.add %xval, %expr : i32
799    omp.yield(%newval : i32)
800  }
801
802  // CHECK: omp.atomic.update hint(uncontended, nonspeculative) %[[X]] : memref<i32>
803  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
804  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
805  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
806  omp.atomic.update hint(uncontended, nonspeculative) %x : memref<i32> {
807  ^bb0(%xval: i32):
808    %newval = llvm.add %xval, %expr : i32
809    omp.yield(%newval : i32)
810  }
811
812  // CHECK: omp.atomic.update hint(contended, nonspeculative) %[[X]] : memref<i32>
813  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
814  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
815  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
816  omp.atomic.update hint(contended, nonspeculative) %x : memref<i32> {
817  ^bb0(%xval: i32):
818    %newval = llvm.add %xval, %expr : i32
819    omp.yield(%newval : i32)
820  }
821
822  // CHECK: omp.atomic.update hint(uncontended, speculative) %[[X]] : memref<i32>
823  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
824  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
825  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
826  omp.atomic.update hint(uncontended, speculative) %x : memref<i32> {
827  ^bb0(%xval: i32):
828    %newval = llvm.add %xval, %expr : i32
829    omp.yield(%newval : i32)
830  }
831
832  // CHECK: omp.atomic.update hint(contended, speculative) %[[X]] : memref<i32>
833  // CHECK-NEXT: (%[[XVAL:.*]]: i32):
834  // CHECK-NEXT:   %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
835  // CHECK-NEXT:   omp.yield(%[[NEWVAL]] : i32)
836  omp.atomic.update hint(contended, speculative) %x : memref<i32> {
837  ^bb0(%xval: i32):
838    %newval = llvm.add %xval, %expr : i32
839    omp.yield(%newval : i32)
840  }
841
842  return
843}
844
845// CHECK-LABEL: omp_atomic_capture
846// CHECK-SAME: (%[[v:.*]]: memref<i32>, %[[x:.*]]: memref<i32>, %[[expr:.*]]: i32)
847func.func @omp_atomic_capture(%v: memref<i32>, %x: memref<i32>, %expr: i32) {
848  // CHECK: omp.atomic.capture {
849  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
850  // CHECK-NEXT: (%[[xval:.*]]: i32):
851  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
852  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
853  // CHECK-NEXT: }
854  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
855  // CHECK-NEXT: }
856  omp.atomic.capture{
857    omp.atomic.update %x : memref<i32> {
858    ^bb0(%xval: i32):
859      %newval = llvm.add %xval, %expr : i32
860      omp.yield(%newval : i32)
861    }
862    omp.atomic.read %v = %x : memref<i32>
863  }
864  // CHECK: omp.atomic.capture {
865  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
866  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
867  // CHECK-NEXT: (%[[xval:.*]]: i32):
868  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
869  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
870  // CHECK-NEXT: }
871  // CHECK-NEXT: }
872  omp.atomic.capture{
873    omp.atomic.read %v = %x : memref<i32>
874    omp.atomic.update %x : memref<i32> {
875    ^bb0(%xval: i32):
876      %newval = llvm.add %xval, %expr : i32
877      omp.yield(%newval : i32)
878    }
879  }
880  // CHECK: omp.atomic.capture {
881  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
882  // CHECK-NEXT: omp.atomic.write %[[x]] = %[[expr]] : memref<i32>, i32
883  // CHECK-NEXT: }
884  omp.atomic.capture{
885    omp.atomic.read %v = %x : memref<i32>
886    omp.atomic.write %x = %expr : memref<i32>, i32
887  }
888
889  // CHECK: omp.atomic.capture hint(none) {
890  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
891  // CHECK-NEXT: (%[[xval:.*]]: i32):
892  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
893  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
894  // CHECK-NEXT: }
895  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
896  // CHECK-NEXT: }
897  omp.atomic.capture hint(none) {
898    omp.atomic.update %x : memref<i32> {
899    ^bb0(%xval: i32):
900      %newval = llvm.add %xval, %expr : i32
901      omp.yield(%newval : i32)
902    }
903    omp.atomic.read %v = %x : memref<i32>
904  }
905
906  // CHECK: omp.atomic.capture hint(uncontended) {
907  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
908  // CHECK-NEXT: (%[[xval:.*]]: i32):
909  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
910  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
911  // CHECK-NEXT: }
912  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
913  // CHECK-NEXT: }
914  omp.atomic.capture hint(uncontended) {
915    omp.atomic.update %x : memref<i32> {
916    ^bb0(%xval: i32):
917      %newval = llvm.add %xval, %expr : i32
918      omp.yield(%newval : i32)
919    }
920    omp.atomic.read %v = %x : memref<i32>
921  }
922
923  // CHECK: omp.atomic.capture hint(contended) {
924  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
925  // CHECK-NEXT: (%[[xval:.*]]: i32):
926  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
927  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
928  // CHECK-NEXT: }
929  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
930  // CHECK-NEXT: }
931  omp.atomic.capture hint(contended) {
932    omp.atomic.update %x : memref<i32> {
933    ^bb0(%xval: i32):
934      %newval = llvm.add %xval, %expr : i32
935      omp.yield(%newval : i32)
936    }
937    omp.atomic.read %v = %x : memref<i32>
938  }
939
940  // CHECK: omp.atomic.capture hint(nonspeculative) {
941  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
942  // CHECK-NEXT: (%[[xval:.*]]: i32):
943  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
944  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
945  // CHECK-NEXT: }
946  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
947  // CHECK-NEXT: }
948  omp.atomic.capture hint(nonspeculative) {
949    omp.atomic.update %x : memref<i32> {
950    ^bb0(%xval: i32):
951      %newval = llvm.add %xval, %expr : i32
952      omp.yield(%newval : i32)
953    }
954    omp.atomic.read %v = %x : memref<i32>
955  }
956
957  // CHECK: omp.atomic.capture hint(speculative) {
958  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
959  // CHECK-NEXT: (%[[xval:.*]]: i32):
960  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
961  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
962  // CHECK-NEXT: }
963  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
964  // CHECK-NEXT: }
965  omp.atomic.capture hint(speculative) {
966    omp.atomic.update %x : memref<i32> {
967    ^bb0(%xval: i32):
968      %newval = llvm.add %xval, %expr : i32
969      omp.yield(%newval : i32)
970    }
971    omp.atomic.read %v = %x : memref<i32>
972  }
973
974  // CHECK: omp.atomic.capture hint(uncontended, nonspeculative) {
975  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
976  // CHECK-NEXT: (%[[xval:.*]]: i32):
977  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
978  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
979  // CHECK-NEXT: }
980  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
981  // CHECK-NEXT: }
982  omp.atomic.capture hint(uncontended, nonspeculative) {
983    omp.atomic.update %x : memref<i32> {
984    ^bb0(%xval: i32):
985      %newval = llvm.add %xval, %expr : i32
986      omp.yield(%newval : i32)
987    }
988    omp.atomic.read %v = %x : memref<i32>
989  }
990
991  // CHECK: omp.atomic.capture hint(contended, nonspeculative) {
992  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
993  // CHECK-NEXT: (%[[xval:.*]]: i32):
994  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
995  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
996  // CHECK-NEXT: }
997  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
998  // CHECK-NEXT: }
999  omp.atomic.capture hint(contended, nonspeculative) {
1000    omp.atomic.update %x : memref<i32> {
1001    ^bb0(%xval: i32):
1002      %newval = llvm.add %xval, %expr : i32
1003      omp.yield(%newval : i32)
1004    }
1005    omp.atomic.read %v = %x : memref<i32>
1006  }
1007
1008  // CHECK: omp.atomic.capture hint(uncontended, speculative) {
1009  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1010  // CHECK-NEXT: (%[[xval:.*]]: i32):
1011  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1012  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1013  // CHECK-NEXT: }
1014  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
1015  // CHECK-NEXT: }
1016  omp.atomic.capture hint(uncontended, speculative) {
1017    omp.atomic.update %x : memref<i32> {
1018    ^bb0(%xval: i32):
1019      %newval = llvm.add %xval, %expr : i32
1020      omp.yield(%newval : i32)
1021    }
1022    omp.atomic.read %v = %x : memref<i32>
1023  }
1024
1025  // CHECK: omp.atomic.capture hint(contended, speculative) {
1026  // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1027  // CHECK-NEXT: (%[[xval:.*]]: i32):
1028  // CHECK-NEXT:   %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1029  // CHECK-NEXT:   omp.yield(%[[newval]] : i32)
1030  // CHECK-NEXT: }
1031  // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>
1032  // CHECK-NEXT: }
1033  omp.atomic.capture hint(contended, speculative) {
1034    omp.atomic.update %x : memref<i32> {
1035    ^bb0(%xval: i32):
1036      %newval = llvm.add %xval, %expr : i32
1037      omp.yield(%newval : i32)
1038    }
1039    omp.atomic.read %v = %x : memref<i32>
1040  }
1041  return
1042}
1043
1044// CHECK-LABEL: omp_sectionsop
1045func.func @omp_sectionsop(%data_var1 : memref<i32>, %data_var2 : memref<i32>,
1046                     %data_var3 : memref<i32>, %redn_var : !llvm.ptr<f32>) {
1047  // CHECK: omp.sections allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
1048  "omp.sections" (%data_var1, %data_var1) ({
1049    // CHECK: omp.terminator
1050    omp.terminator
1051  }) {operand_segment_sizes = dense<[0,1,1]> : vector<3xi32>} : (memref<i32>, memref<i32>) -> ()
1052
1053    // CHECK: omp.sections reduction(@add_f32 -> %{{.*}} : !llvm.ptr<f32>)
1054  "omp.sections" (%redn_var) ({
1055    // CHECK: omp.terminator
1056    omp.terminator
1057  }) {operand_segment_sizes = dense<[1,0,0]> : vector<3xi32>, reductions=[@add_f32]} : (!llvm.ptr<f32>) -> ()
1058
1059  // CHECK: omp.sections nowait {
1060  omp.sections nowait {
1061    // CHECK: omp.terminator
1062    omp.terminator
1063  }
1064
1065  // CHECK: omp.sections reduction(@add_f32 -> %{{.*}} : !llvm.ptr<f32>) {
1066  omp.sections reduction(@add_f32 -> %redn_var : !llvm.ptr<f32>) {
1067    // CHECK: omp.terminator
1068    omp.terminator
1069  }
1070
1071  // CHECK: omp.sections allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
1072  omp.sections allocate(%data_var1 : memref<i32> -> %data_var1 : memref<i32>) {
1073    // CHECK: omp.terminator
1074    omp.terminator
1075  }
1076
1077  // CHECK: omp.sections nowait
1078  omp.sections nowait {
1079    // CHECK: omp.section
1080    omp.section {
1081      // CHECK: %{{.*}} = "test.payload"() : () -> i32
1082      %1 = "test.payload"() : () -> i32
1083      // CHECK: %{{.*}} = "test.payload"() : () -> i32
1084      %2 = "test.payload"() : () -> i32
1085      // CHECK: %{{.*}} = "test.payload"(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
1086      %3 = "test.payload"(%1, %2) : (i32, i32) -> i32
1087    }
1088    // CHECK: omp.section
1089    omp.section {
1090      // CHECK: %{{.*}} = "test.payload"(%{{.*}}) : (!llvm.ptr<f32>) -> i32
1091      %1 = "test.payload"(%redn_var) : (!llvm.ptr<f32>) -> i32
1092    }
1093    // CHECK: omp.section
1094    omp.section {
1095      // CHECK: "test.payload"(%{{.*}}) : (!llvm.ptr<f32>) -> ()
1096      "test.payload"(%redn_var) : (!llvm.ptr<f32>) -> ()
1097    }
1098    // CHECK: omp.terminator
1099    omp.terminator
1100  }
1101  return
1102}
1103
1104// CHECK-LABEL: func @omp_single
1105func.func @omp_single() {
1106  omp.parallel {
1107    // CHECK: omp.single {
1108    omp.single {
1109      "test.payload"() : () -> ()
1110      // CHECK: omp.terminator
1111      omp.terminator
1112    }
1113    // CHECK: omp.terminator
1114    omp.terminator
1115  }
1116  return
1117}
1118
1119// CHECK-LABEL: func @omp_single_nowait
1120func.func @omp_single_nowait() {
1121  omp.parallel {
1122    // CHECK: omp.single nowait {
1123    omp.single nowait {
1124      "test.payload"() : () -> ()
1125      // CHECK: omp.terminator
1126      omp.terminator
1127    }
1128    // CHECK: omp.terminator
1129    omp.terminator
1130  }
1131  return
1132}
1133
1134// CHECK-LABEL: func @omp_single_allocate
1135func.func @omp_single_allocate(%data_var: memref<i32>) {
1136  omp.parallel {
1137    // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) {
1138    omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
1139      "test.payload"() : () -> ()
1140      // CHECK: omp.terminator
1141      omp.terminator
1142    }
1143    // CHECK: omp.terminator
1144    omp.terminator
1145  }
1146  return
1147}
1148
1149// CHECK-LABEL: func @omp_single_allocate_nowait
1150func.func @omp_single_allocate_nowait(%data_var: memref<i32>) {
1151  omp.parallel {
1152    // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) nowait {
1153    omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) nowait {
1154      "test.payload"() : () -> ()
1155      // CHECK: omp.terminator
1156      omp.terminator
1157    }
1158    // CHECK: omp.terminator
1159    omp.terminator
1160  }
1161  return
1162}
1163
1164// CHECK-LABEL: @omp_task
1165// CHECK-SAME: (%[[bool_var:.*]]: i1, %[[i64_var:.*]]: i64, %[[i32_var:.*]]: i32, %[[data_var:.*]]: memref<i32>)
1166func.func @omp_task(%bool_var: i1, %i64_var: i64, %i32_var: i32, %data_var: memref<i32>) {
1167
1168  // Checking simple task
1169  // CHECK: omp.task {
1170  omp.task {
1171    // CHECK: "test.foo"() : () -> ()
1172    "test.foo"() : () -> ()
1173    // CHECK: omp.terminator
1174    omp.terminator
1175  }
1176
1177  // Checking `if` clause
1178  // CHECK: omp.task if(%[[bool_var]]) {
1179  omp.task if(%bool_var) {
1180    // CHECK: "test.foo"() : () -> ()
1181    "test.foo"() : () -> ()
1182    // CHECK: omp.terminator
1183    omp.terminator
1184  }
1185
1186  // Checking `final` clause
1187  // CHECK: omp.task final(%[[bool_var]]) {
1188  omp.task final(%bool_var) {
1189    // CHECK: "test.foo"() : () -> ()
1190    "test.foo"() : () -> ()
1191    // CHECK: omp.terminator
1192    omp.terminator
1193  }
1194
1195  // Checking `untied` clause
1196  // CHECK: omp.task untied {
1197  omp.task untied {
1198    // CHECK: "test.foo"() : () -> ()
1199    "test.foo"() : () -> ()
1200    // CHECK: omp.terminator
1201    omp.terminator
1202  }
1203
1204  // Checking `in_reduction` clause
1205  %c1 = arith.constant 1 : i32
1206  // CHECK: %[[redn_var1:.*]] = llvm.alloca %{{.*}} x f32 : (i32) -> !llvm.ptr<f32>
1207  %0 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr<f32>
1208  // CHECK: %[[redn_var2:.*]] = llvm.alloca %{{.*}} x f32 : (i32) -> !llvm.ptr<f32>
1209  %1 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr<f32>
1210  // CHECK: omp.task in_reduction(@add_f32 -> %[[redn_var1]] : !llvm.ptr<f32>, @add_f32 -> %[[redn_var2]] : !llvm.ptr<f32>) {
1211  omp.task in_reduction(@add_f32 -> %0 : !llvm.ptr<f32>, @add_f32 -> %1 : !llvm.ptr<f32>) {
1212    // CHECK: "test.foo"() : () -> ()
1213    "test.foo"() : () -> ()
1214    // CHECK: omp.terminator
1215    omp.terminator
1216  }
1217
1218  // Checking priority clause
1219  // CHECK: omp.task priority(%[[i32_var]]) {
1220  omp.task priority(%i32_var) {
1221    // CHECK: "test.foo"() : () -> ()
1222    "test.foo"() : () -> ()
1223    // CHECK: omp.terminator
1224    omp.terminator
1225  }
1226
1227  // Checking allocate clause
1228  // CHECK: omp.task allocate(%[[data_var]] : memref<i32> -> %[[data_var]] : memref<i32>) {
1229  omp.task allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
1230    // CHECK: "test.foo"() : () -> ()
1231    "test.foo"() : () -> ()
1232    // CHECK: omp.terminator
1233    omp.terminator
1234  }
1235
1236  // Checking multiple clauses
1237  // CHECK: omp.task if(%[[bool_var]]) final(%[[bool_var]]) untied
1238  omp.task if(%bool_var) final(%bool_var) untied
1239      // CHECK-SAME: in_reduction(@add_f32 -> %[[redn_var1]] : !llvm.ptr<f32>, @add_f32 -> %[[redn_var2]] : !llvm.ptr<f32>)
1240      in_reduction(@add_f32 -> %0 : !llvm.ptr<f32>, @add_f32 -> %1 : !llvm.ptr<f32>)
1241      // CHECK-SAME: priority(%[[i32_var]])
1242      priority(%i32_var)
1243      // CHECK-SAME: allocate(%[[data_var]] : memref<i32> -> %[[data_var]] : memref<i32>)
1244      allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
1245    // CHECK: "test.foo"() : () -> ()
1246    "test.foo"() : () -> ()
1247    // CHECK: omp.terminator
1248    omp.terminator
1249  }
1250
1251  return
1252}
1253
1254// -----
1255
1256func.func @omp_threadprivate() {
1257  %0 = arith.constant 1 : i32
1258  %1 = arith.constant 2 : i32
1259  %2 = arith.constant 3 : i32
1260
1261  // CHECK: [[ARG0:%.*]] = llvm.mlir.addressof @_QFsubEx : !llvm.ptr<i32>
1262  // CHECK: {{.*}} = omp.threadprivate [[ARG0]] : !llvm.ptr<i32> -> !llvm.ptr<i32>
1263  %3 = llvm.mlir.addressof @_QFsubEx : !llvm.ptr<i32>
1264  %4 = omp.threadprivate %3 : !llvm.ptr<i32> -> !llvm.ptr<i32>
1265  llvm.store %0, %4 : !llvm.ptr<i32>
1266
1267  // CHECK:  omp.parallel
1268  // CHECK:    {{.*}} = omp.threadprivate [[ARG0]] : !llvm.ptr<i32> -> !llvm.ptr<i32>
1269  omp.parallel  {
1270    %5 = omp.threadprivate %3 : !llvm.ptr<i32> -> !llvm.ptr<i32>
1271    llvm.store %1, %5 : !llvm.ptr<i32>
1272    omp.terminator
1273  }
1274  llvm.store %2, %4 : !llvm.ptr<i32>
1275  return
1276}
1277
1278llvm.mlir.global internal @_QFsubEx() : i32
1279
1280func.func @omp_cancel_parallel(%if_cond : i1) -> () {
1281  // Test with optional operand; if_expr.
1282  omp.parallel {
1283    // CHECK: omp.cancel cancellation_construct_type(parallel) if(%{{.*}})
1284    omp.cancel cancellation_construct_type(parallel) if(%if_cond)
1285    // CHECK: omp.terminator
1286    omp.terminator
1287  }
1288  return
1289}
1290
1291func.func @omp_cancel_wsloop(%lb : index, %ub : index, %step : index) {
1292  omp.wsloop
1293  for (%iv) : index = (%lb) to (%ub) step (%step) {
1294    // CHECK: omp.cancel cancellation_construct_type(loop)
1295    omp.cancel cancellation_construct_type(loop)
1296    // CHECK: omp.terminator
1297    omp.terminator
1298  }
1299  return
1300}
1301
1302func.func @omp_cancel_sections() -> () {
1303  omp.sections {
1304    omp.section {
1305      // CHECK: omp.cancel cancellation_construct_type(sections)
1306      omp.cancel cancellation_construct_type(sections)
1307      omp.terminator
1308    }
1309    // CHECK: omp.terminator
1310    omp.terminator
1311  }
1312  return
1313}
1314
1315func.func @omp_cancellationpoint_parallel() -> () {
1316  omp.parallel {
1317    // CHECK: omp.cancellationpoint cancellation_construct_type(parallel)
1318    omp.cancellationpoint cancellation_construct_type(parallel)
1319    // CHECK: omp.cancel cancellation_construct_type(parallel)
1320    omp.cancel cancellation_construct_type(parallel)
1321    omp.terminator
1322  }
1323  return
1324}
1325
1326func.func @omp_cancellationpoint_wsloop(%lb : index, %ub : index, %step : index) {
1327  omp.wsloop
1328  for (%iv) : index = (%lb) to (%ub) step (%step) {
1329    // CHECK: omp.cancellationpoint cancellation_construct_type(loop)
1330    omp.cancellationpoint cancellation_construct_type(loop)
1331    // CHECK: omp.cancel cancellation_construct_type(loop)
1332    omp.cancel cancellation_construct_type(loop)
1333    // CHECK: omp.terminator
1334    omp.terminator
1335  }
1336  return
1337}
1338
1339func.func @omp_cancellationpoint_sections() -> () {
1340  omp.sections {
1341    omp.section {
1342      // CHECK: omp.cancellationpoint cancellation_construct_type(sections)
1343      omp.cancellationpoint cancellation_construct_type(sections)
1344      // CHECK: omp.cancel cancellation_construct_type(sections)
1345      omp.cancel cancellation_construct_type(sections)
1346      omp.terminator
1347    }
1348    // CHECK: omp.terminator
1349    omp.terminator
1350  }
1351  return
1352}
1353