1 // RUN: mlir-opt %s | mlir-opt | FileCheck %s
3 func.func @omp_barrier() -> () {
9 func.func @omp_master() -> () {
12 // CHECK: omp.terminator
19 // CHECK-LABEL: omp_masked
20 func.func @omp_masked(%filtered_thread_id : i32) -> () {
21 // CHECK: omp.masked filter(%{{.*}} : i32)
22 "omp.masked" (%filtered_thread_id) ({
33 func.func @omp_taskwait() -> () {
34 // CHECK: omp.taskwait
39 func.func @omp_taskyield() -> () {
40 // CHECK: omp.taskyield
45 // CHECK-LABEL: func @omp_flush
46 // CHECK-SAME: ([[ARG0:%.*]]: memref<i32>) {
47 func.func @omp_flush(%arg0 : memref<i32>) -> () {
48 // Test without data var
52 // Test with one data var
53 // CHECK: omp.flush([[ARG0]] : memref<i32>)
54 omp.flush(%arg0 : memref<i32>)
56 // Test with two data var
57 // CHECK: omp.flush([[ARG0]], [[ARG0]] : memref<i32>, memref<i32>)
58 omp.flush(%arg0, %arg0: memref<i32>, memref<i32>)
63 func.func @omp_terminator() -> () {
64 // CHECK: omp.terminator
68 func.func @omp_parallel(%data_var : memref<i32>, %if_cond : i1, %num_threads : i32, %idx : index) -> () {
69 // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) if(%{{.*}}) num_threads(%{{.*}} : i32)
70 "omp.parallel" (%data_var, %data_var, %if_cond, %num_threads) ({
72 // test without if condition
73 // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) num_threads(%{{.*}} : i32)
74 "omp.parallel"(%data_var, %data_var, %num_threads) ({
76 }) {operandSegmentSizes = array<i32: 1,1,0,1,0,0>} : (memref<i32>, memref<i32>, i32) -> ()
81 // test without num_threads
82 // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) if(%{{.*}})
83 "omp.parallel"(%data_var, %data_var, %if_cond) ({
85 }) {operandSegmentSizes = array<i32: 1,1,1,0,0,0>} : (memref<i32>, memref<i32>, i1) -> ()
87 // test without allocate
88 // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32)
89 "omp.parallel"(%if_cond, %num_threads) ({
91 }) {operandSegmentSizes = array<i32: 0,0,1,1,0,0>} : (i1, i32) -> ()
94 }) {operandSegmentSizes = array<i32: 1,1,1,1,0,0>, proc_bind_kind = #omp<procbindkind spread>} : (memref<i32>, memref<i32>, i1, i32) -> ()
96 // test with multiple parameters for single variadic argument
97 // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
98 "omp.parallel" (%data_var, %data_var) ({
100 }) {operandSegmentSizes = array<i32: 1,1,0,0,0,0>} : (memref<i32>, memref<i32>) -> ()
102 // CHECK: omp.parallel
104 // CHECK-NOT: omp.terminator
105 // CHECK: omp.distribute
107 // CHECK-NEXT: omp.wsloop
109 // CHECK-NEXT: omp.loop_nest
110 omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
118 // CHECK: omp.parallel
120 // CHECK-NOT: omp.terminator
121 // CHECK: omp.distribute
123 // CHECK-NEXT: omp.wsloop
125 // CHECK-NEXT: omp.simd
127 // CHECK-NEXT: omp.loop_nest
128 omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
140 func.func @omp_parallel_pretty(%data_var : memref<i32>, %if_cond : i1, %num_threads : i32, %allocator : si32) -> () {
141 // CHECK: omp.parallel
146 // CHECK: omp.parallel num_threads(%{{.*}} : i32)
147 omp.parallel num_threads(%num_threads : i32) {
151 %n_index = arith.constant 2 : index
152 // CHECK: omp.parallel num_threads(%{{.*}} : index)
153 omp.parallel num_threads(%n_index : index) {
157 %n_i64 = arith.constant 4 : i64
158 // CHECK: omp.parallel num_threads(%{{.*}} : i64)
159 omp.parallel num_threads(%n_i64 : i64) {
163 // CHECK: omp.parallel allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
164 omp.parallel allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
168 // CHECK: omp.parallel
169 // CHECK-NEXT: omp.parallel if(%{{.*}})
171 omp.parallel if(%if_cond) {
177 // CHECK: omp.parallel if(%{{.*}}) num_threads(%{{.*}} : i32) proc_bind(close)
178 omp.parallel num_threads(%num_threads : i32) if(%if_cond) proc_bind(close) {
185 // CHECK-LABEL: omp_loop_nest
186 func.func @omp_loop_nest(%lb : index, %ub : index, %step : index) -> () {
188 // CHECK: omp.loop_nest
189 // CHECK-SAME: (%{{.*}}) : index =
190 // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}})
191 "omp.loop_nest" (%lb, %ub, %step) ({
194 }) : (index, index, index) -> ()
198 // CHECK: omp.loop_nest
199 // CHECK-SAME: (%{{.*}}) : index =
200 // CHECK-SAME: (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}})
201 "omp.loop_nest" (%lb, %ub, %step) ({
204 }) {loop_inclusive} : (index, index, index) -> ()
208 // CHECK: omp.loop_nest
209 // CHECK-SAME: (%{{.*}}, %{{.*}}) : index =
210 // CHECK-SAME: (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}})
211 "omp.loop_nest" (%lb, %lb, %ub, %ub, %step, %step) ({
212 ^bb0(%iv: index, %iv3: index):
214 }) : (index, index, index, index, index, index) -> ()
218 // CHECK: omp.loop_nest
219 // CHECK-SAME: (%{{.*}}) : index =
220 // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}})
221 "omp.loop_nest" (%lb, %ub, %step) ({
224 "test.op1"(%lb) : (index) -> ()
226 "test.op2"() : () -> ()
229 }) : (index, index, index) -> ()
235 // CHECK-LABEL: omp_loop_nest_pretty
236 func.func @omp_loop_nest_pretty(%lb : index, %ub : index, %step : index) -> () {
238 // CHECK: omp.loop_nest
239 // CHECK-SAME: (%{{.*}}) : index =
240 // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}})
241 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
247 // CHECK: omp.loop_nest
248 // CHECK-SAME: (%{{.*}}) : index =
249 // CHECK-SAME: (%{{.*}}) to (%{{.*}}) inclusive step (%{{.*}})
250 omp.loop_nest (%iv) : index = (%lb) to (%ub) inclusive step (%step) {
256 // CHECK: omp.loop_nest
257 // CHECK-SAME: (%{{.*}}) : index =
258 // CHECK-SAME: (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}})
259 omp.loop_nest (%iv1, %iv2) : index = (%lb, %lb) to (%ub, %ub) step (%step, %step) {
265 // CHECK: omp.loop_nest
266 // CHECK-SAME: (%{{.*}}) : index =
267 // CHECK-SAME: (%{{.*}}) to (%{{.*}}) step (%{{.*}})
268 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
270 "test.op1"(%lb) : (index) -> ()
272 "test.op2"() : () -> ()
281 // CHECK-LABEL: omp_loop_nest_pretty_multi_block
282 func.func @omp_loop_nest_pretty_multi_block(%lb : index, %ub : index,
283 %step : index, %data1 : memref<?xi32>, %data2 : memref<?xi32>) -> () {
286 // CHECK: omp.loop_nest (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
287 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
288 %1 = "test.payload"(%iv) : (index) -> (i32)
291 memref.store %arg, %data1[%iv] : memref<?xi32>
297 // CHECK: omp.loop_nest (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
298 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
299 %c = "test.condition"(%iv) : (index) -> (i1)
300 %v1 = "test.payload"(%iv) : (index) -> (i32)
301 cf.cond_br %c, ^bb1(%v1: i32), ^bb2(%v1: i32)
303 memref.store %arg0, %data1[%iv] : memref<?xi32>
306 memref.store %arg1, %data2[%iv] : memref<?xi32>
314 // CHECK: omp.loop_nest (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
315 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
316 %c = "test.condition"(%iv) : (index) -> (i1)
317 %v1 = "test.payload"(%iv) : (index) -> (i32)
318 cf.cond_br %c, ^bb1(%v1: i32), ^bb2(%v1: i32)
320 memref.store %arg0, %data1[%iv] : memref<?xi32>
323 memref.store %arg1, %data2[%iv] : memref<?xi32>
331 // CHECK-LABEL: omp_loop_nest_pretty_non_index
332 func.func @omp_loop_nest_pretty_non_index(%lb1 : i32, %ub1 : i32, %step1 : i32,
333 %lb2 : i64, %ub2 : i64, %step2 : i64, %data1 : memref<?xi32>,
334 %data2 : memref<?xi64>) -> () {
337 // CHECK: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
338 omp.loop_nest (%iv1) : i32 = (%lb1) to (%ub1) step (%step1) {
339 %1 = "test.payload"(%iv1) : (i32) -> (index)
340 cf.br ^bb1(%1: index)
342 memref.store %iv1, %data1[%arg1] : memref<?xi32>
348 // CHECK: omp.loop_nest (%{{.*}}) : i64 = (%{{.*}}) to (%{{.*}}) step (%{{.*}})
349 omp.loop_nest (%iv) : i64 = (%lb2) to (%ub2) step (%step2) {
350 %2 = "test.payload"(%iv) : (i64) -> (index)
351 cf.br ^bb1(%2: index)
353 memref.store %iv, %data2[%arg2] : memref<?xi64>
361 // CHECK-LABEL: omp_loop_nest_pretty_multiple
362 func.func @omp_loop_nest_pretty_multiple(%lb1 : i32, %ub1 : i32, %step1 : i32,
363 %lb2 : i32, %ub2 : i32, %step2 : i32, %data1 : memref<?xi32>) -> () {
366 // CHECK: omp.loop_nest (%{{.*}}, %{{.*}}) : i32 = (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}})
367 omp.loop_nest (%iv1, %iv2) : i32 = (%lb1, %lb2) to (%ub1, %ub2) step (%step1, %step2) {
368 %1 = "test.payload"(%iv1) : (i32) -> (index)
369 %2 = "test.payload"(%iv2) : (i32) -> (index)
370 memref.store %iv1, %data1[%1] : memref<?xi32>
371 memref.store %iv2, %data1[%2] : memref<?xi32>
379 // CHECK-LABEL: omp_wsloop
380 func.func @omp_wsloop(%lb : index, %ub : index, %step : index, %data_var : memref<i32>, %linear_var : i32, %chunk_var : i32) -> () {
382 // CHECK: omp.wsloop ordered(1) {
383 // CHECK-NEXT: omp.loop_nest
385 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
388 }) {operandSegmentSizes = array<i32: 0,0,0,0,0,0,0>, ordered = 1} :
391 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static) {
392 // CHECK-NEXT: omp.loop_nest
393 "omp.wsloop" (%data_var, %linear_var) ({
394 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
397 }) {operandSegmentSizes = array<i32: 0,0,1,1,0,0,0>, schedule_kind = #omp<schedulekind static>} :
398 (memref<i32>, i32) -> ()
400 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>, %{{.*}} = %{{.*}} : memref<i32>) schedule(static) {
401 // CHECK-NEXT: omp.loop_nest
402 "omp.wsloop" (%data_var, %data_var, %linear_var, %linear_var) ({
403 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
406 }) {operandSegmentSizes = array<i32: 0,0,2,2,0,0,0>, schedule_kind = #omp<schedulekind static>} :
407 (memref<i32>, memref<i32>, i32, i32) -> ()
409 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(dynamic = %{{.*}}) {
410 // CHECK-NEXT: omp.loop_nest
411 "omp.wsloop" (%data_var, %linear_var, %chunk_var) ({
412 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
415 }) {operandSegmentSizes = array<i32: 0,0,1,1,0,0,1>, schedule_kind = #omp<schedulekind dynamic>, ordered = 2} :
416 (memref<i32>, i32, i32) -> ()
418 // CHECK: omp.wsloop nowait schedule(auto) {
419 // CHECK-NEXT: omp.loop_nest
421 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
424 }) {operandSegmentSizes = array<i32: 0,0,0,0,0,0,0>, nowait, schedule_kind = #omp<schedulekind auto>} :
427 // CHECK: omp.wsloop {
428 // CHECK-NEXT: omp.simd
429 // CHECK-NEXT: omp.loop_nest
432 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
436 }) {omp.composite} : () -> ()
441 // CHECK-LABEL: omp_wsloop_pretty
442 func.func @omp_wsloop_pretty(%lb : index, %ub : index, %step : index, %data_var : memref<i32>, %linear_var : i32, %chunk_var : i32, %chunk_var2 : i16) -> () {
444 // CHECK: omp.wsloop ordered(2) {
445 // CHECK-NEXT: omp.loop_nest
446 omp.wsloop ordered(2) {
447 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
452 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) schedule(static) {
453 // CHECK-NEXT: omp.loop_nest
454 omp.wsloop schedule(static) linear(%data_var = %linear_var : memref<i32>) {
455 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
460 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(static = %{{.*}} : i32) {
461 // CHECK-NEXT: omp.loop_nest
462 omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(static = %chunk_var : i32) {
463 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
468 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(dynamic = %{{.*}} : i32, nonmonotonic) {
469 // CHECK-NEXT: omp.loop_nest
470 omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var : i32, nonmonotonic) {
471 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
476 // CHECK: omp.wsloop linear(%{{.*}} = %{{.*}} : memref<i32>) ordered(2) schedule(dynamic = %{{.*}} : i16, monotonic) {
477 // CHECK-NEXT: omp.loop_nest
478 omp.wsloop ordered(2) linear(%data_var = %linear_var : memref<i32>) schedule(dynamic = %chunk_var2 : i16, monotonic) {
479 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
484 // CHECK: omp.wsloop {
485 // CHECK-NEXT: omp.loop_nest
487 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
492 // CHECK: omp.wsloop nowait {
493 // CHECK-NEXT: omp.loop_nest
495 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
500 // CHECK: omp.wsloop nowait order(concurrent) {
501 // CHECK-NEXT: omp.loop_nest
502 omp.wsloop order(concurrent) nowait {
503 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
508 // CHECK: omp.wsloop nowait order(reproducible:concurrent) {
509 // CHECK-NEXT: omp.loop_nest
510 omp.wsloop order(reproducible:concurrent) nowait {
511 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
515 // CHECK: omp.wsloop nowait order(unconstrained:concurrent) {
516 // CHECK-NEXT: omp.loop_nest
517 omp.wsloop order(unconstrained:concurrent) nowait {
518 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
522 // CHECK: omp.wsloop {
523 // CHECK-NEXT: omp.simd
524 // CHECK-NEXT: omp.loop_nest
527 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
536 // CHECK-LABEL: omp_simd
537 func.func @omp_simd(%lb : index, %ub : index, %step : index) -> () {
540 "omp.loop_nest" (%lb, %ub, %step) ({
542 "omp.yield"() : () -> ()
543 }) : (index, index, index) -> ()
549 // CHECK-LABEL: omp_simd_aligned_list
550 func.func @omp_simd_aligned_list(%arg0 : index, %arg1 : index, %arg2 : index,
551 %arg3 : memref<i32>, %arg4 : memref<i32>) -> () {
552 // CHECK: omp.simd aligned(
553 // CHECK-SAME: %{{.*}} : memref<i32> -> 32 : i64,
554 // CHECK-SAME: %{{.*}} : memref<i32> -> 128 : i64)
555 "omp.simd"(%arg3, %arg4) ({
556 "omp.loop_nest" (%arg0, %arg1, %arg2) ({
558 "omp.yield"() : () -> ()
559 }) : (index, index, index) -> ()
560 }) {alignments = [32, 128],
561 operandSegmentSizes = array<i32: 2, 0, 0, 0, 0, 0, 0>} : (memref<i32>, memref<i32>) -> ()
565 // CHECK-LABEL: omp_simd_aligned_single
566 func.func @omp_simd_aligned_single(%arg0 : index, %arg1 : index, %arg2 : index,
567 %arg3 : memref<i32>, %arg4 : memref<i32>) -> () {
568 // CHECK: omp.simd aligned(%{{.*}} : memref<i32> -> 32 : i64)
570 "omp.loop_nest" (%arg0, %arg1, %arg2) ({
572 "omp.yield"() : () -> ()
573 }) : (index, index, index) -> ()
574 }) {alignments = [32],
575 operandSegmentSizes = array<i32: 1, 0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
579 // CHECK-LABEL: omp_simd_nontemporal_list
580 func.func @omp_simd_nontemporal_list(%arg0 : index, %arg1 : index,
581 %arg2 : index, %arg3 : memref<i32>,
582 %arg4 : memref<i64>) -> () {
583 // CHECK: omp.simd nontemporal(%{{.*}}, %{{.*}} : memref<i32>, memref<i64>)
584 "omp.simd"(%arg3, %arg4) ({
585 "omp.loop_nest" (%arg0, %arg1, %arg2) ({
587 "omp.yield"() : () -> ()
588 }) : (index, index, index) -> ()
589 }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 2, 0, 0>} : (memref<i32>, memref<i64>) -> ()
593 // CHECK-LABEL: omp_simd_nontemporal_single
594 func.func @omp_simd_nontemporal_single(%arg0 : index, %arg1 : index,
595 %arg2 : index, %arg3 : memref<i32>,
596 %arg4 : memref<i64>) -> () {
597 // CHECK: omp.simd nontemporal(%{{.*}} : memref<i32>)
599 "omp.loop_nest" (%arg0, %arg1, %arg2) ({
601 "omp.yield"() : () -> ()
602 }) : (index, index, index) -> ()
603 }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 1, 0, 0>} : (memref<i32>) -> ()
607 // CHECK-LABEL: omp_simd_pretty
608 func.func @omp_simd_pretty(%lb : index, %ub : index, %step : index) -> () {
611 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
618 // CHECK-LABEL: func.func @omp_simd_pretty_aligned(
619 func.func @omp_simd_pretty_aligned(%lb : index, %ub : index, %step : index,
620 %data_var : memref<i32>,
621 %data_var1 : memref<i32>) -> () {
622 // CHECK: omp.simd aligned(
623 // CHECK-SAME: %{{.*}} : memref<i32> -> 32 : i64,
624 // CHECK-SAME: %{{.*}} : memref<i32> -> 128 : i64)
625 omp.simd aligned(%data_var : memref<i32> -> 32, %data_var1 : memref<i32> -> 128) {
626 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
633 // CHECK-LABEL: omp_simd_pretty_if
634 func.func @omp_simd_pretty_if(%lb : index, %ub : index, %step : index, %if_cond : i1) -> () {
635 // CHECK: omp.simd if(%{{.*}})
636 omp.simd if(%if_cond) {
637 omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
644 // CHECK-LABEL: func.func @omp_simd_pretty_nontemporal
645 func.func @omp_simd_pretty_nontemporal(%lb : index, %ub : index, %step : index,
646 %data_var : memref<i32>,
647 %data_var1 : memref<i32>) -> () {
648 // CHECK: omp.simd nontemporal(%{{.*}}, %{{.*}} : memref<i32>, memref<i32>)
649 omp.simd nontemporal(%data_var, %data_var1 : memref<i32>, memref<i32>) {
650 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
657 // CHECK-LABEL: omp_simd_pretty_order
658 func.func @omp_simd_pretty_order(%lb : index, %ub : index, %step : index) -> () {
659 // CHECK: omp.simd order(concurrent)
660 omp.simd order(concurrent) {
661 omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
665 // CHECK: omp.simd order(reproducible:concurrent)
666 omp.simd order(reproducible:concurrent) {
667 omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
671 // CHECK: omp.simd order(unconstrained:concurrent)
672 omp.simd order(unconstrained:concurrent) {
673 omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
680 // CHECK-LABEL: omp_simd_pretty_simdlen
681 func.func @omp_simd_pretty_simdlen(%lb : index, %ub : index, %step : index) -> () {
682 // CHECK: omp.simd simdlen(2)
683 omp.simd simdlen(2) {
684 omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
691 // CHECK-LABEL: omp_simd_pretty_safelen
692 func.func @omp_simd_pretty_safelen(%lb : index, %ub : index, %step : index) -> () {
693 // CHECK: omp.simd safelen(2)
694 omp.simd safelen(2) {
695 omp.loop_nest (%iv): index = (%lb) to (%ub) step (%step) {
702 // CHECK-LABEL: omp_distribute
703 func.func @omp_distribute(%chunk_size : i32, %data_var : memref<i32>, %arg0 : i32) -> () {
704 // CHECK: omp.distribute
705 "omp.distribute" () ({
706 "omp.loop_nest" (%arg0, %arg0, %arg0) ({
708 "omp.yield"() : () -> ()
709 }) : (i32, i32, i32) -> ()
711 // CHECK: omp.distribute
713 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
717 // CHECK: omp.distribute dist_schedule_static
718 omp.distribute dist_schedule_static {
719 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
723 // CHECK: omp.distribute dist_schedule_static dist_schedule_chunk_size(%{{.+}} : i32)
724 omp.distribute dist_schedule_static dist_schedule_chunk_size(%chunk_size : i32) {
725 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
729 // CHECK: omp.distribute order(concurrent)
730 omp.distribute order(concurrent) {
731 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
735 // CHECK: omp.distribute order(reproducible:concurrent)
736 omp.distribute order(reproducible:concurrent) {
737 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
741 // CHECK: omp.distribute order(unconstrained:concurrent)
742 omp.distribute order(unconstrained:concurrent) {
743 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
747 // CHECK: omp.distribute allocate(%{{.+}} : memref<i32> -> %{{.+}} : memref<i32>)
748 omp.distribute allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
749 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
753 // CHECK: omp.distribute
756 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
765 // CHECK-LABEL: omp_target
766 func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32, %device_ptr: memref<i32>, %device_addr: memref<?xi32>, %map1: memref<?xi32>, %map2: memref<?xi32>) -> () {
768 // Test with optional operands; if_expr, device, thread_limit, private, firstprivate and nowait.
769 // CHECK: omp.target device({{.*}}) if({{.*}}) nowait thread_limit({{.*}})
770 "omp.target"(%device, %if_cond, %num_threads) ({
771 // CHECK: omp.terminator
773 }) {nowait, operandSegmentSizes = array<i32: 0,0,0,1,0,0,1,0,0,0,0,1>} : ( si32, i1, i32 ) -> ()
775 // Test with optional map clause.
776 // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
777 // CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
778 // CHECK: omp.target has_device_addr(%[[VAL_5:.*]] : memref<?xi32>) is_device_ptr(%[[VAL_4:.*]] : memref<i32>) map_entries(%[[MAP_A]] -> {{.*}}, %[[MAP_B]] -> {{.*}} : memref<?xi32>, memref<?xi32>) {
779 %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
780 %mapv2 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
781 omp.target is_device_ptr(%device_ptr : memref<i32>) has_device_addr(%device_addr : memref<?xi32>) map_entries(%mapv1 -> %arg0, %mapv2 -> %arg1 : memref<?xi32>, memref<?xi32>) {
784 // CHECK: %[[MAP_C:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""}
785 // CHECK: %[[MAP_D:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
786 // CHECK: omp.target map_entries(%[[MAP_C]] -> {{.*}}, %[[MAP_D]] -> {{.*}} : memref<?xi32>, memref<?xi32>) {
787 %mapv3 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32> {name = ""}
788 %mapv4 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
789 omp.target map_entries(%mapv3 -> %arg0, %mapv4 -> %arg1 : memref<?xi32>, memref<?xi32>) {
792 // CHECK: omp.barrier
798 func.func @omp_target_data (%if_cond : i1, %device : si32, %device_ptr: memref<i32>, %device_addr: memref<?xi32>, %map1: memref<?xi32>, %map2: memref<?xi32>) -> () {
799 // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
800 // CHECK: omp.target_data device(%[[VAL_1:.*]] : si32) if(%[[VAL_0:.*]]) map_entries(%[[MAP_A]] : memref<?xi32>)
801 %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(always, from) capture(ByRef) -> memref<?xi32> {name = ""}
802 omp.target_data if(%if_cond) device(%device : si32) map_entries(%mapv1 : memref<?xi32>){}
804 // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(close, present, to) capture(ByRef) -> memref<?xi32> {name = ""}
805 // CHECK: omp.target_data map_entries(%[[MAP_A]] : memref<?xi32>) use_device_addr(%[[VAL_3:.*]] -> %{{.*}} : memref<?xi32>) use_device_ptr(%[[VAL_4:.*]] -> %{{.*}} : memref<i32>)
806 %mapv2 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(close, present, to) capture(ByRef) -> memref<?xi32> {name = ""}
807 omp.target_data map_entries(%mapv2 : memref<?xi32>) use_device_addr(%device_addr -> %arg0 : memref<?xi32>) use_device_ptr(%device_ptr -> %arg1 : memref<i32>) {
811 // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
812 // CHECK: %[[MAP_B:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
813 // CHECK: omp.target_data map_entries(%[[MAP_A]], %[[MAP_B]] : memref<?xi32>, memref<?xi32>)
814 %mapv3 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
815 %mapv4 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
816 omp.target_data map_entries(%mapv3, %mapv4 : memref<?xi32>, memref<?xi32>) {}
818 // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_3:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
819 // CHECK: omp.target_enter_data device(%[[VAL_1:.*]] : si32) if(%[[VAL_0:.*]]) map_entries(%[[MAP_A]] : memref<?xi32>) nowait
820 %mapv5 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
821 omp.target_enter_data if(%if_cond) device(%device : si32) nowait map_entries(%mapv5 : memref<?xi32>)
823 // CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_3:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
824 // CHECK: omp.target_exit_data device(%[[VAL_1:.*]] : si32) if(%[[VAL_0:.*]]) map_entries(%[[MAP_A]] : memref<?xi32>) nowait
825 %mapv6 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
826 omp.target_exit_data if(%if_cond) device(%device : si32) nowait map_entries(%mapv6 : memref<?xi32>)
831 // CHECK-LABEL: omp_target_pretty
832 func.func @omp_target_pretty(%if_cond : i1, %device : si32, %num_threads : i32) -> () {
833 // CHECK: omp.target device({{.*}}) if({{.*}})
834 omp.target if(%if_cond) device(%device : si32) {
838 // CHECK: omp.target device({{.*}}) if({{.*}}) nowait
839 omp.target if(%if_cond) device(%device : si32) thread_limit(%num_threads : i32) nowait {
846 // CHECK: omp.declare_reduction
847 // CHECK-LABEL: @add_f32
850 // CHECK: ^{{.+}}(%{{.+}}: f32):
853 // CHECK: ^{{.+}}(%{{.+}}: f32, %{{.+}}: f32):
856 // CHECK: ^{{.+}}(%{{.+}}: !llvm.ptr, %{{.+}}: !llvm.ptr):
860 omp.declare_reduction @add_f32 : f32
863 %0 = arith.constant 0.0 : f32
867 ^bb1(%arg0: f32, %arg1: f32):
868 %1 = arith.addf %arg0, %arg1 : f32
872 ^bb2(%arg2: !llvm.ptr, %arg3: !llvm.ptr):
873 %2 = llvm.load %arg3 : !llvm.ptr -> f32
874 llvm.atomicrmw fadd %arg2, %2 monotonic : !llvm.ptr, f32
882 // CHECK-LABEL: func @wsloop_reduction
883 func.func @wsloop_reduction(%lb : index, %ub : index, %step : index) {
884 %c1 = arith.constant 1 : i32
885 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
886 // CHECK: reduction(@add_f32 %{{.+}} -> %[[PRV:.+]] : !llvm.ptr)
887 omp.wsloop reduction(@add_f32 %0 -> %prv : !llvm.ptr) {
888 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
889 // CHECK: %[[CST:.+]] = arith.constant 2.0{{.*}} : f32
890 %cst = arith.constant 2.0 : f32
891 // CHECK: %[[LPRV:.+]] = llvm.load %[[PRV]] : !llvm.ptr -> f32
892 %lprv = llvm.load %prv : !llvm.ptr -> f32
893 // CHECK: %[[RES:.+]] = llvm.fadd %[[LPRV]], %[[CST]] : f32
894 %res = llvm.fadd %lprv, %cst: f32
895 // CHECK: llvm.store %[[RES]], %[[PRV]] : f32, !llvm.ptr
896 llvm.store %res, %prv : f32, !llvm.ptr
903 // CHECK-LABEL: func @wsloop_reduction_byref
904 func.func @wsloop_reduction_byref(%lb : index, %ub : index, %step : index) {
905 %c1 = arith.constant 1 : i32
906 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
907 // CHECK: reduction(byref @add_f32 %{{.+}} -> %[[PRV:.+]] : !llvm.ptr)
908 omp.wsloop reduction(byref @add_f32 %0 -> %prv : !llvm.ptr) {
909 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
910 // CHECK: %[[CST:.+]] = arith.constant 2.0{{.*}} : f32
911 %cst = arith.constant 2.0 : f32
912 // CHECK: %[[LPRV:.+]] = llvm.load %[[PRV]] : !llvm.ptr -> f32
913 %lprv = llvm.load %prv : !llvm.ptr -> f32
914 // CHECK: %[[RES:.+]] = llvm.fadd %[[LPRV]], %[[CST]] : f32
915 %res = llvm.fadd %lprv, %cst: f32
916 // CHECK: llvm.store %[[RES]], %[[PRV]] : f32, !llvm.ptr
917 llvm.store %res, %prv : f32, !llvm.ptr
924 // CHECK-LABEL: func @parallel_reduction
925 func.func @parallel_reduction() {
926 %c1 = arith.constant 1 : i32
927 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
928 // CHECK: omp.parallel reduction(@add_f32 {{.+}} -> {{.+}} : !llvm.ptr)
929 omp.parallel reduction(@add_f32 %0 -> %prv : !llvm.ptr) {
930 %1 = arith.constant 2.0 : f32
931 %2 = llvm.load %prv : !llvm.ptr -> f32
932 // CHECK: llvm.fadd %{{.*}}, %{{.*}} : f32
933 %3 = llvm.fadd %1, %2 : f32
934 llvm.store %3, %prv : f32, !llvm.ptr
940 // CHECK-LABEL: func @parallel_reduction_byref
941 func.func @parallel_reduction_byref() {
942 %c1 = arith.constant 1 : i32
943 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
944 // CHECK: omp.parallel reduction(byref @add_f32 {{.+}} -> {{.+}} : !llvm.ptr)
945 omp.parallel reduction(byref @add_f32 %0 -> %prv : !llvm.ptr) {
946 %1 = arith.constant 2.0 : f32
947 %2 = llvm.load %prv : !llvm.ptr -> f32
948 // CHECK: llvm.fadd %{{.*}}, %{{.*}} : f32
949 %3 = llvm.fadd %1, %2 : f32
950 llvm.store %3, %prv : f32, !llvm.ptr
956 // CHECK: func @parallel_wsloop_reduction
957 func.func @parallel_wsloop_reduction(%lb : index, %ub : index, %step : index) {
958 %c1 = arith.constant 1 : i32
959 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
960 // CHECK: omp.parallel {
962 // CHECK: omp.wsloop reduction(@add_f32 %{{.*}} -> %{{.+}} : !llvm.ptr) {
963 omp.wsloop reduction(@add_f32 %0 -> %prv : !llvm.ptr) {
964 // CHECK: omp.loop_nest (%{{.+}}) : index = (%{{.+}}) to (%{{.+}}) step (%{{.+}}) {
965 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
966 %1 = arith.constant 2.0 : f32
967 %2 = llvm.load %prv : !llvm.ptr -> f32
968 // CHECK: llvm.fadd %{{.+}}, %{{.+}} : f32
969 llvm.fadd %1, %2 : f32
974 // CHECK: omp.terminator
980 // CHECK-LABEL: omp_teams
981 func.func @omp_teams(%lb : i32, %ub : i32, %if_cond : i1, %num_threads : i32,
982 %data_var : memref<i32>) -> () {
983 // Test nesting inside of omp.target
987 // CHECK: omp.terminator
990 // CHECK: omp.terminator
996 %0 = arith.constant 1 : i32
997 // CHECK: omp.terminator
1002 // CHECK: omp.teams num_teams(%{{.+}} : i32 to %{{.+}} : i32)
1003 omp.teams num_teams(%lb : i32 to %ub : i32) {
1004 // CHECK: omp.terminator
1008 // CHECK: omp.teams num_teams( to %{{.+}} : i32)
1009 omp.teams num_teams(to %ub : i32) {
1010 // CHECK: omp.terminator
1015 // CHECK: omp.teams if(%{{.+}})
1016 omp.teams if(%if_cond) {
1017 // CHECK: omp.terminator
1021 // Test thread limit.
1022 // CHECK: omp.teams thread_limit(%{{.+}} : i32)
1023 omp.teams thread_limit(%num_threads : i32) {
1024 // CHECK: omp.terminator
1029 %c1 = arith.constant 1 : i32
1030 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
1031 // CHECK: omp.teams reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) {
1032 omp.teams reduction(@add_f32 %0 -> %arg0 : !llvm.ptr) {
1033 %1 = arith.constant 2.0 : f32
1034 // CHECK: omp.terminator
1038 // Test reduction byref
1039 // CHECK: omp.teams reduction(byref @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) {
1040 omp.teams reduction(byref @add_f32 %0 -> %arg0 : !llvm.ptr) {
1041 %1 = arith.constant 2.0 : f32
1042 // CHECK: omp.terminator
1047 // CHECK: omp.teams allocate(%{{.+}} : memref<i32> -> %{{.+}} : memref<i32>)
1048 omp.teams allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
1049 // CHECK: omp.terminator
1056 // CHECK-LABEL: func @sections_reduction
1057 func.func @sections_reduction() {
1058 %c1 = arith.constant 1 : i32
1059 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
1060 // CHECK: omp.sections reduction(@add_f32 %{{.+}} -> {{.+}} : !llvm.ptr)
1061 omp.sections reduction(@add_f32 %0 -> %arg0 : !llvm.ptr) {
1062 // CHECK: omp.section
1064 ^bb0(%arg1 : !llvm.ptr):
1065 %1 = arith.constant 2.0 : f32
1068 // CHECK: omp.section
1070 ^bb0(%arg1 : !llvm.ptr):
1071 %1 = arith.constant 3.0 : f32
1079 // CHECK-LABEL: func @sections_reduction_byref
1080 func.func @sections_reduction_byref() {
1081 %c1 = arith.constant 1 : i32
1082 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
1083 // CHECK: omp.sections reduction(byref @add_f32 %{{.+}} -> {{.+}} : !llvm.ptr)
1084 omp.sections reduction(byref @add_f32 %0 -> %arg0 : !llvm.ptr) {
1085 // CHECK: omp.section
1087 ^bb0(%arg1 : !llvm.ptr):
1088 %1 = arith.constant 2.0 : f32
1091 // CHECK: omp.section
1093 ^bb0(%arg1 : !llvm.ptr):
1094 %1 = arith.constant 3.0 : f32
1102 // CHECK: omp.declare_reduction
1103 // CHECK-LABEL: @add2_f32
1104 omp.declare_reduction @add2_f32 : f32
1108 %0 = arith.constant 0.0 : f32
1109 omp.yield (%0 : f32)
1113 ^bb1(%arg0: f32, %arg1: f32):
1114 %1 = arith.addf %arg0, %arg1 : f32
1115 omp.yield (%1 : f32)
1117 // CHECK-NOT: atomic
1118 // CHECK-NOT: cleanup
1120 // CHECK-LABEL: func @wsloop_reduction2
1121 func.func @wsloop_reduction2(%lb : index, %ub : index, %step : index) {
1122 %0 = memref.alloca() : memref<1xf32>
1123 // CHECK: omp.wsloop reduction(@add2_f32 %{{.+}} -> %{{.+}} : memref<1xf32>) {
1124 omp.wsloop reduction(@add2_f32 %0 -> %prv : memref<1xf32>) {
1125 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
1126 %1 = arith.constant 2.0 : f32
1127 %2 = arith.constant 0 : index
1128 %3 = memref.load %prv[%2] : memref<1xf32>
1130 %4 = llvm.fadd %1, %3 : f32
1131 memref.store %4, %prv[%2] : memref<1xf32>
1138 // CHECK-LABEL: func @parallel_reduction2
1139 func.func @parallel_reduction2() {
1140 %0 = memref.alloca() : memref<1xf32>
1141 // CHECK: omp.parallel reduction(@add2_f32 %{{.+}} -> %{{.+}} : memref<1xf32>)
1142 omp.parallel reduction(@add2_f32 %0 -> %prv : memref<1xf32>) {
1143 %1 = arith.constant 2.0 : f32
1144 %2 = arith.constant 0 : index
1145 %3 = memref.load %prv[%2] : memref<1xf32>
1147 %4 = llvm.fadd %1, %3 : f32
1148 memref.store %4, %prv[%2] : memref<1xf32>
1154 // CHECK: func @parallel_wsloop_reduction2
1155 func.func @parallel_wsloop_reduction2(%lb : index, %ub : index, %step : index) {
1156 %c1 = arith.constant 1 : i32
1157 %0 = llvm.alloca %c1 x i32 : (i32) -> !llvm.ptr
1158 // CHECK: omp.parallel {
1160 // CHECK: omp.wsloop reduction(@add2_f32 %{{.*}} -> %{{.+}} : !llvm.ptr) {
1161 omp.wsloop reduction(@add2_f32 %0 -> %prv : !llvm.ptr) {
1162 // CHECK: omp.loop_nest (%{{.+}}) : index = (%{{.+}}) to (%{{.+}}) step (%{{.+}}) {
1163 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
1164 %1 = arith.constant 2.0 : f32
1165 %2 = llvm.load %prv : !llvm.ptr -> f32
1166 // CHECK: llvm.fadd %{{.+}}, %{{.+}} : f32
1167 %3 = llvm.fadd %1, %2 : f32
1172 // CHECK: omp.terminator
1178 // CHECK-LABEL: func @sections_reduction2
1179 func.func @sections_reduction2() {
1180 %0 = memref.alloca() : memref<1xf32>
1181 // CHECK: omp.sections reduction(@add2_f32 %{{.+}} -> %{{.+}} : memref<1xf32>)
1182 omp.sections reduction(@add2_f32 %0 -> %arg0 : memref<1xf32>) {
1184 ^bb0(%arg1 : !llvm.ptr):
1185 %1 = arith.constant 2.0 : f32
1189 ^bb0(%arg1 : !llvm.ptr):
1190 %1 = arith.constant 2.0 : f32
1198 // CHECK: omp.critical.declare @mutex1 hint(uncontended)
1199 omp.critical.declare @mutex1 hint(uncontended)
1200 // CHECK: omp.critical.declare @mutex2 hint(contended)
1201 omp.critical.declare @mutex2 hint(contended)
1202 // CHECK: omp.critical.declare @mutex3 hint(nonspeculative)
1203 omp.critical.declare @mutex3 hint(nonspeculative)
1204 // CHECK: omp.critical.declare @mutex4 hint(speculative)
1205 omp.critical.declare @mutex4 hint(speculative)
1206 // CHECK: omp.critical.declare @mutex5 hint(uncontended, nonspeculative)
1207 omp.critical.declare @mutex5 hint(uncontended, nonspeculative)
1208 // CHECK: omp.critical.declare @mutex6 hint(contended, nonspeculative)
1209 omp.critical.declare @mutex6 hint(contended, nonspeculative)
1210 // CHECK: omp.critical.declare @mutex7 hint(uncontended, speculative)
1211 omp.critical.declare @mutex7 hint(uncontended, speculative)
1212 // CHECK: omp.critical.declare @mutex8 hint(contended, speculative)
1213 omp.critical.declare @mutex8 hint(contended, speculative)
1214 // CHECK: omp.critical.declare @mutex9
1215 omp.critical.declare @mutex9 hint(none)
1216 // CHECK: omp.critical.declare @mutex10
1217 omp.critical.declare @mutex10
1220 // CHECK-LABEL: omp_critical
1221 func.func @omp_critical() -> () {
1222 // CHECK: omp.critical
1227 // CHECK: omp.critical(@{{.*}})
1228 omp.critical(@mutex1) {
1234 func.func @omp_ordered(%arg1 : i32, %arg2 : i32, %arg3 : i32,
1235 %vec0 : i64, %vec1 : i64, %vec2 : i64, %vec3 : i64) -> () {
1236 // CHECK: omp.ordered.region
1237 omp.ordered.region {
1238 // CHECK: omp.terminator
1242 omp.wsloop ordered(0) {
1243 omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
1244 // CHECK: omp.ordered.region
1245 omp.ordered.region {
1246 // CHECK: omp.terminator
1253 omp.wsloop ordered(1) {
1254 omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
1255 // Only one DEPEND(SINK: vec) clause
1256 // CHECK: omp.ordered depend_type(dependsink) depend_vec(%{{.*}} : i64) {doacross_num_loops = 1 : i64}
1257 omp.ordered depend_type(dependsink) depend_vec(%vec0 : i64) {doacross_num_loops = 1 : i64}
1259 // CHECK: omp.ordered depend_type(dependsource) depend_vec(%{{.*}} : i64) {doacross_num_loops = 1 : i64}
1260 omp.ordered depend_type(dependsource) depend_vec(%vec0 : i64) {doacross_num_loops = 1 : i64}
1266 omp.wsloop ordered(2) {
1267 omp.loop_nest (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {
1268 // Multiple DEPEND(SINK: vec) clauses
1269 // CHECK: omp.ordered depend_type(dependsink) depend_vec(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : i64, i64, i64, i64) {doacross_num_loops = 2 : i64}
1270 omp.ordered depend_type(dependsink) depend_vec(%vec0, %vec1, %vec2, %vec3 : i64, i64, i64, i64) {doacross_num_loops = 2 : i64}
1272 // CHECK: omp.ordered depend_type(dependsource) depend_vec(%{{.*}}, %{{.*}} : i64, i64) {doacross_num_loops = 2 : i64}
1273 omp.ordered depend_type(dependsource) depend_vec(%vec0, %vec1 : i64, i64) {doacross_num_loops = 2 : i64}
1282 // CHECK-LABEL: omp_atomic_read
1283 // CHECK-SAME: (%[[v:.*]]: memref<i32>, %[[x:.*]]: memref<i32>)
1284 func.func @omp_atomic_read(%v: memref<i32>, %x: memref<i32>) {
1285 // CHECK: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1286 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1287 // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1288 omp.atomic.read %v = %x memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1289 // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(acquire) : memref<i32>, memref<i32>, i32
1290 omp.atomic.read %v = %x memory_order(acquire) : memref<i32>, memref<i32>, i32
1291 // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(relaxed) : memref<i32>, memref<i32>, i32
1292 omp.atomic.read %v = %x memory_order(relaxed) : memref<i32>, memref<i32>, i32
1293 // CHECK: omp.atomic.read %[[v]] = %[[x]] hint(contended, nonspeculative) : memref<i32>, memref<i32>, i32
1294 omp.atomic.read %v = %x hint(nonspeculative, contended) : memref<i32>, memref<i32>, i32
1295 // CHECK: omp.atomic.read %[[v]] = %[[x]] hint(contended, speculative) memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1296 omp.atomic.read %v = %x hint(speculative, contended) memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1297 // CHECK: omp.atomic.read %[[v]] = %[[x]] memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1298 omp.atomic.read %v = %x hint(none) memory_order(seq_cst) : memref<i32>, memref<i32>, i32
1302 // CHECK-LABEL: omp_atomic_write
1303 // CHECK-SAME: (%[[ADDR:.*]]: memref<i32>, %[[VAL:.*]]: i32)
1304 func.func @omp_atomic_write(%addr : memref<i32>, %val : i32) {
1305 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] : memref<i32>, i32
1306 omp.atomic.write %addr = %val : memref<i32>, i32
1307 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(seq_cst) : memref<i32>, i32
1308 omp.atomic.write %addr = %val memory_order(seq_cst) : memref<i32>, i32
1309 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(release) : memref<i32>, i32
1310 omp.atomic.write %addr = %val memory_order(release) : memref<i32>, i32
1311 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] memory_order(relaxed) : memref<i32>, i32
1312 omp.atomic.write %addr = %val memory_order(relaxed) : memref<i32>, i32
1313 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] hint(uncontended, speculative) : memref<i32>, i32
1314 omp.atomic.write %addr = %val hint(speculative, uncontended) : memref<i32>, i32
1315 // CHECK: omp.atomic.write %[[ADDR]] = %[[VAL]] : memref<i32>, i32
1316 omp.atomic.write %addr = %val hint(none) : memref<i32>, i32
1320 // CHECK-LABEL: omp_atomic_update
1321 // CHECK-SAME: (%[[X:.*]]: memref<i32>, %[[EXPR:.*]]: i32, %[[XBOOL:.*]]: memref<i1>, %[[EXPRBOOL:.*]]: i1)
1322 func.func @omp_atomic_update(%x : memref<i32>, %expr : i32, %xBool : memref<i1>, %exprBool : i1) {
1323 // CHECK: omp.atomic.update %[[X]] : memref<i32>
1324 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1325 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1326 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1327 omp.atomic.update %x : memref<i32> {
1329 %newval = llvm.add %xval, %expr : i32
1330 omp.yield(%newval : i32)
1332 // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
1333 // CHECK-NEXT: (%[[XVAL:.*]]: i1):
1334 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.and %[[XVAL]], %[[EXPRBOOL]] : i1
1335 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i1)
1336 omp.atomic.update %xBool : memref<i1> {
1338 %newval = llvm.and %xval, %exprBool : i1
1339 omp.yield(%newval : i1)
1341 // CHECK: omp.atomic.update %[[X]] : memref<i32>
1342 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1343 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.shl %[[XVAL]], %[[EXPR]] : i32
1344 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1346 omp.atomic.update %x : memref<i32> {
1348 %newval = llvm.shl %xval, %expr : i32
1349 omp.yield(%newval : i32)
1351 // CHECK: omp.atomic.update %[[X]] : memref<i32>
1352 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1353 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.intr.smax(%[[XVAL]], %[[EXPR]]) : (i32, i32) -> i32
1354 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1356 omp.atomic.update %x : memref<i32> {
1358 %newval = llvm.intr.smax(%xval, %expr) : (i32, i32) -> i32
1359 omp.yield(%newval : i32)
1362 // CHECK: omp.atomic.update %[[XBOOL]] : memref<i1>
1363 // CHECK-NEXT: (%[[XVAL:.*]]: i1):
1364 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.icmp "eq" %[[XVAL]], %[[EXPRBOOL]] : i1
1365 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i1)
1367 omp.atomic.update %xBool : memref<i1> {
1369 %newval = llvm.icmp "eq" %xval, %exprBool : i1
1370 omp.yield(%newval : i1)
1373 // CHECK: omp.atomic.update %[[X]] : memref<i32> {
1374 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1375 // CHECK-NEXT: omp.yield(%[[XVAL]] : i32)
1377 omp.atomic.update %x : memref<i32> {
1379 omp.yield(%xval:i32)
1382 // CHECK: omp.atomic.update %[[X]] : memref<i32> {
1383 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1384 // CHECK-NEXT: omp.yield(%{{.+}} : i32)
1386 %const = arith.constant 42 : i32
1387 omp.atomic.update %x : memref<i32> {
1389 omp.yield(%const:i32)
1392 // CHECK: omp.atomic.update %[[X]] : memref<i32>
1393 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1394 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1395 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1396 omp.atomic.update hint(none) %x : memref<i32> {
1398 %newval = llvm.add %xval, %expr : i32
1399 omp.yield(%newval : i32)
1402 // CHECK: omp.atomic.update hint(uncontended) %[[X]] : memref<i32>
1403 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1404 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1405 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1406 omp.atomic.update hint(uncontended) %x : memref<i32> {
1408 %newval = llvm.add %xval, %expr : i32
1409 omp.yield(%newval : i32)
1412 // CHECK: omp.atomic.update hint(contended) %[[X]] : memref<i32>
1413 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1414 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1415 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1416 omp.atomic.update hint(contended) %x : memref<i32> {
1418 %newval = llvm.add %xval, %expr : i32
1419 omp.yield(%newval : i32)
1422 // CHECK: omp.atomic.update hint(nonspeculative) %[[X]] : memref<i32>
1423 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1424 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1425 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1426 omp.atomic.update hint(nonspeculative) %x : memref<i32> {
1428 %newval = llvm.add %xval, %expr : i32
1429 omp.yield(%newval : i32)
1432 // CHECK: omp.atomic.update hint(speculative) %[[X]] : memref<i32>
1433 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1434 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1435 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1436 omp.atomic.update hint(speculative) %x : memref<i32> {
1438 %newval = llvm.add %xval, %expr : i32
1439 omp.yield(%newval : i32)
1442 // CHECK: omp.atomic.update hint(uncontended, nonspeculative) %[[X]] : memref<i32>
1443 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1444 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1445 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1446 omp.atomic.update hint(uncontended, nonspeculative) %x : memref<i32> {
1448 %newval = llvm.add %xval, %expr : i32
1449 omp.yield(%newval : i32)
1452 // CHECK: omp.atomic.update hint(contended, nonspeculative) %[[X]] : memref<i32>
1453 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1454 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1455 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1456 omp.atomic.update hint(contended, nonspeculative) %x : memref<i32> {
1458 %newval = llvm.add %xval, %expr : i32
1459 omp.yield(%newval : i32)
1462 // CHECK: omp.atomic.update hint(uncontended, speculative) %[[X]] : memref<i32>
1463 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1464 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1465 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1466 omp.atomic.update hint(uncontended, speculative) %x : memref<i32> {
1468 %newval = llvm.add %xval, %expr : i32
1469 omp.yield(%newval : i32)
1472 // CHECK: omp.atomic.update hint(contended, speculative) %[[X]] : memref<i32>
1473 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1474 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1475 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1476 omp.atomic.update hint(contended, speculative) %x : memref<i32> {
1478 %newval = llvm.add %xval, %expr : i32
1479 omp.yield(%newval : i32)
1482 // CHECK: omp.atomic.update memory_order(seq_cst) %[[X]] : memref<i32>
1483 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1484 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1485 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1486 omp.atomic.update memory_order(seq_cst) %x : memref<i32> {
1488 %newval = llvm.add %xval, %expr : i32
1489 omp.yield(%newval : i32)
1492 // CHECK: omp.atomic.update memory_order(release) %[[X]] : memref<i32>
1493 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1494 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1495 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1496 omp.atomic.update memory_order(release) %x : memref<i32> {
1498 %newval = llvm.add %xval, %expr : i32
1499 omp.yield(%newval : i32)
1502 // CHECK: omp.atomic.update memory_order(relaxed) %[[X]] : memref<i32>
1503 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1504 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1505 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1506 omp.atomic.update memory_order(relaxed) %x : memref<i32> {
1508 %newval = llvm.add %xval, %expr : i32
1509 omp.yield(%newval : i32)
1512 // CHECK: omp.atomic.update hint(uncontended, speculative) memory_order(seq_cst) %[[X]] : memref<i32>
1513 // CHECK-NEXT: (%[[XVAL:.*]]: i32):
1514 // CHECK-NEXT: %[[NEWVAL:.*]] = llvm.add %[[XVAL]], %[[EXPR]] : i32
1515 // CHECK-NEXT: omp.yield(%[[NEWVAL]] : i32)
1516 omp.atomic.update memory_order(seq_cst) hint(uncontended, speculative) %x : memref<i32> {
1518 %newval = llvm.add %xval, %expr : i32
1519 omp.yield(%newval : i32)
1525 // CHECK-LABEL: omp_atomic_capture
1526 // CHECK-SAME: (%[[v:.*]]: memref<i32>, %[[x:.*]]: memref<i32>, %[[expr:.*]]: i32)
1527 func.func @omp_atomic_capture(%v: memref<i32>, %x: memref<i32>, %expr: i32) {
1528 // CHECK: omp.atomic.capture {
1529 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1530 // CHECK-NEXT: (%[[xval:.*]]: i32):
1531 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1532 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1534 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1537 omp.atomic.update %x : memref<i32> {
1539 %newval = llvm.add %xval, %expr : i32
1540 omp.yield(%newval : i32)
1542 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1544 // CHECK: omp.atomic.capture {
1545 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1546 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1547 // CHECK-NEXT: (%[[xval:.*]]: i32):
1548 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1549 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1553 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1554 omp.atomic.update %x : memref<i32> {
1556 %newval = llvm.add %xval, %expr : i32
1557 omp.yield(%newval : i32)
1560 // CHECK: omp.atomic.capture {
1561 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1562 // CHECK-NEXT: omp.atomic.write %[[x]] = %[[expr]] : memref<i32>, i32
1565 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1566 omp.atomic.write %x = %expr : memref<i32>, i32
1569 // CHECK: omp.atomic.capture {
1570 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1571 // CHECK-NEXT: (%[[xval:.*]]: i32):
1572 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1573 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1575 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1577 omp.atomic.capture hint(none) {
1578 omp.atomic.update %x : memref<i32> {
1580 %newval = llvm.add %xval, %expr : i32
1581 omp.yield(%newval : i32)
1583 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1586 // CHECK: omp.atomic.capture hint(uncontended) {
1587 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1588 // CHECK-NEXT: (%[[xval:.*]]: i32):
1589 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1590 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1592 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1594 omp.atomic.capture hint(uncontended) {
1595 omp.atomic.update %x : memref<i32> {
1597 %newval = llvm.add %xval, %expr : i32
1598 omp.yield(%newval : i32)
1600 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1603 // CHECK: omp.atomic.capture hint(contended) {
1604 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1605 // CHECK-NEXT: (%[[xval:.*]]: i32):
1606 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1607 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1609 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1611 omp.atomic.capture hint(contended) {
1612 omp.atomic.update %x : memref<i32> {
1614 %newval = llvm.add %xval, %expr : i32
1615 omp.yield(%newval : i32)
1617 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1620 // CHECK: omp.atomic.capture hint(nonspeculative) {
1621 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1622 // CHECK-NEXT: (%[[xval:.*]]: i32):
1623 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1624 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1626 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1628 omp.atomic.capture hint(nonspeculative) {
1629 omp.atomic.update %x : memref<i32> {
1631 %newval = llvm.add %xval, %expr : i32
1632 omp.yield(%newval : i32)
1634 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1637 // CHECK: omp.atomic.capture hint(speculative) {
1638 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1639 // CHECK-NEXT: (%[[xval:.*]]: i32):
1640 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1641 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1643 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1645 omp.atomic.capture hint(speculative) {
1646 omp.atomic.update %x : memref<i32> {
1648 %newval = llvm.add %xval, %expr : i32
1649 omp.yield(%newval : i32)
1651 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1654 // CHECK: omp.atomic.capture hint(uncontended, nonspeculative) {
1655 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1656 // CHECK-NEXT: (%[[xval:.*]]: i32):
1657 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1658 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1660 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1662 omp.atomic.capture hint(uncontended, nonspeculative) {
1663 omp.atomic.update %x : memref<i32> {
1665 %newval = llvm.add %xval, %expr : i32
1666 omp.yield(%newval : i32)
1668 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1671 // CHECK: omp.atomic.capture hint(contended, nonspeculative) {
1672 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1673 // CHECK-NEXT: (%[[xval:.*]]: i32):
1674 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1675 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1677 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1679 omp.atomic.capture hint(contended, nonspeculative) {
1680 omp.atomic.update %x : memref<i32> {
1682 %newval = llvm.add %xval, %expr : i32
1683 omp.yield(%newval : i32)
1685 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1688 // CHECK: omp.atomic.capture hint(uncontended, speculative) {
1689 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1690 // CHECK-NEXT: (%[[xval:.*]]: i32):
1691 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1692 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1694 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1696 omp.atomic.capture hint(uncontended, speculative) {
1697 omp.atomic.update %x : memref<i32> {
1699 %newval = llvm.add %xval, %expr : i32
1700 omp.yield(%newval : i32)
1702 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1705 // CHECK: omp.atomic.capture hint(contended, speculative) {
1706 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1707 // CHECK-NEXT: (%[[xval:.*]]: i32):
1708 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1709 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1711 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1713 omp.atomic.capture hint(contended, speculative) {
1714 omp.atomic.update %x : memref<i32> {
1716 %newval = llvm.add %xval, %expr : i32
1717 omp.yield(%newval : i32)
1719 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1722 // CHECK: omp.atomic.capture memory_order(seq_cst) {
1723 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1724 // CHECK-NEXT: (%[[xval:.*]]: i32):
1725 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1726 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1728 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1730 omp.atomic.capture memory_order(seq_cst) {
1731 omp.atomic.update %x : memref<i32> {
1733 %newval = llvm.add %xval, %expr : i32
1734 omp.yield(%newval : i32)
1736 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1739 // CHECK: omp.atomic.capture memory_order(acq_rel) {
1740 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1741 // CHECK-NEXT: (%[[xval:.*]]: i32):
1742 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1743 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1745 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1747 omp.atomic.capture memory_order(acq_rel) {
1748 omp.atomic.update %x : memref<i32> {
1750 %newval = llvm.add %xval, %expr : i32
1751 omp.yield(%newval : i32)
1753 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1756 // CHECK: omp.atomic.capture memory_order(acquire) {
1757 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1758 // CHECK-NEXT: (%[[xval:.*]]: i32):
1759 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1760 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1762 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1764 omp.atomic.capture memory_order(acquire) {
1765 omp.atomic.update %x : memref<i32> {
1767 %newval = llvm.add %xval, %expr : i32
1768 omp.yield(%newval : i32)
1770 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1773 // CHECK: omp.atomic.capture memory_order(release) {
1774 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1775 // CHECK-NEXT: (%[[xval:.*]]: i32):
1776 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1777 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1779 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1781 omp.atomic.capture memory_order(release) {
1782 omp.atomic.update %x : memref<i32> {
1784 %newval = llvm.add %xval, %expr : i32
1785 omp.yield(%newval : i32)
1787 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1790 // CHECK: omp.atomic.capture memory_order(relaxed) {
1791 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1792 // CHECK-NEXT: (%[[xval:.*]]: i32):
1793 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1794 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1796 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1798 omp.atomic.capture memory_order(relaxed) {
1799 omp.atomic.update %x : memref<i32> {
1801 %newval = llvm.add %xval, %expr : i32
1802 omp.yield(%newval : i32)
1804 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1807 // CHECK: omp.atomic.capture hint(contended, speculative) memory_order(seq_cst) {
1808 // CHECK-NEXT: omp.atomic.update %[[x]] : memref<i32>
1809 // CHECK-NEXT: (%[[xval:.*]]: i32):
1810 // CHECK-NEXT: %[[newval:.*]] = llvm.add %[[xval]], %[[expr]] : i32
1811 // CHECK-NEXT: omp.yield(%[[newval]] : i32)
1813 // CHECK-NEXT: omp.atomic.read %[[v]] = %[[x]] : memref<i32>, memref<i32>, i32
1815 omp.atomic.capture hint(contended, speculative) memory_order(seq_cst) {
1816 omp.atomic.update %x : memref<i32> {
1818 %newval = llvm.add %xval, %expr : i32
1819 omp.yield(%newval : i32)
1821 omp.atomic.read %v = %x : memref<i32>, memref<i32>, i32
1827 // CHECK-LABEL: omp_sectionsop
1828 func.func @omp_sectionsop(%data_var1 : memref<i32>, %data_var2 : memref<i32>,
1829 %data_var3 : memref<i32>, %redn_var : !llvm.ptr) {
1830 // CHECK: omp.sections allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
1831 "omp.sections" (%data_var1, %data_var1) ({
1832 // CHECK: omp.terminator
1834 }) {operandSegmentSizes = array<i32: 1,1,0,0>} : (memref<i32>, memref<i32>) -> ()
1836 // CHECK: omp.sections reduction(@add_f32 %{{.*}} -> %{{.*}} : !llvm.ptr)
1837 "omp.sections" (%redn_var) ({
1838 ^bb0(%arg0: !llvm.ptr):
1839 // CHECK: omp.terminator
1841 }) {operandSegmentSizes = array<i32: 0,0,0,1>, reduction_byref = array<i1: false>, reduction_syms=[@add_f32]} : (!llvm.ptr) -> ()
1843 // CHECK: omp.sections nowait {
1844 omp.sections nowait {
1845 // CHECK: omp.terminator
1849 // CHECK: omp.sections reduction(@add_f32 %{{.*}} -> %{{.*}} : !llvm.ptr) {
1850 omp.sections reduction(@add_f32 %redn_var -> %arg0 : !llvm.ptr) {
1851 // CHECK: omp.terminator
1855 // CHECK: omp.sections allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>)
1856 omp.sections allocate(%data_var1 : memref<i32> -> %data_var1 : memref<i32>) {
1857 // CHECK: omp.terminator
1861 // CHECK: omp.sections nowait
1862 omp.sections nowait {
1863 // CHECK: omp.section
1865 // CHECK: %{{.*}} = "test.payload"() : () -> i32
1866 %1 = "test.payload"() : () -> i32
1867 // CHECK: %{{.*}} = "test.payload"() : () -> i32
1868 %2 = "test.payload"() : () -> i32
1869 // CHECK: %{{.*}} = "test.payload"(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
1870 %3 = "test.payload"(%1, %2) : (i32, i32) -> i32
1872 // CHECK: omp.section
1874 // CHECK: %{{.*}} = "test.payload"(%{{.*}}) : (!llvm.ptr) -> i32
1875 %1 = "test.payload"(%redn_var) : (!llvm.ptr) -> i32
1877 // CHECK: omp.section
1879 // CHECK: "test.payload"(%{{.*}}) : (!llvm.ptr) -> ()
1880 "test.payload"(%redn_var) : (!llvm.ptr) -> ()
1882 // CHECK: omp.terminator
1888 // CHECK-LABEL: func @omp_single
1889 func.func @omp_single() {
1891 // CHECK: omp.single {
1893 "test.payload"() : () -> ()
1894 // CHECK: omp.terminator
1897 // CHECK: omp.terminator
1903 // CHECK-LABEL: func @omp_single_nowait
1904 func.func @omp_single_nowait() {
1906 // CHECK: omp.single nowait {
1908 "test.payload"() : () -> ()
1909 // CHECK: omp.terminator
1912 // CHECK: omp.terminator
1918 // CHECK-LABEL: func @omp_single_allocate
1919 func.func @omp_single_allocate(%data_var: memref<i32>) {
1921 // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) {
1922 omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
1923 "test.payload"() : () -> ()
1924 // CHECK: omp.terminator
1927 // CHECK: omp.terminator
1933 // CHECK-LABEL: func @omp_single_allocate_nowait
1934 func.func @omp_single_allocate_nowait(%data_var: memref<i32>) {
1936 // CHECK: omp.single allocate(%{{.*}} : memref<i32> -> %{{.*}} : memref<i32>) nowait {
1937 omp.single allocate(%data_var : memref<i32> -> %data_var : memref<i32>) nowait {
1938 "test.payload"() : () -> ()
1939 // CHECK: omp.terminator
1942 // CHECK: omp.terminator
1948 // CHECK-LABEL: func @omp_single_multiple_blocks
1949 func.func @omp_single_multiple_blocks() {
1950 // CHECK: omp.single {
1954 // CHECK: omp.terminator
1960 func.func private @copy_i32(memref<i32>, memref<i32>)
1962 // CHECK-LABEL: func @omp_single_copyprivate
1963 func.func @omp_single_copyprivate(%data_var: memref<i32>) {
1965 // CHECK: omp.single copyprivate(%{{.*}} -> @copy_i32 : memref<i32>) {
1966 omp.single copyprivate(%data_var -> @copy_i32 : memref<i32>) {
1967 "test.payload"() : () -> ()
1968 // CHECK: omp.terminator
1971 // CHECK: omp.terminator
1977 // CHECK-LABEL: @omp_task
1978 // CHECK-SAME: (%[[bool_var:.*]]: i1, %[[i64_var:.*]]: i64, %[[i32_var:.*]]: i32, %[[data_var:.*]]: memref<i32>, %[[event_handle:.*]]: !llvm.ptr)
1979 func.func @omp_task(%bool_var: i1, %i64_var: i64, %i32_var: i32, %data_var: memref<i32>, %event_handle : !llvm.ptr) {
1981 // Checking simple task
1982 // CHECK: omp.task {
1984 // CHECK: "test.foo"() : () -> ()
1985 "test.foo"() : () -> ()
1986 // CHECK: omp.terminator
1990 // Checking `if` clause
1991 // CHECK: omp.task if(%[[bool_var]]) {
1992 omp.task if(%bool_var) {
1993 // CHECK: "test.foo"() : () -> ()
1994 "test.foo"() : () -> ()
1995 // CHECK: omp.terminator
1999 // Checking `final` clause
2000 // CHECK: omp.task final(%[[bool_var]]) {
2001 omp.task final(%bool_var) {
2002 // CHECK: "test.foo"() : () -> ()
2003 "test.foo"() : () -> ()
2004 // CHECK: omp.terminator
2008 // Checking `untied` clause
2009 // CHECK: omp.task untied {
2011 // CHECK: "test.foo"() : () -> ()
2012 "test.foo"() : () -> ()
2013 // CHECK: omp.terminator
2017 // Checking `in_reduction` clause
2018 %c1 = arith.constant 1 : i32
2019 // CHECK: %[[redn_var1:.*]] = llvm.alloca %{{.*}} x f32 : (i32) -> !llvm.ptr
2020 %0 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr
2021 // CHECK: %[[redn_var2:.*]] = llvm.alloca %{{.*}} x f32 : (i32) -> !llvm.ptr
2022 %1 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr
2023 // CHECK: omp.task in_reduction(@add_f32 %[[redn_var1]] -> %{{.+}}, @add_f32 %[[redn_var2]] -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2024 omp.task in_reduction(@add_f32 %0 -> %arg0, @add_f32 %1 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2025 // CHECK: "test.foo"() : () -> ()
2026 "test.foo"() : () -> ()
2027 // CHECK: omp.terminator
2031 // Checking `in_reduction` clause (mixed) byref
2032 // CHECK: omp.task in_reduction(byref @add_f32 %[[redn_var1]] -> %{{.+}}, @add_f32 %[[redn_var2]] -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2033 omp.task in_reduction(byref @add_f32 %0 -> %arg0, @add_f32 %1 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2034 // CHECK: "test.foo"() : () -> ()
2035 "test.foo"() : () -> ()
2036 // CHECK: omp.terminator
2040 // Checking priority clause
2041 // CHECK: omp.task priority(%[[i32_var]] : i32) {
2042 omp.task priority(%i32_var : i32) {
2043 // CHECK: "test.foo"() : () -> ()
2044 "test.foo"() : () -> ()
2045 // CHECK: omp.terminator
2049 // Checking allocate clause
2050 // CHECK: omp.task allocate(%[[data_var]] : memref<i32> -> %[[data_var]] : memref<i32>) {
2051 omp.task allocate(%data_var : memref<i32> -> %data_var : memref<i32>) {
2052 // CHECK: "test.foo"() : () -> ()
2053 "test.foo"() : () -> ()
2054 // CHECK: omp.terminator
2057 // Checking detach clause
2058 // CHECK: omp.task detach(%[[event_handle]] : !llvm.ptr)
2059 omp.task detach(%event_handle : !llvm.ptr){
2062 // Checking multiple clauses
2063 // CHECK: omp.task allocate(%[[data_var]] : memref<i32> -> %[[data_var]] : memref<i32>)
2064 omp.task allocate(%data_var : memref<i32> -> %data_var : memref<i32>)
2065 // CHECK-SAME: final(%[[bool_var]]) if(%[[bool_var]])
2066 final(%bool_var) if(%bool_var)
2067 // CHECK-SAME: priority(%[[i32_var]] : i32) untied
2068 priority(%i32_var : i32) untied
2069 // CHECK-SAME: in_reduction(@add_f32 %[[redn_var1]] -> %{{.+}}, byref @add_f32 %[[redn_var2]] -> %{{.+}} : !llvm.ptr, !llvm.ptr)
2070 in_reduction(@add_f32 %0 -> %arg0, byref @add_f32 %1 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2071 // CHECK: "test.foo"() : () -> ()
2072 "test.foo"() : () -> ()
2073 // CHECK: omp.terminator
2080 // CHECK-LABEL: @omp_task_depend
2081 // CHECK-SAME: (%arg0: memref<i32>, %arg1: memref<i32>) {
2082 func.func @omp_task_depend(%arg0: memref<i32>, %arg1: memref<i32>) {
2083 // CHECK: omp.task depend(taskdependin -> %arg0 : memref<i32>, taskdependin -> %arg1 : memref<i32>, taskdependinout -> %arg0 : memref<i32>) {
2084 omp.task depend(taskdependin -> %arg0 : memref<i32>, taskdependin -> %arg1 : memref<i32>, taskdependinout -> %arg0 : memref<i32>) {
2085 // CHECK: "test.foo"() : () -> ()
2086 "test.foo"() : () -> ()
2087 // CHECK: omp.terminator
2094 // CHECK-LABEL: @omp_target_depend
2095 // CHECK-SAME: (%arg0: memref<i32>, %arg1: memref<i32>) {
2096 func.func @omp_target_depend(%arg0: memref<i32>, %arg1: memref<i32>) {
2097 // CHECK: omp.target depend(taskdependin -> %arg0 : memref<i32>, taskdependin -> %arg1 : memref<i32>, taskdependinout -> %arg0 : memref<i32>) {
2098 omp.target depend(taskdependin -> %arg0 : memref<i32>, taskdependin -> %arg1 : memref<i32>, taskdependinout -> %arg0 : memref<i32>) {
2099 // CHECK: omp.terminator
2101 } {operandSegmentSizes = array<i32: 0,0,0,3,0,0,0,0>}
2105 func.func @omp_threadprivate() {
2106 %0 = arith.constant 1 : i32
2107 %1 = arith.constant 2 : i32
2108 %2 = arith.constant 3 : i32
2110 // CHECK: [[ARG0:%.*]] = llvm.mlir.addressof @_QFsubEx : !llvm.ptr
2111 // CHECK: {{.*}} = omp.threadprivate [[ARG0]] : !llvm.ptr -> !llvm.ptr
2112 %3 = llvm.mlir.addressof @_QFsubEx : !llvm.ptr
2113 %4 = omp.threadprivate %3 : !llvm.ptr -> !llvm.ptr
2114 llvm.store %0, %4 : i32, !llvm.ptr
2116 // CHECK: omp.parallel
2117 // CHECK: {{.*}} = omp.threadprivate [[ARG0]] : !llvm.ptr -> !llvm.ptr
2119 %5 = omp.threadprivate %3 : !llvm.ptr -> !llvm.ptr
2120 llvm.store %1, %5 : i32, !llvm.ptr
2123 llvm.store %2, %4 : i32, !llvm.ptr
2127 llvm.mlir.global internal @_QFsubEx() : i32
2129 func.func @omp_cancel_parallel(%if_cond : i1) -> () {
2130 // Test with optional operand; if_expr.
2132 // CHECK: omp.cancel cancellation_construct_type(parallel) if(%{{.*}})
2133 omp.cancel cancellation_construct_type(parallel) if(%if_cond)
2134 // CHECK: omp.terminator
2140 func.func @omp_cancel_wsloop(%lb : index, %ub : index, %step : index) {
2142 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2143 // CHECK: omp.cancel cancellation_construct_type(loop)
2144 omp.cancel cancellation_construct_type(loop)
2152 func.func @omp_cancel_sections() -> () {
2155 // CHECK: omp.cancel cancellation_construct_type(sections)
2156 omp.cancel cancellation_construct_type(sections)
2159 // CHECK: omp.terminator
2165 func.func @omp_cancellationpoint_parallel() -> () {
2167 // CHECK: omp.cancellation_point cancellation_construct_type(parallel)
2168 omp.cancellation_point cancellation_construct_type(parallel)
2169 // CHECK: omp.cancel cancellation_construct_type(parallel)
2170 omp.cancel cancellation_construct_type(parallel)
2176 func.func @omp_cancellationpoint_wsloop(%lb : index, %ub : index, %step : index) {
2178 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2179 // CHECK: omp.cancellation_point cancellation_construct_type(loop)
2180 omp.cancellation_point cancellation_construct_type(loop)
2181 // CHECK: omp.cancel cancellation_construct_type(loop)
2182 omp.cancel cancellation_construct_type(loop)
2190 func.func @omp_cancellationpoint_sections() -> () {
2193 // CHECK: omp.cancellation_point cancellation_construct_type(sections)
2194 omp.cancellation_point cancellation_construct_type(sections)
2195 // CHECK: omp.cancel cancellation_construct_type(sections)
2196 omp.cancel cancellation_construct_type(sections)
2199 // CHECK: omp.terminator
2205 // CHECK-LABEL: @omp_taskgroup_no_tasks
2206 func.func @omp_taskgroup_no_tasks() -> () {
2208 // CHECK: omp.taskgroup
2210 // CHECK: "test.foo"() : () -> ()
2211 "test.foo"() : () -> ()
2212 // CHECK: omp.terminator
2218 // CHECK-LABEL: @omp_taskgroup_multiple_tasks
2219 func.func @omp_taskgroup_multiple_tasks() -> () {
2220 // CHECK: omp.taskgroup
2224 "test.foo"() : () -> ()
2225 // CHECK: omp.terminator
2230 "test.foo"() : () -> ()
2231 // CHECK: omp.terminator
2234 // CHECK: omp.terminator
2240 // CHECK-LABEL: @omp_taskgroup_clauses
2241 func.func @omp_taskgroup_clauses() -> () {
2242 %testmemref = "test.memref"() : () -> (memref<i32>)
2243 %testf32 = "test.f32"() : () -> (!llvm.ptr)
2244 // CHECK: omp.taskgroup allocate(%{{.+}}: memref<i32> -> %{{.+}} : memref<i32>) task_reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr)
2245 omp.taskgroup allocate(%testmemref : memref<i32> -> %testmemref : memref<i32>) task_reduction(@add_f32 %testf32 -> %arg0 : !llvm.ptr) {
2248 "test.foo"() : () -> ()
2249 // CHECK: omp.terminator
2254 "test.foo"() : () -> ()
2255 // CHECK: omp.terminator
2258 // CHECK: omp.terminator
2264 // CHECK-LABEL: @omp_taskloop
2265 func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
2267 // CHECK: omp.taskloop {
2269 omp.loop_nest (%i) : i32 = (%lb) to (%ub) step (%step) {
2275 %testbool = "test.bool"() : () -> (i1)
2277 // CHECK: omp.taskloop if(%{{[^)]+}}) {
2278 omp.taskloop if(%testbool) {
2279 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2285 // CHECK: omp.taskloop final(%{{[^)]+}}) {
2286 omp.taskloop final(%testbool) {
2287 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2293 // CHECK: omp.taskloop untied {
2294 omp.taskloop untied {
2295 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2301 // CHECK: omp.taskloop mergeable {
2302 omp.taskloop mergeable {
2303 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2309 %testf32 = "test.f32"() : () -> (!llvm.ptr)
2310 %testf32_2 = "test.f32"() : () -> (!llvm.ptr)
2311 // CHECK: omp.taskloop in_reduction(@add_f32 %{{.+}} -> %{{.+}}, @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2312 omp.taskloop in_reduction(@add_f32 %testf32 -> %arg0, @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2313 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2319 // Checking byref attribute for in_reduction
2320 // CHECK: omp.taskloop in_reduction(byref @add_f32 %{{.+}} -> %{{.+}}, @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2321 omp.taskloop in_reduction(byref @add_f32 %testf32 -> %arg0, @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2322 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2328 // CHECK: omp.taskloop reduction(byref @add_f32 %{{.+}} -> %{{.+}}, @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2329 omp.taskloop reduction(byref @add_f32 %testf32 -> %arg0, @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2330 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2336 // check byref attrbute for reduction
2337 // CHECK: omp.taskloop reduction(byref @add_f32 %{{.+}} -> %{{.+}}, byref @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
2338 omp.taskloop reduction(byref @add_f32 %testf32 -> %arg0, byref @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
2339 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2345 // CHECK: omp.taskloop in_reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) {
2346 omp.taskloop in_reduction(@add_f32 %testf32 -> %arg0 : !llvm.ptr) reduction(@add_f32 %testf32_2 -> %arg1 : !llvm.ptr) {
2347 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2353 %testi32 = "test.i32"() : () -> (i32)
2354 // CHECK: omp.taskloop priority(%{{[^:]+}}: i32) {
2355 omp.taskloop priority(%testi32 : i32) {
2356 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2362 %testmemref = "test.memref"() : () -> (memref<i32>)
2363 // CHECK: omp.taskloop allocate(%{{.+}} : memref<i32> -> %{{.+}} : memref<i32>) {
2364 omp.taskloop allocate(%testmemref : memref<i32> -> %testmemref : memref<i32>) {
2365 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2371 %testi64 = "test.i64"() : () -> (i64)
2372 // CHECK: omp.taskloop grainsize(%{{[^:]+}}: i64) {
2373 omp.taskloop grainsize(%testi64: i64) {
2374 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2380 // CHECK: omp.taskloop num_tasks(%{{[^:]+}}: i64) {
2381 omp.taskloop num_tasks(%testi64: i64) {
2382 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2388 // CHECK: omp.taskloop nogroup {
2389 omp.taskloop nogroup {
2390 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2396 // CHECK: omp.taskloop {
2399 omp.loop_nest (%i, %j) : i32 = (%lb, %ub) to (%ub, %lb) step (%step, %step) {
2410 // CHECK: func.func @omp_requires_one
2411 // CHECK-SAME: omp.requires = #omp<clause_requires reverse_offload>
2412 func.func @omp_requires_one() -> ()
2413 attributes {omp.requires = #omp<clause_requires reverse_offload>} {
2417 // CHECK: func.func @omp_requires_multiple
2418 // CHECK-SAME: omp.requires = #omp<clause_requires unified_address|dynamic_allocators>
2419 func.func @omp_requires_multiple() -> ()
2420 attributes {omp.requires = #omp<clause_requires unified_address|dynamic_allocators>} {
2424 // CHECK-LABEL: @opaque_pointers_atomic_rwu
2425 // CHECK-SAME: (%[[v:.*]]: !llvm.ptr, %[[x:.*]]: !llvm.ptr)
2426 func.func @opaque_pointers_atomic_rwu(%v: !llvm.ptr, %x: !llvm.ptr) {
2427 // CHECK: omp.atomic.read %[[v]] = %[[x]] : !llvm.ptr, !llvm.ptr, i32
2428 // CHECK: %[[VAL:.*]] = llvm.load %[[x]] : !llvm.ptr -> i32
2429 // CHECK: omp.atomic.write %[[v]] = %[[VAL]] : !llvm.ptr, i32
2430 // CHECK: omp.atomic.update %[[x]] : !llvm.ptr {
2431 // CHECK-NEXT: ^{{[[:alnum:]]+}}(%[[XVAL:.*]]: i32):
2432 // CHECK-NEXT: omp.yield(%[[XVAL]] : i32)
2434 omp.atomic.read %v = %x : !llvm.ptr, !llvm.ptr, i32
2435 %val = llvm.load %x : !llvm.ptr -> i32
2436 omp.atomic.write %v = %val : !llvm.ptr, i32
2437 omp.atomic.update %x : !llvm.ptr {
2439 omp.yield(%xval : i32)
2444 // CHECK-LABEL: @opaque_pointers_reduction
2446 // CHECK-NEXT: ^{{[[:alnum:]]+}}(%{{.*}}: !llvm.ptr, %{{.*}}: !llvm.ptr):
2447 // CHECK-NOT: cleanup
2448 omp.declare_reduction @opaque_pointers_reduction : f32
2451 %0 = arith.constant 0.0 : f32
2452 omp.yield (%0 : f32)
2455 ^bb1(%arg0: f32, %arg1: f32):
2456 %1 = arith.addf %arg0, %arg1 : f32
2457 omp.yield (%1 : f32)
2460 ^bb2(%arg2: !llvm.ptr, %arg3: !llvm.ptr):
2461 %2 = llvm.load %arg3 : !llvm.ptr -> f32
2462 llvm.atomicrmw fadd %arg2, %2 monotonic : !llvm.ptr, f32
2466 // CHECK-LABEL: @alloc_reduction
2467 // CHECK-SAME: alloc {
2468 // CHECK-NEXT: ^bb0(%[[ARG0:.*]]: !llvm.ptr):
2471 // CHECK-NEXT: } init {
2472 // CHECK: } combiner {
2474 omp.declare_reduction @alloc_reduction : !llvm.ptr
2476 ^bb0(%arg: !llvm.ptr):
2477 %c1 = arith.constant 1 : i32
2478 %0 = llvm.alloca %c1 x f32 : (i32) -> !llvm.ptr
2479 omp.yield (%0 : !llvm.ptr)
2482 ^bb0(%mold: !llvm.ptr, %alloc: !llvm.ptr):
2483 %cst = arith.constant 1.0 : f32
2484 llvm.store %cst, %alloc : f32, !llvm.ptr
2485 omp.yield (%alloc : !llvm.ptr)
2488 ^bb1(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
2489 %0 = llvm.load %arg0 : !llvm.ptr -> f32
2490 %1 = llvm.load %arg1 : !llvm.ptr -> f32
2491 %2 = arith.addf %0, %1 : f32
2492 llvm.store %2, %arg0 : f32, !llvm.ptr
2493 omp.yield (%arg0 : !llvm.ptr)
2496 // CHECK-LABEL: omp_targets_with_map_bounds
2497 // CHECK-SAME: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr)
2498 func.func @omp_targets_with_map_bounds(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () {
2499 // CHECK: %[[C_00:.*]] = llvm.mlir.constant(4 : index) : i64
2500 // CHECK: %[[C_01:.*]] = llvm.mlir.constant(1 : index) : i64
2501 // CHECK: %[[C_02:.*]] = llvm.mlir.constant(1 : index) : i64
2502 // CHECK: %[[C_03:.*]] = llvm.mlir.constant(1 : index) : i64
2503 // CHECK: %[[BOUNDS0:.*]] = omp.map.bounds lower_bound(%[[C_01]] : i64) upper_bound(%[[C_00]] : i64) stride(%[[C_02]] : i64) start_idx(%[[C_03]] : i64)
2504 // CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""}
2505 %0 = llvm.mlir.constant(4 : index) : i64
2506 %1 = llvm.mlir.constant(1 : index) : i64
2507 %2 = llvm.mlir.constant(1 : index) : i64
2508 %3 = llvm.mlir.constant(1 : index) : i64
2509 %4 = omp.map.bounds lower_bound(%1 : i64) upper_bound(%0 : i64) stride(%2 : i64) start_idx(%3 : i64)
2511 %mapv1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(tofrom) capture(ByRef) bounds(%4) -> !llvm.ptr {name = ""}
2512 // CHECK: %[[C_10:.*]] = llvm.mlir.constant(9 : index) : i64
2513 // CHECK: %[[C_11:.*]] = llvm.mlir.constant(1 : index) : i64
2514 // CHECK: %[[C_12:.*]] = llvm.mlir.constant(2 : index) : i64
2515 // CHECK: %[[C_13:.*]] = llvm.mlir.constant(2 : index) : i64
2516 // CHECK: %[[BOUNDS1:.*]] = omp.map.bounds lower_bound(%[[C_11]] : i64) upper_bound(%[[C_10]] : i64) stride(%[[C_12]] : i64) start_idx(%[[C_13]] : i64)
2517 // CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByCopy) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""}
2518 %6 = llvm.mlir.constant(9 : index) : i64
2519 %7 = llvm.mlir.constant(1 : index) : i64
2520 %8 = llvm.mlir.constant(2 : index) : i64
2521 %9 = llvm.mlir.constant(2 : index) : i64
2522 %10 = omp.map.bounds lower_bound(%7 : i64) upper_bound(%6 : i64) stride(%8 : i64) start_idx(%9 : i64)
2523 %mapv2 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(ByCopy) bounds(%10) -> !llvm.ptr {name = ""}
2525 // CHECK: omp.target map_entries(%[[MAP0]] -> {{.*}}, %[[MAP1]] -> {{.*}} : !llvm.ptr, !llvm.ptr)
2526 omp.target map_entries(%mapv1 -> %arg2, %mapv2 -> %arg3 : !llvm.ptr, !llvm.ptr) {
2530 // CHECK: omp.target_data map_entries(%[[MAP0]], %[[MAP1]] : !llvm.ptr, !llvm.ptr)
2531 omp.target_data map_entries(%mapv1, %mapv2 : !llvm.ptr, !llvm.ptr){}
2533 // CHECK: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(VLAType) bounds(%[[BOUNDS0]]) -> !llvm.ptr {name = ""}
2534 // CHECK: omp.target_enter_data map_entries(%[[MAP2]] : !llvm.ptr)
2535 %mapv3 = omp.map.info var_ptr(%arg0 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(VLAType) bounds(%4) -> !llvm.ptr {name = ""}
2536 omp.target_enter_data map_entries(%mapv3 : !llvm.ptr){}
2538 // CHECK: %[[MAP3:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(This) bounds(%[[BOUNDS1]]) -> !llvm.ptr {name = ""}
2539 // CHECK: omp.target_exit_data map_entries(%[[MAP3]] : !llvm.ptr)
2540 %mapv4 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.array<10 x i32>) map_clauses(exit_release_or_enter_alloc) capture(This) bounds(%10) -> !llvm.ptr {name = ""}
2541 omp.target_exit_data map_entries(%mapv4 : !llvm.ptr){}
2546 // CHECK-LABEL: omp_target_update_data
2547 func.func @omp_target_update_data (%if_cond : i1, %device : si32, %map1: memref<?xi32>, %map2: memref<?xi32>) -> () {
2548 %mapv_from = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32> {name = ""}
2550 %mapv_to = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(present, to) capture(ByRef) -> memref<?xi32> {name = ""}
2552 // CHECK: omp.target_update device(%[[VAL_1:.*]] : si32) if(%[[VAL_0:.*]]) map_entries(%{{.*}}, %{{.*}} : memref<?xi32>, memref<?xi32>) nowait
2553 omp.target_update if(%if_cond) device(%device : si32) nowait map_entries(%mapv_from , %mapv_to : memref<?xi32>, memref<?xi32>)
2557 // CHECK-LABEL: omp_targets_is_allocatable
2558 // CHECK-SAME: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr)
2559 func.func @omp_targets_is_allocatable(%arg0: !llvm.ptr, %arg1: !llvm.ptr) -> () {
2560 // CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
2561 %mapv1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
2562 // CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%[[MAP0]] : [0] : !llvm.ptr) -> !llvm.ptr {name = ""}
2563 %mapv2 = omp.map.info var_ptr(%arg1 : !llvm.ptr, !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) map_clauses(tofrom) capture(ByRef) members(%mapv1 : [0] : !llvm.ptr) -> !llvm.ptr {name = ""}
2564 // CHECK: omp.target map_entries(%[[MAP0]] -> {{.*}}, %[[MAP1]] -> {{.*}} : !llvm.ptr, !llvm.ptr)
2565 omp.target map_entries(%mapv1 -> %arg2, %mapv2 -> %arg3 : !llvm.ptr, !llvm.ptr) {
2571 // CHECK-LABEL: func @omp_target_enter_update_exit_data_depend
2572 // CHECK-SAME:([[ARG0:%.*]]: memref<?xi32>, [[ARG1:%.*]]: memref<?xi32>, [[ARG2:%.*]]: memref<?xi32>) {
2573 func.func @omp_target_enter_update_exit_data_depend(%a: memref<?xi32>, %b: memref<?xi32>, %c: memref<?xi32>) {
2574 // CHECK-NEXT: [[MAP0:%.*]] = omp.map.info
2575 // CHECK-NEXT: [[MAP1:%.*]] = omp.map.info
2576 // CHECK-NEXT: [[MAP2:%.*]] = omp.map.info
2577 %map_a = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32>
2578 %map_b = omp.map.info var_ptr(%b: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32>
2579 %map_c = omp.map.info var_ptr(%c: memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32>
2581 // Do some work on the host that writes to 'a'
2582 omp.task depend(taskdependout -> %a : memref<?xi32>) {
2583 "test.foo"(%a) : (memref<?xi32>) -> ()
2587 // Then map that over to the target
2588 // CHECK: omp.target_enter_data depend(taskdependin -> [[ARG0]] : memref<?xi32>) map_entries([[MAP0]], [[MAP2]] : memref<?xi32>, memref<?xi32>) nowait
2589 omp.target_enter_data depend(taskdependin -> %a: memref<?xi32>) nowait map_entries(%map_a, %map_c: memref<?xi32>, memref<?xi32>)
2591 // Compute 'b' on the target and copy it back
2592 // CHECK: omp.target map_entries([[MAP1]] -> {{%.*}} : memref<?xi32>) {
2593 omp.target map_entries(%map_b -> %arg0 : memref<?xi32>) {
2594 "test.foo"(%arg0) : (memref<?xi32>) -> ()
2598 // Update 'a' on the host using 'b'
2599 omp.task depend(taskdependout -> %a: memref<?xi32>){
2600 "test.bar"(%a, %b) : (memref<?xi32>, memref<?xi32>) -> ()
2603 // Copy the updated 'a' onto the target
2604 // CHECK: omp.target_update depend(taskdependin -> [[ARG0]] : memref<?xi32>) map_entries([[MAP0]] : memref<?xi32>) nowait
2605 omp.target_update depend(taskdependin -> %a : memref<?xi32>) nowait map_entries(%map_a : memref<?xi32>)
2607 // Compute 'c' on the target and copy it back
2608 %map_c_from = omp.map.info var_ptr(%c: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32>
2609 omp.target depend(taskdependout -> %c : memref<?xi32>) map_entries(%map_a -> %arg0, %map_c_from -> %arg1 : memref<?xi32>, memref<?xi32>) {
2610 "test.foobar"() : ()->()
2613 // CHECK: omp.target_exit_data depend(taskdependin -> [[ARG2]] : memref<?xi32>) map_entries([[MAP2]] : memref<?xi32>)
2614 omp.target_exit_data depend(taskdependin -> %c : memref<?xi32>) map_entries(%map_c : memref<?xi32>)
2619 // CHECK-LABEL: omp_map_with_members
2620 // CHECK-SAME: (%[[ARG0:.*]]: !llvm.ptr, %[[ARG1:.*]]: !llvm.ptr, %[[ARG2:.*]]: !llvm.ptr, %[[ARG3:.*]]: !llvm.ptr, %[[ARG4:.*]]: !llvm.ptr, %[[ARG5:.*]]: !llvm.ptr)
2621 func.func @omp_map_with_members(%arg0: !llvm.ptr, %arg1: !llvm.ptr, %arg2: !llvm.ptr, %arg3: !llvm.ptr, %arg4: !llvm.ptr, %arg5: !llvm.ptr) -> () {
2622 // CHECK: %[[MAP0:.*]] = omp.map.info var_ptr(%[[ARG0]] : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
2623 %mapv1 = omp.map.info var_ptr(%arg0 : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
2625 // CHECK: %[[MAP1:.*]] = omp.map.info var_ptr(%[[ARG1]] : !llvm.ptr, f32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
2626 %mapv2 = omp.map.info var_ptr(%arg1 : !llvm.ptr, f32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
2628 // CHECK: %[[MAP2:.*]] = omp.map.info var_ptr(%[[ARG2]] : !llvm.ptr, !llvm.struct<(i32, f32)>) map_clauses(to) capture(ByRef) members(%[[MAP0]], %[[MAP1]] : [0], [1] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {name = "", partial_map = true}
2629 %mapv3 = omp.map.info var_ptr(%arg2 : !llvm.ptr, !llvm.struct<(i32, f32)>) map_clauses(to) capture(ByRef) members(%mapv1, %mapv2 : [0], [1] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {name = "", partial_map = true}
2631 // CHECK: omp.target_enter_data map_entries(%[[MAP0]], %[[MAP1]], %[[MAP2]] : !llvm.ptr, !llvm.ptr, !llvm.ptr)
2632 omp.target_enter_data map_entries(%mapv1, %mapv2, %mapv3 : !llvm.ptr, !llvm.ptr, !llvm.ptr){}
2634 // CHECK: %[[MAP3:.*]] = omp.map.info var_ptr(%[[ARG3]] : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
2635 %mapv4 = omp.map.info var_ptr(%arg3 : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
2637 // CHECK: %[[MAP4:.*]] = omp.map.info var_ptr(%[[ARG4]] : !llvm.ptr, f32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
2638 %mapv5 = omp.map.info var_ptr(%arg4 : !llvm.ptr, f32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
2640 // CHECK: %[[MAP5:.*]] = omp.map.info var_ptr(%[[ARG5]] : !llvm.ptr, !llvm.struct<(i32, struct<(i32, f32)>)>) map_clauses(from) capture(ByRef) members(%[[MAP3]], %[[MAP4]] : [1, 0], [1, 1] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {name = "", partial_map = true}
2641 %mapv6 = omp.map.info var_ptr(%arg5 : !llvm.ptr, !llvm.struct<(i32, struct<(i32, f32)>)>) map_clauses(from) capture(ByRef) members(%mapv4, %mapv5 : [1, 0], [1, 1] : !llvm.ptr, !llvm.ptr) -> !llvm.ptr {name = "", partial_map = true}
2643 // CHECK: omp.target_exit_data map_entries(%[[MAP3]], %[[MAP4]], %[[MAP5]] : !llvm.ptr, !llvm.ptr, !llvm.ptr)
2644 omp.target_exit_data map_entries(%mapv4, %mapv5, %mapv6 : !llvm.ptr, !llvm.ptr, !llvm.ptr){}
2649 // CHECK-LABEL: parallel_op_privatizers
2650 // CHECK-SAME: (%[[ARG0:[^[:space:]]+]]: !llvm.ptr, %[[ARG1:[^[:space:]]+]]: !llvm.ptr)
2651 func.func @parallel_op_privatizers(%arg0: !llvm.ptr, %arg1: !llvm.ptr) {
2652 // CHECK: omp.parallel private(
2653 // CHECK-SAME: @x.privatizer %[[ARG0]] -> %[[ARG0_PRIV:[^[:space:]]+]],
2654 // CHECK-SAME: @y.privatizer %[[ARG1]] -> %[[ARG1_PRIV:[^[:space:]]+]] : !llvm.ptr, !llvm.ptr)
2655 omp.parallel private(@x.privatizer %arg0 -> %arg2, @y.privatizer %arg1 -> %arg3 : !llvm.ptr, !llvm.ptr) {
2656 // CHECK: llvm.load %[[ARG0_PRIV]]
2657 %0 = llvm.load %arg2 : !llvm.ptr -> i32
2658 // CHECK: llvm.load %[[ARG1_PRIV]]
2659 %1 = llvm.load %arg3 : !llvm.ptr -> i32
2665 // CHECK-LABEL: omp.private {type = private} @a.privatizer : !llvm.ptr alloc {
2666 omp.private {type = private} @a.privatizer : !llvm.ptr alloc {
2667 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2668 ^bb0(%arg0: !llvm.ptr):
2669 omp.yield(%arg0 : !llvm.ptr)
2672 // CHECK-LABEL: omp.private {type = private} @x.privatizer : !llvm.ptr alloc {
2673 omp.private {type = private} @x.privatizer : !llvm.ptr alloc {
2674 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2675 ^bb0(%arg0: !llvm.ptr):
2676 omp.yield(%arg0 : !llvm.ptr)
2678 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2679 ^bb0(%arg0: !llvm.ptr):
2683 // CHECK-LABEL: omp.private {type = firstprivate} @y.privatizer : !llvm.ptr alloc {
2684 omp.private {type = firstprivate} @y.privatizer : !llvm.ptr alloc {
2685 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2686 ^bb0(%arg0: !llvm.ptr):
2687 omp.yield(%arg0 : !llvm.ptr)
2690 // CHECK: ^bb0(%{{.*}}: {{.*}}, %{{.*}}: {{.*}}):
2691 ^bb0(%arg0: !llvm.ptr, %arg1: !llvm.ptr):
2692 omp.yield(%arg0 : !llvm.ptr)
2694 // CHECK: ^bb0(%{{.*}}: {{.*}}):
2695 ^bb0(%arg0: !llvm.ptr):
2699 // CHECK-LABEL: parallel_op_reduction_and_private
2700 func.func @parallel_op_reduction_and_private(%priv_var: !llvm.ptr, %priv_var2: !llvm.ptr, %reduc_var: !llvm.ptr, %reduc_var2: !llvm.ptr) {
2701 // CHECK: omp.parallel
2702 // CHECK-SAME: private(
2703 // CHECK-SAME: @x.privatizer %[[PRIV_VAR:[^[:space:]]+]] -> %[[PRIV_ARG:[^[:space:]]+]],
2704 // CHECK-SAME: @y.privatizer %[[PRIV_VAR2:[^[:space:]]+]] -> %[[PRIV_ARG2:[^[:space:]]+]] : !llvm.ptr, !llvm.ptr)
2706 // CHECK-SAME: reduction(
2707 // CHECK-SAME: @add_f32 %[[REDUC_VAR:[^[:space:]]+]] -> %[[REDUC_ARG:[^[:space:]]+]],
2708 // CHECK-SAME: @add_f32 %[[REDUC_VAR2:[^[:space:]]+]] -> %[[REDUC_ARG2:[^[:space:]]+]] : !llvm.ptr, !llvm.ptr)
2709 omp.parallel private(@x.privatizer %priv_var -> %priv_arg, @y.privatizer %priv_var2 -> %priv_arg2 : !llvm.ptr, !llvm.ptr)
2710 reduction(@add_f32 %reduc_var -> %reduc_arg, @add_f32 %reduc_var2 -> %reduc_arg2 : !llvm.ptr, !llvm.ptr) {
2711 // CHECK: llvm.load %[[PRIV_ARG]]
2712 %0 = llvm.load %priv_arg : !llvm.ptr -> f32
2713 // CHECK: llvm.load %[[PRIV_ARG2]]
2714 %1 = llvm.load %priv_arg2 : !llvm.ptr -> f32
2715 // CHECK: llvm.load %[[REDUC_ARG]]
2716 %2 = llvm.load %reduc_arg : !llvm.ptr -> f32
2717 // CHECK: llvm.load %[[REDUC_ARG2]]
2718 %3 = llvm.load %reduc_arg2 : !llvm.ptr -> f32
2724 // CHECK-LABEL: omp_target_private
2725 func.func @omp_target_private(%map1: memref<?xi32>, %map2: memref<?xi32>, %priv_var: !llvm.ptr) -> () {
2726 %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
2727 %mapv2 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
2729 // CHECK: omp.target
2730 // CHECK-SAME: private(
2731 // CHECK-SAME: @x.privatizer %{{[^[:space:]]+}} -> %[[PRIV_ARG:[^[:space:]]+]]
2732 // CHECK-SAME: : !llvm.ptr
2734 omp.target private(@x.privatizer %priv_var -> %priv_arg : !llvm.ptr) {
2738 // CHECK: omp.target
2740 // CHECK-SAME: map_entries(
2741 // CHECK-SAME: %{{[^[:space:]]+}} -> %[[MAP1_ARG:[^[:space:]]+]],
2742 // CHECK-SAME: %{{[^[:space:]]+}} -> %[[MAP2_ARG:[^[:space:]]+]]
2743 // CHECK-SAME: : memref<?xi32>, memref<?xi32>
2746 // CHECK-SAME: private(
2747 // CHECK-SAME: @x.privatizer %{{[^[:space:]]+}} -> %[[PRIV_ARG:[^[:space:]]+]]
2748 // CHECK-SAME: : !llvm.ptr
2750 omp.target map_entries(%mapv1 -> %arg0, %mapv2 -> %arg1 : memref<?xi32>, memref<?xi32>) private(@x.privatizer %priv_var -> %priv_arg : !llvm.ptr) {
2757 // CHECK-LABEL: omp_target_private_with_map_idx
2758 func.func @omp_target_private_with_map_idx(%map1: memref<?xi32>, %map2: memref<?xi32>, %priv_var: !llvm.ptr) -> () {
2759 %mapv1 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(tofrom) capture(ByRef) -> memref<?xi32> {name = ""}
2760 %mapv2 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
2762 // CHECK: omp.target
2764 // CHECK-SAME: map_entries(
2765 // CHECK-SAME: %{{[^[:space:]]+}} -> %[[MAP1_ARG:[^[:space:]]+]],
2766 // CHECK-SAME: %{{[^[:space:]]+}} -> %[[MAP2_ARG:[^[:space:]]+]]
2767 // CHECK-SAME: : memref<?xi32>, memref<?xi32>
2770 // CHECK-SAME: private(
2771 // CHECK-SAME: @x.privatizer %{{[^[:space:]]+}} -> %[[PRIV_ARG:[^[:space:]]+]] [map_idx=1]
2772 // CHECK-SAME: : !llvm.ptr
2774 omp.target map_entries(%mapv1 -> %arg0, %mapv2 -> %arg1 : memref<?xi32>, memref<?xi32>) private(@x.privatizer %priv_var -> %priv_arg [map_idx=1] : !llvm.ptr) {
2781 func.func @omp_target_host_eval(%x : i32) {
2782 // CHECK: omp.target host_eval(%{{.*}} -> %[[HOST_ARG:.*]] : i32) {
2783 // CHECK: omp.teams num_teams( to %[[HOST_ARG]] : i32)
2784 // CHECK-SAME: thread_limit(%[[HOST_ARG]] : i32)
2785 omp.target host_eval(%x -> %arg0 : i32) {
2786 omp.teams num_teams(to %arg0 : i32) thread_limit(%arg0 : i32) {
2792 // CHECK: omp.target host_eval(%{{.*}} -> %[[HOST_ARG:.*]] : i32) {
2793 // CHECK: omp.teams {
2794 // CHECK: omp.parallel num_threads(%[[HOST_ARG]] : i32) {
2795 // CHECK: omp.distribute {
2796 // CHECK: omp.wsloop {
2797 // CHECK: omp.loop_nest (%{{.*}}) : i32 = (%[[HOST_ARG]]) to (%[[HOST_ARG]]) step (%[[HOST_ARG]]) {
2798 omp.target host_eval(%x -> %arg0 : i32) {
2800 omp.parallel num_threads(%arg0 : i32) {
2803 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
2815 // CHECK: omp.target host_eval(%{{.*}} -> %[[HOST_ARG:.*]] : i32) {
2816 // CHECK: omp.teams {
2817 // CHECK: omp.distribute {
2818 // CHECK: omp.loop_nest (%{{.*}}) : i32 = (%[[HOST_ARG]]) to (%[[HOST_ARG]]) step (%[[HOST_ARG]]) {
2819 omp.target host_eval(%x -> %arg0 : i32) {
2822 omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
2833 // CHECK-LABEL: omp_loop
2834 func.func @omp_loop(%lb : index, %ub : index, %step : index) {
2835 // CHECK: omp.loop {
2837 // CHECK: omp.loop_nest {{.*}} {
2838 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2846 // CHECK: omp.loop bind(teams) {
2847 omp.loop bind(teams) {
2848 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2854 // CHECK: omp.loop bind(parallel) {
2855 omp.loop bind(parallel) {
2856 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2862 // CHECK: omp.loop bind(thread) {
2863 omp.loop bind(thread) {
2864 omp.loop_nest (%iv) : index = (%lb) to (%ub) step (%step) {
2873 // CHECK-LABEL: func @omp_workshare
2874 func.func @omp_workshare() {
2875 // CHECK: omp.workshare {
2877 "test.payload"() : () -> ()
2878 // CHECK: omp.terminator
2884 // CHECK-LABEL: func @omp_workshare_nowait
2885 func.func @omp_workshare_nowait() {
2886 // CHECK: omp.workshare nowait {
2887 omp.workshare nowait {
2888 "test.payload"() : () -> ()
2889 // CHECK: omp.terminator
2895 // CHECK-LABEL: func @omp_workshare_multiple_blocks
2896 func.func @omp_workshare_multiple_blocks() {
2897 // CHECK: omp.workshare {
2901 // CHECK: omp.terminator
2907 // CHECK-LABEL: func @omp_workshare_loop_wrapper
2908 func.func @omp_workshare_loop_wrapper(%idx : index) {
2909 // CHECK-NEXT: omp.workshare {
2911 // CHECK-NEXT: omp.workshare.loop_wrapper
2912 omp.workshare.loop_wrapper {
2913 // CHECK-NEXT: omp.loop_nest
2914 omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2923 // CHECK-LABEL: func @omp_workshare_loop_wrapper_attrs
2924 func.func @omp_workshare_loop_wrapper_attrs(%idx : index) {
2925 // CHECK-NEXT: omp.workshare {
2927 // CHECK-NEXT: omp.workshare.loop_wrapper {
2928 omp.workshare.loop_wrapper {
2929 // CHECK-NEXT: omp.loop_nest
2930 omp.loop_nest (%iv) : index = (%idx) to (%idx) step (%idx) {
2933 // CHECK: } {attr_in_dict}