1 ! This test checks lowering of `LASTPRIVATE` clause for scalar types.
3 ! RUN: bbc -fopenmp -emit-hlfir %s -o - | FileCheck %s
4 ! RUN: flang -fc1 -fopenmp -emit-hlfir %s -o - | FileCheck %s
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>>)
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>>)
16 ! Check that we are accessing the clone inside the loop
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]])
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>
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>>
46 subroutine lastprivate_character(arg1
)
49 !$OMP DO LASTPRIVATE(arg1)
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>)
64 !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
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>
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>
84 subroutine lastprivate_int(arg1
)
87 !$OMP DO LASTPRIVATE(arg1)
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>)
106 !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
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>
127 subroutine mult_lastprivate_int(arg1
, arg2
)
128 integer :: arg1
, arg2
130 !$OMP DO LASTPRIVATE(arg1) LASTPRIVATE(arg2)
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>)
150 !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
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>
171 subroutine mult_lastprivate_int2(arg1
, arg2
)
172 integer :: arg1
, arg2
174 !$OMP DO LASTPRIVATE(arg1, arg2)
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
199 !CHECK-NEXT: omp.loop_nest (%[[INDX_WS:.*]]) : {{.*}} {
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>
214 !CHECK-NEXT: omp.yield
218 subroutine firstpriv_lastpriv_int(arg1
, arg2
)
219 integer :: arg1
, arg2
221 !$OMP DO FIRSTPRIVATE(arg1) LASTPRIVATE(arg2)
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 {
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>
242 !CHECK-NEXT: %[[IV:.*]] = fir.alloca i32 {bindc_name = "n", pinned, {{.*}}}
243 !CHECK-NEXT: hlfir.declare %[[IV]]
245 !CHECK-NEXT: omp.barrier
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>
261 !CHECK-NEXT: omp.yield
265 subroutine firstpriv_lastpriv_int2(arg1
)
268 !$OMP DO FIRSTPRIVATE(arg1) LASTPRIVATE(arg1)