1! This test checks lowering of OpenMP DO Directive (Worksharing). 2 3! RUN: bbc -fopenmp -emit-fir %s -o - | FileCheck %s 4 5! CHECK-LABEL: func @_QPsimple_parallel_do() 6subroutine 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 23end subroutine 24 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"} 27subroutine 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 49end subroutine 50 51! CHECK-LABEL: func @_QPparallel_do_with_clauses 52! CHECK-SAME: %[[NT_REF:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"} 53subroutine 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 72end subroutine 73 74!=============================================================================== 75! Checking for the following construct: 76! !$omp parallel do private(...) firstprivate(...) 77!=============================================================================== 78 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"} 81subroutine 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: omp.barrier 91 ! CHECK: %[[WS_LB:.*]] = arith.constant 1 : i32 92 ! CHECK: %[[WS_UB:.*]] = arith.constant 9 : i32 93 ! CHECK: %[[WS_STEP:.*]] = arith.constant 1 : i32 94 ! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[WS_LB]]) to (%[[WS_UB]]) inclusive step (%[[WS_STEP]]) 95 !$OMP PARALLEL DO PRIVATE(cond) FIRSTPRIVATE(nt) 96 do i=1, 9 97 ! CHECK: fir.store %[[I]] to %[[IV_ADDR:.*]] : !fir.ref<i32> 98 ! CHECK: %[[LOAD_IV:.*]] = fir.load %[[IV_ADDR]] : !fir.ref<i32> 99 ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LOAD_IV]]) : (!fir.ref<i8>, i32) -> i1 100 ! CHECK: %[[PRIVATE_COND_VAL:.*]] = fir.load %[[PRIVATE_COND_REF]] : !fir.ref<!fir.logical<4>> 101 ! CHECK: %[[PRIVATE_COND_VAL_CVT:.*]] = fir.convert %[[PRIVATE_COND_VAL]] : (!fir.logical<4>) -> i1 102 ! CHECK: fir.call @_FortranAioOutputLogical({{.*}}, %[[PRIVATE_COND_VAL_CVT]]) : (!fir.ref<i8>, i1) -> i1 103 ! CHECK: %[[PRIVATE_NT_VAL:.*]] = fir.load %[[PRIVATE_NT_REF]] : !fir.ref<i32> 104 ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[PRIVATE_NT_VAL]]) : (!fir.ref<i8>, i32) -> i1 105 print*, i, cond, nt 106 end do 107 ! CHECK: omp.yield 108 ! CHECK: omp.terminator 109 !$OMP END PARALLEL DO 110end subroutine 111 112!=============================================================================== 113! Checking for the following construct 114! !$omp parallel private(...) firstprivate(...) 115! !$omp do 116!=============================================================================== 117 118subroutine parallel_private_do(cond,nt) 119logical :: cond 120 integer :: nt 121 integer :: i 122 !$OMP PARALLEL PRIVATE(cond) FIRSTPRIVATE(nt) 123 !$OMP DO 124 do i=1, 9 125 call foo(i, cond, nt) 126 end do 127 !$OMP END DO 128 !$OMP END PARALLEL 129end subroutine parallel_private_do 130 131! CHECK-LABEL: func.func @_QPparallel_private_do( 132! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}, 133! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"}) { 134! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFparallel_private_doEi"} 135! CHECK: omp.parallel { 136! CHECK: %[[I_PRIV:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} 137! CHECK: %[[COND_ADDR:.*]] = fir.alloca !fir.logical<4> {bindc_name = "cond", pinned, uniq_name = "_QFparallel_private_doEcond"} 138! CHECK: %[[NT_ADDR:.*]] = fir.alloca i32 {bindc_name = "nt", pinned, uniq_name = "_QFparallel_private_doEnt"} 139! CHECK: %[[NT:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32> 140! CHECK: fir.store %[[NT]] to %[[NT_ADDR]] : !fir.ref<i32> 141! CHECK: omp.barrier 142! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 143! CHECK: %[[VAL_8:.*]] = arith.constant 9 : i32 144! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 145! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { 146! CHECK: fir.store %[[I]] to %[[I_PRIV]] : !fir.ref<i32> 147! CHECK: fir.call @_QPfoo(%[[I_PRIV]], %[[COND_ADDR]], %[[NT_ADDR]]) : (!fir.ref<i32>, !fir.ref<!fir.logical<4>>, !fir.ref<i32>) -> () 148! CHECK: omp.yield 149! CHECK: } 150! CHECK: omp.terminator 151! CHECK: } 152! CHECK: return 153! CHECK: } 154 155!=============================================================================== 156! Checking for the following construct - multiple firstprivate clauses must emit 157! only one barrier 158! !$omp parallel 159! !$omp do firstprivate(...) firstprivate(...) 160!=============================================================================== 161 162subroutine omp_parallel_multiple_firstprivate_do(a, b) 163 integer::a, b 164 !$OMP PARALLEL FIRSTPRIVATE(a) FIRSTPRIVATE(b) 165 !$OMP DO 166 do i=1, 10 167 call bar(i, a) 168 end do 169 !$OMP END DO 170 !$OMP END PARALLEL 171end subroutine omp_parallel_multiple_firstprivate_do 172 173! CHECK-LABEL: func.func @_QPomp_parallel_multiple_firstprivate_do( 174! CHECK-SAME: %[[A_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, 175! CHECK-SAME: %[[B_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) { 176! CHECK: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_parallel_multiple_firstprivate_doEi"} 177! CHECK: omp.parallel { 178! CHECK: %[[I_PRIV_ADDR:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} 179! CHECK: %[[A_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "a", pinned, uniq_name = "_QFomp_parallel_multiple_firstprivate_doEa"} 180! CHECK: %[[A:.*]] = fir.load %[[A_ADDR]] : !fir.ref<i32> 181! CHECK: fir.store %[[A]] to %[[A_PRIV_ADDR]] : !fir.ref<i32> 182! CHECK: %[[B_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "b", pinned, uniq_name = "_QFomp_parallel_multiple_firstprivate_doEb"} 183! CHECK: %[[B:.*]] = fir.load %[[B_ADDR]] : !fir.ref<i32> 184! CHECK: fir.store %[[B]] to %[[B_PRIV_ADDR]] : !fir.ref<i32> 185! CHECK: omp.barrier 186! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 187! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32 188! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 189! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { 190! CHECK: fir.store %[[I]] to %[[I_PRIV_ADDR]] : !fir.ref<i32> 191! CHECK: fir.call @_QPbar(%[[I_PRIV_ADDR]], %[[A_PRIV_ADDR]]) : (!fir.ref<i32>, !fir.ref<i32>) -> () 192! CHECK: omp.yield 193! CHECK: } 194! CHECK: omp.terminator 195! CHECK: } 196! CHECK: return 197! CHECK: } 198 199!=============================================================================== 200! Checking for the following construct 201! !$omp parallel 202! !$omp do private(...) firstprivate(...) 203!=============================================================================== 204 205subroutine parallel_do_private(cond,nt) 206logical :: cond 207 integer :: nt 208 integer :: i 209 !$OMP PARALLEL 210 !$OMP DO PRIVATE(cond) FIRSTPRIVATE(nt) 211 do i=1, 9 212 call foo(i, cond, nt) 213 end do 214 !$OMP END DO 215 !$OMP END PARALLEL 216end subroutine parallel_do_private 217 218! CHECK-LABEL: func.func @_QPparallel_do_private( 219! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}, 220! CHECK-SAME: %[[VAL_1:.*]]: !fir.ref<i32> {fir.bindc_name = "nt"}) { 221! CHECK: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFparallel_do_privateEi"} 222! CHECK: omp.parallel { 223! CHECK: %[[COND_ADDR:.*]] = fir.alloca !fir.logical<4> {bindc_name = "cond", pinned, uniq_name = "_QFparallel_do_privateEcond"} 224! CHECK: %[[NT_ADDR:.*]] = fir.alloca i32 {bindc_name = "nt", pinned, uniq_name = "_QFparallel_do_privateEnt"} 225! CHECK: %[[NT:.*]] = fir.load %[[VAL_1]] : !fir.ref<i32> 226! CHECK: fir.store %[[NT]] to %[[NT_ADDR]] : !fir.ref<i32> 227! CHECK: omp.barrier 228! CHECK: %[[I_PRIV_ADDR:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} 229! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32 230! CHECK: %[[VAL_8:.*]] = arith.constant 9 : i32 231! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32 232! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_7]]) to (%[[VAL_8]]) inclusive step (%[[VAL_9]]) { 233! CHECK: fir.store %[[I]] to %[[I_PRIV_ADDR]] : !fir.ref<i32> 234! CHECK: fir.call @_QPfoo(%[[I_PRIV_ADDR]], %[[COND_ADDR]], %[[NT_ADDR]]) : (!fir.ref<i32>, !fir.ref<!fir.logical<4>>, !fir.ref<i32>) -> () 235! CHECK: omp.yield 236! CHECK: } 237! CHECK: omp.terminator 238! CHECK: } 239! CHECK: return 240! CHECK: } 241 242!=============================================================================== 243! Checking for the following construct - multiple firstprivate clauses must emit 244! only one barrier 245! !$omp parallel 246! !$omp do firstprivate(...) firstprivate(...) 247!=============================================================================== 248 249subroutine omp_parallel_do_multiple_firstprivate(a, b) 250 integer::a, b 251 !$OMP PARALLEL 252 !$OMP DO FIRSTPRIVATE(a) FIRSTPRIVATE(b) 253 do i=1, 10 254 call bar(i, a) 255 end do 256 !$OMP END DO 257 !$OMP END PARALLEL 258end subroutine omp_parallel_do_multiple_firstprivate 259 260! CHECK-LABEL: func.func @_QPomp_parallel_do_multiple_firstprivate( 261! CHECK-SAME: %[[A_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "a"}, 262! CHECK-SAME: %[[B_ADDR:.*]]: !fir.ref<i32> {fir.bindc_name = "b"}) { 263! CHECK: %[[I_ADDR:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFomp_parallel_do_multiple_firstprivateEi"} 264! CHECK: omp.parallel { 265! CHECK: %[[A_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "a", pinned, uniq_name = "_QFomp_parallel_do_multiple_firstprivateEa"} 266! CHECK: %[[A:.*]] = fir.load %[[A_ADDR]] : !fir.ref<i32> 267! CHECK: fir.store %[[A]] to %[[A_PRIV_ADDR]] : !fir.ref<i32> 268! CHECK: %[[B_PRIV_ADDR:.*]] = fir.alloca i32 {bindc_name = "b", pinned, uniq_name = "_QFomp_parallel_do_multiple_firstprivateEb"} 269! CHECK: %[[B:.*]] = fir.load %[[B_ADDR]] : !fir.ref<i32> 270! CHECK: fir.store %[[B]] to %[[B_PRIV_ADDR]] : !fir.ref<i32> 271! CHECK: omp.barrier 272! CHECK-NOT: omp.barrier 273! CHECK: %[[I_PRIV_ADDR:.*]] = fir.alloca i32 {adapt.valuebyref, pinned} 274! CHECK: %[[VAL_8:.*]] = arith.constant 1 : i32 275! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32 276! CHECK: %[[VAL_10:.*]] = arith.constant 1 : i32 277! CHECK: omp.wsloop for (%[[I:.*]]) : i32 = (%[[VAL_8]]) to (%[[VAL_9]]) inclusive step (%[[VAL_10]]) { 278! CHECK: fir.store %[[I]] to %[[I_PRIV_ADDR]] : !fir.ref<i32> 279! CHECK: fir.call @_QPbar(%[[I_PRIV_ADDR]], %[[A_PRIV_ADDR]]) : (!fir.ref<i32>, !fir.ref<i32>) -> () 280! CHECK: omp.yield 281! CHECK: } 282! CHECK: omp.terminator 283! CHECK: } 284! CHECK: return 285! CHECK: } 286