Skip to content

Commit 83bf8e9

Browse files
authored
[flang][OpenMP] Port OpenMP FIR tests for atomic update/capture to HLFIR (#70627)
Port atomic update and capture tests to HLFIR.
1 parent 75881db commit 83bf8e9

File tree

3 files changed

+247
-23
lines changed

3 files changed

+247
-23
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
! This test checks the lowering of atomic capture
2+
3+
! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
4+
! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
5+
6+
7+
8+
program OmpAtomicCapture
9+
use omp_lib
10+
11+
!CHECK: %[[VAL_X_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"}
12+
!CHECK: %[[VAL_X_DECLARE:.*]]:2 = hlfir.declare %[[VAL_X_ALLOCA]] {{.*}}
13+
!CHECK: %[[VAL_Y_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"}
14+
!CHECK: %[[VAL_Y_DECLARE:.*]]:2 = hlfir.declare %[[VAL_Y_ALLOCA]] {{.*}}
15+
integer :: x, y
16+
17+
!CHECK: %[[VAL_Y_LOADED:.*]] = fir.load %[[VAL_X_DECLARE]]#0 : !fir.ref<i32>
18+
!CHECK: omp.atomic.capture hint(uncontended) {
19+
!CHECK: omp.atomic.update %[[VAL_Y_DECLARE]]#1 : !fir.ref<i32> {
20+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
21+
!CHECK: %[[TEMP:.*]] = arith.muli %[[VAL_Y_LOADED]], %[[ARG]] : i32
22+
!CHECK: omp.yield(%[[TEMP]] : i32)
23+
!CHECK: }
24+
!CHECK: omp.atomic.read %[[VAL_X_DECLARE]]#1 = %[[VAL_Y_DECLARE]]#1 : !fir.ref<i32>, i32
25+
!CHECK: }
26+
!$omp atomic hint(omp_sync_hint_uncontended) capture
27+
y = x * y
28+
x = y
29+
!$omp end atomic
30+
31+
!CHECK: %[[VAL_20:.*]] = arith.constant 20 : i32
32+
!CHECK: %[[VAL_8:.*]] = arith.constant 8 : i32
33+
!CHECK: %[[VAL_X_LOADED:.*]] = fir.load %[[VAL_X_DECLARE]]#0 : !fir.ref<i32>
34+
!CHECK: %[[SUB:.*]] = arith.subi %[[VAL_8]], %[[VAL_X_LOADED]] : i32
35+
!CHECK: %[[NO_REASSOC:.*]] = hlfir.no_reassoc %[[SUB]] : i32
36+
!CHECK: %[[ADD:.*]] = arith.addi %[[VAL_20]], %[[NO_REASSOC]] : i32
37+
!CHECK: omp.atomic.capture memory_order(acquire) hint(nonspeculative) {
38+
!CHECK: omp.atomic.read %[[VAL_X_DECLARE]]#1 = %[[VAL_Y_DECLARE]]#1 : !fir.ref<i32>, i32
39+
!CHECK: omp.atomic.write %[[VAL_Y_DECLARE]]#1 = %[[ADD]] : !fir.ref<i32>, i32
40+
!CHECK: }
41+
!CHECK: return
42+
!CHECK: }
43+
!$omp atomic hint(omp_lock_hint_nonspeculative) capture acquire
44+
x = y
45+
y = 2 * 10 + (8 - x)
46+
!$omp end atomic
47+
end program
48+
49+
50+
!CHECK: func.func @_QPpointers_in_atomic_capture() {
51+
subroutine pointers_in_atomic_capture()
52+
53+
!CHECK: %[[VAL_A_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "a", uniq_name = "_QFpointers_in_atomic_captureEa"}
54+
!CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.ptr<i32>
55+
!CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
56+
!CHECK: fir.store %[[EMBOX]] to %[[VAL_A_ALLOCA]] : !fir.ref<!fir.box<!fir.ptr<i32>>>
57+
!CHECK: %[[VAL_A_DECLARE:.*]]:2 = hlfir.declare %[[VAL_A_ALLOCA]] {{.*}}
58+
!CHECK: %[[VAL_B_ALLOCA:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "b", uniq_name = "_QFpointers_in_atomic_captureEb"}
59+
!CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.ptr<i32>
60+
!CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
61+
!CHECK: fir.store %[[EMBOX]] to %[[VAL_B_ALLOCA]] : !fir.ref<!fir.box<!fir.ptr<i32>>>
62+
!CHECK: %[[VAL_B_DECLARE:.*]]:2 = hlfir.declare %[[VAL_B_ALLOCA]] {{.*}}
63+
!CHECK: %[[VAL_C_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "c", fir.target, uniq_name = "_QFpointers_in_atomic_captureEc"}
64+
!CHECK: %[[VAL_C_DECLARE:.*]]:2 = hlfir.declare %[[VAL_C_ALLOCA]] {{.*}}
65+
!CHECK: %[[VAL_D_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "d", fir.target, uniq_name = "_QFpointers_in_atomic_captureEd"}
66+
!CHECK: %[[VAL_D_DECLARE:.*]]:2 = hlfir.declare %[[VAL_D_ALLOCA]] {{.*}}
67+
integer, pointer :: a, b
68+
integer, target :: c, d
69+
70+
!CHECK: %[[EMBOX:.*]] = fir.embox %[[VAL_C_DECLARE]]#1 : (!fir.ref<i32>) -> !fir.box<!fir.ptr<i32>>
71+
!CHECK: fir.store %[[EMBOX]] to %[[VAL_A_DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>
72+
!CHECK: %[[EMBOX:.*]] = fir.embox %[[VAL_D_DECLARE]]#1 : (!fir.ref<i32>) -> !fir.box<!fir.ptr<i32>>
73+
!CHECK: fir.store %[[EMBOX]] to %[[VAL_B_DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>
74+
a=>c
75+
b=>d
76+
77+
!CHECK: %[[VAL_A_LOADED:.*]] = fir.load %[[VAL_A_DECLARE]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
78+
!CHECK: %[[VAL_A_BOX_ADDR:.*]] = fir.box_addr %[[VAL_A_LOADED]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
79+
!CHECK: %[[VAL_B_LOADED:.*]] = fir.load %[[VAL_B_DECLARE]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
80+
!CHECK: %[[VAL_B_BOX_ADDR:.*]] = fir.box_addr %[[VAL_B_LOADED]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
81+
!CHECK: %[[VAL_B_LOADED_2:.*]] = fir.load %[[VAL_B_DECLARE]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
82+
!CHECK: %[[VAL_B_BOX_ADDR_2:.*]] = fir.box_addr %[[VAL_B_LOADED_2]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
83+
!CHECK: %[[VAL_B:.*]] = fir.load %[[VAL_B_BOX_ADDR_2]] : !fir.ptr<i32>
84+
!CHECK: omp.atomic.capture {
85+
!CHECK: omp.atomic.update %[[VAL_A_BOX_ADDR]] : !fir.ptr<i32> {
86+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
87+
!CHECK: %[[TEMP:.*]] = arith.addi %[[ARG]], %[[VAL_B]] : i32
88+
!CHECK: omp.yield(%[[TEMP]] : i32)
89+
!CHECK: }
90+
!CHECK: omp.atomic.read %[[VAL_B_BOX_ADDR]] = %[[VAL_A_BOX_ADDR]] : !fir.ptr<i32>, i32
91+
!CHECK: }
92+
!CHECK: return
93+
!CHECK: }
94+
!$omp atomic capture
95+
a = a + b
96+
b = a
97+
!$omp end atomic
98+
end subroutine

flang/test/Lower/OpenMP/atomic-update-hlfir.f90

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
! This test checks lowering of atomic and atomic update constructs
2+
! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
3+
! RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
4+
5+
program OmpAtomicUpdate
6+
use omp_lib
7+
!CHECK: %[[VAL_A:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "a", uniq_name = "_QFEa"}
8+
!CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.ptr<i32>
9+
!CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
10+
!CHECK: fir.store %[[EMBOX]] to %[[VAL_A]] : !fir.ref<!fir.box<!fir.ptr<i32>>>
11+
!CHECK: %[[VAL_A_DECLARE:.*]]:2 = hlfir.declare %[[VAL_A]] {{.*}}
12+
!CHECK: %[[VAL_B:.*]] = fir.alloca !fir.box<!fir.ptr<i32>> {bindc_name = "b", uniq_name = "_QFEb"}
13+
!CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.ptr<i32>
14+
!CHECK: %[[EMBOX:.*]] = fir.embox %[[ZERO]] : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
15+
!CHECK: fir.store %[[EMBOX]] to %[[VAL_B]] : !fir.ref<!fir.box<!fir.ptr<i32>>>
16+
!CHECK: %[[VAL_B_DECLARE:.*]]:2 = hlfir.declare %[[VAL_B]] {{.*}}
17+
!CHECK: %[[VAL_C_ADDRESS:.*]] = fir.address_of(@_QFEc) : !fir.ref<i32>
18+
!CHECK: %[[VAL_C_DECLARE:.*]]:2 = hlfir.declare %[[VAL_C_ADDRESS]] {{.*}}
19+
!CHECK: %[[VAL_D_ADDRESS:.*]] = fir.address_of(@_QFEd) : !fir.ref<i32>
20+
!CHECK: %[[VAL_D_DECLARE:.*]]:2 = hlfir.declare %[[VAL_D_ADDRESS]] {{.}}
21+
!CHECK: %[[VAL_i1_ALLOCA:.*]] = fir.alloca i8 {bindc_name = "i1", uniq_name = "_QFEi1"}
22+
!CHECK: %[[VAL_i1_DECLARE:.*]]:2 = hlfir.declare %[[VAL_i1_ALLOCA]] {{.*}}
23+
!CHECK: %[[VAL_c5:.*]] = arith.constant 5 : index
24+
!CHECK: %[[VAL_K_ALLOCA:.*]] = fir.alloca !fir.array<5xi32> {bindc_name = "k", uniq_name = "_QFEk"}
25+
!CHECK: %[[VAL_K_SHAPED:.*]] = fir.shape %[[VAL_c5]] : (index) -> !fir.shape<1>
26+
!CHECK: %[[VAL_K_DECLARE:.*]]:2 = hlfir.declare %[[VAL_K_ALLOCA]](%[[VAL_K_SHAPED]]) {{.*}}
27+
28+
!CHECK: %[[VAL_X_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFEx"}
29+
!CHECK: %[[VAL_X_DECLARE:.*]]:2 = hlfir.declare %[[VAL_X_ALLOCA]] {uniq_name = "_QFEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
30+
!CHECK: %[[VAL_Y_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFEy"}
31+
!CHECK: %[[VAL_Y_DECLARE:.*]]:2 = hlfir.declare %[[VAL_Y_ALLOCA]] {uniq_name = "_QFEy"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
32+
!CHECK: %[[VAL_Z_ALLOCA:.*]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFEz"}
33+
!CHECK: %[[VAL_Z_DECLARE:.*]]:2 = hlfir.declare %[[VAL_Z_ALLOCA]] {uniq_name = "_QFEz"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
34+
integer :: x, y, z
35+
integer, pointer :: a, b
36+
integer, target :: c, d
37+
integer(1) :: i1
38+
integer, dimension(5) :: k
39+
40+
!CHECK: %[[EMBOX:.*]] = fir.embox %[[VAL_C_DECLARE]]#1 : (!fir.ref<i32>) -> !fir.box<!fir.ptr<i32>>
41+
!CHECK: fir.store %[[EMBOX]] to %[[VAL_A_DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>
42+
!CHECK: %[[EMBOX:.*]] = fir.embox %[[VAL_D_DECLARE]]#1 : (!fir.ref<i32>) -> !fir.box<!fir.ptr<i32>>
43+
!CHECK: fir.store %[[EMBOX]] to %[[VAL_B_DECLARE]]#1 : !fir.ref<!fir.box<!fir.ptr<i32>>>
44+
a=>c
45+
b=>d
46+
47+
!CHECK: %[[VAL_c3:.*]] = arith.constant 3 : index
48+
!CHECK: %[[VAL_K_DESIGNATE:.*]] = hlfir.designate %[[VAL_K_DECLARE]]#0 (%[[VAL_c3]]) : (!fir.ref<!fir.array<5xi32>>, index) -> !fir.ref<i32>
49+
!CHECK: %[[LOADED_Z:.*]] = fir.load %[[VAL_Z_DECLARE]]#0 : !fir.ref<i32>
50+
!CHECK: omp.atomic.update %[[VAL_K_DESIGNATE]] : !fir.ref<i32> {
51+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
52+
!CHECK: %[[TEMP:.*]] = arith.muli %[[LOADED_Z]], %[[ARG]] : i32
53+
!CHECK: omp.yield(%[[TEMP]] : i32)
54+
!CHECK: }
55+
!$omp atomic update
56+
k(3) = z * k(3)
57+
58+
!CHECK: %[[VAL_A_LOADED:.*]] = fir.load %[[VAL_A_DECLARE]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
59+
!CHECK: %[[VAL_A_BOX_ADDR:.*]] = fir.box_addr %[[VAL_A_LOADED]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
60+
!CHECK: %[[VAL_B_LOADED:.*]] = fir.load %[[VAL_B_DECLARE]]#0 : !fir.ref<!fir.box<!fir.ptr<i32>>>
61+
!CHECK: %[[VAL_B_BOX_ADDR:.*]] = fir.box_addr %[[VAL_B_LOADED]] : (!fir.box<!fir.ptr<i32>>) -> !fir.ptr<i32>
62+
!CHECK: %[[VAL_B:.*]] = fir.load %[[VAL_B_BOX_ADDR]] : !fir.ptr<i32>
63+
!CHECK: omp.atomic.update %[[VAL_A_BOX_ADDR]] : !fir.ptr<i32> {
64+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
65+
!CHECK: %[[TEMP:.*]] = arith.addi %[[ARG]], %[[VAL_B]] : i32
66+
!CHECK: omp.yield(%[[TEMP]] : i32)
67+
!CHECK: }
68+
!$omp atomic update
69+
a = a + b
70+
71+
!CHECK: %[[VAL_c1:.*]] = arith.constant 1 : i32
72+
!CHECK: omp.atomic.update %[[VAL_Y_DECLARE]]#1 : !fir.ref<i32> {
73+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
74+
!CHECK: %[[TEMP:.*]] = arith.addi %[[ARG]], %[[VAL_c1]] : i32
75+
!CHECK: omp.yield(%[[TEMP]] : i32)
76+
!CHECK: }
77+
!$omp atomic
78+
y = y + 1
79+
80+
!CHECK: %[[VAL_X_LOADED:.*]] = fir.load %[[VAL_X_DECLARE]]#0 : !fir.ref<i32>
81+
!CHECK: omp.atomic.update %[[VAL_Z_DECLARE]]#1 : !fir.ref<i32> {
82+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
83+
!CHECK: %[[TEMP:.*]] = arith.muli %[[VAL_X_LOADED]], %[[ARG]] : i32
84+
!CHECK: omp.yield(%[[TEMP]] : i32)
85+
!CHECK: }
86+
!$omp atomic update
87+
z = x * z
88+
89+
!CHECK: %[[VAL_c1:.*]] = arith.constant 1 : i32
90+
!CHECK: omp.atomic.update memory_order(relaxed) hint(uncontended) %[[VAL_X_DECLARE]]#1 : !fir.ref<i32> {
91+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
92+
!CHECK: %[[TEMP:.*]] = arith.subi %[[ARG]], %[[VAL_c1]] : i32
93+
!CHECK: omp.yield(%[[TEMP]] : i32)
94+
!CHECK: }
95+
!$omp atomic relaxed update hint(omp_sync_hint_uncontended)
96+
x = x - 1
97+
98+
!CHECK: omp.atomic.update memory_order(relaxed) %[[VAL_Y_DECLARE]]#1 : !fir.ref<i32> {
99+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
100+
!CHECK: %[[VAL_C_LOADED:.*]] = fir.load %[[VAL_C_DECLARE]]#0 : !fir.ref<i32>
101+
!CHECK: %[[VAL_D_LOADED:.*]] = fir.load %[[VAL_D_DECLARE]]#0 : !fir.ref<i32>
102+
!CHECK: {{.*}} = arith.cmpi sgt, %[[ARG]], {{.*}} : i32
103+
!CHECK: {{.*}} = arith.select {{.*}}, %[[ARG]], {{.*}} : i32
104+
!CHECK: {{.*}} = arith.cmpi sgt, {{.*}}
105+
!CHECK: %[[TEMP:.*]] = arith.select {{.*}} : i32
106+
!CHECK: omp.yield(%[[TEMP]] : i32)
107+
!CHECK: }
108+
!$omp atomic update relaxed
109+
y = max(y, c, d)
110+
111+
!CHECK: %[[VAL_X_LOADED:.*]] = fir.load %[[VAL_X_DECLARE]]#0 : !fir.ref<i32>
112+
!CHECK: omp.atomic.update memory_order(relaxed) hint(contended) %[[VAL_Z_DECLARE]]#1 : !fir.ref<i32> {
113+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
114+
!CHECK: %[[TEMP:.*]] = arith.addi %[[ARG]], %[[VAL_X_LOADED]] : i32
115+
!CHECK: omp.yield(%[[TEMP]] : i32)
116+
!CHECK: }
117+
!$omp atomic relaxed hint(omp_sync_hint_contended)
118+
z = z + x
119+
120+
!CHECK: %[[VAL_c10:.*]] = arith.constant 10 : i32
121+
!CHECK: omp.atomic.update memory_order(release) hint(contended) %[[VAL_Z_DECLARE]]#1 : !fir.ref<i32> {
122+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
123+
!CHECK: %[[TEMP:.*]] = arith.muli %[[VAL_c10]], %[[ARG]] : i32
124+
!CHECK: omp.yield(%[[TEMP]] : i32)
125+
!CHECK: }
126+
!$omp atomic release update hint(omp_lock_hint_contended)
127+
z = z * 10
128+
129+
!CHECK: %[[VAL_Z_LOADED:.*]] = fir.load %[[VAL_Z_DECLARE]]#0 : !fir.ref<i32>
130+
!CHECK: omp.atomic.update memory_order(release) hint(speculative) %[[VAL_X_DECLARE]]#1 : !fir.ref<i32> {
131+
!CHECK: ^bb0(%[[ARG:.*]]: i32):
132+
!CHECK: %[[TEMP:.*]] = arith.divsi %[[ARG]], %[[VAL_Z_LOADED]] : i32
133+
!CHECK: omp.yield(%[[TEMP]] : i32)
134+
!CHECK: }
135+
!$omp atomic hint(omp_lock_hint_speculative) update release
136+
x = x / z
137+
138+
!CHECK: %[[VAL_c1:.*]] = arith.constant 1 : i32
139+
!CHECK: omp.atomic.update %[[VAL_i1_DECLARE]]#1 : !fir.ref<i8> {
140+
!CHECK: ^bb0(%[[ARG:.*]]: i8):
141+
!CHECK: %[[CONVERT:.*]] = fir.convert %[[ARG]] : (i8) -> i32
142+
!CHECK: %[[ADD:.*]] = arith.addi %[[CONVERT]], %[[VAL_c1]] : i32
143+
!CHECK: %[[TEMP:.*]] = fir.convert %[[ADD]] : (i32) -> i8
144+
!CHECK: omp.yield(%[[TEMP]] : i8)
145+
!CHECK: }
146+
!$omp atomic
147+
i1 = i1 + 1
148+
!$omp end atomic
149+
end program OmpAtomicUpdate

0 commit comments

Comments
 (0)