xref: /llvm-project/flang/test/Lower/OpenMP/sections.f90 (revision 797f01198e8b41982916ba02d703bd6a96b5347e)
1! REQUIRES: openmp_runtime
2
3! This test checks the lowering of OpenMP sections construct with several clauses present
4
5! RUN: %flang_fc1 -flang-experimental-hlfir -emit-hlfir %openmp_flags %s -o - | FileCheck %s
6! RUN: bbc -hlfir -emit-hlfir %openmp_flags %s -o - | FileCheck %s
7
8!CHECK: func @_QQmain() attributes {fir.bindc_name = "sample"} {
9!CHECK:   %[[COUNT:.*]] = fir.address_of(@_QFEcount) : !fir.ref<i32>
10!CHECK:   %[[COUNT_DECL:.*]]:2 = hlfir.declare %[[COUNT]] {uniq_name = "_QFEcount"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
11!CHECK:   %[[ETA:.*]] = fir.alloca f32 {bindc_name = "eta", uniq_name = "_QFEeta"}
12!CHECK:   %[[CONST_1:.*]] = arith.constant 4 : i64
13!CHECK:   %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"}
14!CHECK:   %[[PRIVATE_ETA_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_ETA]] {uniq_name = "_QFEeta"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
15!CHECK:   %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"}
16!CHECK:   %[[PRIVATE_DOUBLE_COUNT_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_DOUBLE_COUNT]] {uniq_name = "_QFEdouble_count"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
17!CHECK:   omp.sections allocate(%[[CONST_1]] : i64 -> %[[COUNT_DECL]]#1 : !fir.ref<i32>)  {
18!CHECK:     omp.section {
19!CHECK:       %[[CONST5:.*]] = arith.constant 5 : i32
20!CHECK:       hlfir.assign %[[CONST5]] to %[[COUNT_DECL]]#0 : i32, !fir.ref<i32>
21!CHECK:       %[[TEMP_COUNT:.*]] = fir.load %[[COUNT_DECL]]#0 : !fir.ref<i32>
22!CHECK:       %[[TEMP_DOUBLE_COUNT:.*]] = fir.load %[[PRIVATE_DOUBLE_COUNT_DECL]]#0 : !fir.ref<i32>
23!CHECK:       %[[RESULT:.*]] = arith.muli %[[TEMP_COUNT]], %[[TEMP_DOUBLE_COUNT]] : i32
24!CHECK:       %[[RESULT_CONVERT:.*]] = fir.convert %[[RESULT]] : (i32) -> f32
25!CHECK:       hlfir.assign %[[RESULT_CONVERT]] to %[[PRIVATE_ETA_DECL]]#0 : f32, !fir.ref<f32>
26!CHECK:       omp.terminator
27!CHECK:     }
28!CHECK:     omp.section {
29!CHECK:       %[[TEMP:.*]] = fir.load %[[PRIVATE_DOUBLE_COUNT_DECL]]#0 : !fir.ref<i32>
30!CHECK:       %[[CONST:.*]] = arith.constant 1 : i32
31!CHECK:       %[[RESULT:.*]] = arith.addi %[[TEMP]], %[[CONST]] : i32
32!CHECK:       hlfir.assign %[[RESULT]] to %[[PRIVATE_DOUBLE_COUNT_DECL]]#0 : i32, !fir.ref<i32>
33!CHECK:       omp.terminator
34!CHECK:     }
35!CHECK:     omp.section {
36!CHECK:       %[[TEMP:.*]] = fir.load %[[PRIVATE_ETA_DECL]]#0 : !fir.ref<f32>
37!CHECK:       %[[CONST:.*]] = arith.constant 7.000000e+00 : f32
38!CHECK:       %[[RESULT:.*]] = arith.subf %[[TEMP]], %[[CONST]] {{.*}}: f32
39!CHECK:       hlfir.assign %[[RESULT]] to %[[PRIVATE_ETA_DECL]]#0 : f32, !fir.ref<f32>
40!CHECK:       %[[TEMP_COUNT1:.*]] = fir.load %[[COUNT_DECL]]#0 : !fir.ref<i32>
41!CHECK:       %[[TEMP_COUNT:.*]] = fir.convert %[[TEMP_COUNT1]] : (i32) -> f32
42!CHECK:       %[[TEMP_ETA:.*]] = fir.load %[[PRIVATE_ETA_DECL]]#0 : !fir.ref<f32>
43!CHECK:       %[[TEMP_COUNT2:.*]] = arith.mulf %[[TEMP_COUNT]], %[[TEMP_ETA]] {{.*}}: f32
44!CHECK:       %[[RESULT:.*]] = fir.convert %[[TEMP_COUNT2]] : (f32) -> i32
45!CHECK:       hlfir.assign %[[RESULT]] to %[[COUNT_DECL]]#0 : i32, !fir.ref<i32>
46!CHECK:       %[[TEMP_COUNT3:.*]] = fir.load %[[COUNT_DECL]]#0 : !fir.ref<i32>
47!CHECK:       %[[TEMP_COUNT4:.*]] = fir.convert %[[TEMP_COUNT3]] : (i32) -> f32
48!CHECK:       %[[TEMP_ETA:.*]] = fir.load %[[PRIVATE_ETA_DECL]]#0 : !fir.ref<f32>
49!CHECK:       %[[TEMP_COUNT5:.*]] = arith.subf %[[TEMP_COUNT4]], %[[TEMP_ETA]] {{.*}}: f32
50!CHECK:       %[[RESULT2:.*]] = fir.convert %[[TEMP_COUNT5]] : (f32) -> i32
51!CHECK:       hlfir.assign %[[RESULT2]] to %[[PRIVATE_DOUBLE_COUNT_DECL]]#0 : i32, !fir.ref<i32>
52!CHECK:       omp.terminator
53!CHECK:     }
54!CHECK:     omp.terminator
55!CHECK:   }
56!CHECK:   omp.sections nowait {
57!CHECK:     omp.terminator
58!CHECK:   }
59!CHECK:   return
60!CHECK: }
61
62program sample
63    use omp_lib
64    integer :: count = 0, double_count = 1
65    !$omp sections private (eta, double_count) allocate(omp_high_bw_mem_alloc: count)
66        !$omp section
67            count = 1 + 4
68            eta = count * double_count
69        !$omp section
70            double_count = double_count + 1
71        !$omp section
72            eta = eta - 7
73            count = count * eta
74            double_count = count - eta
75    !$omp end sections
76
77    !$omp sections
78    !$omp end sections nowait
79end program sample
80
81!CHECK: func @_QPfirstprivate(%[[ARG:.*]]: !fir.ref<f32> {fir.bindc_name = "alpha"}) {
82!CHECK:   %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstprivateEalpha"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
83!CHECK:   %[[PRIVATE_ALPHA:.*]] = fir.alloca f32 {bindc_name = "alpha", pinned, uniq_name = "_QFfirstprivateEalpha"}
84!CHECK:   %[[PRIVATE_ALPHA_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_ALPHA]] {uniq_name = "_QFfirstprivateEalpha"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
85!CHECK:   %[[TEMP:.*]] = fir.load %[[ARG_DECL]]#0 : !fir.ref<f32>
86!CHECK:   hlfir.assign %[[TEMP]] to %[[PRIVATE_ALPHA_DECL]]#0 : f32, !fir.ref<f32>
87!CHECK:   omp.sections {
88!CHECK:     omp.section  {
89!CHECK:       omp.terminator
90!CHECK:     }
91!CHECK:     omp.terminator
92!CHECK:   }
93!CHECK:   omp.sections {
94!CHECK:     omp.section  {
95!CHECK:       %[[PRIVATE_VAR:.*]] = fir.load %[[ARG_DECL]]#0 : !fir.ref<f32>
96!CHECK:       %[[CONSTANT:.*]] = arith.constant 5.000000e+00 : f32
97!CHECK:       %[[PRIVATE_VAR_2:.*]] = arith.mulf %[[PRIVATE_VAR]], %[[CONSTANT]] {{.*}}: f32
98!CHECK:       hlfir.assign %[[PRIVATE_VAR_2]] to %[[ARG_DECL]]#0 : f32, !fir.ref<f32>
99!CHECK:       omp.terminator
100!CHECK:     }
101!CHECK:     omp.terminator
102!CHECK:   }
103!CHECK:   return
104!CHECK: }
105
106subroutine firstprivate(alpha)
107    real :: alpha
108    !$omp sections firstprivate(alpha)
109    !$omp end sections
110
111    !$omp sections
112        alpha = alpha * 5
113    !$omp end sections
114end subroutine
115
116!CHECK-LABEL: func @_QPlastprivate
117subroutine lastprivate()
118        integer :: x
119!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFlastprivateEx"}
120!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFlastprivateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
121!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
122!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFlastprivateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
123!CHECK: omp.sections   {
124	!$omp sections lastprivate(x)
125!CHECK: omp.section {
126!CHECK: %[[CONST10:.*]] = arith.constant 10 : i32
127!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
128!CHECK: %[[RESULT:.*]] = arith.muli %[[CONST10]], %[[TEMP]] : i32
129!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32>
130!CHECK: omp.terminator
131!CHECK: }
132        !$omp section
133            x = x * 10
134
135!CHECK: omp.section {
136!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
137!CHECK: %[[CONST:.*]] = arith.constant 1 : i32
138!CHECK: %[[RESULT:.*]] = arith.addi %[[TEMP]], %[[CONST]] : i32
139!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32>
140!CHECK: %[[TEMP1:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
141!CHECK: hlfir.assign %[[TEMP1]] to %[[X_DECL]]#0 : i32, !fir.ref<i32>
142!CHECK: omp.terminator
143!CHECK: }
144        !$omp section
145            x = x + 1
146!CHECK: omp.terminator
147!CHECK: }
148    !$omp end sections
149
150!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
151!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFlastprivateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
152!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<i32>
153!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32>
154!CHECK: omp.barrier
155!CHECK: omp.sections {
156    !$omp sections firstprivate(x) lastprivate(x)
157!CHECK: omp.section {
158!CHECK: %[[CONST:.*]] = arith.constant 10 : i32
159!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
160!CHECK: %[[RESULT:.*]] = arith.muli %[[CONST]], %[[TEMP]] : i32
161!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32>
162!CHECK: omp.terminator
163!CHECK: }
164        !$omp section
165            x = x * 10
166!CHECK: omp.section {
167!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
168!CHECK: %[[CONST:.*]] = arith.constant 1 : i32
169!CHECK: %[[RESULT:.*]] = arith.addi %[[TEMP]], %[[CONST]] : i32
170!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32>
171!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
172!CHECK: hlfir.assign %[[TEMP]] to %[[X_DECL]]#0 : i32, !fir.ref<i32>
173!CHECK: omp.terminator
174!CHECK: }
175        !$omp section
176            x = x + 1
177!CHECK: omp.terminator
178!CHECK: }
179    !$omp end sections
180
181!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
182!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFlastprivateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
183!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<i32>
184!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32>
185!CHECK: omp.barrier
186!CHECK: omp.sections nowait {
187    !$omp sections firstprivate(x) lastprivate(x)
188!CHECK: omp.section {
189!CHECK: %[[CONST:.*]] = arith.constant 10 : i32
190!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
191!CHECK: %[[RESULT:.*]] = arith.muli %[[CONST]], %[[TEMP]] : i32
192!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32>
193!CHECK: omp.terminator
194!CHECK: }
195        !$omp section
196            x = x * 10
197!CHECK: omp.section {
198!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
199!CHECK: %[[CONST:.*]] = arith.constant 1 : i32
200!CHECK: %[[RESULT:.*]] = arith.addi %[[TEMP]], %[[CONST]] : i32
201!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32>
202!CHECK: %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
203!CHECK: hlfir.assign %[[TEMP]] to %[[X_DECL]]#0 : i32, !fir.ref<i32>
204!CHECK: omp.terminator
205!CHECK: }
206        !$omp section
207            x = x + 1
208!CHECK: omp.terminator
209!CHECK: }
210!CHECK: omp.barrier
211     !$omp end sections nowait
212
213!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"}
214!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFlastprivateEx"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
215!CHECK: omp.sections {
216!CHECK: omp.section {
217!CHECK: cf.br ^bb1
218!CHECK: ^bb1:  // pred: ^bb0
219!CHECK: %[[INNER_PRIVATE_X:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
220!CHECK: %[[CONST:.*]] = arith.constant 1 : i32
221!CHECK: %[[RESULT:.*]] = arith.addi %[[INNER_PRIVATE_X]], %[[CONST]] : i32
222!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : i32, !fir.ref<i32>
223!CHECK: %[[LOADED_VALUE:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
224!CHECK: hlfir.assign %[[LOADED_VALUE]] to %[[X_DECL]]#0 : i32, !fir.ref<i32>
225!CHECK: omp.terminator
226!CHECK: }
227!CHECK: omp.terminator
228!CHECK: }
229!CHECK: return
230!CHECK: }
231    !$omp sections lastprivate(x)
232        !$omp section
233                goto 30
234        30  x = x + 1
235    !$omp end sections
236end subroutine
237
238!CHECK-LABEL: func @_QPlastprivate2
239!CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFlastprivate2Ex"}
240!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFlastprivate2Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
241!CHECK: %[[Y:.*]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFlastprivate2Ey"}
242!CHECK: %[[Y_DECL:.*]]:2 = hlfir.declare %[[Y]] {uniq_name = "_QFlastprivate2Ey"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
243!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivate2Ex"}
244!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFlastprivate2Ex"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
245!CHECK: %[[PRIVATE_Y:.*]] = fir.alloca i32 {bindc_name = "y", pinned, uniq_name = "_QFlastprivate2Ey"}
246!CHECK: %[[PRIVATE_Y_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_Y]] {uniq_name = "_QFlastprivate2Ey"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
247!CHECK: omp.sections {
248!CHECK:   omp.section {
249!CHECK:     %[[TEMP:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<i32>
250!CHECK:     hlfir.assign %[[TEMP]] to %[[X_DECL]]#0 : i32, !fir.ref<i32>
251!CHECK:     %[[TEMP2:.*]] = fir.load %[[PRIVATE_Y_DECL]]#0 : !fir.ref<i32>
252!CHECK:     hlfir.assign %[[TEMP2]] to %[[Y_DECL]]#0 : i32, !fir.ref<i32>
253!CHECK:     omp.terminator
254!CHECK:   }
255!CHECK:   omp.terminator
256!CHECK: }
257subroutine lastprivate2()
258    integer :: x, y
259
260    !$omp sections lastprivate(x) lastprivate(y)
261        !$omp section
262          x = y + 1
263    !$omp end sections
264end subroutine
265
266!CHECK-LABEL: func @_QPunstructured_sections_privatization
267subroutine unstructured_sections_privatization()
268!CHECK: %[[X:.*]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFunstructured_sections_privatizationEx"}
269!CHECK: %[[X_DECL:.*]]:2 = hlfir.declare %[[X]] {uniq_name = "_QFunstructured_sections_privatizationEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
270!CHECK: %[[PRIVATE_X:.*]] = fir.alloca f32 {bindc_name = "x", pinned, uniq_name = "_QFunstructured_sections_privatizationEx"}
271!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFunstructured_sections_privatizationEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
272!CHECK: omp.sections {
273!CHECK: omp.section {
274!CHECK: cf.br ^bb1
275!CHECK: ^bb1:  // pred: ^bb0
276!CHECK: %[[INNER_PRIVATE_X:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<f32>
277!CHECK: %[[CONSTANT:.*]] = arith.constant 1.000000e+00 : f32
278!CHECK: %[[RESULT:.*]] = arith.addf %[[INNER_PRIVATE_X]], %[[CONSTANT]] fastmath<contract> : f32
279!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : f32, !fir.ref<f32>
280!CHECK: omp.terminator
281!CHECK: }
282!CHECK: omp.terminator
283!CHECK: }
284    !$omp sections private(x)
285        !$omp section
286            goto 40
287        40  x = x + 1
288    !$omp end sections
289!CHECK: %[[PRIVATE_X:.*]] = fir.alloca f32 {bindc_name = "x", pinned, uniq_name = "_QFunstructured_sections_privatizationEx"}
290!CHECK: %[[PRIVATE_X_DECL:.*]]:2 = hlfir.declare %[[PRIVATE_X]] {uniq_name = "_QFunstructured_sections_privatizationEx"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
291!CHECK: %[[TEMP:.*]] = fir.load %[[X_DECL]]#0 : !fir.ref<f32>
292!CHECK: hlfir.assign %[[TEMP]] to %[[PRIVATE_X_DECL]]#0 : f32, !fir.ref<f32>
293!CHECK: omp.sections {
294!CHECK: omp.section {
295!CHECK: cf.br ^bb1
296!CHECK: ^bb1:
297!CHECK: %[[INNER_PRIVATE_X:.*]] = fir.load %[[PRIVATE_X_DECL]]#0 : !fir.ref<f32>
298!CHECK: %[[CONSTANT:.*]] = arith.constant 1.000000e+00 : f32
299!CHECK: %[[RESULT:.*]] = arith.addf %[[INNER_PRIVATE_X]], %[[CONSTANT]] fastmath<contract> : f32
300!CHECK: hlfir.assign %[[RESULT]] to %[[PRIVATE_X_DECL]]#0 : f32, !fir.ref<f32>
301!CHECK: omp.terminator
302!CHECK: }
303!CHECK: omp.terminator
304!CHECK: }
305    !$omp sections firstprivate(x)
306        !$omp section
307            goto 50
308        50  x = x + 1
309    !$omp end sections
310end subroutine
311