1 ! This test checks lowering of OpenMP DO Directive (Worksharing).
3 ! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s
5 ! CHECK-LABEL: func @_QPsimple_parallel_do()
6 subroutine simple_parallel_do
9 ! CHECK: %[[WS_LB:.*]] = arith.constant 1 : i32
10 ! CHECK: %[[WS_UB:.*]] = arith.constant 9 : i32
11 ! CHECK: %[[WS_STEP:.*]] = arith.constant 1 : i32
12 ! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]])
15 ! CHECK: fir.store %[[I]] to %[[IV_ADDR:.*]] : !fir.ref<i32>
16 ! CHECK: %[[LOAD_IV:.*]] = fir.load %[[IV_ADDR]] : !fir.ref<i32>
17 ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LOAD_IV]]) {{.*}}: (!fir.ref<i8>, i32) -> i1
21 ! CHECK: omp.terminator
25 ! CHECK-LABEL: func @_QPparallel_do_with_parallel_clauses
26 ! CHECK-SAME: %[[COND_REF:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}, %[[NT_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"}
27 subroutine parallel_do_with_parallel_clauses(cond
, nt
)
31 ! CHECK: %[[COND:.*]] = fir.load %[[COND_REF]] : !fir.ref<!fir.logical<4>>
32 ! CHECK: %[[COND_CVT:.*]] = fir.convert %[[COND]] : (!fir.logical<4>) -> i1
33 ! CHECK: %[[NT:.*]] = fir.load %[[NT_REF]] : !fir.ref<i32>
34 ! CHECK: omp.parallel if(%[[COND_CVT]] : i1) num_threads(%[[NT]] : i32) proc_bind(close)
35 ! CHECK: %[[WS_LB:.*]] = arith.constant 1 : i32
36 ! CHECK: %[[WS_UB:.*]] = arith.constant 9 : i32
37 ! CHECK: %[[WS_STEP:.*]] = arith.constant 1 : i32
38 ! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]])
39 !$OMP PARALLEL DO IF(cond) NUM_THREADS(nt) PROC_BIND(close)
41 ! CHECK: fir.store %[[I]] to %[[IV_ADDR:.*]] : !fir.ref<i32>
42 ! CHECK: %[[LOAD_IV:.*]] = fir.load %[[IV_ADDR]] : !fir.ref<i32>
43 ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LOAD_IV]]) {{.*}}: (!fir.ref<i8>, i32) -> i1
47 ! CHECK: omp.terminator
51 ! CHECK-LABEL: func @_QPparallel_do_with_clauses
52 ! CHECK-SAME: %[[NT_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"}
53 subroutine parallel_do_with_clauses(nt
)
56 ! CHECK: %[[NT:.*]] = fir.load %[[NT_REF]] : !fir.ref<i32>
57 ! CHECK: omp.parallel num_threads(%[[NT]] : i32)
58 ! CHECK: %[[WS_LB:.*]] = arith.constant 1 : i32
59 ! CHECK: %[[WS_UB:.*]] = arith.constant 9 : i32
60 ! CHECK: %[[WS_STEP:.*]] = arith.constant 1 : i32
61 ! CHECK: omp.wsloop schedule(dynamic) for (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]])
62 !$OMP PARALLEL DO NUM_THREADS(nt) SCHEDULE(dynamic)
64 ! CHECK: fir.store %[[I]] to %[[IV_ADDR:.*]] : !fir.ref<i32>
65 ! CHECK: %[[LOAD_IV:.*]] = fir.load %[[IV_ADDR]] : !fir.ref<i32>
66 ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LOAD_IV]]) {{.*}}: (!fir.ref<i8>, i32) -> i1
70 ! CHECK: omp.terminator
74 !===============================================================================
75 ! Checking for the following construct:
76 ! !$omp parallel do private(...) firstprivate(...)
77 !===============================================================================
79 ! CHECK-LABEL: func @_QPparallel_do_with_privatisation_clauses
80 ! CHECK-SAME: %[[COND_REF:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}, %[[NT_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"}
81 subroutine parallel_do_with_privatisation_clauses(cond
,nt
)
86 ! CHECK: %[[PRIVATE_COND_REF:.*]] = fir.alloca !fir.logical<4> {bindc_name = "cond", pinned, uniq_name = "_QFparallel_do_with_privatisation_clausesEcond"}
87 ! CHECK: %[[PRIVATE_NT_REF:.*]] = fir.alloca i32 {bindc_name = "nt", pinned, uniq_name = "_QFparallel_do_with_privatisation_clausesEnt"}
88 ! CHECK: %[[NT_VAL:.*]] = fir.load %[[NT_REF]] : !fir.ref<i32>
89 ! CHECK: fir.store %[[NT_VAL]] to %[[PRIVATE_NT_REF]] : !fir.ref<i32>
90 ! CHECK: %[[WS_LB:.*]] = arith.constant 1 : i32
91 ! CHECK: %[[WS_UB:.*]] = arith.constant 9 : i32
92 ! CHECK: %[[WS_STEP:.*]] = arith.constant 1 : i32
93 ! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]])
94 !$OMP PARALLEL DO PRIVATE(cond) FIRSTPRIVATE(nt)
96 ! CHECK: fir.store %[[I]] to %[[IV_ADDR:.*]] : !fir.ref<i32>
97 ! CHECK: %[[LOAD_IV:.*]] = fir.load %[[IV_ADDR]] : !fir.ref<i32>
98 ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LOAD_IV]]) {{.*}}: (!fir.ref<i8>, i32) -> i1
99 ! CHECK: %[[PRIVATE_COND_VAL:.*]] = fir.load %[[PRIVATE_COND_REF]] : !fir.ref<!fir.logical<4>>
100 ! CHECK: %[[PRIVATE_COND_VAL_CVT:.*]] = fir.convert %[[PRIVATE_COND_VAL]] : (!fir.logical<4>) -> i1
101 ! CHECK: fir.call @_FortranAioOutputLogical({{.*}}, %[[PRIVATE_COND_VAL_CVT]]) {{.*}}: (!fir.ref<i8>, i1) -> i1
102 ! CHECK: %[[PRIVATE_NT_VAL:.*]] = fir.load %[[PRIVATE_NT_REF]] : !fir.ref<i32>
103 ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[PRIVATE_NT_VAL]]) {{.*}}: (!fir.ref<i8>, i32) -> i1
107 ! CHECK: omp.terminator
108 !$OMP END PARALLEL DO
111 !===============================================================================
112 ! Checking for the following construct
113 ! !$omp parallel private(...) firstprivate(...)
115 !===============================================================================
117 subroutine parallel_private_do(cond
,nt
)
121 !$OMP PARALLEL PRIVATE(cond) FIRSTPRIVATE(nt)
124 call foo(i
, cond
, nt
)
128 end subroutine parallel_private_do
130 ! CHECK-LABEL: func.func @_QPparallel_private_do(
131 ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"},
132 ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"}) {
133 ! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFparallel_private_doEi"}
134 ! CHECK: omp.parallel {
135 ! CHECK: %[[I_PRIV:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
136 ! CHECK: %[[COND_ADDR:.*]] = fir.alloca !fir.logical<4> {bindc_name = "cond", pinned, uniq_name = "_QFparallel_private_doEcond"}
137 ! CHECK: %[[NT_ADDR:.*]] = fir.alloca i32 {bindc_name = "nt", pinned, uniq_name = "_QFparallel_private_doEnt"}
138 ! CHECK: %[[NT:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32>
139 ! CHECK: fir.store %[[NT]] to %[[NT_ADDR]] : !fir.ref<i32>
140 ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
141 ! CHECK: %[[VAL_8:.*]] = arith.constant 9 : i32
142 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
143 ! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) {
144 ! CHECK: fir.store %[[I]] to %[[I_PRIV]] : !fir.ref<i32>
145 ! CHECK: fir.call @_QPfoo(%[[I_PRIV]], %[[COND_ADDR]], %[[NT_ADDR]]) {{.*}}: (!fir.ref<i32>, !fir.ref<!fir.logical<4>>, !fir.ref<i32>) -> ()
148 ! CHECK: omp.terminator
153 !===============================================================================
154 ! Checking for the following construct
156 ! !$omp do firstprivate(...) firstprivate(...)
157 !===============================================================================
159 subroutine omp_parallel_multiple_firstprivate_do(a
, b
)
161 !$OMP PARALLEL FIRSTPRIVATE(a) FIRSTPRIVATE(b)
168 end subroutine omp_parallel_multiple_firstprivate_do
170 ! CHECK-LABEL: func.func @_QPomp_parallel_multiple_firstprivate_do(
171 ! CHECK-SAME: %[[A_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "a"},
172 ! CHECK-SAME: %[[B_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) {
173 ! CHECK: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_parallel_multiple_firstprivate_doEi"}
174 ! CHECK: omp.parallel {
175 ! CHECK: %[[I_PRIV_ADDR:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
176 ! CHECK: %[[A_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "a", pinned, uniq_name = "_QFomp_parallel_multiple_firstprivate_doEa"}
177 ! CHECK: %[[A:.*]] = fir.load %[[A_ADDR]] : !fir.ref<i32>
178 ! CHECK: fir.store %[[A]] to %[[A_PRIV_ADDR]] : !fir.ref<i32>
179 ! CHECK: %[[B_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "b", pinned, uniq_name = "_QFomp_parallel_multiple_firstprivate_doEb"}
180 ! CHECK: %[[B:.*]] = fir.load %[[B_ADDR]] : !fir.ref<i32>
181 ! CHECK: fir.store %[[B]] to %[[B_PRIV_ADDR]] : !fir.ref<i32>
182 ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32
183 ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32
184 ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32
185 ! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) {
186 ! CHECK: fir.store %[[I]] to %[[I_PRIV_ADDR]] : !fir.ref<i32>
187 ! CHECK: fir.call @_QPbar(%[[I_PRIV_ADDR]], %[[A_PRIV_ADDR]]) {{.*}}: (!fir.ref<i32>, !fir.ref<i32>) -> ()
190 ! CHECK: omp.terminator
195 !===============================================================================
196 ! Checking for the following construct
198 ! !$omp do private(...) firstprivate(...)
199 !===============================================================================
201 subroutine parallel_do_private(cond
,nt
)
206 !$OMP DO PRIVATE(cond) FIRSTPRIVATE(nt)
208 call foo(i
, cond
, nt
)
212 end subroutine parallel_do_private
214 ! CHECK-LABEL: func.func @_QPparallel_do_private(
215 ! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"},
216 ! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"}) {
217 ! CHECK: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFparallel_do_privateEi"}
218 ! CHECK: omp.parallel {
219 ! CHECK: %[[COND_ADDR:.*]] = fir.alloca !fir.logical<4> {bindc_name = "cond", pinned, uniq_name = "_QFparallel_do_privateEcond"}
220 ! CHECK: %[[NT_ADDR:.*]] = fir.alloca i32 {bindc_name = "nt", pinned, uniq_name = "_QFparallel_do_privateEnt"}
221 ! CHECK: %[[NT:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32>
222 ! CHECK: fir.store %[[NT]] to %[[NT_ADDR]] : !fir.ref<i32>
223 ! CHECK: %[[I_PRIV_ADDR:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
224 ! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
225 ! CHECK: %[[VAL_8:.*]] = arith.constant 9 : i32
226 ! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
227 ! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) {
228 ! CHECK: fir.store %[[I]] to %[[I_PRIV_ADDR]] : !fir.ref<i32>
229 ! CHECK: fir.call @_QPfoo(%[[I_PRIV_ADDR]], %[[COND_ADDR]], %[[NT_ADDR]]) {{.*}}: (!fir.ref<i32>, !fir.ref<!fir.logical<4>>, !fir.ref<i32>) -> ()
232 ! CHECK: omp.terminator
237 !===============================================================================
238 ! Checking for the following construct
240 ! !$omp do firstprivate(...) firstprivate(...)
241 !===============================================================================
243 subroutine omp_parallel_do_multiple_firstprivate(a
, b
)
246 !$OMP DO FIRSTPRIVATE(a) FIRSTPRIVATE(b)
252 end subroutine omp_parallel_do_multiple_firstprivate
254 ! CHECK-LABEL: func.func @_QPomp_parallel_do_multiple_firstprivate(
255 ! CHECK-SAME: %[[A_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "a"},
256 ! CHECK-SAME: %[[B_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) {
257 ! CHECK: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_parallel_do_multiple_firstprivateEi"}
258 ! CHECK: omp.parallel {
259 ! CHECK: %[[A_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "a", pinned, uniq_name = "_QFomp_parallel_do_multiple_firstprivateEa"}
260 ! CHECK: %[[A:.*]] = fir.load %[[A_ADDR]] : !fir.ref<i32>
261 ! CHECK: fir.store %[[A]] to %[[A_PRIV_ADDR]] : !fir.ref<i32>
262 ! CHECK: %[[B_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "b", pinned, uniq_name = "_QFomp_parallel_do_multiple_firstprivateEb"}
263 ! CHECK: %[[B:.*]] = fir.load %[[B_ADDR]] : !fir.ref<i32>
264 ! CHECK: fir.store %[[B]] to %[[B_PRIV_ADDR]] : !fir.ref<i32>
265 ! CHECK: %[[I_PRIV_ADDR:.*]] = fir.alloca i32 {adapt.valuebyref, pinned}
266 ! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32
267 ! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32
268 ! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32
269 ! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) {
270 ! CHECK: fir.store %[[I]] to %[[I_PRIV_ADDR]] : !fir.ref<i32>
271 ! CHECK: fir.call @_QPbar(%[[I_PRIV_ADDR]], %[[A_PRIV_ADDR]]) {{.*}}: (!fir.ref<i32>, !fir.ref<i32>) -> ()
274 ! CHECK: omp.terminator