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