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