Break circular dependency between FIR dialect and utilities
[llvm-project.git] / flang / test / Lower / OpenMP / parallel-wsloop.f90
blob51ee77c82f5a85908663d6df967e37d660587e35
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
7 integer :: i
8 ! CHECK: omp.parallel
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]])
13 !$OMP PARALLEL DO
14 do i=1, 9
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
18 print*, i
19 end do
20 ! CHECK: omp.yield
21 ! CHECK: omp.terminator
22 !$OMP END PARALLEL DO
23 end subroutine
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)
28 logical :: cond
29 integer :: nt
30 integer :: i
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)
40 do i=1, 9
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
44 print*, i
45 end do
46 ! CHECK: omp.yield
47 ! CHECK: omp.terminator
48 !$OMP END PARALLEL DO
49 end subroutine
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)
54 integer :: nt
55 integer :: i
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)
63 do i=1, 9
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
67 print*, i
68 end do
69 ! CHECK: omp.yield
70 ! CHECK: omp.terminator
71 !$OMP END PARALLEL DO
72 end subroutine
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)
82 logical :: cond
83 integer :: nt
84 integer :: i
85 ! CHECK: omp.parallel
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)
95 do i=1, 9
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
104 print*, i, cond, nt
105 end do
106 ! CHECK: omp.yield
107 ! CHECK: omp.terminator
108 !$OMP END PARALLEL DO
109 end subroutine
111 !===============================================================================
112 ! Checking for the following construct
113 ! !$omp parallel private(...) firstprivate(...)
114 ! !$omp do
115 !===============================================================================
117 subroutine parallel_private_do(cond,nt)
118 logical :: cond
119 integer :: nt
120 integer :: i
121 !$OMP PARALLEL PRIVATE(cond) FIRSTPRIVATE(nt)
122 !$OMP DO
123 do i=1, 9
124 call foo(i, cond, nt)
125 end do
126 !$OMP END DO
127 !$OMP END PARALLEL
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>) -> ()
146 ! CHECK: omp.yield
147 ! CHECK: }
148 ! CHECK: omp.terminator
149 ! CHECK: }
150 ! CHECK: return
151 ! CHECK: }
153 !===============================================================================
154 ! Checking for the following construct
155 ! !$omp parallel
156 ! !$omp do firstprivate(...) firstprivate(...)
157 !===============================================================================
159 subroutine omp_parallel_multiple_firstprivate_do(a, b)
160 integer::a, b
161 !$OMP PARALLEL FIRSTPRIVATE(a) FIRSTPRIVATE(b)
162 !$OMP DO
163 do i=1, 10
164 call bar(i, a)
165 end do
166 !$OMP END DO
167 !$OMP END PARALLEL
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>) -> ()
188 ! CHECK: omp.yield
189 ! CHECK: }
190 ! CHECK: omp.terminator
191 ! CHECK: }
192 ! CHECK: return
193 ! CHECK: }
195 !===============================================================================
196 ! Checking for the following construct
197 ! !$omp parallel
198 ! !$omp do private(...) firstprivate(...)
199 !===============================================================================
201 subroutine parallel_do_private(cond,nt)
202 logical :: cond
203 integer :: nt
204 integer :: i
205 !$OMP PARALLEL
206 !$OMP DO PRIVATE(cond) FIRSTPRIVATE(nt)
207 do i=1, 9
208 call foo(i, cond, nt)
209 end do
210 !$OMP END DO
211 !$OMP END PARALLEL
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>) -> ()
230 ! CHECK: omp.yield
231 ! CHECK: }
232 ! CHECK: omp.terminator
233 ! CHECK: }
234 ! CHECK: return
235 ! CHECK: }
237 !===============================================================================
238 ! Checking for the following construct
239 ! !$omp parallel
240 ! !$omp do firstprivate(...) firstprivate(...)
241 !===============================================================================
243 subroutine omp_parallel_do_multiple_firstprivate(a, b)
244 integer::a, b
245 !$OMP PARALLEL
246 !$OMP DO FIRSTPRIVATE(a) FIRSTPRIVATE(b)
247 do i=1, 10
248 call bar(i, a)
249 end do
250 !$OMP END DO
251 !$OMP END PARALLEL
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>) -> ()
272 ! CHECK: omp.yield
273 ! CHECK: }
274 ! CHECK: omp.terminator
275 ! CHECK: }
276 ! CHECK: return
277 ! CHECK: }