xref: /llvm-project/flang/test/Lower/OpenMP/parallel-lastprivate-clause-scalar.f90 (revision 937cbce14c9aa956342a9c818c26a8a557802843)
1! This test checks lowering of `LASTPRIVATE` clause for scalar types.
2
3! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
4! RUN: flang -fc1 -fopenmp -emit-hlfir %s -o - | FileCheck %s
5
6!CHECK: func @_QPlastprivate_character(%[[ARG1:.*]]: !fir.boxchar<1>{{.*}}) {
7!CHECK-DAG: %[[ARG1_UNBOX:.*]]:2 = fir.unboxchar
8!CHECK-DAG: %[[FIVE:.*]] = arith.constant 5 : index
9!CHECK-DAG: %[[ARG1_REF:.*]] = fir.convert %[[ARG1_UNBOX]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.char<1,5>>
10!CHECK-DAG: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1_REF]] typeparams %[[FIVE]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFlastprivate_characterEarg1"} : (!fir.ref<!fir.char<1,5>>, index, !fir.dscope) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>)
11
12!CHECK: omp.parallel {
13!CHECK-DAG: %[[ARG1_PVT:.*]] = fir.alloca !fir.char<1,5> {bindc_name = "arg1", pinned, {{.*}}}
14!CHECK-DAG: %[[ARG1_PVT_DECL:.*]]:2 = hlfir.declare %[[ARG1_PVT]] typeparams %[[FIVE]] {uniq_name = "_QFlastprivate_characterEarg1"} : (!fir.ref<!fir.char<1,5>>, index) -> (!fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>)
15
16! Check that we are accessing the clone inside the loop
17!CHECK: omp.wsloop {
18!CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
19!CHECK: %[[UNIT:.*]] = arith.constant 6 : i32
20!CHECK-NEXT: %[[ADDR:.*]] = fir.address_of(@_QQclX
21!CHECK-NEXT: %[[CVT0:.*]] = fir.convert %[[ADDR]]
22!CHECK-NEXT: %[[CNST:.*]] = arith.constant
23!CHECK-NEXT: %[[CALL_BEGIN_IO:.*]] = fir.call @_FortranAioBeginExternalListOutput(%[[UNIT]], %[[CVT0]], %[[CNST]]) {{.*}}: (i32, !fir.ref<i8>, i32) -> !fir.ref<i8>
24!CHECK-NEXT: %[[CVT_0_1:.*]] = fir.convert %[[ARG1_PVT_DECL]]#1
25!CHECK-NEXT: %[[CVT_0_2:.*]] = fir.convert %[[FIVE]]
26!CHECK-NEXT: %[[CALL_OP_ASCII:.*]] = fir.call @_FortranAioOutputAscii(%[[CALL_BEGIN_IO]], %[[CVT_0_1]], %[[CVT_0_2]])
27!CHECK-NEXT: %[[CALL_END_IO:.*]] = fir.call @_FortranAioEndIoStatement(%[[CALL_BEGIN_IO]])
28
29! Testing last iteration check
30!CHECK: %[[V:.*]] = arith.addi %[[INDX_WS]], %{{.*}} : i32
31!CHECK: %[[C0:.*]] = arith.constant 0 : i32
32!CHECK: %[[T1:.*]] = arith.cmpi slt, %{{.*}}, %[[C0]] : i32
33!CHECK: %[[T2:.*]] = arith.cmpi slt, %[[V]], %{{.*}} : i32
34!CHECK: %[[T3:.*]] = arith.cmpi sgt, %[[V]], %{{.*}} : i32
35!CHECK: %[[IV_CMP:.*]] = arith.select %[[T1]], %[[T2]], %[[T3]] : i1
36!CHECK: fir.if %[[IV_CMP]] {
37!CHECK: fir.store %[[V]] to %{{.*}} : !fir.ref<i32>
38
39! Testing lastprivate val update
40!CHECK: hlfir.assign %[[ARG1_PVT_DECL]]#0 to %[[ARG1_DECL]]#0 : !fir.ref<!fir.char<1,5>>, !fir.ref<!fir.char<1,5>>
41!CHECK: }
42!CHECK: omp.yield
43!CHECK: }
44!CHECK: }
45
46subroutine lastprivate_character(arg1)
47        character(5) :: arg1
48!$OMP PARALLEL
49!$OMP DO LASTPRIVATE(arg1)
50do n = 1, 5
51        arg1(n:n) = 'c'
52        print *, arg1
53end do
54!$OMP END DO
55!$OMP END PARALLEL
56end subroutine
57
58!CHECK: func @_QPlastprivate_int(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}) {
59!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFlastprivate_intEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
60!CHECK-DAG: omp.parallel  {
61!CHECK-DAG: %[[CLONE:.*]] = fir.alloca i32 {bindc_name = "arg1", pinned, {{.*}}}
62!CHECK-DAG: %[[CLONE_DECL:.*]]:2 = hlfir.declare %[[CLONE]] {uniq_name = "_QFlastprivate_intEarg1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
63!CHECK: omp.wsloop {
64!CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
65
66! Testing last iteration check
67!CHECK: %[[V:.*]] = arith.addi %[[INDX_WS]], %{{.*}} : i32
68!CHECK: %[[C0:.*]] = arith.constant 0 : i32
69!CHECK: %[[T1:.*]] = arith.cmpi slt, %{{.*}}, %[[C0]] : i32
70!CHECK: %[[T2:.*]] = arith.cmpi slt, %[[V]], %{{.*}} : i32
71!CHECK: %[[T3:.*]] = arith.cmpi sgt, %[[V]], %{{.*}} : i32
72!CHECK: %[[IV_CMP:.*]] = arith.select %[[T1]], %[[T2]], %[[T3]] : i1
73!CHECK: fir.if %[[IV_CMP]] {
74!CHECK: fir.store %[[V]] to %{{.*}} : !fir.ref<i32>
75
76! Testing lastprivate val update
77!CHECK-NEXT: %[[CLONE_LD:.*]] = fir.load %[[CLONE_DECL]]#0 : !fir.ref<i32>
78!CHECK:      hlfir.assign %[[CLONE_LD]] to %[[ARG1_DECL]]#0 : i32, !fir.ref<i32>
79!CHECK: }
80!CHECK: omp.yield
81!CHECK: }
82!CHECK: }
83
84subroutine lastprivate_int(arg1)
85        integer :: arg1
86!$OMP PARALLEL
87!$OMP DO LASTPRIVATE(arg1)
88do n = 1, 5
89        arg1 = 2
90        print *, arg1
91end do
92!$OMP END DO
93!$OMP END PARALLEL
94print *, arg1
95end subroutine
96
97!CHECK: func.func @_QPmult_lastprivate_int(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}, %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "arg2"}) {
98!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_intEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
99!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_intEarg2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
100!CHECK: omp.parallel  {
101!CHECK-DAG: %[[CLONE1:.*]] = fir.alloca i32 {bindc_name = "arg1", pinned, {{.*}}}
102!CHECK-DAG: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFmult_lastprivate_intEarg1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
103!CHECK-DAG: %[[CLONE2:.*]] = fir.alloca i32 {bindc_name = "arg2", pinned, {{.*}}}
104!CHECK-DAG: %[[CLONE2_DECL:.*]]:2 = hlfir.declare %[[CLONE2]] {uniq_name = "_QFmult_lastprivate_intEarg2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
105!CHECK: omp.wsloop {
106!CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
107
108! Testing last iteration check
109!CHECK: %[[V:.*]] = arith.addi %[[INDX_WS]], %{{.*}} : i32
110!CHECK: %[[C0:.*]] = arith.constant 0 : i32
111!CHECK: %[[T1:.*]] = arith.cmpi slt, %{{.*}}, %[[C0]] : i32
112!CHECK: %[[T2:.*]] = arith.cmpi slt, %[[V]], %{{.*}} : i32
113!CHECK: %[[T3:.*]] = arith.cmpi sgt, %[[V]], %{{.*}} : i32
114!CHECK: %[[IV_CMP:.*]] = arith.select %[[T1]], %[[T2]], %[[T3]] : i1
115!CHECK: fir.if %[[IV_CMP]] {
116!CHECK: fir.store %[[V]] to %{{.*}} : !fir.ref<i32>
117! Testing lastprivate val update
118!CHECK-DAG: %[[CLONE_LD1:.*]] = fir.load %[[CLONE1_DECL]]#0 : !fir.ref<i32>
119!CHECK-DAG: hlfir.assign %[[CLONE_LD1]] to %[[ARG1_DECL]]#0 : i32, !fir.ref<i32>
120!CHECK-DAG: %[[CLONE_LD2:.*]] = fir.load %[[CLONE2_DECL]]#0 : !fir.ref<i32>
121!CHECK-DAG: hlfir.assign %[[CLONE_LD2]] to %[[ARG2_DECL]]#0 : i32, !fir.ref<i32>
122!CHECK: }
123!CHECK: omp.yield
124!CHECK: }
125!CHECK: }
126
127subroutine mult_lastprivate_int(arg1, arg2)
128        integer :: arg1, arg2
129!$OMP PARALLEL
130!$OMP DO LASTPRIVATE(arg1) LASTPRIVATE(arg2)
131do n = 1, 5
132        arg1 = 2
133        arg2 = 3
134        print *, arg1, arg2
135end do
136!$OMP END DO
137!$OMP END PARALLEL
138print *, arg1, arg2
139end subroutine
140
141!CHECK: func.func @_QPmult_lastprivate_int2(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}, %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "arg2"}) {
142!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
143!CHECK: %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
144!CHECK: omp.parallel  {
145!CHECK-DAG: %[[CLONE2:.*]] = fir.alloca i32 {bindc_name = "arg2", pinned, {{.*}}}
146!CHECK-DAG: %[[CLONE2_DECL:.*]]:2 = hlfir.declare %[[CLONE2]] {uniq_name = "_QFmult_lastprivate_int2Earg2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
147!CHECK-DAG: %[[CLONE1:.*]] = fir.alloca i32 {bindc_name = "arg1", pinned, {{.*}}}
148!CHECK-DAG: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFmult_lastprivate_int2Earg1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
149!CHECK: omp.wsloop {
150!CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
151
152!Testing last iteration check
153!CHECK: %[[V:.*]] = arith.addi %[[INDX_WS]], %{{.*}} : i32
154!CHECK: %[[C0:.*]] = arith.constant 0 : i32
155!CHECK: %[[T1:.*]] = arith.cmpi slt, %{{.*}}, %[[C0]] : i32
156!CHECK: %[[T2:.*]] = arith.cmpi slt, %[[V]], %{{.*}} : i32
157!CHECK: %[[T3:.*]] = arith.cmpi sgt, %[[V]], %{{.*}} : i32
158!CHECK: %[[IV_CMP:.*]] = arith.select %[[T1]], %[[T2]], %[[T3]] : i1
159!CHECK: fir.if %[[IV_CMP]] {
160!CHECK: fir.store %[[V]] to %{{.*}} : !fir.ref<i32>
161!Testing lastprivate val update
162!CHECK-DAG: %[[CLONE_LD2:.*]] = fir.load %[[CLONE2_DECL]]#0 : !fir.ref<i32>
163!CHECK-DAG: hlfir.assign %[[CLONE_LD2]] to %[[ARG2_DECL]]#0 : i32, !fir.ref<i32>
164!CHECK-DAG: %[[CLONE_LD1:.*]] = fir.load %[[CLONE1_DECL]]#0 : !fir.ref<i32>
165!CHECK-DAG: hlfir.assign %[[CLONE_LD1]] to %[[ARG1_DECL]]#0 : i32, !fir.ref<i32>
166!CHECK: }
167!CHECK: omp.yield
168!CHECK: }
169!CHECK: }
170
171subroutine mult_lastprivate_int2(arg1, arg2)
172        integer :: arg1, arg2
173!$OMP PARALLEL
174!$OMP DO LASTPRIVATE(arg1, arg2)
175do n = 1, 5
176        arg1 = 2
177        arg2 = 3
178        print *, arg1, arg2
179end do
180!$OMP END DO
181!$OMP END PARALLEL
182print *, arg1, arg2
183end subroutine
184
185!CHECK: func.func @_QPfirstpriv_lastpriv_int(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}, %[[ARG2:.*]]: !fir.ref<i32> {fir.bindc_name = "arg2"}) {
186!CHECK:    %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstpriv_lastpriv_intEarg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
187!CHECK:    %[[ARG2_DECL:.*]]:2 = hlfir.declare %[[ARG2]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstpriv_lastpriv_intEarg2"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
188!CHECK: omp.parallel  {
189! Firstprivate update
190!CHECK: %[[CLONE1:.*]] = fir.alloca i32 {bindc_name = "arg1", pinned, {{.*}}}
191!CHECK: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFfirstpriv_lastpriv_intEarg1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
192!CHECK: %[[FPV_LD:.*]] = fir.load %[[ARG1_DECL]]#0 : !fir.ref<i32>
193!CHECK: hlfir.assign %[[FPV_LD]] to %[[CLONE1_DECL]]#0 : i32, !fir.ref<i32>
194! Lastprivate Allocation
195!CHECK: %[[CLONE2:.*]] = fir.alloca i32 {bindc_name = "arg2", pinned, {{.*}}}
196!CHECK: %[[CLONE2_DECL:.*]]:2 = hlfir.declare %[[CLONE2]] {uniq_name = "_QFfirstpriv_lastpriv_intEarg2"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
197!CHECK-NOT: omp.barrier
198!CHECK: omp.wsloop {
199!CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
200
201! Testing last iteration check
202!CHECK: %[[V:.*]] = arith.addi %[[INDX_WS]], %{{.*}} : i32
203!CHECK: %[[C0:.*]] = arith.constant 0 : i32
204!CHECK: %[[T1:.*]] = arith.cmpi slt, %{{.*}}, %[[C0]] : i32
205!CHECK: %[[T2:.*]] = arith.cmpi slt, %[[V]], %{{.*}} : i32
206!CHECK: %[[T3:.*]] = arith.cmpi sgt, %[[V]], %{{.*}} : i32
207!CHECK: %[[IV_CMP:.*]] = arith.select %[[T1]], %[[T2]], %[[T3]] : i1
208!CHECK: fir.if %[[IV_CMP]] {
209!CHECK: fir.store %[[V]] to %{{.*}} : !fir.ref<i32>
210! Testing lastprivate val update
211!CHECK-NEXT: %[[CLONE_LD:.*]] = fir.load %[[CLONE2_DECL]]#0 : !fir.ref<i32>
212!CHECK-NEXT: hlfir.assign %[[CLONE_LD]] to %[[ARG2_DECL]]#0 : i32, !fir.ref<i32>
213!CHECK-NEXT: }
214!CHECK-NEXT: omp.yield
215!CHECK-NEXT: }
216!CHECK-NEXT: }
217
218subroutine firstpriv_lastpriv_int(arg1, arg2)
219        integer :: arg1, arg2
220!$OMP PARALLEL
221!$OMP DO FIRSTPRIVATE(arg1) LASTPRIVATE(arg2)
222do n = 1, 5
223        arg1 = 2
224        arg2 = 3
225        print *, arg1, arg2
226end do
227!$OMP END DO
228!$OMP END PARALLEL
229print *, arg1, arg2
230end subroutine
231
232!CHECK: func.func @_QPfirstpriv_lastpriv_int2(%[[ARG1:.*]]: !fir.ref<i32> {fir.bindc_name = "arg1"}) {
233!CHECK: %[[ARG1_DECL:.*]]:2 = hlfir.declare %[[ARG1]] dummy_scope %{{[0-9]+}} {uniq_name = "_QFfirstpriv_lastpriv_int2Earg1"} : (!fir.ref<i32>, !fir.dscope) -> (!fir.ref<i32>, !fir.ref<i32>)
234!CHECK: omp.parallel  {
235
236! Firstprivate update
237!CHECK: %[[CLONE1:.*]] = fir.alloca i32 {bindc_name = "arg1", pinned, {{.*}}}
238!CHECK: %[[CLONE1_DECL:.*]]:2 = hlfir.declare %[[CLONE1]] {uniq_name = "_QFfirstpriv_lastpriv_int2Earg1"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
239!CHECK-NEXT: %[[FPV_LD:.*]] = fir.load %[[ARG1_DECL]]#0 : !fir.ref<i32>
240!CHECK-NEXT: hlfir.assign %[[FPV_LD]] to %[[CLONE1_DECL]]#0 : i32, !fir.ref<i32>
241
242!CHECK-NEXT: %[[IV:.*]] = fir.alloca i32 {bindc_name = "n", pinned, {{.*}}}
243!CHECK-NEXT: hlfir.declare %[[IV]]
244
245!CHECK-NEXT: omp.barrier
246!CHECK: omp.wsloop {
247!CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
248! Testing last iteration check
249!CHECK: %[[V:.*]] = arith.addi %[[INDX_WS]], %{{.*}} : i32
250!CHECK: %[[C0:.*]] = arith.constant 0 : i32
251!CHECK: %[[T1:.*]] = arith.cmpi slt, %{{.*}}, %[[C0]] : i32
252!CHECK: %[[T2:.*]] = arith.cmpi slt, %[[V]], %{{.*}} : i32
253!CHECK: %[[T3:.*]] = arith.cmpi sgt, %[[V]], %{{.*}} : i32
254!CHECK: %[[IV_CMP:.*]] = arith.select %[[T1]], %[[T2]], %[[T3]] : i1
255!CHECK: fir.if %[[IV_CMP]] {
256!CHECK: fir.store %[[V]] to %{{.*}} : !fir.ref<i32>
257! Testing lastprivate val update
258!CHECK-NEXT: %[[CLONE_LD:.*]] = fir.load %[[CLONE1_DECL]]#0 : !fir.ref<i32>
259!CHECK-NEXT: hlfir.assign %[[CLONE_LD]] to %[[ARG1_DECL]]#0 : i32, !fir.ref<i32>
260!CHECK-NEXT: }
261!CHECK-NEXT: omp.yield
262!CHECK-NEXT: }
263!CHECK-NEXT: }
264
265subroutine firstpriv_lastpriv_int2(arg1)
266        integer :: arg1
267!$OMP PARALLEL
268!$OMP DO FIRSTPRIVATE(arg1) LASTPRIVATE(arg1)
269do n = 1, 5
270        arg1 = 2
271        print *, arg1
272end do
273!$OMP END DO
274!$OMP END PARALLEL
275print *, arg1
276end subroutine
277