[TTI] getTypeBasedIntrinsicInstrCost - add basic handling for strided load/store...
[llvm-project.git] / mlir / test / Target / LLVMIR / openmp-llvm.mlir
blob8a95793b96fd5319613e3c9055930a4f0d3f79ad
1 // RUN: mlir-translate -mlir-to-llvmir -split-input-file %s | FileCheck %s
3 // CHECK-LABEL: define void @test_stand_alone_directives()
4 llvm.func @test_stand_alone_directives() {
5   // CHECK: [[OMP_THREAD:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})
6   // CHECK-NEXT:  call void @__kmpc_barrier(ptr @{{[0-9]+}}, i32 [[OMP_THREAD]])
7   omp.barrier
9   // CHECK: [[OMP_THREAD1:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})
10   // CHECK-NEXT:  [[RET_VAL:%.*]] = call i32 @__kmpc_omp_taskwait(ptr @{{[0-9]+}}, i32 [[OMP_THREAD1]])
11   omp.taskwait
13   // CHECK: [[OMP_THREAD2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})
14   // CHECK-NEXT:  [[RET_VAL:%.*]] = call i32 @__kmpc_omp_taskyield(ptr @{{[0-9]+}}, i32 [[OMP_THREAD2]], i32 0)
15   omp.taskyield
17   // CHECK-NEXT:    ret void
18   llvm.return
21 // CHECK-LABEL: define void @test_flush_construct(ptr %{{[0-9]+}})
22 llvm.func @test_flush_construct(%arg0: !llvm.ptr) {
23   // CHECK: call void @__kmpc_flush(ptr @{{[0-9]+}}
24   omp.flush
26   // CHECK: call void @__kmpc_flush(ptr @{{[0-9]+}}
27   omp.flush (%arg0 : !llvm.ptr)
29   // CHECK: call void @__kmpc_flush(ptr @{{[0-9]+}}
30   omp.flush (%arg0, %arg0 : !llvm.ptr, !llvm.ptr)
32   %0 = llvm.mlir.constant(1 : i64) : i64
33   //  CHECK: alloca {{.*}} align 4
34   %1 = llvm.alloca %0 x i32 {in_type = i32, name = "a"} : (i64) -> !llvm.ptr
35   // CHECK: call void @__kmpc_flush(ptr @{{[0-9]+}}
36   omp.flush
37   //  CHECK: load i32, ptr
38   %2 = llvm.load %1 : !llvm.ptr -> i32
40   // CHECK-NEXT:    ret void
41   llvm.return
44 // CHECK-LABEL: define void @test_omp_parallel_1()
45 llvm.func @test_omp_parallel_1() -> () {
46   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_1:.*]])
47   omp.parallel {
48     omp.barrier
49     omp.terminator
50   }
52   llvm.return
55 // CHECK: define internal void @[[OMP_OUTLINED_FN_1]]
56   // CHECK: call void @__kmpc_barrier
58 llvm.func @body(i64)
60 // CHECK-LABEL: define void @test_omp_parallel_2()
61 llvm.func @test_omp_parallel_2() -> () {
62   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_2:.*]])
63   omp.parallel {
64     ^bb0:
65       %0 = llvm.mlir.constant(1 : index) : i64
66       %1 = llvm.mlir.constant(42 : index) : i64
67       llvm.call @body(%0) : (i64) -> ()
68       llvm.call @body(%1) : (i64) -> ()
69       llvm.br ^bb1
71     ^bb1:
72       %2 = llvm.add %0, %1 : i64
73       llvm.call @body(%2) : (i64) -> ()
74       omp.terminator
75   }
76   llvm.return
79 // CHECK: define internal void @[[OMP_OUTLINED_FN_2]]
80   // CHECK-LABEL: omp.par.region:
81   // CHECK: br label %omp.par.region1
82   // CHECK-LABEL: omp.par.region1:
83   // CHECK: call void @body(i64 1)
84   // CHECK: call void @body(i64 42)
85   // CHECK: br label %omp.par.region2
86   // CHECK-LABEL: omp.par.region2:
87   // CHECK: call void @body(i64 43)
88   // CHECK: br label %omp.par.pre_finalize
90 // CHECK: define void @test_omp_parallel_num_threads_1(i32 %[[NUM_THREADS_VAR_1:.*]])
91 llvm.func @test_omp_parallel_num_threads_1(%arg0: i32) -> () {
92   // CHECK: %[[GTN_NUM_THREADS_VAR_1:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GTN_SI_VAR_1:.*]])
93   // CHECK: call void @__kmpc_push_num_threads(ptr @[[GTN_SI_VAR_1]], i32 %[[GTN_NUM_THREADS_VAR_1]], i32 %[[NUM_THREADS_VAR_1]])
94   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_NUM_THREADS_1:.*]])
95   omp.parallel num_threads(%arg0: i32) {
96     omp.barrier
97     omp.terminator
98   }
100   llvm.return
103 // CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_1]]
104   // CHECK: call void @__kmpc_barrier
106 // CHECK: define void @test_omp_parallel_num_threads_2()
107 llvm.func @test_omp_parallel_num_threads_2() -> () {
108   %0 = llvm.mlir.constant(4 : index) : i32
109   // CHECK: %[[GTN_NUM_THREADS_VAR_2:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GTN_SI_VAR_2:.*]])
110   // CHECK: call void @__kmpc_push_num_threads(ptr @[[GTN_SI_VAR_2]], i32 %[[GTN_NUM_THREADS_VAR_2]], i32 4)
111   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_NUM_THREADS_2:.*]])
112   omp.parallel num_threads(%0: i32) {
113     omp.barrier
114     omp.terminator
115   }
117   llvm.return
120 // CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_2]]
121   // CHECK: call void @__kmpc_barrier
123 // CHECK: define void @test_omp_parallel_num_threads_3()
124 llvm.func @test_omp_parallel_num_threads_3() -> () {
125   %0 = llvm.mlir.constant(4 : index) : i32
126   // CHECK: %[[GTN_NUM_THREADS_VAR_3_1:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GTN_SI_VAR_3_1:.*]])
127   // CHECK: call void @__kmpc_push_num_threads(ptr @[[GTN_SI_VAR_3_1]], i32 %[[GTN_NUM_THREADS_VAR_3_1]], i32 4)
128   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_NUM_THREADS_3_1:.*]])
129   omp.parallel num_threads(%0: i32) {
130     omp.barrier
131     omp.terminator
132   }
133   %1 = llvm.mlir.constant(8 : index) : i32
134   // CHECK: %[[GTN_NUM_THREADS_VAR_3_2:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GTN_SI_VAR_3_2:.*]])
135   // CHECK: call void @__kmpc_push_num_threads(ptr @[[GTN_SI_VAR_3_2]], i32 %[[GTN_NUM_THREADS_VAR_3_2]], i32 8)
136   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_NUM_THREADS_3_2:.*]])
137   omp.parallel num_threads(%1: i32) {
138     omp.barrier
139     omp.terminator
140   }
142   llvm.return
145 // CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_3_2]]
146   // CHECK: call void @__kmpc_barrier
148 // CHECK: define internal void @[[OMP_OUTLINED_FN_NUM_THREADS_3_1]]
149   // CHECK: call void @__kmpc_barrier
151 // CHECK: define void @test_omp_parallel_if_1(i32 %[[IF_EXPR_1:.*]])
152 llvm.func @test_omp_parallel_if_1(%arg0: i32) -> () {
154   %0 = llvm.mlir.constant(0 : index) : i32
155   %1 = llvm.icmp "slt" %arg0, %0 : i32
156 // CHECK: %[[IF_COND_VAR_1:.*]] = icmp slt i32 %[[IF_EXPR_1]], 0
159 // CHECK: %[[GTN_IF_1:.*]] = call i32 @__kmpc_global_thread_num(ptr @[[SI_VAR_IF_1:.*]])
160 // CHECK: br label %[[OUTLINED_CALL_IF_BLOCK_1:.*]]
161 // CHECK: [[OUTLINED_CALL_IF_BLOCK_1]]:
162 // CHECK: %[[I32_IF_COND_VAR_1:.*]] = sext i1 %[[IF_COND_VAR_1]] to i32
163 // CHECK: call void @__kmpc_fork_call_if(ptr @[[SI_VAR_IF_1]], i32 0, ptr @[[OMP_OUTLINED_FN_IF_1:.*]], i32 %[[I32_IF_COND_VAR_1]], ptr null)
164 // CHECK: br label %[[OUTLINED_EXIT_IF_1:.*]]
165 // CHECK: [[OUTLINED_EXIT_IF_1]]:
166 // CHECK: br label %[[RETURN_BLOCK_IF_1:.*]]
167   omp.parallel if(%1) {
168     omp.barrier
169     omp.terminator
170   }
172 // CHECK: [[RETURN_BLOCK_IF_1]]:
173 // CHECK: ret void
174   llvm.return
177 // CHECK: define internal void @[[OMP_OUTLINED_FN_IF_1]]
178   // CHECK: call void @__kmpc_barrier
180 // -----
182 // CHECK-LABEL: define void @test_omp_parallel_attrs()
183 llvm.func @test_omp_parallel_attrs() -> () attributes {
184   target_cpu = "x86-64",
185   target_features = #llvm.target_features<["+mmx", "+sse"]>
186 } {
187   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN:.*]])
188   omp.parallel {
189     omp.barrier
190     omp.terminator
191   }
193   llvm.return
196 // CHECK: define {{.*}} @[[OMP_OUTLINED_FN]]{{.*}} #[[ATTRS:[0-9]+]]
197 // CHECK: attributes #[[ATTRS]] = {
198 // CHECK-SAME: "target-cpu"="x86-64"
199 // CHECK-SAME: "target-features"="+mmx,+sse"
201 // -----
203 // CHECK-LABEL: define void @test_omp_parallel_3()
204 llvm.func @test_omp_parallel_3() -> () {
205   // CHECK: [[OMP_THREAD_3_1:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})
206   // CHECK: call void @__kmpc_push_proc_bind(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_1]], i32 2)
207   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_3_1:.*]])
208   omp.parallel proc_bind(master) {
209     omp.barrier
210     omp.terminator
211   }
212   // CHECK: [[OMP_THREAD_3_2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})
213   // CHECK: call void @__kmpc_push_proc_bind(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_2]], i32 3)
214   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_3_2:.*]])
215   omp.parallel proc_bind(close) {
216     omp.barrier
217     omp.terminator
218   }
219   // CHECK: [[OMP_THREAD_3_3:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})
220   // CHECK: call void @__kmpc_push_proc_bind(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_3]], i32 4)
221   // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_3_3:.*]])
222   omp.parallel proc_bind(spread) {
223     omp.barrier
224     omp.terminator
225   }
227   llvm.return
230 // CHECK: define internal void @[[OMP_OUTLINED_FN_3_3]]
231 // CHECK: define internal void @[[OMP_OUTLINED_FN_3_2]]
232 // CHECK: define internal void @[[OMP_OUTLINED_FN_3_1]]
234 // CHECK-LABEL: define void @test_omp_parallel_4()
235 llvm.func @test_omp_parallel_4() -> () {
236 // CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_4_1:.*]])
237 // CHECK: define internal void @[[OMP_OUTLINED_FN_4_1]]
238 // CHECK: call void @__kmpc_barrier
239 // CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_4_1_1:.*]])
240 // CHECK: call void @__kmpc_barrier
241   omp.parallel {
242     omp.barrier
244 // CHECK: define internal void @[[OMP_OUTLINED_FN_4_1_1]]
245 // CHECK: call void @__kmpc_barrier
246     omp.parallel {
247       omp.barrier
248       omp.terminator
249     }
251     omp.barrier
252     omp.terminator
253   }
254   llvm.return
257 llvm.func @test_omp_parallel_5() -> () {
258 // CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_5_1:.*]])
259 // CHECK: define internal void @[[OMP_OUTLINED_FN_5_1]]
260 // CHECK: call void @__kmpc_barrier
261 // CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_5_1_1:.*]])
262 // CHECK: call void @__kmpc_barrier
263   omp.parallel {
264     omp.barrier
266 // CHECK: define internal void @[[OMP_OUTLINED_FN_5_1_1]]
267     omp.parallel {
268 // CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @[[OMP_OUTLINED_FN_5_1_1_1:.*]])
269 // CHECK: define internal void @[[OMP_OUTLINED_FN_5_1_1_1]]
270 // CHECK: call void @__kmpc_barrier
271       omp.parallel {
272         omp.barrier
273         omp.terminator
274       }
275       omp.terminator
276     }
278     omp.barrier
279     omp.terminator
280   }
281   llvm.return
284 // CHECK-LABEL: define void @test_omp_master()
285 llvm.func @test_omp_master() -> () {
286 // CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @{{.*}})
287 // CHECK: omp.par.region1:
288   omp.parallel {
289     omp.master {
290 // CHECK: [[OMP_THREAD_3_4:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})
291 // CHECK: {{[0-9]+}} = call i32 @__kmpc_master(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]])
292 // CHECK: omp.master.region
293 // CHECK: call void @__kmpc_end_master(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]])
294 // CHECK: br label %omp_region.end
295       omp.terminator
296     }
297     omp.terminator
298   }
299   omp.parallel {
300     omp.parallel {
301       omp.master {
302         omp.terminator
303       }
304       omp.terminator
305     }
306     omp.terminator
307   }
308   llvm.return
311 // -----
313 // CHECK-LABEL: define void @test_omp_masked({{.*}})
314 llvm.func @test_omp_masked(%arg0: i32)-> () {
315 // CHECK: call void {{.*}}@__kmpc_fork_call{{.*}} @{{.*}})
316 // CHECK: omp.par.region1:
317   omp.parallel {
318     omp.masked filter(%arg0: i32) {
319 // CHECK: [[OMP_THREAD_3_4:%.*]] = call i32 @__kmpc_global_thread_num(ptr @{{[0-9]+}})
320 // CHECK: {{[0-9]+}} = call i32 @__kmpc_masked(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]], i32 %{{[0-9]+}})
321 // CHECK: omp.masked.region
322 // CHECK: call void @__kmpc_end_masked(ptr @{{[0-9]+}}, i32 [[OMP_THREAD_3_4]])
323 // CHECK: br label %omp_region.end
324       omp.terminator
325     }
326     omp.terminator
327   }
328   llvm.return
331 // -----
333 // CHECK: %struct.ident_t = type
334 // CHECK: @[[$loc:.*]] = private unnamed_addr constant {{.*}} c";unknown;unknown;{{[0-9]+}};{{[0-9]+}};;\00"
335 // CHECK: @[[$loc_struct:.*]] = private unnamed_addr constant %struct.ident_t {{.*}} @[[$loc]] {{.*}}
337 // CHECK-LABEL: @wsloop_simple
338 llvm.func @wsloop_simple(%arg0: !llvm.ptr) {
339   %0 = llvm.mlir.constant(42 : index) : i64
340   %1 = llvm.mlir.constant(10 : index) : i64
341   %2 = llvm.mlir.constant(1 : index) : i64
342   omp.parallel {
343     "omp.wsloop"() ({
344       omp.loop_nest (%arg1) : i64 = (%1) to (%0) step (%2) {
345         // The form of the emitted IR is controlled by OpenMPIRBuilder and
346         // tested there. Just check that the right functions are called.
347         // CHECK: call i32 @__kmpc_global_thread_num
348         // CHECK: call void @__kmpc_for_static_init_{{.*}}(ptr @[[$loc_struct]],
349         %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
350         %4 = llvm.getelementptr %arg0[%arg1] : (!llvm.ptr, i64) -> !llvm.ptr, f32
351         llvm.store %3, %4 : f32, !llvm.ptr
352         omp.yield
353       }
354       // CHECK: call void @__kmpc_for_static_fini(ptr @[[$loc_struct]],
355     }) : () -> ()
356     omp.terminator
357   }
358   llvm.return
361 // -----
363 // CHECK-LABEL: @wsloop_inclusive_1
364 llvm.func @wsloop_inclusive_1(%arg0: !llvm.ptr) {
365   %0 = llvm.mlir.constant(42 : index) : i64
366   %1 = llvm.mlir.constant(10 : index) : i64
367   %2 = llvm.mlir.constant(1 : index) : i64
368   // CHECK: store i64 31, ptr %{{.*}}upperbound
369   "omp.wsloop"() ({
370     omp.loop_nest (%arg1) : i64 = (%1) to (%0) step (%2) {
371       %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
372       %4 = llvm.getelementptr %arg0[%arg1] : (!llvm.ptr, i64) -> !llvm.ptr, f32
373       llvm.store %3, %4 : f32, !llvm.ptr
374       omp.yield
375     }
376   }) : () -> ()
377   llvm.return
380 // -----
382 // CHECK-LABEL: @wsloop_inclusive_2
383 llvm.func @wsloop_inclusive_2(%arg0: !llvm.ptr) {
384   %0 = llvm.mlir.constant(42 : index) : i64
385   %1 = llvm.mlir.constant(10 : index) : i64
386   %2 = llvm.mlir.constant(1 : index) : i64
387   // CHECK: store i64 32, ptr %{{.*}}upperbound
388   "omp.wsloop"() ({
389     omp.loop_nest (%arg1) : i64 = (%1) to (%0) inclusive step (%2) {
390       %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
391       %4 = llvm.getelementptr %arg0[%arg1] : (!llvm.ptr, i64) -> !llvm.ptr, f32
392       llvm.store %3, %4 : f32, !llvm.ptr
393       omp.yield
394     }
395   }) : () -> ()
396   llvm.return
399 // -----
401 llvm.func @body(i32)
403 // CHECK-LABEL: @test_omp_wsloop_static_defchunk
404 llvm.func @test_omp_wsloop_static_defchunk(%lb : i32, %ub : i32, %step : i32) -> () {
405   omp.wsloop schedule(static) {
406     omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
407       // CHECK: call void @__kmpc_for_static_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 34, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i32 1, i32 0)
408       // CHECK: call void @__kmpc_for_static_fini
409       llvm.call @body(%iv) : (i32) -> ()
410       omp.yield
411     }
412   }
413   llvm.return
416 // -----
418 llvm.func @body(i32)
420 // CHECK-LABEL: @test_omp_wsloop_static_1
421 llvm.func @test_omp_wsloop_static_1(%lb : i32, %ub : i32, %step : i32) -> () {
422   %static_chunk_size = llvm.mlir.constant(1 : i32) : i32
423   omp.wsloop schedule(static = %static_chunk_size : i32) {
424     omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
425       // CHECK: call void @__kmpc_for_static_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 33, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i32 1, i32 1)
426       // CHECK: call void @__kmpc_for_static_fini
427       llvm.call @body(%iv) : (i32) -> ()
428       omp.yield
429     }
430   }
431   llvm.return
434 // -----
436 llvm.func @body(i32)
438 // CHECK-LABEL: @test_omp_wsloop_static_2
439 llvm.func @test_omp_wsloop_static_2(%lb : i32, %ub : i32, %step : i32) -> () {
440   %static_chunk_size = llvm.mlir.constant(2 : i32) : i32
441   omp.wsloop schedule(static = %static_chunk_size : i32) {
442     omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
443       // CHECK: call void @__kmpc_for_static_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 33, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, i32 1, i32 2)
444       // CHECK: call void @__kmpc_for_static_fini
445       llvm.call @body(%iv) : (i32) -> ()
446       omp.yield
447     }
448   }
449   llvm.return
452 // -----
454 llvm.func @body(i64)
456 llvm.func @test_omp_wsloop_dynamic(%lb : i64, %ub : i64, %step : i64) -> () {
457   omp.wsloop schedule(dynamic) {
458     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step)  {
459       // CHECK: call void @__kmpc_dispatch_init_8u
460       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
461       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
462       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
463       llvm.call @body(%iv) : (i64) -> ()
464       omp.yield
465     }
466   }
467   llvm.return
470 // -----
472 llvm.func @body(i64)
474 llvm.func @test_omp_wsloop_dynamic_chunk_const(%lb : i64, %ub : i64, %step : i64) -> () {
475   %chunk_size_const = llvm.mlir.constant(2 : i16) : i16
476   omp.wsloop schedule(dynamic = %chunk_size_const : i16) {
477     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step)  {
478       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859, i64 {{.*}}, i64 %{{.*}}, i64 {{.*}}, i64 2)
479       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
480       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
481       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
482       llvm.call @body(%iv) : (i64) -> ()
483       omp.yield
484     }
485   }
486   llvm.return
489 // -----
491 llvm.func @body(i32)
493 llvm.func @test_omp_wsloop_dynamic_chunk_var(%lb : i32, %ub : i32, %step : i32) -> () {
494   %1 = llvm.mlir.constant(1 : i64) : i64
495   %chunk_size_alloca = llvm.alloca %1 x i16 {bindc_name = "chunk_size", in_type = i16, uniq_name = "_QFsub1Echunk_size"} : (i64) -> !llvm.ptr
496   %chunk_size_var = llvm.load %chunk_size_alloca : !llvm.ptr -> i16
497   omp.wsloop schedule(dynamic = %chunk_size_var : i16) {
498     omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
499       // CHECK: %[[CHUNK_SIZE:.*]] = sext i16 %{{.*}} to i32
500       // CHECK: call void @__kmpc_dispatch_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859, i32 {{.*}}, i32 %{{.*}}, i32 {{.*}}, i32 %[[CHUNK_SIZE]])
501       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_4u
502       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
503       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
504       llvm.call @body(%iv) : (i32) -> ()
505       omp.yield
506     }
507   }
508   llvm.return
511 // -----
513 llvm.func @body(i32)
515 llvm.func @test_omp_wsloop_dynamic_chunk_var2(%lb : i32, %ub : i32, %step : i32) -> () {
516   %1 = llvm.mlir.constant(1 : i64) : i64
517   %chunk_size_alloca = llvm.alloca %1 x i64 {bindc_name = "chunk_size", in_type = i64, uniq_name = "_QFsub1Echunk_size"} : (i64) -> !llvm.ptr
518   %chunk_size_var = llvm.load %chunk_size_alloca : !llvm.ptr -> i64
519   omp.wsloop schedule(dynamic = %chunk_size_var : i64) {
520     omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
521       // CHECK: %[[CHUNK_SIZE:.*]] = trunc i64 %{{.*}} to i32
522       // CHECK: call void @__kmpc_dispatch_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859, i32 {{.*}}, i32 %{{.*}}, i32 {{.*}}, i32 %[[CHUNK_SIZE]])
523       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_4u
524       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
525       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
526       llvm.call @body(%iv) : (i32) -> ()
527       omp.yield
528     }
529   }
530   llvm.return
533 // -----
535 llvm.func @body(i32)
537 llvm.func @test_omp_wsloop_dynamic_chunk_var3(%lb : i32, %ub : i32, %step : i32, %chunk_size : i32) -> () {
538   omp.wsloop schedule(dynamic = %chunk_size : i32) {
539     omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
540       // CHECK: call void @__kmpc_dispatch_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859, i32 {{.*}}, i32 %{{.*}}, i32 {{.*}}, i32 %{{.*}})
541       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_4u
542       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
543       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
544       llvm.call @body(%iv) : (i32) -> ()
545       omp.yield
546     }
547   }
548   llvm.return
551 // -----
553 llvm.func @body(i64)
555 llvm.func @test_omp_wsloop_auto(%lb : i64, %ub : i64, %step : i64) -> () {
556   omp.wsloop schedule(auto) {
557     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
558       // CHECK: call void @__kmpc_dispatch_init_8u
559       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
560       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
561       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
562       llvm.call @body(%iv) : (i64) -> ()
563       omp.yield
564     }
565   }
566   llvm.return
569 // -----
571 llvm.func @body(i64)
573 llvm.func @test_omp_wsloop_runtime(%lb : i64, %ub : i64, %step : i64) -> () {
574   omp.wsloop schedule(runtime) {
575     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
576       // CHECK: call void @__kmpc_dispatch_init_8u
577       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
578       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
579       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
580       llvm.call @body(%iv) : (i64) -> ()
581       omp.yield
582     }
583   }
584   llvm.return
587 // -----
589 llvm.func @body(i64)
591 llvm.func @test_omp_wsloop_guided(%lb : i64, %ub : i64, %step : i64) -> () {
592   omp.wsloop schedule(guided) {
593     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
594       // CHECK: call void @__kmpc_dispatch_init_8u
595       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
596       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
597       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
598       llvm.call @body(%iv) : (i64) -> ()
599       omp.yield
600     }
601   }
602   llvm.return
605 // -----
607 llvm.func @body(i64)
609 llvm.func @test_omp_wsloop_dynamic_nonmonotonic(%lb : i64, %ub : i64, %step : i64) -> () {
610   omp.wsloop schedule(dynamic, nonmonotonic) {
611     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
612       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741859
613       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
614       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
615       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
616       llvm.call @body(%iv) : (i64) -> ()
617       omp.yield
618     }
619   }
620   llvm.return
623 // -----
625 llvm.func @body(i64)
627 llvm.func @test_omp_wsloop_dynamic_monotonic(%lb : i64, %ub : i64, %step : i64) -> () {
628   omp.wsloop schedule(dynamic, monotonic) {
629     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
630       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 536870947
631       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
632       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
633       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
634       llvm.call @body(%iv) : (i64) -> ()
635       omp.yield
636     }
637   }
638   llvm.return
641 // -----
643 llvm.func @body(i64)
645 llvm.func @test_omp_wsloop_runtime_simd(%lb : i64, %ub : i64, %step : i64) -> () {
646   omp.wsloop schedule(runtime, simd) {
647     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
648       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741871
649       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
650       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
651       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
652       llvm.call @body(%iv) : (i64) -> ()
653       omp.yield
654     }
655   }
656   llvm.return
659 // -----
661 llvm.func @body(i64)
663 llvm.func @test_omp_wsloop_guided_simd(%lb : i64, %ub : i64, %step : i64) -> () {
664   omp.wsloop schedule(guided, simd) {
665     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
666       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741870
667       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
668       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
669       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
670       llvm.call @body(%iv) : (i64) -> ()
671       omp.yield
672     }
673   }
674   llvm.return
677 // -----
679 // CHECK-LABEL: @simd_simple
680 llvm.func @simd_simple(%lb : i64, %ub : i64, %step : i64, %arg0: !llvm.ptr) {
681   "omp.simd" () ({
682     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
683       %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
684       // The form of the emitted IR is controlled by OpenMPIRBuilder and
685       // tested there. Just check that the right metadata is added.
686       // CHECK: llvm.access.group
687       %4 = llvm.getelementptr %arg0[%iv] : (!llvm.ptr, i64) -> !llvm.ptr, f32
688       llvm.store %3, %4 : f32, !llvm.ptr
689       omp.yield
690     }
691   }) : () -> ()
693   llvm.return
695 // CHECK: llvm.loop.parallel_accesses
696 // CHECK-NEXT: llvm.loop.vectorize.enable
698 // -----
700 // CHECK-LABEL: @simd_simple_multiple
701 llvm.func @simd_simple_multiple(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr, %arg1: !llvm.ptr) {
702   omp.simd {
703     omp.loop_nest (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
704       %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
705       // The form of the emitted IR is controlled by OpenMPIRBuilder and
706       // tested there. Just check that the right metadata is added and collapsed
707       // loop bound is generated (Collapse clause is represented as a loop with
708       // list of indices, bounds and steps where the size of the list is equal
709       // to the collapse value.)
710       // CHECK: icmp slt i64
711       // CHECK-COUNT-3: select
712       // CHECK: %[[TRIPCOUNT0:.*]] = select
713       // CHECK: br label %[[PREHEADER:.*]]
714       // CHECK: [[PREHEADER]]:
715       // CHECK: icmp slt i64
716       // CHECK-COUNT-3: select
717       // CHECK: %[[TRIPCOUNT1:.*]] = select
718       // CHECK: mul nuw i64 %[[TRIPCOUNT0]], %[[TRIPCOUNT1]]
719       // CHECK: br label %[[COLLAPSED_PREHEADER:.*]]
720       // CHECK: [[COLLAPSED_PREHEADER]]:
721       // CHECK: br label %[[COLLAPSED_HEADER:.*]]
722       // CHECK: llvm.access.group
723       // CHECK-NEXT: llvm.access.group
724       %4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr, i64) -> !llvm.ptr, f32
725       %5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr, i64) -> !llvm.ptr, f32
726       llvm.store %3, %4 : f32, !llvm.ptr
727       llvm.store %3, %5 : f32, !llvm.ptr
728       omp.yield
729     }
730   }
731   llvm.return
733 // CHECK: llvm.loop.parallel_accesses
734 // CHECK-NEXT: llvm.loop.vectorize.enable
736 // -----
738 // CHECK-LABEL: @simd_simple_multiple_simdlen
739 llvm.func @simd_simple_multiple_simdlen(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr, %arg1: !llvm.ptr) {
740   omp.simd simdlen(2) {
741     omp.loop_nest (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
742       %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
743       // The form of the emitted IR is controlled by OpenMPIRBuilder and
744       // tested there. Just check that the right metadata is added.
745       // CHECK: llvm.access.group
746       // CHECK-NEXT: llvm.access.group
747       %4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr, i64) -> !llvm.ptr, f32
748       %5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr, i64) -> !llvm.ptr, f32
749       llvm.store %3, %4 : f32, !llvm.ptr
750       llvm.store %3, %5 : f32, !llvm.ptr
751       omp.yield
752     }
753   }
754   llvm.return
756 // CHECK: llvm.loop.parallel_accesses
757 // CHECK-NEXT: llvm.loop.vectorize.enable
758 // CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 2
760 // -----
762 // CHECK-LABEL: @simd_simple_multiple_safelen
763 llvm.func @simd_simple_multiple_safelen(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr, %arg1: !llvm.ptr) {
764   omp.simd safelen(2) {
765     omp.loop_nest (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
766       %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
767       %4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr, i64) -> !llvm.ptr, f32
768       %5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr, i64) -> !llvm.ptr, f32
769       llvm.store %3, %4 : f32, !llvm.ptr
770       llvm.store %3, %5 : f32, !llvm.ptr
771       omp.yield
772     }
773   }
774   llvm.return
776 // CHECK: llvm.loop.vectorize.enable
777 // CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 2
779 // -----
781 // CHECK-LABEL: @simd_simple_multiple_simdlen_safelen
782 llvm.func @simd_simple_multiple_simdlen_safelen(%lb1 : i64, %ub1 : i64, %step1 : i64, %lb2 : i64, %ub2 : i64, %step2 : i64, %arg0: !llvm.ptr, %arg1: !llvm.ptr) {
783   omp.simd simdlen(1) safelen(2) {
784     omp.loop_nest (%iv1, %iv2) : i64 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
785       %3 = llvm.mlir.constant(2.000000e+00 : f32) : f32
786       %4 = llvm.getelementptr %arg0[%iv1] : (!llvm.ptr, i64) -> !llvm.ptr, f32
787       %5 = llvm.getelementptr %arg1[%iv2] : (!llvm.ptr, i64) -> !llvm.ptr, f32
788       llvm.store %3, %4 : f32, !llvm.ptr
789       llvm.store %3, %5 : f32, !llvm.ptr
790       omp.yield
791     }
792   }
793   llvm.return
795 // CHECK: llvm.loop.vectorize.enable
796 // CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 1
798 // -----
800 // CHECK-LABEL: @simd_if
801 llvm.func @simd_if(%arg0: !llvm.ptr {fir.bindc_name = "n"}, %arg1: !llvm.ptr {fir.bindc_name = "threshold"}) {
802   %0 = llvm.mlir.constant(1 : i64) : i64
803   %1 = llvm.alloca %0 x i32 {adapt.valuebyref, in_type = i32, operandSegmentSizes = array<i32: 0, 0>} : (i64) -> !llvm.ptr
804   %2 = llvm.mlir.constant(1 : i64) : i64
805   %3 = llvm.alloca %2 x i32 {bindc_name = "i", in_type = i32, operandSegmentSizes = array<i32: 0, 0>, uniq_name = "_QFtest_simdEi"} : (i64) -> !llvm.ptr
806   %4 = llvm.mlir.constant(0 : i32) : i32
807   %5 = llvm.load %arg0 : !llvm.ptr -> i32
808   %6 = llvm.mlir.constant(1 : i32) : i32
809   %7 = llvm.load %arg0 : !llvm.ptr -> i32
810   %8 = llvm.load %arg1 : !llvm.ptr -> i32
811   %9 = llvm.icmp "sge" %7, %8 : i32
812   omp.simd if(%9) {
813     omp.loop_nest (%arg2) : i32 = (%4) to (%5) inclusive step (%6) {
814       // The form of the emitted IR is controlled by OpenMPIRBuilder and
815       // tested there. Just check that the right metadata is added.
816       // CHECK: llvm.access.group
817       llvm.store %arg2, %1 : i32, !llvm.ptr
818       omp.yield
819     }
820   }
821   llvm.return
823 // Be sure that llvm.loop.vectorize.enable metadata appears twice
824 // CHECK: llvm.loop.parallel_accesses
825 // CHECK-NEXT: llvm.loop.vectorize.enable
826 // CHECK: llvm.loop.vectorize.enable
828 // -----
830 // CHECK-LABEL: @simd_order
831 llvm.func @simd_order() {
832   %0 = llvm.mlir.constant(10 : i64) : i64
833   %1 = llvm.mlir.constant(1 : i64) : i64
834   %2 = llvm.alloca %1 x i64 : (i64) -> !llvm.ptr
835   omp.simd order(concurrent) safelen(2) {
836     omp.loop_nest (%arg0) : i64 = (%1) to (%0) inclusive step (%1) {
837       llvm.store %arg0, %2 : i64, !llvm.ptr
838       omp.yield
839     }
840   }
841   llvm.return
843 // If clause order(concurrent) is specified then the memory instructions
844 // are marked parallel even if 'safelen' is finite.
845 // CHECK: llvm.loop.parallel_accesses
846 // CHECK-NEXT: llvm.loop.vectorize.enable
847 // CHECK-NEXT: llvm.loop.vectorize.width{{.*}}i64 2
848 // -----
850 llvm.func @body(i64)
852 llvm.func @test_omp_wsloop_ordered(%lb : i64, %ub : i64, %step : i64) -> () {
853   omp.wsloop ordered(0) {
854     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
855       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 66, i64 1, i64 %{{.*}}, i64 1, i64 1)
856       // CHECK: call void @__kmpc_dispatch_fini_8u
857       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
858       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
859       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
860       llvm.call @body(%iv) : (i64) -> ()
861       omp.yield
862     }
863   }
864   llvm.return
867 // -----
869 llvm.func @body(i64)
871 llvm.func @test_omp_wsloop_static_ordered(%lb : i64, %ub : i64, %step : i64) -> () {
872   omp.wsloop schedule(static) ordered(0) {
873     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
874       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 66, i64 1, i64 %{{.*}}, i64 1, i64 1)
875       // CHECK: call void @__kmpc_dispatch_fini_8u
876       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
877       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
878       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
879       llvm.call @body(%iv) : (i64) -> ()
880       omp.yield
881     }
882   }
883   llvm.return
886 // -----
888 llvm.func @body(i32)
890 llvm.func @test_omp_wsloop_static_chunk_ordered(%lb : i32, %ub : i32, %step : i32) -> () {
891   %static_chunk_size = llvm.mlir.constant(1 : i32) : i32
892   omp.wsloop schedule(static = %static_chunk_size : i32) ordered(0) {
893     omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
894       // CHECK: call void @__kmpc_dispatch_init_4u(ptr @{{.*}}, i32 %{{.*}}, i32 65, i32 1, i32 %{{.*}}, i32 1, i32 1)
895       // CHECK: call void @__kmpc_dispatch_fini_4u
896       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_4u
897       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
898       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
899       llvm.call @body(%iv) : (i32) -> ()
900       omp.yield
901     }
902   }
903   llvm.return
906 // -----
908 llvm.func @body(i64)
910 llvm.func @test_omp_wsloop_dynamic_ordered(%lb : i64, %ub : i64, %step : i64) -> () {
911   omp.wsloop schedule(dynamic) ordered(0) {
912     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
913       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 67, i64 1, i64 %{{.*}}, i64 1, i64 1)
914       // CHECK: call void @__kmpc_dispatch_fini_8u
915       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
916       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
917       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
918       llvm.call @body(%iv) : (i64) -> ()
919       omp.yield
920     }
921   }
922   llvm.return
925 // -----
927 llvm.func @body(i64)
929 llvm.func @test_omp_wsloop_auto_ordered(%lb : i64, %ub : i64, %step : i64) -> () {
930   omp.wsloop schedule(auto) ordered(0) {
931     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
932       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 70, i64 1, i64 %{{.*}}, i64 1, i64 1)
933       // CHECK: call void @__kmpc_dispatch_fini_8u
934       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
935       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
936       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
937       llvm.call @body(%iv) : (i64) -> ()
938       omp.yield
939     }
940   }
941   llvm.return
944 // -----
946 llvm.func @body(i64)
948 llvm.func @test_omp_wsloop_runtime_ordered(%lb : i64, %ub : i64, %step : i64) -> () {
949   omp.wsloop schedule(runtime) ordered(0) {
950     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
951       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 69, i64 1, i64 %{{.*}}, i64 1, i64 1)
952       // CHECK: call void @__kmpc_dispatch_fini_8u
953       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
954       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
955       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
956       llvm.call @body(%iv) : (i64) -> ()
957       omp.yield
958     }
959   }
960   llvm.return
963 // -----
965 llvm.func @body(i64)
967 llvm.func @test_omp_wsloop_guided_ordered(%lb : i64, %ub : i64, %step : i64) -> () {
968   omp.wsloop schedule(guided) ordered(0) {
969     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
970       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 68, i64 1, i64 %{{.*}}, i64 1, i64 1)
971       // CHECK: call void @__kmpc_dispatch_fini_8u
972       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
973       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
974       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
975       llvm.call @body(%iv) : (i64) -> ()
976       omp.yield
977     }
978   }
979   llvm.return
982 // -----
984 llvm.func @body(i64)
986 llvm.func @test_omp_wsloop_dynamic_nonmonotonic_ordered(%lb : i64, %ub : i64, %step : i64) -> () {
987   omp.wsloop schedule(dynamic, nonmonotonic) ordered(0) {
988     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
989       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 1073741891, i64 1, i64 %{{.*}}, i64 1, i64 1)
990       // CHECK: call void @__kmpc_dispatch_fini_8u
991       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
992       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
993       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
994       llvm.call @body(%iv) : (i64) -> ()
995       omp.yield
996     }
997   }
998   llvm.return
1001 // -----
1003 llvm.func @body(i64)
1005 llvm.func @test_omp_wsloop_dynamic_monotonic_ordered(%lb : i64, %ub : i64, %step : i64) -> () {
1006   omp.wsloop schedule(dynamic, monotonic) ordered(0) {
1007     omp.loop_nest (%iv) : i64 = (%lb) to (%ub) step (%step) {
1008       // CHECK: call void @__kmpc_dispatch_init_8u(ptr @{{.*}}, i32 %{{.*}}, i32 536870979, i64 1, i64 %{{.*}}, i64 1, i64 1)
1009       // CHECK: call void @__kmpc_dispatch_fini_8u
1010       // CHECK: %[[continue:.*]] = call i32 @__kmpc_dispatch_next_8u
1011       // CHECK: %[[cond:.*]] = icmp ne i32 %[[continue]], 0
1012       // CHECK: br i1 %[[cond]], label %omp_loop.header{{.*}}, label %omp_loop.exit{{.*}}
1013       llvm.call @body(%iv) : (i64) -> ()
1014       omp.yield
1015     }
1016   }
1017   llvm.return
1020 // -----
1022 omp.critical.declare @mutex_none hint(none) // 0
1023 omp.critical.declare @mutex_uncontended hint(uncontended) // 1
1024 omp.critical.declare @mutex_contended hint(contended) // 2
1025 omp.critical.declare @mutex_nonspeculative hint(nonspeculative) // 4
1026 omp.critical.declare @mutex_nonspeculative_uncontended hint(nonspeculative, uncontended) // 5
1027 omp.critical.declare @mutex_nonspeculative_contended hint(nonspeculative, contended) // 6
1028 omp.critical.declare @mutex_speculative hint(speculative) // 8
1029 omp.critical.declare @mutex_speculative_uncontended hint(speculative, uncontended) // 9
1030 omp.critical.declare @mutex_speculative_contended hint(speculative, contended) // 10
1032 // CHECK-LABEL: @omp_critical
1033 llvm.func @omp_critical(%x : !llvm.ptr, %xval : i32) -> () {
1034   // CHECK: call void @__kmpc_critical({{.*}}critical_user_.var{{.*}})
1035   // CHECK: br label %omp.critical.region
1036   // CHECK: omp.critical.region
1037   omp.critical {
1038   // CHECK: store
1039     llvm.store %xval, %x : i32, !llvm.ptr
1040     omp.terminator
1041   }
1042   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_.var{{.*}})
1044   // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_none.var{{.*}}, i32 0)
1045   // CHECK: br label %omp.critical.region
1046   // CHECK: omp.critical.region
1047   omp.critical(@mutex_none) {
1048   // CHECK: store
1049     llvm.store %xval, %x : i32, !llvm.ptr
1050     omp.terminator
1051   }
1052   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_none.var{{.*}})
1054   // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_uncontended.var{{.*}}, i32 1)
1055   // CHECK: br label %omp.critical.region
1056   // CHECK: omp.critical.region
1057   omp.critical(@mutex_uncontended) {
1058   // CHECK: store
1059     llvm.store %xval, %x : i32, !llvm.ptr
1060     omp.terminator
1061   }
1062   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_uncontended.var{{.*}})
1064   // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_contended.var{{.*}}, i32 2)
1065   // CHECK: br label %omp.critical.region
1066   // CHECK: omp.critical.region
1067   omp.critical(@mutex_contended) {
1068   // CHECK: store
1069     llvm.store %xval, %x : i32, !llvm.ptr
1070     omp.terminator
1071   }
1072   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_contended.var{{.*}})
1074   // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_nonspeculative.var{{.*}}, i32 4)
1075   // CHECK: br label %omp.critical.region
1076   // CHECK: omp.critical.region
1077   omp.critical(@mutex_nonspeculative) {
1078   // CHECK: store
1079     llvm.store %xval, %x : i32, !llvm.ptr
1080     omp.terminator
1081   }
1082   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_nonspeculative.var{{.*}})
1084   // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_nonspeculative_uncontended.var{{.*}}, i32 5)
1085   // CHECK: br label %omp.critical.region
1086   // CHECK: omp.critical.region
1087   omp.critical(@mutex_nonspeculative_uncontended) {
1088   // CHECK: store
1089     llvm.store %xval, %x : i32, !llvm.ptr
1090     omp.terminator
1091   }
1092   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_nonspeculative_uncontended.var{{.*}})
1094   // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_nonspeculative_contended.var{{.*}}, i32 6)
1095   // CHECK: br label %omp.critical.region
1096   // CHECK: omp.critical.region
1097   omp.critical(@mutex_nonspeculative_contended) {
1098   // CHECK: store
1099     llvm.store %xval, %x : i32, !llvm.ptr
1100     omp.terminator
1101   }
1102   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_nonspeculative_contended.var{{.*}})
1104   // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_speculative.var{{.*}}, i32 8)
1105   // CHECK: br label %omp.critical.region
1106   // CHECK: omp.critical.region
1107   omp.critical(@mutex_speculative) {
1108   // CHECK: store
1109     llvm.store %xval, %x : i32, !llvm.ptr
1110     omp.terminator
1111   }
1112   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative.var{{.*}})
1114   // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_speculative_uncontended.var{{.*}}, i32 9)
1115   // CHECK: br label %omp.critical.region
1116   // CHECK: omp.critical.region
1117   omp.critical(@mutex_speculative_uncontended) {
1118   // CHECK: store
1119     llvm.store %xval, %x : i32, !llvm.ptr
1120     omp.terminator
1121   }
1122   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative_uncontended.var{{.*}})
1124   // CHECK: call void @__kmpc_critical_with_hint({{.*}}critical_user_mutex_speculative_contended.var{{.*}}, i32 10)
1125   // CHECK: br label %omp.critical.region
1126   // CHECK: omp.critical.region
1127   omp.critical(@mutex_speculative_contended) {
1128   // CHECK: store
1129     llvm.store %xval, %x : i32, !llvm.ptr
1130     omp.terminator
1131   }
1132   // CHECK: call void @__kmpc_end_critical({{.*}}critical_user_mutex_speculative_contended.var{{.*}})
1133   llvm.return
1136 // -----
1138 // Check that the loop bounds are emitted in the correct location in case of
1139 // collapse. This only checks the overall shape of the IR, detailed checking
1140 // is done by the OpenMPIRBuilder.
1142 // CHECK-LABEL: @collapse_wsloop
1143 // CHECK: ptr noalias %[[TIDADDR:[0-9A-Za-z.]*]]
1144 // CHECK: load i32, ptr %[[TIDADDR]]
1145 // CHECK: store
1146 // CHECK: load
1147 // CHECK: %[[LB0:.*]] = load i32
1148 // CHECK: %[[UB0:.*]] = load i32
1149 // CHECK: %[[STEP0:.*]] = load i32
1150 // CHECK: %[[LB1:.*]] = load i32
1151 // CHECK: %[[UB1:.*]] = load i32
1152 // CHECK: %[[STEP1:.*]] = load i32
1153 // CHECK: %[[LB2:.*]] = load i32
1154 // CHECK: %[[UB2:.*]] = load i32
1155 // CHECK: %[[STEP2:.*]] = load i32
1156 llvm.func @collapse_wsloop(
1157     %0: i32, %1: i32, %2: i32,
1158     %3: i32, %4: i32, %5: i32,
1159     %6: i32, %7: i32, %8: i32,
1160     %20: !llvm.ptr) {
1161   omp.parallel {
1162     // CHECK: icmp slt i32 %[[LB0]], 0
1163     // CHECK-COUNT-4: select
1164     // CHECK: %[[TRIPCOUNT0:.*]] = select
1165     // CHECK: br label %[[PREHEADER:.*]]
1166     //
1167     // CHECK: [[PREHEADER]]:
1168     // CHECK: icmp slt i32 %[[LB1]], 0
1169     // CHECK-COUNT-4: select
1170     // CHECK: %[[TRIPCOUNT1:.*]] = select
1171     // CHECK: icmp slt i32 %[[LB2]], 0
1172     // CHECK-COUNT-4: select
1173     // CHECK: %[[TRIPCOUNT2:.*]] = select
1174     // CHECK: %[[PROD:.*]] = mul nuw i32 %[[TRIPCOUNT0]], %[[TRIPCOUNT1]]
1175     // CHECK: %[[TOTAL:.*]] = mul nuw i32 %[[PROD]], %[[TRIPCOUNT2]]
1176     // CHECK: br label %[[COLLAPSED_PREHEADER:.*]]
1177     //
1178     // CHECK: [[COLLAPSED_PREHEADER]]:
1179     // CHECK: store i32 0, ptr
1180     // CHECK: %[[TOTAL_SUB_1:.*]] = sub i32 %[[TOTAL]], 1
1181     // CHECK: store i32 %[[TOTAL_SUB_1]], ptr
1182     // CHECK: call void @__kmpc_for_static_init_4u
1183     omp.wsloop {
1184       omp.loop_nest (%arg0, %arg1, %arg2) : i32 = (%0, %1, %2) to (%3, %4, %5) step (%6, %7, %8) {
1185         %31 = llvm.load %20 : !llvm.ptr -> i32
1186         %32 = llvm.add %31, %arg0 : i32
1187         %33 = llvm.add %32, %arg1 : i32
1188         %34 = llvm.add %33, %arg2 : i32
1189         llvm.store %34, %20 : i32, !llvm.ptr
1190         omp.yield
1191       }
1192     }
1193     omp.terminator
1194   }
1195   llvm.return
1198 // -----
1200 // Check that the loop bounds are emitted in the correct location in case of
1201 // collapse for dynamic schedule. This only checks the overall shape of the IR,
1202 // detailed checking is done by the OpenMPIRBuilder.
1204 // CHECK-LABEL: @collapse_wsloop_dynamic
1205 // CHECK: ptr noalias %[[TIDADDR:[0-9A-Za-z.]*]]
1206 // CHECK: load i32, ptr %[[TIDADDR]]
1207 // CHECK: store
1208 // CHECK: load
1209 // CHECK: %[[LB0:.*]] = load i32
1210 // CHECK: %[[UB0:.*]] = load i32
1211 // CHECK: %[[STEP0:.*]] = load i32
1212 // CHECK: %[[LB1:.*]] = load i32
1213 // CHECK: %[[UB1:.*]] = load i32
1214 // CHECK: %[[STEP1:.*]] = load i32
1215 // CHECK: %[[LB2:.*]] = load i32
1216 // CHECK: %[[UB2:.*]] = load i32
1217 // CHECK: %[[STEP2:.*]] = load i32
1219 llvm.func @collapse_wsloop_dynamic(
1220     %0: i32, %1: i32, %2: i32,
1221     %3: i32, %4: i32, %5: i32,
1222     %6: i32, %7: i32, %8: i32,
1223     %20: !llvm.ptr) {
1224   omp.parallel {
1225     // CHECK: icmp slt i32 %[[LB0]], 0
1226     // CHECK-COUNT-4: select
1227     // CHECK: %[[TRIPCOUNT0:.*]] = select
1228     // CHECK: br label %[[PREHEADER:.*]]
1229     //
1230     // CHECK: [[PREHEADER]]:
1231     // CHECK: icmp slt i32 %[[LB1]], 0
1232     // CHECK-COUNT-4: select
1233     // CHECK: %[[TRIPCOUNT1:.*]] = select
1234     // CHECK: icmp slt i32 %[[LB2]], 0
1235     // CHECK-COUNT-4: select
1236     // CHECK: %[[TRIPCOUNT2:.*]] = select
1237     // CHECK: %[[PROD:.*]] = mul nuw i32 %[[TRIPCOUNT0]], %[[TRIPCOUNT1]]
1238     // CHECK: %[[TOTAL:.*]] = mul nuw i32 %[[PROD]], %[[TRIPCOUNT2]]
1239     // CHECK: br label %[[COLLAPSED_PREHEADER:.*]]
1240     //
1241     // CHECK: [[COLLAPSED_PREHEADER]]:
1242     // CHECK: store i32 1, ptr
1243     // CHECK: store i32 %[[TOTAL]], ptr
1244     // CHECK: call void @__kmpc_dispatch_init_4u
1245     omp.wsloop schedule(dynamic) {
1246       omp.loop_nest (%arg0, %arg1, %arg2) : i32 = (%0, %1, %2) to (%3, %4, %5) step (%6, %7, %8) {
1247         %31 = llvm.load %20 : !llvm.ptr -> i32
1248         %32 = llvm.add %31, %arg0 : i32
1249         %33 = llvm.add %32, %arg1 : i32
1250         %34 = llvm.add %33, %arg2 : i32
1251         llvm.store %34, %20 : i32, !llvm.ptr
1252         omp.yield
1253       }
1254     }
1255     omp.terminator
1256   }
1257   llvm.return
1260 // -----
1262 // CHECK-LABEL: @omp_ordered
1263 llvm.func @omp_ordered(%arg0 : i32, %arg1 : i32, %arg2 : i32, %arg3 : i64,
1264     %arg4: i64, %arg5: i64, %arg6: i64) -> () {
1265   // CHECK: [[ADDR9:%.*]] = alloca [2 x i64], align 8
1266   // CHECK: [[ADDR7:%.*]] = alloca [2 x i64], align 8
1267   // CHECK: [[ADDR5:%.*]] = alloca [2 x i64], align 8
1268   // CHECK: [[ADDR3:%.*]] = alloca [1 x i64], align 8
1269   // CHECK: [[ADDR:%.*]] = alloca [1 x i64], align 8
1271   // CHECK: [[OMP_THREAD:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB1:[0-9]+]])
1272   // CHECK-NEXT:  call void @__kmpc_ordered(ptr @[[GLOB1]], i32 [[OMP_THREAD]])
1273   omp.ordered.region {
1274     omp.terminator
1275   // CHECK: call void @__kmpc_end_ordered(ptr @[[GLOB1]], i32 [[OMP_THREAD]])
1276   }
1278   omp.wsloop ordered(0) {
1279     omp.loop_nest (%arg7) : i32 = (%arg0) to (%arg1) step (%arg2) {
1280       // CHECK:  call void @__kmpc_ordered(ptr @[[GLOB3:[0-9]+]], i32 [[OMP_THREAD2:%.*]])
1281       omp.ordered.region  {
1282         omp.terminator
1283       // CHECK: call void @__kmpc_end_ordered(ptr @[[GLOB3]], i32 [[OMP_THREAD2]])
1284       }
1285       omp.yield
1286     }
1287   }
1289   omp.wsloop ordered(1) {
1290     omp.loop_nest (%arg7) : i32 = (%arg0) to (%arg1) step (%arg2) {
1291       // CHECK: [[TMP:%.*]] = getelementptr inbounds [1 x i64], ptr [[ADDR]], i64 0, i64 0
1292       // CHECK: store i64 [[ARG0:%.*]], ptr [[TMP]], align 8
1293       // CHECK: [[TMP2:%.*]] = getelementptr inbounds [1 x i64], ptr [[ADDR]], i64 0, i64 0
1294       // CHECK: [[OMP_THREAD2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB3:[0-9]+]])
1295       // CHECK: call void @__kmpc_doacross_wait(ptr @[[GLOB3]], i32 [[OMP_THREAD2]], ptr [[TMP2]])
1296       omp.ordered depend_type(dependsink) depend_vec(%arg3 : i64) {doacross_num_loops = 1 : i64}
1298       // CHECK: [[TMP3:%.*]] = getelementptr inbounds [1 x i64], ptr [[ADDR3]], i64 0, i64 0
1299       // CHECK: store i64 [[ARG0]], ptr [[TMP3]], align 8
1300       // CHECK: [[TMP4:%.*]] = getelementptr inbounds [1 x i64], ptr [[ADDR3]], i64 0, i64 0
1301       // CHECK: [[OMP_THREAD4:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB5:[0-9]+]])
1302       // CHECK: call void @__kmpc_doacross_post(ptr @[[GLOB5]], i32 [[OMP_THREAD4]], ptr [[TMP4]])
1303       omp.ordered depend_type(dependsource) depend_vec(%arg3 : i64) {doacross_num_loops = 1 : i64}
1305       omp.yield
1306     }
1307   }
1309   omp.wsloop ordered(2) {
1310     omp.loop_nest (%arg7) : i32 = (%arg0) to (%arg1) step (%arg2) {
1311       // CHECK: [[TMP5:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR5]], i64 0, i64 0
1312       // CHECK: store i64 [[ARG0]], ptr [[TMP5]], align 8
1313       // CHECK: [[TMP6:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR5]], i64 0, i64 1
1314       // CHECK: store i64 [[ARG1:%.*]], ptr [[TMP6]], align 8
1315       // CHECK: [[TMP7:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR5]], i64 0, i64 0
1316       // CHECK: [[OMP_THREAD6:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB7:[0-9]+]])
1317       // CHECK: call void @__kmpc_doacross_wait(ptr @[[GLOB7]], i32 [[OMP_THREAD6]], ptr [[TMP7]])
1318       // CHECK: [[TMP8:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR7]], i64 0, i64 0
1319       // CHECK: store i64 [[ARG2:%.*]], ptr [[TMP8]], align 8
1320       // CHECK: [[TMP9:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR7]], i64 0, i64 1
1321       // CHECK: store i64 [[ARG3:%.*]], ptr [[TMP9]], align 8
1322       // CHECK: [[TMP10:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR7]], i64 0, i64 0
1323       // CHECK: [[OMP_THREAD8:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB7]])
1324       // CHECK: call void @__kmpc_doacross_wait(ptr @[[GLOB7]], i32 [[OMP_THREAD8]], ptr [[TMP10]])
1325       omp.ordered depend_type(dependsink) depend_vec(%arg3, %arg4, %arg5, %arg6 : i64, i64, i64, i64) {doacross_num_loops = 2 : i64}
1327       // CHECK: [[TMP11:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR9]], i64 0, i64 0
1328       // CHECK: store i64 [[ARG0]], ptr [[TMP11]], align 8
1329       // CHECK: [[TMP12:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR9]], i64 0, i64 1
1330       // CHECK: store i64 [[ARG1]], ptr [[TMP12]], align 8
1331       // CHECK: [[TMP13:%.*]] = getelementptr inbounds [2 x i64], ptr [[ADDR9]], i64 0, i64 0
1332       // CHECK: [[OMP_THREAD10:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB9:[0-9]+]])
1333       // CHECK: call void @__kmpc_doacross_post(ptr @[[GLOB9]], i32 [[OMP_THREAD10]], ptr [[TMP13]])
1334       omp.ordered depend_type(dependsource) depend_vec(%arg3, %arg4 : i64, i64) {doacross_num_loops = 2 : i64}
1336       omp.yield
1337     }
1338   }
1340   llvm.return
1343 // -----
1345 // CHECK-LABEL: @omp_atomic_read
1346 // CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]])
1347 llvm.func @omp_atomic_read(%arg0 : !llvm.ptr, %arg1 : !llvm.ptr) -> () {
1349   // CHECK: %[[X1:.*]] = load atomic i32, ptr %[[ARG0]] monotonic, align 4
1350   // CHECK: store i32 %[[X1]], ptr %[[ARG1]], align 4
1351   omp.atomic.read %arg1 = %arg0 : !llvm.ptr, !llvm.ptr, i32
1353   // CHECK: %[[X2:.*]] = load atomic i32, ptr %[[ARG0]] seq_cst, align 4
1354   // CHECK: call void @__kmpc_flush(ptr @{{.*}})
1355   // CHECK: store i32 %[[X2]], ptr %[[ARG1]], align 4
1356   omp.atomic.read %arg1 = %arg0 memory_order(seq_cst) : !llvm.ptr, !llvm.ptr, i32
1358   // CHECK: %[[X3:.*]] = load atomic i32, ptr %[[ARG0]] acquire, align 4
1359   // CHECK: call void @__kmpc_flush(ptr @{{.*}})
1360   // CHECK: store i32 %[[X3]], ptr %[[ARG1]], align 4
1361   omp.atomic.read %arg1 = %arg0 memory_order(acquire) : !llvm.ptr, !llvm.ptr, i32
1363   // CHECK: %[[X4:.*]] = load atomic i32, ptr %[[ARG0]] monotonic, align 4
1364   // CHECK: store i32 %[[X4]], ptr %[[ARG1]], align 4
1365   omp.atomic.read %arg1 = %arg0 memory_order(relaxed) : !llvm.ptr, !llvm.ptr, i32
1366   llvm.return
1369 // -----
1371 // CHECK-LABEL: @omp_atomic_read_implicit_cast
1372 llvm.func @omp_atomic_read_implicit_cast () {
1373 //CHECK: %[[Z:.*]] = alloca float, i64 1, align 4
1374 //CHECK: %[[Y:.*]] = alloca double, i64 1, align 8
1375 //CHECK: %[[X:.*]] = alloca [2 x { float, float }], i64 1, align 8
1376 //CHECK: %[[W:.*]] = alloca i32, i64 1, align 4
1377 //CHECK: %[[X_ELEMENT:.*]] = getelementptr { float, float }, ptr %3, i64 0
1378   %0 = llvm.mlir.constant(1 : i64) : i64
1379   %1 = llvm.alloca %0 x f32 {bindc_name = "z"} : (i64) -> !llvm.ptr
1380   %2 = llvm.mlir.constant(1 : i64) : i64
1381   %3 = llvm.alloca %2 x f64 {bindc_name = "y"} : (i64) -> !llvm.ptr
1382   %4 = llvm.mlir.constant(1 : i64) : i64
1383   %5 = llvm.alloca %4 x !llvm.array<2 x struct<(f32, f32)>> {bindc_name = "x"} : (i64) -> !llvm.ptr
1384   %6 = llvm.mlir.constant(1 : i64) : i64
1385   %7 = llvm.alloca %6 x i32 {bindc_name = "w"} : (i64) -> !llvm.ptr
1386   %8 = llvm.mlir.constant(1 : index) : i64
1387   %9 = llvm.mlir.constant(2 : index) : i64
1388   %10 = llvm.mlir.constant(1 : i64) : i64
1389   %11 = llvm.mlir.constant(0 : i64) : i64
1390   %12 = llvm.sub %8, %10 overflow<nsw> : i64
1391   %13 = llvm.mul %12, %10 overflow<nsw> : i64
1392   %14 = llvm.mul %13, %10 overflow<nsw> : i64
1393   %15 = llvm.add %14, %11 overflow<nsw> : i64
1394   %16 = llvm.mul %10, %9 overflow<nsw> : i64
1395   %17 = llvm.getelementptr %5[%15] : (!llvm.ptr, i64) -> !llvm.ptr, !llvm.struct<(f32, f32)>
1397 //CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = alloca { float, float }, align 8
1398 //CHECK: call void @__atomic_load(i64 8, ptr %[[X_ELEMENT]], ptr %[[ATOMIC_LOAD_TEMP]], i32 0)
1399 //CHECK: %[[LOAD:.*]] = load { float, float }, ptr %[[ATOMIC_LOAD_TEMP]], align 8
1400 //CHECK: %[[EXT:.*]] = extractvalue { float, float } %[[LOAD]], 0
1401 //CHECK: store float %[[EXT]], ptr %[[Y]], align 4
1402   omp.atomic.read %3 = %17 : !llvm.ptr, !llvm.ptr, !llvm.struct<(f32, f32)>
1404 //CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i32, ptr %[[Z]] monotonic, align 4
1405 //CHECK: %[[CAST:.*]] = bitcast i32 %[[ATOMIC_LOAD_TEMP]] to float
1406 //CHECK: %[[LOAD:.*]] = fpext float %[[CAST]] to double
1407 //CHECK: store double %[[LOAD]], ptr %[[Y]], align 8
1408   omp.atomic.read %3 = %1 : !llvm.ptr, !llvm.ptr, f32
1410 //CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i32, ptr %[[W]] monotonic, align 4
1411 //CHECK: %[[LOAD:.*]] = sitofp i32 %[[ATOMIC_LOAD_TEMP]] to double
1412 //CHECK: store double %[[LOAD]], ptr %[[Y]], align 8
1413   omp.atomic.read %3 = %7 : !llvm.ptr, !llvm.ptr, i32
1415 //CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i64, ptr %[[Y]] monotonic, align 4
1416 //CHECK: %[[CAST:.*]] = bitcast i64 %[[ATOMIC_LOAD_TEMP]] to double
1417 //CHECK: %[[LOAD:.*]] = fptrunc double %[[CAST]] to float
1418 //CHECK: store float %[[LOAD]], ptr %[[Z]], align 4
1419   omp.atomic.read %1 = %3 : !llvm.ptr, !llvm.ptr, f64
1421 //CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i32, ptr %[[W]] monotonic, align 4
1422 //CHECK: %[[LOAD:.*]] = sitofp i32 %[[ATOMIC_LOAD_TEMP]] to float
1423 //CHECK: store float %[[LOAD]], ptr %[[Z]], align 4
1424   omp.atomic.read %1 = %7 : !llvm.ptr, !llvm.ptr, i32
1426 //CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i64, ptr %[[Y]] monotonic, align 4
1427 //CHECK: %[[CAST:.*]] = bitcast i64 %[[ATOMIC_LOAD_TEMP]] to double
1428 //CHECK: %[[LOAD:.*]] = fptosi double %[[CAST]] to i32
1429 //CHECK: store i32 %[[LOAD]], ptr %[[W]], align 4
1430   omp.atomic.read %7 = %3 : !llvm.ptr, !llvm.ptr, f64
1432 //CHECK: %[[ATOMIC_LOAD_TEMP:.*]] = load atomic i32, ptr %[[Z]] monotonic, align 4
1433 //CHECK: %[[CAST:.*]] = bitcast i32 %[[ATOMIC_LOAD_TEMP]] to float
1434 //CHECK: %[[LOAD:.*]] = fptosi float %[[CAST]] to i32
1435 //CHECK: store i32 %[[LOAD]], ptr %[[W]], align 4
1436   omp.atomic.read %7 = %1 : !llvm.ptr, !llvm.ptr, f32
1437   llvm.return
1440 // -----
1442 // CHECK-LABEL: @omp_atomic_write
1443 // CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]])
1444 llvm.func @omp_atomic_write(%x: !llvm.ptr, %expr: i32) -> () {
1445   // CHECK: store atomic i32 %[[expr]], ptr %[[x]] monotonic, align 4
1446   omp.atomic.write %x = %expr : !llvm.ptr, i32
1447   // CHECK: store atomic i32 %[[expr]], ptr %[[x]] seq_cst, align 4
1448   // CHECK: call void @__kmpc_flush(ptr @{{.*}})
1449   omp.atomic.write %x = %expr memory_order(seq_cst) : !llvm.ptr, i32
1450   // CHECK: store atomic i32 %[[expr]], ptr %[[x]] release, align 4
1451   // CHECK: call void @__kmpc_flush(ptr @{{.*}})
1452   omp.atomic.write %x = %expr memory_order(release) : !llvm.ptr, i32
1453   // CHECK: store atomic i32 %[[expr]], ptr %[[x]] monotonic, align 4
1454   omp.atomic.write %x = %expr memory_order(relaxed) : !llvm.ptr, i32
1455   llvm.return
1458 // -----
1460 // Checking simple atomicrmw and cmpxchg based translation. This also checks for
1461 // ambigous alloca insert point by putting llvm.mul as the first update operation.
1462 // CHECK-LABEL: @omp_atomic_update
1463 // CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]], ptr %[[xbool:.*]], i1 %[[exprbool:.*]])
1464 llvm.func @omp_atomic_update(%x:!llvm.ptr, %expr: i32, %xbool: !llvm.ptr, %exprbool: i1) {
1465   // CHECK: %[[t1:.*]] = mul i32 %[[x_old:.*]], %[[expr]]
1466   // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]
1467   // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]
1468   // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]]
1469   omp.atomic.update %x : !llvm.ptr {
1470   ^bb0(%xval: i32):
1471     %newval = llvm.mul %xval, %expr : i32
1472     omp.yield(%newval : i32)
1473   }
1474   // CHECK: atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic
1475   omp.atomic.update %x : !llvm.ptr {
1476   ^bb0(%xval: i32):
1477     %newval = llvm.add %xval, %expr : i32
1478     omp.yield(%newval : i32)
1479   }
1480   llvm.return
1483 // -----
1485 //CHECK: %[[X_NEW_VAL:.*]] = alloca { float, float }, align 8
1486 //CHECK: {{.*}} = alloca { float, float }, i64 1, align 8
1487 //CHECK: %[[ORIG_VAL:.*]] = alloca { float, float }, i64 1, align 8
1489 //CHECK: br label %entry
1491 //CHECK: entry:
1492 //CHECK: %[[ATOMIC_TEMP_LOAD:.*]] = alloca { float, float }, align 8
1493 //CHECK: call void @__atomic_load(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], i32 0)
1494 //CHECK: %[[PHI_NODE_ENTRY_1:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 8
1495 //CHECK: br label %.atomic.cont
1497 //CHECK: .atomic.cont
1498 //CHECK: %[[VAL_4:.*]] = phi { float, float } [ %[[PHI_NODE_ENTRY_1]], %entry ], [ %{{.*}}, %.atomic.cont ]
1499 //CHECK: %[[VAL_5:.*]] = extractvalue { float, float } %[[VAL_4]], 0
1500 //CHECK: %[[VAL_6:.*]] = extractvalue { float, float } %[[VAL_4]], 1
1501 //CHECK: %[[VAL_7:.*]] = fadd contract float %[[VAL_5]], 1.000000e+00
1502 //CHECK: %[[VAL_8:.*]] = fadd contract float %[[VAL_6]], 1.000000e+00
1503 //CHECK: %[[VAL_9:.*]] = insertvalue { float, float } undef, float %[[VAL_7]], 0
1504 //CHECK: %[[VAL_10:.*]] = insertvalue { float, float } %[[VAL_9]], float %[[VAL_8]], 1
1505 //CHECK: store { float, float } %[[VAL_10]], ptr %[[X_NEW_VAL]], align 4
1506 //CHECK: %[[VAL_11:.*]] = call i1 @__atomic_compare_exchange(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], ptr %[[X_NEW_VAL]], i32 2, i32 2)
1507 //CHECK: %[[VAL_12:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 4
1508 //CHECK: br i1 %[[VAL_11]], label %.atomic.exit, label %.atomic.cont
1510 llvm.func @_QPomp_atomic_update_complex() {
1511     %0 = llvm.mlir.constant(1 : i64) : i64
1512     %1 = llvm.alloca %0 x !llvm.struct<(f32, f32)> {bindc_name = "ib"} : (i64) -> !llvm.ptr
1513     %2 = llvm.mlir.constant(1 : i64) : i64
1514     %3 = llvm.alloca %2 x !llvm.struct<(f32, f32)> {bindc_name = "ia"} : (i64) -> !llvm.ptr
1515     %4 = llvm.mlir.constant(1.000000e+00 : f32) : f32
1516     %5 = llvm.mlir.undef : !llvm.struct<(f32, f32)>
1517     %6 = llvm.insertvalue %4, %5[0] : !llvm.struct<(f32, f32)>
1518     %7 = llvm.insertvalue %4, %6[1] : !llvm.struct<(f32, f32)>
1519     omp.atomic.update %3 : !llvm.ptr {
1520     ^bb0(%arg0: !llvm.struct<(f32, f32)>):
1521       %8 = llvm.extractvalue %arg0[0] : !llvm.struct<(f32, f32)>
1522       %9 = llvm.extractvalue %arg0[1] : !llvm.struct<(f32, f32)>
1523       %10 = llvm.extractvalue %7[0] : !llvm.struct<(f32, f32)>
1524       %11 = llvm.extractvalue %7[1] : !llvm.struct<(f32, f32)>
1525       %12 = llvm.fadd %8, %10  {fastmathFlags = #llvm.fastmath<contract>} : f32
1526       %13 = llvm.fadd %9, %11  {fastmathFlags = #llvm.fastmath<contract>} : f32
1527       %14 = llvm.mlir.undef : !llvm.struct<(f32, f32)>
1528       %15 = llvm.insertvalue %12, %14[0] : !llvm.struct<(f32, f32)>
1529       %16 = llvm.insertvalue %13, %15[1] : !llvm.struct<(f32, f32)>
1530       omp.yield(%16 : !llvm.struct<(f32, f32)>)
1531     }
1532    llvm.return
1535 // -----
1537 //CHECK: %[[X_NEW_VAL:.*]] = alloca { float, float }, align 8
1538 //CHECK: %[[VAL_1:.*]] = alloca { float, float }, i64 1, align 8
1539 //CHECK: %[[ORIG_VAL:.*]] = alloca { float, float }, i64 1, align 8
1540 //CHECK: store { float, float } { float 2.000000e+00, float 2.000000e+00 }, ptr %[[ORIG_VAL]], align 4
1541 //CHECK: br label %entry
1543 //CHECK: entry:                                                 ; preds = %0
1544 //CHECK: %[[ATOMIC_TEMP_LOAD:.*]] = alloca { float, float }, align 8
1545 //CHECK: call void @__atomic_load(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], i32 0)
1546 //CHECK: %[[PHI_NODE_ENTRY_1:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 8
1547 //CHECK: br label %.atomic.cont
1549 //CHECK: .atomic.cont
1550 //CHECK: %[[VAL_4:.*]] = phi { float, float } [ %[[PHI_NODE_ENTRY_1]], %entry ], [ %{{.*}}, %.atomic.cont ]
1551 //CHECK: %[[VAL_5:.*]] = extractvalue { float, float } %[[VAL_4]], 0
1552 //CHECK: %[[VAL_6:.*]] = extractvalue { float, float } %[[VAL_4]], 1
1553 //CHECK: %[[VAL_7:.*]] = fadd contract float %[[VAL_5]], 1.000000e+00
1554 //CHECK: %[[VAL_8:.*]] = fadd contract float %[[VAL_6]], 1.000000e+00
1555 //CHECK: %[[VAL_9:.*]] = insertvalue { float, float } undef, float %[[VAL_7]], 0
1556 //CHECK: %[[VAL_10:.*]] = insertvalue { float, float } %[[VAL_9]], float %[[VAL_8]], 1
1557 //CHECK: store { float, float } %[[VAL_10]], ptr %[[X_NEW_VAL]], align 4 
1558 //CHECK: %[[VAL_11:.*]] = call i1 @__atomic_compare_exchange(i64 8, ptr %[[ORIG_VAL]], ptr %[[ATOMIC_TEMP_LOAD]], ptr %[[X_NEW_VAL]], i32 2, i32 2)
1559 //CHECK: %[[VAL_12:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 4
1560 //CHECK: br i1 %[[VAL_11]], label %.atomic.exit, label %.atomic.cont
1561 //CHECK: .atomic.exit
1562 //CHECK: store { float, float } %[[VAL_10]], ptr %[[VAL_1]], align 4
1564 llvm.func @_QPomp_atomic_capture_complex() {
1565     %0 = llvm.mlir.constant(1 : i64) : i64
1566     %1 = llvm.alloca %0 x !llvm.struct<(f32, f32)> {bindc_name = "ib"} : (i64) -> !llvm.ptr
1567     %2 = llvm.mlir.constant(1 : i64) : i64
1568     %3 = llvm.alloca %2 x !llvm.struct<(f32, f32)> {bindc_name = "ia"} : (i64) -> !llvm.ptr
1569     %4 = llvm.mlir.constant(1.000000e+00 : f32) : f32
1570     %5 = llvm.mlir.constant(2.000000e+00 : f32) : f32
1571     %6 = llvm.mlir.undef : !llvm.struct<(f32, f32)>
1572     %7 = llvm.insertvalue %5, %6[0] : !llvm.struct<(f32, f32)>
1573     %8 = llvm.insertvalue %5, %7[1] : !llvm.struct<(f32, f32)>
1574     llvm.store %8, %3 : !llvm.struct<(f32, f32)>, !llvm.ptr
1575     %9 = llvm.mlir.undef : !llvm.struct<(f32, f32)>
1576     %10 = llvm.insertvalue %4, %9[0] : !llvm.struct<(f32, f32)>
1577     %11 = llvm.insertvalue %4, %10[1] : !llvm.struct<(f32, f32)>
1578     omp.atomic.capture {
1579       omp.atomic.update %3 : !llvm.ptr {
1580       ^bb0(%arg0: !llvm.struct<(f32, f32)>):
1581         %12 = llvm.extractvalue %arg0[0] : !llvm.struct<(f32, f32)>
1582         %13 = llvm.extractvalue %arg0[1] : !llvm.struct<(f32, f32)>
1583         %14 = llvm.extractvalue %11[0] : !llvm.struct<(f32, f32)>
1584         %15 = llvm.extractvalue %11[1] : !llvm.struct<(f32, f32)>
1585         %16 = llvm.fadd %12, %14  {fastmathFlags = #llvm.fastmath<contract>} : f32
1586         %17 = llvm.fadd %13, %15  {fastmathFlags = #llvm.fastmath<contract>} : f32
1587         %18 = llvm.mlir.undef : !llvm.struct<(f32, f32)>
1588         %19 = llvm.insertvalue %16, %18[0] : !llvm.struct<(f32, f32)>
1589         %20 = llvm.insertvalue %17, %19[1] : !llvm.struct<(f32, f32)>
1590         omp.yield(%20 : !llvm.struct<(f32, f32)>)
1591       }
1592       omp.atomic.read %1 = %3 : !llvm.ptr, !llvm.ptr, !llvm.struct<(f32, f32)>
1593     }
1594     llvm.return
1597 // -----
1599 // CHECK-LABEL: define void @omp_atomic_read_complex() {
1600 llvm.func @omp_atomic_read_complex(){
1602 // CHECK: %[[a:.*]] = alloca { float, float }, i64 1, align 8
1603 // CHECK: %[[b:.*]] = alloca { float, float }, i64 1, align 8
1604 // CHECK: %[[ATOMIC_TEMP_LOAD:.*]] = alloca { float, float }, align 8
1605 // CHECK: call void @__atomic_load(i64 8, ptr %[[b]], ptr %[[ATOMIC_TEMP_LOAD]], i32 0)
1606 // CHECK: %[[LOADED_VAL:.*]] = load { float, float }, ptr %[[ATOMIC_TEMP_LOAD]], align 8
1607 // CHECK: store { float, float } %[[LOADED_VAL]], ptr %[[a]], align 4
1608 // CHECK: ret void
1609 // CHECK: }
1611     %0 = llvm.mlir.constant(1 : i64) : i64
1612     %1 = llvm.alloca %0 x !llvm.struct<(f32, f32)> {bindc_name = "ib"} : (i64) -> !llvm.ptr
1613     %2 = llvm.mlir.constant(1 : i64) : i64
1614     %3 = llvm.alloca %2 x !llvm.struct<(f32, f32)> {bindc_name = "ia"} : (i64) -> !llvm.ptr
1615     omp.atomic.read %1 = %3 : !llvm.ptr, !llvm.ptr, !llvm.struct<(f32, f32)>
1616     llvm.return
1619 // -----
1621 // Checking an order-dependent operation when the order is `expr binop x`
1622 // CHECK-LABEL: @omp_atomic_update_ordering
1623 // CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]])
1624 llvm.func @omp_atomic_update_ordering(%x:!llvm.ptr, %expr: i32) {
1625   // CHECK: %[[t1:.*]] = shl i32 %[[expr]], %[[x_old:[^ ,]*]]
1626   // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]
1627   // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]
1628   // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]]
1629   omp.atomic.update %x : !llvm.ptr {
1630   ^bb0(%xval: i32):
1631     %newval = llvm.shl %expr, %xval : i32
1632     omp.yield(%newval : i32)
1633   }
1634   llvm.return
1637 // -----
1639 // Checking an order-dependent operation when the order is `x binop expr`
1640 // CHECK-LABEL: @omp_atomic_update_ordering
1641 // CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]])
1642 llvm.func @omp_atomic_update_ordering(%x:!llvm.ptr, %expr: i32) {
1643   // CHECK: %[[t1:.*]] = shl i32 %[[x_old:.*]], %[[expr]]
1644   // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]
1645   // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]
1646   // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]] monotonic
1647   omp.atomic.update %x : !llvm.ptr {
1648   ^bb0(%xval: i32):
1649     %newval = llvm.shl %xval, %expr : i32
1650     omp.yield(%newval : i32)
1651   }
1652   llvm.return
1655 // -----
1657 // Checking intrinsic translation.
1658 // CHECK-LABEL: @omp_atomic_update_intrinsic
1659 // CHECK-SAME: (ptr %[[x:.*]], i32 %[[expr:.*]])
1660 llvm.func @omp_atomic_update_intrinsic(%x:!llvm.ptr, %expr: i32) {
1661   // CHECK: %[[t1:.*]] = call i32 @llvm.smax.i32(i32 %[[x_old:.*]], i32 %[[expr]])
1662   // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]
1663   // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]
1664   // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]]
1665   omp.atomic.update %x : !llvm.ptr {
1666   ^bb0(%xval: i32):
1667     %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i32
1668     omp.yield(%newval : i32)
1669   }
1670   // CHECK: %[[t1:.*]] = call i32 @llvm.umax.i32(i32 %[[x_old:.*]], i32 %[[expr]])
1671   // CHECK: store i32 %[[t1]], ptr %[[x_new:.*]]
1672   // CHECK: %[[t2:.*]] = load i32, ptr %[[x_new]]
1673   // CHECK: cmpxchg ptr %[[x]], i32 %[[x_old]], i32 %[[t2]]
1674   omp.atomic.update %x : !llvm.ptr {
1675   ^bb0(%xval: i32):
1676     %newval = "llvm.intr.umax"(%xval, %expr) : (i32, i32) -> i32
1677     omp.yield(%newval : i32)
1678   }
1679   llvm.return
1682 // -----
1684 // CHECK-LABEL: @atomic_update_cmpxchg
1685 // CHECK-SAME: (ptr %[[X:.*]], ptr %[[EXPR:.*]]) {
1686 // CHECK:  %[[AT_LOAD_VAL:.*]] = load atomic i32, ptr %[[X]] monotonic, align 4
1687 // CHECK:  %[[LOAD_VAL_PHI:.*]] = phi i32 [ %[[AT_LOAD_VAL]], %entry ], [ %[[LOAD_VAL:.*]], %.atomic.cont ]
1688 // CHECK:  %[[VAL_SUCCESS:.*]] = cmpxchg ptr %[[X]], i32 %[[LOAD_VAL_PHI]], i32 %{{.*}} monotonic monotonic, align 4
1689 // CHECK:  %[[LOAD_VAL]] = extractvalue { i32, i1 } %[[VAL_SUCCESS]], 0
1690 // CHECK:  br i1 %{{.*}}, label %.atomic.exit, label %.atomic.cont
1692 llvm.func @atomic_update_cmpxchg(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {
1693   %0 = llvm.load %arg1 : !llvm.ptr -> f32
1694   omp.atomic.update %arg0 : !llvm.ptr {
1695   ^bb0(%arg2: i32):
1696     %1 = llvm.sitofp %arg2 : i32 to f32
1697     %2 = llvm.fadd %1, %0 : f32
1698     %3 = llvm.fptosi %2 : f32 to i32
1699     omp.yield(%3 : i32)
1700   }
1701   llvm.return
1704 // -----
1706 // CHECK-LABEL: @omp_atomic_capture_prefix_update
1707 // CHECK-SAME: (ptr %[[x:.*]], ptr %[[v:.*]], i32 %[[expr:.*]], ptr %[[xf:.*]], ptr %[[vf:.*]], float %[[exprf:.*]])
1708 llvm.func @omp_atomic_capture_prefix_update(
1709   %x: !llvm.ptr, %v: !llvm.ptr, %expr: i32,
1710   %xf: !llvm.ptr, %vf: !llvm.ptr, %exprf: f32) -> () {
1711   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic
1712   // CHECK-NEXT: %[[newval:.*]] = add i32 %[[res]], %[[expr]]
1713   // CHECK: store i32 %[[newval]], ptr %[[v]]
1714   omp.atomic.capture {
1715     omp.atomic.update %x : !llvm.ptr {
1716     ^bb0(%xval: i32):
1717       %newval = llvm.add %xval, %expr : i32
1718       omp.yield(%newval : i32)
1719     }
1720     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1721   }
1723   // CHECK: %[[res:.*]] = atomicrmw sub ptr %[[x]], i32 %[[expr]] monotonic
1724   // CHECK-NEXT: %[[newval:.*]] = sub i32 %[[res]], %[[expr]]
1725   // CHECK: store i32 %[[newval]], ptr %[[v]]
1726   omp.atomic.capture {
1727     omp.atomic.update %x : !llvm.ptr {
1728     ^bb0(%xval: i32):
1729       %newval = llvm.sub %xval, %expr : i32
1730       omp.yield(%newval : i32)
1731     }
1732     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1733   }
1735   // CHECK: %[[res:.*]] = atomicrmw and ptr %[[x]], i32 %[[expr]] monotonic
1736   // CHECK-NEXT: %[[newval:.*]] = and i32 %[[res]], %[[expr]]
1737   // CHECK: store i32 %[[newval]], ptr %[[v]]
1738   omp.atomic.capture {
1739     omp.atomic.update %x : !llvm.ptr {
1740     ^bb0(%xval: i32):
1741       %newval = llvm.and %xval, %expr : i32
1742       omp.yield(%newval : i32)
1743     }
1744     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1745   }
1747   // CHECK: %[[res:.*]] = atomicrmw or ptr %[[x]], i32 %[[expr]] monotonic
1748   // CHECK-NEXT: %[[newval:.*]] = or i32 %[[res]], %[[expr]]
1749   // CHECK: store i32 %[[newval]], ptr %[[v]]
1750   omp.atomic.capture {
1751     omp.atomic.update %x : !llvm.ptr {
1752     ^bb0(%xval: i32):
1753       %newval = llvm.or %xval, %expr : i32
1754       omp.yield(%newval : i32)
1755     }
1756     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1757   }
1759   // CHECK: %[[res:.*]] = atomicrmw xor ptr %[[x]], i32 %[[expr]] monotonic
1760   // CHECK-NEXT: %[[newval:.*]] = xor i32 %[[res]], %[[expr]]
1761   // CHECK: store i32 %[[newval]], ptr %[[v]]
1762   omp.atomic.capture {
1763     omp.atomic.update %x : !llvm.ptr {
1764     ^bb0(%xval: i32):
1765       %newval = llvm.xor %xval, %expr : i32
1766       omp.yield(%newval : i32)
1767     }
1768     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1769   }
1771   // CHECK: %[[xval:.*]] = phi i32
1772   // CHECK-NEXT: %[[newval:.*]] = mul i32 %[[xval]], %[[expr]]
1773   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1774   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1775   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1776   // CHECK: store i32 %[[newval]], ptr %[[v]]
1777   omp.atomic.capture {
1778     omp.atomic.update %x : !llvm.ptr {
1779     ^bb0(%xval: i32):
1780       %newval = llvm.mul %xval, %expr : i32
1781       omp.yield(%newval : i32)
1782     }
1783     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1784   }
1786   // CHECK: %[[xval:.*]] = phi i32
1787   // CHECK-NEXT: %[[newval:.*]] = sdiv i32 %[[xval]], %[[expr]]
1788   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1789   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1790   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1791   // CHECK: store i32 %[[newval]], ptr %[[v]]
1792   omp.atomic.capture {
1793     omp.atomic.update %x : !llvm.ptr {
1794     ^bb0(%xval: i32):
1795       %newval = llvm.sdiv %xval, %expr : i32
1796       omp.yield(%newval : i32)
1797     }
1798     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1799   }
1801   // CHECK: %[[xval:.*]] = phi i32
1802   // CHECK-NEXT: %[[newval:.*]] = udiv i32 %[[xval]], %[[expr]]
1803   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1804   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1805   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1806   // CHECK: store i32 %[[newval]], ptr %[[v]]
1807   omp.atomic.capture {
1808     omp.atomic.update %x : !llvm.ptr {
1809     ^bb0(%xval: i32):
1810       %newval = llvm.udiv %xval, %expr : i32
1811       omp.yield(%newval : i32)
1812     }
1813     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1814   }
1816   // CHECK: %[[xval:.*]] = phi i32
1817   // CHECK-NEXT: %[[newval:.*]] = shl i32 %[[xval]], %[[expr]]
1818   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1819   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1820   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1821   // CHECK: store i32 %[[newval]], ptr %[[v]]
1822   omp.atomic.capture {
1823     omp.atomic.update %x : !llvm.ptr {
1824     ^bb0(%xval: i32):
1825       %newval = llvm.shl %xval, %expr : i32
1826       omp.yield(%newval : i32)
1827     }
1828     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1829   }
1831   // CHECK: %[[xval:.*]] = phi i32
1832   // CHECK-NEXT: %[[newval:.*]] = lshr i32 %[[xval]], %[[expr]]
1833   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1834   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1835   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1836   // CHECK: store i32 %[[newval]], ptr %[[v]]
1837   omp.atomic.capture {
1838     omp.atomic.update %x : !llvm.ptr {
1839     ^bb0(%xval: i32):
1840       %newval = llvm.lshr %xval, %expr : i32
1841       omp.yield(%newval : i32)
1842     }
1843     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1844   }
1846   // CHECK: %[[xval:.*]] = phi i32
1847   // CHECK-NEXT: %[[newval:.*]] = ashr i32 %[[xval]], %[[expr]]
1848   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1849   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1850   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1851   // CHECK: store i32 %[[newval]], ptr %[[v]]
1852   omp.atomic.capture {
1853     omp.atomic.update %x : !llvm.ptr {
1854     ^bb0(%xval: i32):
1855       %newval = llvm.ashr %xval, %expr : i32
1856       omp.yield(%newval : i32)
1857     }
1858     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1859   }
1861   // CHECK: %[[xval:.*]] = phi i32
1862   // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.smax.i32(i32 %[[xval]], i32 %[[expr]])
1863   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1864   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1865   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1866   // CHECK: store i32 %[[newval]], ptr %[[v]]
1867   omp.atomic.capture {
1868     omp.atomic.update %x : !llvm.ptr {
1869     ^bb0(%xval: i32):
1870       %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i32
1871       omp.yield(%newval : i32)
1872     }
1873     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1874   }
1876   // CHECK: %[[xval:.*]] = phi i32
1877   // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.smin.i32(i32 %[[xval]], i32 %[[expr]])
1878   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1879   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1880   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1881   // CHECK: store i32 %[[newval]], ptr %[[v]]
1882   omp.atomic.capture {
1883     omp.atomic.update %x : !llvm.ptr {
1884     ^bb0(%xval: i32):
1885       %newval = "llvm.intr.smin"(%xval, %expr) : (i32, i32) -> i32
1886       omp.yield(%newval : i32)
1887     }
1888     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1889   }
1891   // CHECK: %[[xval:.*]] = phi i32
1892   // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.umax.i32(i32 %[[xval]], i32 %[[expr]])
1893   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1894   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1895   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1896   // CHECK: store i32 %[[newval]], ptr %[[v]]
1897   omp.atomic.capture {
1898     omp.atomic.update %x : !llvm.ptr {
1899     ^bb0(%xval: i32):
1900       %newval = "llvm.intr.umax"(%xval, %expr) : (i32, i32) -> i32
1901       omp.yield(%newval : i32)
1902     }
1903     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1904   }
1906   // CHECK: %[[xval:.*]] = phi i32
1907   // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.umin.i32(i32 %[[xval]], i32 %[[expr]])
1908   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
1909   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
1910   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1911   // CHECK: store i32 %[[newval]], ptr %[[v]]
1912   omp.atomic.capture {
1913     omp.atomic.update %x : !llvm.ptr {
1914     ^bb0(%xval: i32):
1915       %newval = "llvm.intr.umin"(%xval, %expr) : (i32, i32) -> i32
1916       omp.yield(%newval : i32)
1917     }
1918     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1919   }
1921   // CHECK: %[[xval:.*]] = phi i32
1922   // CHECK: %[[newval:.*]] = fadd float %{{.*}}, %[[exprf]]
1923   // CHECK: store float %[[newval]], ptr %{{.*}}
1924   // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}
1925   // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1926   // CHECK: store float %[[newval]], ptr %[[vf]]
1927   omp.atomic.capture {
1928     omp.atomic.update %xf : !llvm.ptr {
1929     ^bb0(%xval: f32):
1930       %newval = llvm.fadd %xval, %exprf : f32
1931       omp.yield(%newval : f32)
1932     }
1933     omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f32
1934   }
1936   // CHECK: %[[xval:.*]] = phi i32
1937   // CHECK: %[[newval:.*]] = fsub float %{{.*}}, %[[exprf]]
1938   // CHECK: store float %[[newval]], ptr %{{.*}}
1939   // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}
1940   // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
1941   // CHECK: store float %[[newval]], ptr %[[vf]]
1942   omp.atomic.capture {
1943     omp.atomic.update %xf : !llvm.ptr {
1944     ^bb0(%xval: f32):
1945       %newval = llvm.fsub %xval, %exprf : f32
1946       omp.yield(%newval : f32)
1947     }
1948     omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f32
1949   }
1951   llvm.return
1954 // -----
1956 // CHECK-LABEL: @omp_atomic_capture_postfix_update
1957 // CHECK-SAME: (ptr %[[x:.*]], ptr %[[v:.*]], i32 %[[expr:.*]], ptr %[[xf:.*]], ptr %[[vf:.*]], float %[[exprf:.*]])
1958 llvm.func @omp_atomic_capture_postfix_update(
1959   %x: !llvm.ptr, %v: !llvm.ptr, %expr: i32,
1960   %xf: !llvm.ptr, %vf: !llvm.ptr, %exprf: f32) -> () {
1961   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic
1962   // CHECK: store i32 %[[res]], ptr %[[v]]
1963   omp.atomic.capture {
1964     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1965     omp.atomic.update %x : !llvm.ptr {
1966     ^bb0(%xval: i32):
1967       %newval = llvm.add %xval, %expr : i32
1968       omp.yield(%newval : i32)
1969     }
1970   }
1972   // CHECK: %[[res:.*]] = atomicrmw sub ptr %[[x]], i32 %[[expr]] monotonic
1973   // CHECK: store i32 %[[res]], ptr %[[v]]
1974   omp.atomic.capture {
1975     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1976     omp.atomic.update %x : !llvm.ptr {
1977     ^bb0(%xval: i32):
1978       %newval = llvm.sub %xval, %expr : i32
1979       omp.yield(%newval : i32)
1980     }
1981   }
1983   // CHECK: %[[res:.*]] = atomicrmw and ptr %[[x]], i32 %[[expr]] monotonic
1984   // CHECK: store i32 %[[res]], ptr %[[v]]
1985   omp.atomic.capture {
1986     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1987     omp.atomic.update %x : !llvm.ptr {
1988     ^bb0(%xval: i32):
1989       %newval = llvm.and %xval, %expr : i32
1990       omp.yield(%newval : i32)
1991     }
1992   }
1994   // CHECK: %[[res:.*]] = atomicrmw or ptr %[[x]], i32 %[[expr]] monotonic
1995   // CHECK: store i32 %[[res]], ptr %[[v]]
1996   omp.atomic.capture {
1997     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
1998     omp.atomic.update %x : !llvm.ptr {
1999     ^bb0(%xval: i32):
2000       %newval = llvm.or %xval, %expr : i32
2001       omp.yield(%newval : i32)
2002     }
2003   }
2005   // CHECK: %[[res:.*]] = atomicrmw xor ptr %[[x]], i32 %[[expr]] monotonic
2006   // CHECK: store i32 %[[res]], ptr %[[v]]
2007   omp.atomic.capture {
2008     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2009     omp.atomic.update %x : !llvm.ptr {
2010     ^bb0(%xval: i32):
2011       %newval = llvm.xor %xval, %expr : i32
2012       omp.yield(%newval : i32)
2013     }
2014   }
2016   // CHECK: %[[xval:.*]] = phi i32
2017   // CHECK-NEXT: %[[newval:.*]] = mul i32 %[[xval]], %[[expr]]
2018   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2019   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2020   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2021   // CHECK: store i32 %[[xval]], ptr %[[v]]
2022   omp.atomic.capture {
2023     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2024     omp.atomic.update %x : !llvm.ptr {
2025     ^bb0(%xval: i32):
2026       %newval = llvm.mul %xval, %expr : i32
2027       omp.yield(%newval : i32)
2028     }
2029   }
2031   // CHECK: %[[xval:.*]] = phi i32
2032   // CHECK-NEXT: %[[newval:.*]] = sdiv i32 %[[xval]], %[[expr]]
2033   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2034   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2035   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2036   // CHECK: store i32 %[[xval]], ptr %[[v]]
2037   omp.atomic.capture {
2038     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2039     omp.atomic.update %x : !llvm.ptr {
2040     ^bb0(%xval: i32):
2041       %newval = llvm.sdiv %xval, %expr : i32
2042       omp.yield(%newval : i32)
2043     }
2044   }
2046   // CHECK: %[[xval:.*]] = phi i32
2047   // CHECK-NEXT: %[[newval:.*]] = udiv i32 %[[xval]], %[[expr]]
2048   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2049   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2050   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2051   // CHECK: store i32 %[[xval]], ptr %[[v]]
2052   omp.atomic.capture {
2053     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2054     omp.atomic.update %x : !llvm.ptr {
2055     ^bb0(%xval: i32):
2056       %newval = llvm.udiv %xval, %expr : i32
2057       omp.yield(%newval : i32)
2058     }
2059   }
2061   // CHECK: %[[xval:.*]] = phi i32
2062   // CHECK-NEXT: %[[newval:.*]] = shl i32 %[[xval]], %[[expr]]
2063   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2064   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2065   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2066   // CHECK: store i32 %[[xval]], ptr %[[v]]
2067   omp.atomic.capture {
2068     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2069     omp.atomic.update %x : !llvm.ptr {
2070     ^bb0(%xval: i32):
2071       %newval = llvm.shl %xval, %expr : i32
2072       omp.yield(%newval : i32)
2073     }
2074   }
2076   // CHECK: %[[xval:.*]] = phi i32
2077   // CHECK-NEXT: %[[newval:.*]] = lshr i32 %[[xval]], %[[expr]]
2078   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2079   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2080   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2081   // CHECK: store i32 %[[xval]], ptr %[[v]]
2082   omp.atomic.capture {
2083     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2084     omp.atomic.update %x : !llvm.ptr {
2085     ^bb0(%xval: i32):
2086       %newval = llvm.lshr %xval, %expr : i32
2087       omp.yield(%newval : i32)
2088     }
2089   }
2091   // CHECK: %[[xval:.*]] = phi i32
2092   // CHECK-NEXT: %[[newval:.*]] = ashr i32 %[[xval]], %[[expr]]
2093   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2094   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2095   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2096   // CHECK: store i32 %[[xval]], ptr %[[v]]
2097   omp.atomic.capture {
2098     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2099     omp.atomic.update %x : !llvm.ptr {
2100     ^bb0(%xval: i32):
2101       %newval = llvm.ashr %xval, %expr : i32
2102       omp.yield(%newval : i32)
2103     }
2104   }
2106   // CHECK: %[[xval:.*]] = phi i32
2107   // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.smax.i32(i32 %[[xval]], i32 %[[expr]])
2108   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2109   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2110   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2111   // CHECK: store i32 %[[xval]], ptr %[[v]]
2112   omp.atomic.capture {
2113     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2114     omp.atomic.update %x : !llvm.ptr {
2115     ^bb0(%xval: i32):
2116       %newval = "llvm.intr.smax"(%xval, %expr) : (i32, i32) -> i32
2117       omp.yield(%newval : i32)
2118     }
2119   }
2121   // CHECK: %[[xval:.*]] = phi i32
2122   // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.smin.i32(i32 %[[xval]], i32 %[[expr]])
2123   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2124   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2125   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2126   // CHECK: store i32 %[[xval]], ptr %[[v]]
2127   omp.atomic.capture {
2128     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2129     omp.atomic.update %x : !llvm.ptr {
2130     ^bb0(%xval: i32):
2131       %newval = "llvm.intr.smin"(%xval, %expr) : (i32, i32) -> i32
2132       omp.yield(%newval : i32)
2133     }
2134   }
2136   // CHECK: %[[xval:.*]] = phi i32
2137   // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.umax.i32(i32 %[[xval]], i32 %[[expr]])
2138   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2139   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2140   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2141   // CHECK: store i32 %[[xval]], ptr %[[v]]
2142   omp.atomic.capture {
2143     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2144     omp.atomic.update %x : !llvm.ptr {
2145     ^bb0(%xval: i32):
2146       %newval = "llvm.intr.umax"(%xval, %expr) : (i32, i32) -> i32
2147       omp.yield(%newval : i32)
2148     }
2149   }
2151   // CHECK: %[[xval:.*]] = phi i32
2152   // CHECK-NEXT: %[[newval:.*]] = call i32 @llvm.umin.i32(i32 %[[xval]], i32 %[[expr]])
2153   // CHECK-NEXT: store i32 %[[newval]], ptr %{{.*}}
2154   // CHECK-NEXT: %[[newval_:.*]] = load i32, ptr %{{.*}}
2155   // CHECK-NEXT: %{{.*}} = cmpxchg ptr %[[x]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2156   // CHECK: store i32 %[[xval]], ptr %[[v]]
2157   omp.atomic.capture {
2158     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2159     omp.atomic.update %x : !llvm.ptr {
2160     ^bb0(%xval: i32):
2161       %newval = "llvm.intr.umin"(%xval, %expr) : (i32, i32) -> i32
2162       omp.yield(%newval : i32)
2163     }
2164   }
2166   // CHECK: %[[xval:.*]] = phi i32
2167   // CHECK: %[[xvalf:.*]] = bitcast i32 %[[xval]] to float
2168   // CHECK: %[[newval:.*]] = fadd float %{{.*}}, %[[exprf]]
2169   // CHECK: store float %[[newval]], ptr %{{.*}}
2170   // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}
2171   // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2172   // CHECK: store float %[[xvalf]], ptr %[[vf]]
2173   omp.atomic.capture {
2174     omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f32
2175     omp.atomic.update %xf : !llvm.ptr {
2176     ^bb0(%xval: f32):
2177       %newval = llvm.fadd %xval, %exprf : f32
2178       omp.yield(%newval : f32)
2179     }
2180   }
2182   // CHECK: %[[xval:.*]] = phi i32
2183   // CHECK: %[[xvalf:.*]] = bitcast i32 %[[xval]] to float
2184   // CHECK: %[[newval:.*]] = fsub float %{{.*}}, %[[exprf]]
2185   // CHECK: store float %[[newval]], ptr %{{.*}}
2186   // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}
2187   // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2188   // CHECK: store float %[[xvalf]], ptr %[[vf]]
2189   omp.atomic.capture {
2190     omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f32
2191     omp.atomic.update %xf : !llvm.ptr {
2192     ^bb0(%xval: f32):
2193       %newval = llvm.fsub %xval, %exprf : f32
2194       omp.yield(%newval : f32)
2195     }
2196   }
2198   llvm.return
2201 // -----
2202 // CHECK-LABEL: @omp_atomic_capture_misc
2203 // CHECK-SAME: (ptr %[[x:.*]], ptr %[[v:.*]], i32 %[[expr:.*]], ptr %[[xf:.*]], ptr %[[vf:.*]], float %[[exprf:.*]])
2204 llvm.func @omp_atomic_capture_misc(
2205   %x: !llvm.ptr, %v: !llvm.ptr, %expr: i32,
2206   %xf: !llvm.ptr, %vf: !llvm.ptr, %exprf: f32) -> () {
2207   // CHECK: %[[xval:.*]] = atomicrmw xchg ptr %[[x]], i32 %[[expr]] monotonic
2208   // CHECK: store i32 %[[xval]], ptr %[[v]]
2209   omp.atomic.capture{
2210     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2211     omp.atomic.write %x = %expr : !llvm.ptr, i32
2212   }
2214   // CHECK: %[[xval:.*]] = phi i32
2215   // CHECK: %[[xvalf:.*]] = bitcast i32 %[[xval]] to float
2216   // CHECK: store float %[[exprf]], ptr %{{.*}}
2217   // CHECK: %[[newval_:.*]] = load i32, ptr %{{.*}}
2218   // CHECK: %{{.*}} = cmpxchg ptr %[[xf]], i32 %[[xval]], i32 %[[newval_]] monotonic monotonic
2219   // CHECK: store float %[[xvalf]], ptr %[[vf]]
2220   omp.atomic.capture{
2221     omp.atomic.read %vf = %xf : !llvm.ptr, !llvm.ptr, f32
2222     omp.atomic.write %xf = %exprf : !llvm.ptr, f32
2223   }
2225   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] seq_cst
2226   // CHECK: store i32 %[[res]], ptr %[[v]]
2227   omp.atomic.capture memory_order(seq_cst) {
2228     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2229     omp.atomic.update %x : !llvm.ptr {
2230     ^bb0(%xval: i32):
2231       %newval = llvm.add %xval, %expr : i32
2232       omp.yield(%newval : i32)
2233     }
2234   }
2236   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] acquire
2237   // CHECK: store i32 %[[res]], ptr %[[v]]
2238   omp.atomic.capture memory_order(acquire) {
2239     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2240     omp.atomic.update %x : !llvm.ptr {
2241     ^bb0(%xval: i32):
2242       %newval = llvm.add %xval, %expr : i32
2243       omp.yield(%newval : i32)
2244     }
2245   }
2247   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] release
2248   // CHECK: store i32 %[[res]], ptr %[[v]]
2249   omp.atomic.capture memory_order(release) {
2250     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2251     omp.atomic.update %x : !llvm.ptr {
2252     ^bb0(%xval: i32):
2253       %newval = llvm.add %xval, %expr : i32
2254       omp.yield(%newval : i32)
2255     }
2256   }
2258   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] monotonic
2259   // CHECK: store i32 %[[res]], ptr %[[v]]
2260   omp.atomic.capture memory_order(relaxed) {
2261     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2262     omp.atomic.update %x : !llvm.ptr {
2263     ^bb0(%xval: i32):
2264       %newval = llvm.add %xval, %expr : i32
2265       omp.yield(%newval : i32)
2266     }
2267   }
2269   // CHECK: %[[res:.*]] = atomicrmw add ptr %[[x]], i32 %[[expr]] acq_rel
2270   // CHECK: store i32 %[[res]], ptr %[[v]]
2271   omp.atomic.capture memory_order(acq_rel) {
2272     omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2273     omp.atomic.update %x : !llvm.ptr {
2274     ^bb0(%xval: i32):
2275       %newval = llvm.add %xval, %expr : i32
2276       omp.yield(%newval : i32)
2277     }
2278   }
2280   llvm.return
2283 // -----
2285 // CHECK-LABEL: @omp_sections_empty
2286 llvm.func @omp_sections_empty() -> () {
2287   omp.sections {
2288     omp.terminator
2289   }
2290   // CHECK-NEXT: br label %entry
2291   // CHECK: entry:
2292   // CHECK-NEXT: ret void
2293   llvm.return
2296 // -----
2298 // Check IR generation for simple empty sections. This only checks the overall
2299 // shape of the IR, detailed checking is done by the OpenMPIRBuilder.
2301 // CHECK-LABEL: @omp_sections_trivial
2302 llvm.func @omp_sections_trivial() -> () {
2303   // CHECK:   br label %[[ENTRY:[a-zA-Z_.]+]]
2305   // CHECK: [[ENTRY]]:
2306   // CHECK:   br label %[[PREHEADER:.*]]
2308   // CHECK: [[PREHEADER]]:
2309   // CHECK:   %{{.*}} = call i32 @__kmpc_global_thread_num({{.*}})
2310   // CHECK:   call void @__kmpc_for_static_init_4u({{.*}})
2311   // CHECK:   br label %[[HEADER:.*]]
2313   // CHECK: [[HEADER]]:
2314   // CHECK:   br label %[[COND:.*]]
2316   // CHECK: [[COND]]:
2317   // CHECK:   br i1 %{{.*}}, label %[[BODY:.*]], label %[[EXIT:.*]]
2318   // CHECK: [[BODY]]:
2319   // CHECK:   switch i32 %{{.*}}, label %[[INC:.*]] [
2320   // CHECK-NEXT:     i32 0, label %[[SECTION1:.*]]
2321   // CHECK-NEXT:     i32 1, label %[[SECTION2:.*]]
2322   // CHECK-NEXT: ]
2324   omp.sections {
2325     omp.section {
2326       // CHECK: [[SECTION1]]:
2327       // CHECK-NEXT: br label %[[SECTION1_REGION1:[^ ,]*]]
2328       // CHECK-EMPTY:
2329       // CHECK-NEXT: [[SECTION1_REGION1]]:
2330       // CHECK-NEXT: br label %[[SECTION1_REGION2:[^ ,]*]]
2331       // CHECK-EMPTY:
2332       // CHECK-NEXT: [[SECTION1_REGION2]]:
2333       // CHECK-NEXT: br label %[[INC]]
2334       omp.terminator
2335     }
2336     omp.section {
2337       // CHECK: [[SECTION2]]:
2338       // CHECK: br label %[[INC]]
2339       omp.terminator
2340     }
2341     omp.terminator
2342   }
2344   // CHECK: [[INC]]:
2345   // CHECK:   %{{.*}} = add {{.*}}, 1
2346   // CHECK:   br label %[[HEADER]]
2348   // CHECK: [[EXIT]]:
2349   // CHECK:   call void @__kmpc_for_static_fini({{.*}})
2350   // CHECK:   call void @__kmpc_barrier({{.*}})
2351   // CHECK:   br label %[[AFTER:.*]]
2353   // CHECK: [[AFTER]]:
2354   // CHECK:   ret void
2355   llvm.return
2358 // -----
2360 // CHECK: declare void @foo()
2361 llvm.func @foo()
2363 // CHECK: declare void @bar(i32)
2364 llvm.func @bar(%arg0 : i32)
2366 // CHECK-LABEL: @omp_sections
2367 llvm.func @omp_sections(%arg0 : i32, %arg1 : i32, %arg2 : !llvm.ptr) -> () {
2369   // CHECK: switch i32 %{{.*}}, label %{{.*}} [
2370   // CHECK-NEXT:   i32 0, label %[[SECTION1:.*]]
2371   // CHECK-NEXT:   i32 1, label %[[SECTION2:.*]]
2372   // CHECK-NEXT:   i32 2, label %[[SECTION3:.*]]
2373   // CHECK-NEXT: ]
2374   omp.sections {
2375     omp.section {
2376       // CHECK: [[SECTION1]]:
2377       // CHECK:   br label %[[REGION1:[^ ,]*]]
2378       // CHECK: [[REGION1]]:
2379       // CHECK:   call void @foo()
2380       // CHECK:   br label %{{.*}}
2381       llvm.call @foo() : () -> ()
2382       omp.terminator
2383     }
2384     omp.section {
2385       // CHECK: [[SECTION2]]:
2386       // CHECK:   br label %[[REGION2:[^ ,]*]]
2387       // CHECK: [[REGION2]]:
2388       // CHECK:   call void @bar(i32 %{{.*}})
2389       // CHECK:   br label %{{.*}}
2390       llvm.call @bar(%arg0) : (i32) -> ()
2391       omp.terminator
2392     }
2393     omp.section {
2394       // CHECK: [[SECTION3]]:
2395       // CHECK:   br label %[[REGION3:[^ ,]*]]
2396       // CHECK: [[REGION3]]:
2397       // CHECK:   %11 = add i32 %{{.*}}, %{{.*}}
2398       %add = llvm.add %arg0, %arg1 : i32
2399       // CHECK:   store i32 %{{.*}}, ptr %{{.*}}, align 4
2400       // CHECK:   br label %{{.*}}
2401       llvm.store %add, %arg2 : i32, !llvm.ptr
2402       omp.terminator
2403     }
2404     omp.terminator
2405   }
2406   llvm.return
2409 // -----
2411 llvm.func @foo()
2413 // CHECK-LABEL: @omp_sections_with_clauses
2414 llvm.func @omp_sections_with_clauses() -> () {
2415   // CHECK-NOT: call void @__kmpc_barrier
2416   omp.sections nowait {
2417     omp.section {
2418       llvm.call @foo() : () -> ()
2419       omp.terminator
2420     }
2421     omp.section {
2422       llvm.call @foo() : () -> ()
2423       omp.terminator
2424     }
2425     omp.terminator
2426   }
2427   llvm.return
2430 // -----
2432 // Check that translation doesn't crash in presence of repeated successor
2433 // blocks with different arguments within OpenMP operations: LLVM cannot
2434 // represent this and a dummy block will be introduced for forwarding. The
2435 // introduction mechanism itself is tested elsewhere.
2436 // CHECK-LABEL: @repeated_successor
2437 llvm.func @repeated_successor(%arg0: i64, %arg1: i64, %arg2: i64, %arg3: i1) {
2438   omp.wsloop {
2439     omp.loop_nest (%arg4) : i64 = (%arg0) to (%arg1) step (%arg2)  {
2440       llvm.cond_br %arg3, ^bb1(%arg0 : i64), ^bb1(%arg1 : i64)
2441     ^bb1(%0: i64):  // 2 preds: ^bb0, ^bb0
2442       omp.yield
2443     }
2444   }
2445   llvm.return
2448 // -----
2450 // CHECK-LABEL: @single
2451 // CHECK-SAME: (i32 %[[x:.*]], i32 %[[y:.*]], ptr %[[zaddr:.*]])
2452 llvm.func @single(%x: i32, %y: i32, %zaddr: !llvm.ptr) {
2453   // CHECK: %[[a:.*]] = sub i32 %[[x]], %[[y]]
2454   %a = llvm.sub %x, %y : i32
2455   // CHECK: store i32 %[[a]], ptr %[[zaddr]]
2456   llvm.store %a, %zaddr : i32, !llvm.ptr
2457   // CHECK: call i32 @__kmpc_single
2458   omp.single {
2459     // CHECK: %[[z:.*]] = add i32 %[[x]], %[[y]]
2460     %z = llvm.add %x, %y : i32
2461     // CHECK: store i32 %[[z]], ptr %[[zaddr]]
2462     llvm.store %z, %zaddr : i32, !llvm.ptr
2463     // CHECK: call void @__kmpc_end_single
2464     // CHECK: call void @__kmpc_barrier
2465     omp.terminator
2466   }
2467   // CHECK: %[[b:.*]] = mul i32 %[[x]], %[[y]]
2468   %b = llvm.mul %x, %y : i32
2469   // CHECK: store i32 %[[b]], ptr %[[zaddr]]
2470   llvm.store %b, %zaddr : i32, !llvm.ptr
2471   // CHECK: ret void
2472   llvm.return
2475 // -----
2477 // CHECK-LABEL: @single_nowait
2478 // CHECK-SAME: (i32 %[[x:.*]], i32 %[[y:.*]], ptr %[[zaddr:.*]])
2479 llvm.func @single_nowait(%x: i32, %y: i32, %zaddr: !llvm.ptr) {
2480   // CHECK: %[[a:.*]] = sub i32 %[[x]], %[[y]]
2481   %a = llvm.sub %x, %y : i32
2482   // CHECK: store i32 %[[a]], ptr %[[zaddr]]
2483   llvm.store %a, %zaddr : i32, !llvm.ptr
2484   // CHECK: call i32 @__kmpc_single
2485   omp.single nowait {
2486     // CHECK: %[[z:.*]] = add i32 %[[x]], %[[y]]
2487     %z = llvm.add %x, %y : i32
2488     // CHECK: store i32 %[[z]], ptr %[[zaddr]]
2489     llvm.store %z, %zaddr : i32, !llvm.ptr
2490     // CHECK: call void @__kmpc_end_single
2491     // CHECK-NOT: call void @__kmpc_barrier
2492     omp.terminator
2493   }
2494   // CHECK: %[[t:.*]] = mul i32 %[[x]], %[[y]]
2495   %t = llvm.mul %x, %y : i32
2496   // CHECK: store i32 %[[t]], ptr %[[zaddr]]
2497   llvm.store %t, %zaddr : i32, !llvm.ptr
2498   // CHECK: ret void
2499   llvm.return
2502 // -----
2504 llvm.func @copy_i32(!llvm.ptr, !llvm.ptr)
2505 llvm.func @copy_f32(!llvm.ptr, !llvm.ptr)
2507 // CHECK-LABEL: @single_copyprivate
2508 // CHECK-SAME: (ptr %[[ip:.*]], ptr %[[fp:.*]])
2509 llvm.func @single_copyprivate(%ip: !llvm.ptr, %fp: !llvm.ptr) {
2510   // CHECK: %[[didit_addr:.*]] = alloca i32
2511   // CHECK: store i32 0, ptr %[[didit_addr]]
2512   // CHECK: call i32 @__kmpc_single
2513   omp.single copyprivate(%ip -> @copy_i32 : !llvm.ptr, %fp -> @copy_f32 : !llvm.ptr) {
2514     // CHECK: %[[i:.*]] = load i32, ptr %[[ip]]
2515     %i = llvm.load %ip : !llvm.ptr -> i32
2516     // CHECK: %[[i2:.*]] = add i32 %[[i]], %[[i]]
2517     %i2 = llvm.add %i, %i : i32
2518     // CHECK: store i32 %[[i2]], ptr %[[ip]]
2519     llvm.store %i2, %ip : i32, !llvm.ptr
2520     // CHECK: %[[f:.*]] = load float, ptr %[[fp]]
2521     %f = llvm.load %fp : !llvm.ptr -> f32
2522     // CHECK: %[[f2:.*]] = fadd float %[[f]], %[[f]]
2523     %f2 = llvm.fadd %f, %f : f32
2524     // CHECK: store float %[[f2]], ptr %[[fp]]
2525     llvm.store %f2, %fp : f32, !llvm.ptr
2526     // CHECK: store i32 1, ptr %[[didit_addr]]
2527     // CHECK: call void @__kmpc_end_single
2528     // CHECK: %[[didit:.*]] = load i32, ptr %[[didit_addr]]
2529     // CHECK: call void @__kmpc_copyprivate({{.*}}, ptr %[[ip]], ptr @copy_i32, i32 %[[didit]])
2530     // CHECK: %[[didit2:.*]] = load i32, ptr %[[didit_addr]]
2531     // CHECK: call void @__kmpc_copyprivate({{.*}}, ptr %[[fp]], ptr @copy_f32, i32 %[[didit2]])
2532     // CHECK-NOT: call void @__kmpc_barrier
2533     omp.terminator
2534   }
2535   // CHECK: ret void
2536   llvm.return
2539 // -----
2541 // CHECK: @_QFsubEx = internal global i32 undef
2542 // CHECK: @_QFsubEx.cache = common global ptr null
2544 // CHECK-LABEL: @omp_threadprivate
2545 llvm.func @omp_threadprivate() {
2546 // CHECK:  [[THREAD:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB:[0-9]+]])
2547 // CHECK:  [[TMP1:%.*]] = call ptr @__kmpc_threadprivate_cached(ptr @[[GLOB]], i32 [[THREAD]], ptr @_QFsubEx, i64 4, ptr @_QFsubEx.cache)
2548 // CHECK:  store i32 1, ptr [[TMP1]], align 4
2549 // CHECK:  store i32 3, ptr [[TMP1]], align 4
2551 // CHECK-LABEL: omp.par.region{{.*}}
2552 // CHECK:  [[THREAD2:%.*]] = call i32 @__kmpc_global_thread_num(ptr @[[GLOB2:[0-9]+]])
2553 // CHECK:  [[TMP3:%.*]] = call ptr @__kmpc_threadprivate_cached(ptr @[[GLOB2]], i32 [[THREAD2]], ptr @_QFsubEx, i64 4, ptr @_QFsubEx.cache)
2554 // CHECK:  store i32 2, ptr [[TMP3]], align 4
2556   %0 = llvm.mlir.constant(1 : i32) : i32
2557   %1 = llvm.mlir.constant(2 : i32) : i32
2558   %2 = llvm.mlir.constant(3 : i32) : i32
2560   %3 = llvm.mlir.addressof @_QFsubEx : !llvm.ptr
2561   %4 = omp.threadprivate %3 : !llvm.ptr -> !llvm.ptr
2563   llvm.store %0, %4 : i32, !llvm.ptr
2565   omp.parallel  {
2566     %5 = omp.threadprivate %3 : !llvm.ptr -> !llvm.ptr
2567     llvm.store %1, %5 : i32, !llvm.ptr
2568     omp.terminator
2569   }
2571   llvm.store %2, %4 : i32, !llvm.ptr
2572   llvm.return
2575 llvm.mlir.global internal @_QFsubEx() : i32
2577 // -----
2579 // CHECK-LABEL: define void @omp_task_detach
2580 // CHECK-SAME: (ptr %[[event_handle:.*]])
2581 llvm.func @omp_task_detach(%event_handle : !llvm.ptr){
2582    // CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})
2583    // CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc
2584    // CHECK: %[[return_val:.*]] = call ptr @__kmpc_task_allow_completion_event(ptr {{.*}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
2585    // CHECK: %[[conv:.*]] = ptrtoint ptr %[[return_val]] to i64
2586    // CHECK: store i64 %[[conv]], ptr %[[event_handle]], align 4
2587    // CHECK: call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
2588    omp.task detach(%event_handle : !llvm.ptr){
2589      omp.terminator
2590    }
2591    llvm.return
2594 // -----
2596 // CHECK-LABEL: define void @omp_task
2597 // CHECK-SAME: (i32 %[[x:.+]], i32 %[[y:.+]], ptr %[[zaddr:.+]])
2598 llvm.func @omp_task(%x: i32, %y: i32, %zaddr: !llvm.ptr) {
2599   // CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})
2600   // CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc
2601   // CHECK-SAME: (ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 1, i64 40,
2602   // CHECK-SAME:  i64 0, ptr @[[outlined_fn:.+]])
2603   // CHECK: call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
2604   omp.task {
2605     %n = llvm.mlir.constant(1 : i64) : i64
2606     %valaddr = llvm.alloca %n x i32 : (i64) -> !llvm.ptr
2607     %val = llvm.load %valaddr : !llvm.ptr -> i32
2608     %double = llvm.add %val, %val : i32
2609     llvm.store %double, %valaddr : i32, !llvm.ptr
2610     omp.terminator
2611   }
2612   llvm.return
2615 // CHECK: define internal void @[[outlined_fn]](i32 %[[global_tid:[^ ,]+]])
2616 // CHECK: task.alloca{{.*}}:
2617 // CHECK:   br label %[[task_body:[^, ]+]]
2618 // CHECK: [[task_body]]:
2619 // CHECK:   br label %[[task_region:[^, ]+]]
2620 // CHECK: [[task_region]]:
2621 // CHECK:   %[[alloca:.+]] = alloca i32, i64 1
2622 // CHECK:   %[[val:.+]] = load i32, ptr %[[alloca]]
2623 // CHECK:   %[[newval:.+]] = add i32 %[[val]], %[[val]]
2624 // CHECK:   store i32 %[[newval]], ptr %{{[^, ]+}}
2625 // CHECK:   br label %[[exit_stub:[^, ]+]]
2626 // CHECK: [[exit_stub]]:
2627 // CHECK:   ret void
2629 // -----
2631 // CHECK-LABEL: define void @omp_task_attrs()
2632 llvm.func @omp_task_attrs() -> () attributes {
2633   target_cpu = "x86-64",
2634   target_features = #llvm.target_features<["+mmx", "+sse"]>
2635 } {
2636   // CHECK: %[[task_data:.*]] = call {{.*}}@__kmpc_omp_task_alloc{{.*}}@[[outlined_fn:.*]])
2637   // CHECK: call {{.*}}@__kmpc_omp_task(
2638   // CHECK-SAME: ptr %[[task_data]]
2639   omp.task {
2640     omp.terminator
2641   }
2643   llvm.return
2646 // CHECK: define {{.*}} @[[outlined_fn]]{{.*}} #[[attrs:[0-9]+]]
2647 // CHECK: attributes #[[attrs]] = {
2648 // CHECK-SAME: "target-cpu"="x86-64"
2649 // CHECK-SAME: "target-features"="+mmx,+sse"
2651 // -----
2653 // CHECK-LABEL: define void @omp_task_with_deps
2654 // CHECK-SAME: (ptr %[[zaddr:.+]])
2655 // CHECK:  %[[dep_arr_addr:.+]] = alloca [1 x %struct.kmp_dep_info], align 8
2656 // CHECK:  %[[dep_arr_addr_0:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[dep_arr_addr]], i64 0, i64 0
2657 // CHECK:  %[[dep_arr_addr_0_val:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[dep_arr_addr_0]], i32 0, i32 0
2658 // CHECK:  %[[dep_arr_addr_0_val_int:.+]] = ptrtoint ptr %0 to i64
2659 // CHECK:  store i64 %[[dep_arr_addr_0_val_int]], ptr %[[dep_arr_addr_0_val]], align 4
2660 // CHECK:  %[[dep_arr_addr_0_size:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[dep_arr_addr_0]], i32 0, i32 1
2661 // CHECK:  store i64 8, ptr %[[dep_arr_addr_0_size]], align 4
2662 // CHECK:  %[[dep_arr_addr_0_kind:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[dep_arr_addr_0]], i32 0, i32 2
2663 // CHECK: store i8 1, ptr %[[dep_arr_addr_0_kind]], align 1
2664 // -----
2665 // dependence_type: Out
2666 // CHECK:  %[[DEP_ARR_ADDR1:.+]] = alloca [1 x %struct.kmp_dep_info], align 8
2667 // CHECK:  %[[DEP_ARR_ADDR_1:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[DEP_ARR_ADDR1]], i64 0, i64 0
2668 //         [...]
2669 // CHECK:  %[[DEP_TYPE_1:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[DEP_ARR_ADDR_1]], i32 0, i32 2
2670 // CHECK:  store i8 3, ptr %[[DEP_TYPE_1]], align 1
2671 // -----
2672 // dependence_type: Inout
2673 // CHECK:  %[[DEP_ARR_ADDR2:.+]] = alloca [1 x %struct.kmp_dep_info], align 8
2674 // CHECK:  %[[DEP_ARR_ADDR_2:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[DEP_ARR_ADDR2]], i64 0, i64 0
2675 //         [...]
2676 // CHECK:  %[[DEP_TYPE_2:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[DEP_ARR_ADDR_2]], i32 0, i32 2
2677 // CHECK:  store i8 3, ptr %[[DEP_TYPE_2]], align 1
2678 // -----
2679 // dependence_type: Mutexinoutset
2680 // CHECK:  %[[DEP_ARR_ADDR3:.+]] = alloca [1 x %struct.kmp_dep_info], align 8
2681 // CHECK:  %[[DEP_ARR_ADDR_3:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[DEP_ARR_ADDR3]], i64 0, i64 0
2682 //         [...]
2683 // CHECK:  %[[DEP_TYPE_3:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[DEP_ARR_ADDR_3]], i32 0, i32 2
2684 // CHECK:  store i8 4, ptr %[[DEP_TYPE_3]], align 1
2685 // -----
2686 // dependence_type: Inoutset
2687 // CHECK:  %[[DEP_ARR_ADDR4:.+]] = alloca [1 x %struct.kmp_dep_info], align 8
2688 // CHECK:  %[[DEP_ARR_ADDR_4:.+]] = getelementptr inbounds [1 x %struct.kmp_dep_info], ptr %[[DEP_ARR_ADDR4]], i64 0, i64 0
2689 //         [...]
2690 // CHECK:  %[[DEP_TYPE_4:.+]] = getelementptr inbounds nuw %struct.kmp_dep_info, ptr %[[DEP_ARR_ADDR_4]], i32 0, i32 2
2691 // CHECK:  store i8 8, ptr %[[DEP_TYPE_4]], align 1
2692 llvm.func @omp_task_with_deps(%zaddr: !llvm.ptr) {
2693   // CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})
2694   // CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc
2695   // CHECK-SAME: (ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 1, i64 40,
2696   // CHECK-SAME:  i64 0, ptr @[[outlined_fn:.+]])
2697   // CHECK: call i32 @__kmpc_omp_task_with_deps(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]], {{.*}})
2698   omp.task depend(taskdependin -> %zaddr : !llvm.ptr) {
2699     %n = llvm.mlir.constant(1 : i64) : i64
2700     %valaddr = llvm.alloca %n x i32 : (i64) -> !llvm.ptr
2701     %val = llvm.load %valaddr : !llvm.ptr -> i32
2702     %double = llvm.add %val, %val : i32
2703     llvm.store %double, %valaddr : i32, !llvm.ptr
2704     omp.terminator
2705   }
2706   omp.task depend(taskdependout -> %zaddr : !llvm.ptr) {
2707     omp.terminator
2708   }
2709   omp.task depend(taskdependinout -> %zaddr : !llvm.ptr) {
2710     omp.terminator
2711   }
2712   omp.task depend(taskdependmutexinoutset -> %zaddr : !llvm.ptr) {
2713     omp.terminator
2714   }
2715   omp.task depend(taskdependinoutset -> %zaddr : !llvm.ptr) {
2716     omp.terminator
2717   }
2718   llvm.return
2721 // CHECK: define internal void @[[outlined_fn]](i32 %[[global_tid:[^ ,]+]])
2722 // CHECK: task.alloca{{.*}}:
2723 // CHECK:   br label %[[task_body:[^, ]+]]
2724 // CHECK: [[task_body]]:
2725 // CHECK:   br label %[[task_region:[^, ]+]]
2726 // CHECK: [[task_region]]:
2727 // CHECK:   %[[alloca:.+]] = alloca i32, i64 1
2728 // CHECK:   %[[val:.+]] = load i32, ptr %[[alloca]]
2729 // CHECK:   %[[newval:.+]] = add i32 %[[val]], %[[val]]
2730 // CHECK:   store i32 %[[newval]], ptr %{{[^, ]+}}
2731 // CHECK:   br label %[[exit_stub:[^, ]+]]
2732 // CHECK: [[exit_stub]]:
2733 // CHECK:   ret void
2735 // -----
2737 // CHECK-LABEL: define void @omp_task
2738 // CHECK-SAME: (i32 %[[x:.+]], i32 %[[y:.+]], ptr %[[zaddr:.+]])
2739 module attributes {llvm.target_triple = "x86_64-unknown-linux-gnu"} {
2740   llvm.func @omp_task(%x: i32, %y: i32, %zaddr: !llvm.ptr) {
2741     // CHECK: %[[diff:.+]] = sub i32 %[[x]], %[[y]]
2742     %diff = llvm.sub %x, %y : i32
2743     // CHECK: store i32 %[[diff]], ptr %2
2744     llvm.store %diff, %zaddr : i32, !llvm.ptr
2745     // CHECK: %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num({{.+}})
2746     // CHECK: %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc
2747     // CHECK-SAME: (ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 1, i64 40, i64 16,
2748     // CHECK-SAME: ptr @[[outlined_fn:.+]])
2749     // CHECK: %[[shareds:.+]] = load ptr, ptr %[[task_data]]
2750     // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr {{.+}} %[[shareds]], ptr {{.+}}, i64 16, i1 false)
2751     // CHECK: call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
2752     omp.task {
2753       %z = llvm.add %x, %y : i32
2754       llvm.store %z, %zaddr : i32, !llvm.ptr
2755       omp.terminator
2756     }
2757     // CHECK: %[[prod:.+]] = mul i32 %[[x]], %[[y]]
2758     %b = llvm.mul %x, %y : i32
2759     // CHECK: store i32 %[[prod]], ptr %[[zaddr]]
2760     llvm.store %b, %zaddr : i32, !llvm.ptr
2761     llvm.return
2762   }
2765 // CHECK: define internal void @[[outlined_fn]](i32 %[[global_tid:[^ ,]+]], ptr %[[task_data:.+]])
2766 // CHECK: task.alloca{{.*}}:
2767 // CHECK:   %[[shareds:.+]] = load ptr, ptr %[[task_data]]
2768 // CHECK:   br label %[[task_body:[^, ]+]]
2769 // CHECK: [[task_body]]:
2770 // CHECK:   br label %[[task_region:[^, ]+]]
2771 // CHECK: [[task_region]]:
2772 // CHECK:   %[[sum:.+]] = add i32 %{{.+}}, %{{.+}}
2773 // CHECK:   store i32 %[[sum]], ptr %{{.+}}
2774 // CHECK:   br label %[[exit_stub:[^, ]+]]
2775 // CHECK: [[exit_stub]]:
2776 // CHECK:   ret void
2778 // -----
2780 llvm.func @par_task_(%arg0: !llvm.ptr {fir.bindc_name = "a"}) {
2781   %0 = llvm.mlir.constant(1 : i32) : i32
2782   omp.task   {
2783     omp.parallel   {
2784       llvm.store %0, %arg0 : i32, !llvm.ptr
2785       omp.terminator
2786     }
2787     omp.terminator
2788   }
2789   llvm.return
2792 // CHECK-LABEL: @par_task_
2793 // CHECK: %[[TASK_ALLOC:.*]] = call ptr @__kmpc_omp_task_alloc({{.*}}ptr @[[task_outlined_fn:.+]])
2794 // CHECK: call i32 @__kmpc_omp_task({{.*}}, ptr %[[TASK_ALLOC]])
2795 // CHECK: define internal void @[[task_outlined_fn]]
2796 // CHECK: %[[ARG_ALLOC:.*]] = alloca { ptr }, align 8
2797 // CHECK: call void ({{.*}}) @__kmpc_fork_call({{.*}}, ptr @[[parallel_outlined_fn:.+]], ptr %[[ARG_ALLOC]])
2798 // CHECK: define internal void @[[parallel_outlined_fn]]
2799 // -----
2801 llvm.func @foo(!llvm.ptr) -> ()
2802 llvm.func @destroy(!llvm.ptr) -> ()
2804 omp.private {type = firstprivate} @privatizer : i32 copy {
2805 ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
2806   %0 = llvm.load %arg0 : !llvm.ptr -> i32
2807   llvm.store %0, %arg1 : i32, !llvm.ptr
2808   omp.yield(%arg1 : !llvm.ptr)
2809 } dealloc {
2810 ^bb0(%arg0 : !llvm.ptr):
2811   llvm.call @destroy(%arg0) : (!llvm.ptr) -> ()
2812   omp.yield
2815 llvm.func @task(%arg0 : !llvm.ptr) {
2816   omp.task private(@privatizer %arg0 -> %arg1 : !llvm.ptr) {
2817     llvm.call @foo(%arg1) : (!llvm.ptr) -> ()
2818     omp.terminator
2819   }
2820   llvm.return
2822 // CHECK-LABEL: @task..omp_par
2823 // CHECK:       task.alloca:
2824 // CHECK:         %[[VAL_11:.*]] = load ptr, ptr %[[VAL_12:.*]], align 8
2825 // CHECK:         %[[VAL_13:.*]] = getelementptr { ptr }, ptr %[[VAL_11]], i32 0, i32 0
2826 // CHECK:         %[[VAL_14:.*]] = load ptr, ptr %[[VAL_13]], align 8
2827 // CHECK:         %[[VAL_15:.*]] = alloca i32, align 4
2828 // CHECK:         br label %omp.private.init
2829 // CHECK:       omp.private.init:                                 ; preds = %task.alloca
2830 // CHECK:         br label %omp.private.copy
2831 // CHECK:       omp.private.copy:                                 ; preds = %omp.private.init
2832 // CHECK:         %[[VAL_19:.*]] = load i32, ptr %[[VAL_14]], align 4
2833 // CHECK:         store i32 %[[VAL_19]], ptr %[[VAL_15]], align 4
2834 // CHECK:         br label %[[VAL_20:.*]]
2835 // CHECK:       [[VAL_20]]:
2836 // CHECK:         br label %task.body
2837 // CHECK:       task.body:                                        ; preds = %[[VAL_20]]
2838 // CHECK:         br label %omp.task.region
2839 // CHECK:       omp.task.region:                                  ; preds = %task.body
2840 // CHECK:         call void @foo(ptr %[[VAL_15]])
2841 // CHECK:         br label %omp.region.cont
2842 // CHECK:       omp.region.cont:                                  ; preds = %omp.task.region
2843 // CHECK:         call void @destroy(ptr %[[VAL_15]])
2844 // CHECK:         br label %task.exit.exitStub
2845 // CHECK:       task.exit.exitStub:                               ; preds = %omp.region.cont
2846 // CHECK:         ret void
2847 // -----
2849 llvm.func @foo() -> ()
2851 llvm.func @omp_taskgroup(%x: i32, %y: i32, %zaddr: !llvm.ptr) {
2852   omp.taskgroup {
2853     llvm.call @foo() : () -> ()
2854     omp.terminator
2855   }
2856   llvm.return
2859 // CHECK-LABEL: define void @omp_taskgroup(
2860 // CHECK-SAME:                             i32 %[[x:.+]], i32 %[[y:.+]], ptr %[[zaddr:.+]])
2861 // CHECK:         br label %[[entry:[^,]+]]
2862 // CHECK:       [[entry]]:
2863 // CHECK:         %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})
2864 // CHECK:         call void @__kmpc_taskgroup(ptr @{{.+}}, i32 %[[omp_global_thread_num]])
2865 // CHECK:         br label %[[omp_taskgroup_region:[^,]+]]
2866 // CHECK:       [[omp_taskgroup_region]]:
2867 // CHECK:         call void @foo()
2868 // CHECK:         br label %[[omp_region_cont:[^,]+]]
2869 // CHECK:       [[omp_region_cont]]:
2870 // CHECK:         br label %[[taskgroup_exit:[^,]+]]
2871 // CHECK:       [[taskgroup_exit]]:
2872 // CHECK:         call void @__kmpc_end_taskgroup(ptr @{{.+}}, i32 %[[omp_global_thread_num]])
2873 // CHECK:         ret void
2875 // -----
2877 llvm.func @foo() -> ()
2878 llvm.func @bar(i32, i32, !llvm.ptr) -> ()
2880 llvm.func @omp_taskgroup_task(%x: i32, %y: i32, %zaddr: !llvm.ptr) {
2881   omp.taskgroup {
2882     %c1 = llvm.mlir.constant(1) : i32
2883     %ptr1 = llvm.alloca %c1 x i8 : (i32) -> !llvm.ptr
2884     omp.task {
2885       llvm.call @foo() : () -> ()
2886       omp.terminator
2887     }
2888     omp.task {
2889       llvm.call @bar(%x, %y, %zaddr) : (i32, i32, !llvm.ptr) -> ()
2890       omp.terminator
2891     }
2892     llvm.br ^bb1
2893   ^bb1:
2894     llvm.call @foo() : () -> ()
2895     omp.terminator
2896   }
2897   llvm.return
2900 // CHECK-LABEL: define void @omp_taskgroup_task(
2901 // CHECK-SAME:                                  i32 %[[x:.+]], i32 %[[y:.+]], ptr %[[zaddr:.+]])
2902 // CHECK:         %[[structArg:.+]] = alloca { i32, i32, ptr }, align 8
2903 // CHECK:         br label %[[entry:[^,]+]]
2904 // CHECK:       [[entry]]:                                            ; preds = %3
2905 // CHECK:         %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})
2906 // CHECK:         call void @__kmpc_taskgroup(ptr @{{.+}}, i32 %[[omp_global_thread_num]])
2907 // CHECK:         br label %[[omp_taskgroup_region:[^,]+]]
2908 // CHECK:       [[omp_taskgroup_region1:.+]]:
2909 // CHECK:         call void @foo()
2910 // CHECK:         br label %[[omp_region_cont:[^,]+]]
2911 // CHECK:       [[omp_taskgroup_region]]:
2912 // CHECK:         %{{.+}} = alloca i8, align 1
2913 // CHECK:         br label %[[codeRepl:[^,]+]]
2914 // CHECK:       [[codeRepl]]:
2915 // CHECK:         %[[omp_global_thread_num_t1:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})
2916 // CHECK:         %[[t1_alloc:.+]] = call ptr @__kmpc_omp_task_alloc(ptr @{{.+}}, i32 %[[omp_global_thread_num_t1]], i32 1, i64 40, i64 0, ptr @[[outlined_task_fn:.+]])
2917 // CHECK:         %{{.+}} = call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num_t1]], ptr %[[t1_alloc]])
2918 // CHECK:         br label %[[task_exit:[^,]+]]
2919 // CHECK:       [[task_exit]]:
2920 // CHECK:         br label %[[codeRepl9:[^,]+]]
2921 // CHECK:       [[codeRepl9]]:
2922 // CHECK:         %[[gep1:.+]] = getelementptr { i32, i32, ptr }, ptr %[[structArg]], i32 0, i32 0
2923 // CHECK:         store i32 %[[x]], ptr %[[gep1]], align 4
2924 // CHECK:         %[[gep2:.+]] = getelementptr { i32, i32, ptr }, ptr %[[structArg]], i32 0, i32 1
2925 // CHECK:         store i32 %[[y]], ptr %[[gep2]], align 4
2926 // CHECK:         %[[gep3:.+]] = getelementptr { i32, i32, ptr }, ptr %[[structArg]], i32 0, i32 2
2927 // CHECK:         store ptr %[[zaddr]], ptr %[[gep3]], align 8
2928 // CHECK:         %[[omp_global_thread_num_t2:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})
2929 // CHECK:         %[[t2_alloc:.+]] = call ptr @__kmpc_omp_task_alloc(ptr @{{.+}}, i32 %[[omp_global_thread_num_t2]], i32 1, i64 40, i64 16, ptr @[[outlined_task_fn:.+]])
2930 // CHECK:         %[[shareds:.+]] = load ptr, ptr %[[t2_alloc]]
2931 // CHECK:         call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[shareds]], ptr align 1 %[[structArg]], i64 16, i1 false)
2932 // CHECK:         %{{.+}} = call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num_t2]], ptr %[[t2_alloc]])
2933 // CHECK:         br label %[[task_exit3:[^,]+]]
2934 // CHECK:       [[task_exit3]]:
2935 // CHECK:         br label %[[omp_taskgroup_region1]]
2936 // CHECK:       [[omp_region_cont]]:
2937 // CHECK:         br label %[[taskgroup_exit:[^,]+]]
2938 // CHECK:       [[taskgroup_exit]]:
2939 // CHECK:         call void @__kmpc_end_taskgroup(ptr @{{.+}}, i32 %[[omp_global_thread_num]])
2940 // CHECK:         ret void
2941 // CHECK:       }
2943 // -----
2945 llvm.func @test_01() attributes {sym_visibility = "private"}
2946 llvm.func @test_02() attributes {sym_visibility = "private"}
2947 // CHECK-LABEL: define void @_QPomp_task_priority() {
2948 llvm.func @_QPomp_task_priority() {
2949   %0 = llvm.mlir.constant(1 : i64) : i64
2950   %1 = llvm.alloca %0 x i32 {bindc_name = "x"} : (i64) -> !llvm.ptr
2951   %2 = llvm.mlir.constant(4 : i32) : i32
2952   %3 = llvm.mlir.constant(true) : i1
2953   %4 = llvm.load %1 : !llvm.ptr -> i32
2954 // CHECK:   %[[GID_01:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}})
2955 // CHECK:   %[[I_01:.*]] = call ptr @__kmpc_omp_task_alloc(ptr {{.*}}, i32 %[[GID_01]], i32 33, i64 40, i64 0, ptr @{{.*}})
2956 // CHECK:   %[[I_02:.*]] = getelementptr inbounds { ptr }, ptr %[[I_01]], i32 0, i32 0
2957 // CHECK:   %[[I_03:.*]] = getelementptr inbounds { ptr, ptr, i32, ptr, ptr }, ptr %[[I_02]], i32 0, i32 4
2958 // CHECK:   %[[I_04:.*]] = getelementptr inbounds { ptr, ptr }, ptr %[[I_03]], i32 0, i32 0
2959 // CHECK:   store i32 {{.*}}, ptr %[[I_04]], align 4
2960 // CHECK:   %{{.*}} = call i32 @__kmpc_omp_task(ptr {{.*}}, i32 %[[GID_01]], ptr %[[I_01]])
2961   omp.task priority(%4 : i32) {
2962     llvm.call @test_01() : () -> ()
2963     omp.terminator
2964   }
2965 // CHECK:   %[[GID_02:.*]] = call i32 @__kmpc_global_thread_num(ptr {{.*}})
2966 // CHECK:   %[[I_05:.*]] = call ptr @__kmpc_omp_task_alloc(ptr {{.*}}, i32 %[[GID_02]], i32 35, i64 40, i64 0, ptr @{{.*}})
2967 // CHECK:   %[[I_06:.*]] = getelementptr inbounds { ptr }, ptr %[[I_05]], i32 0, i32 0
2968 // CHECK:   %[[I_07:.*]] = getelementptr inbounds { ptr, ptr, i32, ptr, ptr }, ptr %[[I_06]], i32 0, i32 4
2969 // CHECK:   %[[I_08:.*]] = getelementptr inbounds { ptr, ptr }, ptr %[[I_07]], i32 0, i32 0
2970 // CHECK:   store i32 4, ptr %[[I_08]], align 4
2971 // CHECK:   %{{.*}} = call i32 @__kmpc_omp_task(ptr {{.*}}, i32 %[[GID_02]], ptr %[[I_05]])
2972   omp.task final(%3) priority(%2 : i32) {
2973     llvm.call @test_02() : () -> ()
2974     omp.terminator
2975   }
2976   llvm.return
2977 // CHECK:   ret void
2978 // CHECK: }
2981 // -----
2983 // CHECK-LABEL: @omp_opaque_pointers
2984 // CHECK-SAME: (ptr %[[ARG0:.*]], ptr %[[ARG1:.*]], i32 %[[EXPR:.*]])
2985 llvm.func @omp_opaque_pointers(%arg0 : !llvm.ptr, %arg1: !llvm.ptr, %expr: i32) -> () {
2986   // CHECK: %[[X1:.*]] = load atomic i32, ptr %[[ARG0]] monotonic, align 4
2987   // CHECK: store i32 %[[X1]], ptr %[[ARG1]], align 4
2988   omp.atomic.read %arg1 = %arg0 : !llvm.ptr, !llvm.ptr, i32
2990   // CHECK: %[[RES:.*]] = atomicrmw add ptr %[[ARG1]], i32 %[[EXPR]] acq_rel
2991   // CHECK: store i32 %[[RES]], ptr %[[ARG0]]
2992   omp.atomic.capture memory_order(acq_rel) {
2993     omp.atomic.read %arg0 = %arg1 : !llvm.ptr, !llvm.ptr, i32
2994     omp.atomic.update %arg1 : !llvm.ptr {
2995     ^bb0(%xval: i32):
2996       %newval = llvm.add %xval, %expr : i32
2997       omp.yield(%newval : i32)
2998     }
2999   }
3000   llvm.return
3003 // -----
3005 // CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 1
3006 // CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 1
3007 // CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 1
3008 // CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 1
3009 // CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 1
3010 module attributes {omp.flags = #omp.flags<debug_kind = 1, assume_teams_oversubscription = true, 
3011                                           assume_threads_oversubscription = true, assume_no_thread_state = true, 
3012                                           assume_no_nested_parallelism = true>} {}
3013 // -----
3015 // CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 0
3016 // CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 0
3017 // CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 0
3018 // CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 0
3019 // CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 0
3020 // CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp-device", i32 50}
3021 module attributes {omp.flags = #omp.flags<>} {}
3023 // -----
3025 // CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 0
3026 // CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 0
3027 // CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 0
3028 // CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 0
3029 // CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 0
3030 // CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp-device", i32 51}
3031 module attributes {omp.flags = #omp.flags<openmp_device_version = 51>} {}
3033 // -----
3035 // CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 0
3036 // CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 0
3037 // CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 0
3038 // CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 0
3039 // CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 0
3040 // CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp-device", i32 50}
3041 // CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp", i32 50}
3042 module attributes {omp.version = #omp.version<version = 50>, omp.flags = #omp.flags<>} {}
3044 // -----
3046 // CHECK: [[META0:![0-9]+]] = !{i32 7, !"openmp", i32 51}
3047 // CHECK-NOT: [[META0:![0-9]+]] = !{i32 7, !"openmp-device", i32 50}
3048 module attributes {omp.version = #omp.version<version = 51>} {}
3050 // -----
3051 // CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 0
3052 // CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 0
3053 // CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 0
3054 // CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 0
3055 // CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 0
3056 module attributes {omp.flags = #omp.flags<debug_kind = 0, assume_teams_oversubscription = false, 
3057                                           assume_threads_oversubscription = false, assume_no_thread_state = false, 
3058                                           assume_no_nested_parallelism = false>} {}
3060 // -----
3062 // CHECK: @__omp_rtl_debug_kind = weak_odr hidden constant i32 0
3063 // CHECK: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 1
3064 // CHECK: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 0
3065 // CHECK: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 1
3066 // CHECK: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 0
3067 module attributes {omp.flags = #omp.flags<assume_teams_oversubscription = true, assume_no_thread_state = true>} {}
3069 // -----
3071 // CHECK-NOT: @__omp_rtl_debug_kind = weak_odr hidden constant i32 0
3072 // CHECK-NOT: @__omp_rtl_assume_teams_oversubscription = weak_odr hidden constant i32 1
3073 // CHECK-NOT: @__omp_rtl_assume_threads_oversubscription = weak_odr hidden constant i32 0
3074 // CHECK-NOT: @__omp_rtl_assume_no_thread_state = weak_odr hidden constant i32 1
3075 // CHECK-NOT: @__omp_rtl_assume_no_nested_parallelism = weak_odr hidden constant i32 0
3076 module attributes {omp.flags = #omp.flags<assume_teams_oversubscription = true, assume_no_thread_state = true,
3077                                           no_gpu_lib=true>} {}
3079 // -----
3081 module attributes {omp.is_target_device = false} {
3082   // CHECK: define void @filter_nohost
3083   llvm.func @filter_nohost() -> ()
3084       attributes {
3085         omp.declare_target =
3086           #omp.declaretarget<device_type = (nohost), capture_clause = (to)>
3087       } {
3088     llvm.return
3089   }
3091   // CHECK: define void @filter_host
3092   llvm.func @filter_host() -> ()
3093       attributes {
3094         omp.declare_target =
3095           #omp.declaretarget<device_type = (host), capture_clause = (to)>
3096       } {
3097     llvm.return
3098   }
3101 // -----
3103 module attributes {omp.is_target_device = false} {
3104   // CHECK: define void @filter_nohost
3105   llvm.func @filter_nohost() -> ()
3106       attributes {
3107         omp.declare_target =
3108           #omp.declaretarget<device_type = (nohost), capture_clause = (enter)>
3109       } {
3110     llvm.return
3111   }
3113   // CHECK: define void @filter_host
3114   llvm.func @filter_host() -> ()
3115       attributes {
3116         omp.declare_target =
3117           #omp.declaretarget<device_type = (host), capture_clause = (enter)>
3118       } {
3119     llvm.return
3120   }
3123 // -----
3125 module attributes {omp.is_target_device = true} {
3126   // CHECK: define void @filter_nohost
3127   llvm.func @filter_nohost() -> ()
3128       attributes {
3129         omp.declare_target =
3130           #omp.declaretarget<device_type = (nohost), capture_clause = (to)>
3131       } {
3132     llvm.return
3133   }
3135   // CHECK-NOT: define void @filter_host
3136   llvm.func @filter_host() -> ()
3137       attributes {
3138         omp.declare_target =
3139           #omp.declaretarget<device_type = (host), capture_clause = (to)>
3140       } {
3141     llvm.return
3142   }
3145 // -----
3147 module attributes {omp.is_target_device = true} {
3148   // CHECK: define void @filter_nohost
3149   llvm.func @filter_nohost() -> ()
3150       attributes {
3151         omp.declare_target =
3152           #omp.declaretarget<device_type = (nohost), capture_clause = (enter)>
3153       } {
3154     llvm.return
3155   }
3157   // CHECK-NOT: define void @filter_host
3158   llvm.func @filter_host() -> ()
3159       attributes {
3160         omp.declare_target =
3161           #omp.declaretarget<device_type = (host), capture_clause = (enter)>
3162       } {
3163     llvm.return
3164   }
3167 // -----
3169 llvm.func @omp_task_untied() {
3170   // The third argument is 0: which signifies the untied task
3171   // CHECK: {{.*}} = call ptr @__kmpc_omp_task_alloc(ptr @1, i32 %{{.*}}, i32 0,
3172   // CHECK-SAME:     i64 40, i64 0, ptr @{{.*}})
3173   omp.task untied {
3174         omp.terminator
3175   }
3176   llvm.return
3179 // -----
3181 // Third argument is 5: essentially (4 || 1)
3182 // signifying this task is TIED and MERGEABLE
3184 // CHECK: {{.*}} = call ptr @__kmpc_omp_task_alloc(ptr @1, i32 %omp_global_thread_num, i32 5, i64 40, i64 0, ptr @omp_task_mergeable..omp_par)
3185 llvm.func @omp_task_mergeable() {
3186   omp.task mergeable {
3187     omp.terminator
3188   }
3189   llvm.return
3192 // -----
3194 llvm.func external @foo_before() -> ()
3195 llvm.func external @foo() -> ()
3196 llvm.func external @foo_after() -> ()
3198 llvm.func @omp_task_final(%boolexpr: i1) {
3199   llvm.call @foo_before() : () -> ()
3200   omp.task final(%boolexpr) {
3201     llvm.call @foo() : () -> ()
3202     omp.terminator
3203   }
3204   llvm.call @foo_after() : () -> ()
3205   llvm.return
3208 // CHECK-LABEL: define void @omp_task_final(
3209 // CHECK-SAME:    i1 %[[boolexpr:.+]]) {
3210 // CHECK:         call void @foo_before()
3211 // CHECK:         br label %[[entry:[^,]+]]
3212 // CHECK:       [[entry]]:
3213 // CHECK:         br label %[[codeRepl:[^,]+]]
3214 // CHECK:       [[codeRepl]]:                                         ; preds = %entry
3215 // CHECK:         %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})
3216 // CHECK:         %[[final_flag:.+]] = select i1 %[[boolexpr]], i32 2, i32 0
3217 // CHECK:         %[[task_flags:.+]] = or i32 %[[final_flag]], 1
3218 // CHECK:         %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc(ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 %[[task_flags]], i64 40, i64 0, ptr @[[task_outlined_fn:.+]])
3219 // CHECK:         %{{.+}} = call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
3220 // CHECK:         br label %[[task_exit:[^,]+]]
3221 // CHECK:       [[task_exit]]:
3222 // CHECK:         call void @foo_after()
3223 // CHECK:         ret void
3225 // -----
3227 llvm.func external @foo_before() -> ()
3228 llvm.func external @foo() -> ()
3229 llvm.func external @foo_after() -> ()
3231 llvm.func @omp_task_if(%boolexpr: i1) {
3232   llvm.call @foo_before() : () -> ()
3233   omp.task if(%boolexpr) {
3234     llvm.call @foo() : () -> ()
3235     omp.terminator
3236   }
3237   llvm.call @foo_after() : () -> ()
3238   llvm.return
3241 // CHECK-LABEL: define void @omp_task_if(
3242 // CHECK-SAME:    i1 %[[boolexpr:.+]]) {
3243 // CHECK:         call void @foo_before()
3244 // CHECK:         br label %[[entry:[^,]+]]
3245 // CHECK:       [[entry]]:
3246 // CHECK:         br label %[[codeRepl:[^,]+]]
3247 // CHECK:       [[codeRepl]]:
3248 // CHECK:         %[[omp_global_thread_num:.+]] = call i32 @__kmpc_global_thread_num(ptr @{{.+}})
3249 // CHECK:         %[[task_data:.+]] = call ptr @__kmpc_omp_task_alloc(ptr @{{.+}}, i32 %[[omp_global_thread_num]], i32 1, i64 40, i64 0, ptr @[[task_outlined_fn:.+]])
3250 // CHECK:         br i1 %[[boolexpr]], label %[[true_label:[^,]+]], label %[[false_label:[^,]+]]
3251 // CHECK:       [[true_label]]:
3252 // CHECK:         %{{.+}} = call i32 @__kmpc_omp_task(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
3253 // CHECK:         br label %[[if_else_exit:[^,]+]]
3254 // CHECK:       [[false_label:[^,]+]]:                                                ; preds = %codeRepl
3255 // CHECK:         call void @__kmpc_omp_task_begin_if0(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
3256 // CHECK:         call void @[[task_outlined_fn]](i32 %[[omp_global_thread_num]])
3257 // CHECK:         call void @__kmpc_omp_task_complete_if0(ptr @{{.+}}, i32 %[[omp_global_thread_num]], ptr %[[task_data]])
3258 // CHECK:         br label %[[if_else_exit]]
3259 // CHECK:       [[if_else_exit]]:
3260 // CHECK:         br label %[[task_exit:[^,]+]]
3261 // CHECK:       [[task_exit]]:
3262 // CHECK:         call void @foo_after()
3263 // CHECK:         ret void
3265 // -----
3267 module attributes {omp.requires = #omp<clause_requires reverse_offload|unified_shared_memory>} {}