diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index 3d3fcce44c529..9a8e4da0d61ef 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -382,13 +382,23 @@ static void genPrivateLikeInitRegion(mlir::OpBuilder &builder, RecipeOp recipe, retVal = declareOp.getBase(); } else if (auto seqTy = mlir::dyn_cast_or_null( refTy.getEleTy())) { - if (seqTy.hasDynamicExtents()) - TODO(loc, "private recipe of array with dynamic extents"); if (fir::isa_trivial(seqTy.getEleTy())) { - auto alloca = builder.create(loc, seqTy); - auto shapeOp = genShapeOp(builder, seqTy, loc); + mlir::Value shape; + llvm::SmallVector extents; + if (seqTy.hasDynamicExtents()) { + // Extents are passed as block arguments. First argument is the + // original value. + for (unsigned i = 1; i < recipe.getInitRegion().getArguments().size(); + ++i) + extents.push_back(recipe.getInitRegion().getArgument(i)); + shape = builder.create(loc, extents); + } else { + shape = genShapeOp(builder, seqTy, loc); + } + auto alloca = builder.create( + loc, seqTy, /*typeparams=*/mlir::ValueRange{}, extents); auto declareOp = builder.create( - loc, alloca, accPrivateInitName, shapeOp, + loc, alloca, accPrivateInitName, shape, llvm::ArrayRef{}, fir::FortranVariableFlagsAttr{}); retVal = declareOp.getBase(); } @@ -418,8 +428,22 @@ Fortran::lower::createOrGetPrivateRecipe(mlir::OpBuilder &builder, mlir::OpBuilder modBuilder(mod.getBodyRegion()); auto recipe = modBuilder.create(loc, recipeName, ty); + llvm::SmallVector argsTy{ty}; + llvm::SmallVector argsLoc{loc}; + if (auto refTy = mlir::dyn_cast_or_null(ty)) { + if (auto seqTy = + mlir::dyn_cast_or_null(refTy.getEleTy())) { + if (seqTy.hasDynamicExtents()) { + mlir::Type idxTy = builder.getIndexType(); + for (unsigned i = 0; i < seqTy.getDimension(); ++i) { + argsTy.push_back(idxTy); + argsLoc.push_back(loc); + } + } + } + } builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(), - {ty}, {loc}); + argsTy, argsLoc); builder.setInsertionPointToEnd(&recipe.getInitRegion().back()); genPrivateLikeInitRegion(builder, recipe, ty, loc); @@ -554,6 +578,29 @@ mlir::Type getTypeFromBounds(llvm::SmallVector &bounds, return ty; } +/// Check if the DataBoundsOp is a constant bound (lb and ub are constants or +/// extent is a constant). +bool isConstantBound(mlir::acc::DataBoundsOp &op) { + if (op.getLowerbound() && fir::getIntIfConstant(op.getLowerbound()) && + op.getUpperbound() && fir::getIntIfConstant(op.getUpperbound())) + return true; + if (op.getExtent() && fir::getIntIfConstant(op.getExtent())) + return true; + return false; +} + +/// Return true iff all the bounds are expressed with constant values. +bool areAllBoundConstant(llvm::SmallVector &bounds) { + for (auto bound : bounds) { + auto dataBound = + mlir::dyn_cast(bound.getDefiningOp()); + assert(dataBound && "Must be DataBoundOp operation"); + if (!isConstantBound(dataBound)) + return false; + } + return true; +} + template static void genPrivatizations(const Fortran::parser::AccObjectList &objectList, @@ -683,29 +730,6 @@ static R getReductionInitValue(mlir::acc::ReductionOperator op, mlir::Type ty) { llvm_unreachable("OpenACC reduction unsupported type"); } -/// Check if the DataBoundsOp is a constant bound (lb and ub are constants or -/// extent is a constant). -bool isConstantBound(mlir::acc::DataBoundsOp &op) { - if (op.getLowerbound() && fir::getIntIfConstant(op.getLowerbound()) && - op.getUpperbound() && fir::getIntIfConstant(op.getUpperbound())) - return true; - if (op.getExtent() && fir::getIntIfConstant(op.getExtent())) - return true; - return false; -} - -/// Return true iff all the bounds are expressed with constant values. -bool areAllBoundConstant(llvm::SmallVector &bounds) { - for (auto bound : bounds) { - auto dataBound = - mlir::dyn_cast(bound.getDefiningOp()); - assert(dataBound && "Must be DataBoundOp operation"); - if (!isConstantBound(dataBound)) - return false; - } - return true; -} - /// Return a constant with the initial value for the reduction operator and /// type combination. static mlir::Value getReductionInitValue(fir::FirOpBuilder &builder, diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 index 22726b0f49094..4123211e2f49e 100644 --- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -5,8 +5,8 @@ ! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_10xf32 : !fir.ref> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } copy { diff --git a/flang/test/Lower/OpenACC/acc-parallel.f90 b/flang/test/Lower/OpenACC/acc-parallel.f90 index cdde9128d70c9..9e48cb1a43712 100644 --- a/flang/test/Lower/OpenACC/acc-parallel.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel.f90 @@ -5,8 +5,8 @@ ! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_10x10xf32 : !fir.ref> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10x10xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10x10xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } copy { diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 index ac9e38e596044..cfec2e43930c4 100644 --- a/flang/test/Lower/OpenACC/acc-private.f90 +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -3,6 +3,14 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s --check-prefixes=CHECK,FIR ! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,HLFIR +! CHECK-LABEL: acc.private.recipe @privatization_ref_UxUx2xi32 : !fir.ref> init { +! CHECK: ^bb0(%[[ARG0:.*]]: !fir.ref>, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index, %[[ARG3:.*]]: index): +! HLFIR: %[[SHAPE:.*]] = fir.shape %[[ARG1]], %[[ARG2]], %[[ARG3]] : (index, index, index) -> !fir.shape<3> +! HLFIR: %[[ALLOCA:.*]] = fir.alloca !fir.array, %[[ARG1]], %[[ARG2]], %[[ARG3]] +! HLFIR: %[[DECL:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<3>) -> (!fir.box>, !fir.ref>) +! HLFIR: acc.yield %[[DECL]]#0 : !fir.box> +! CHECK: } + ! CHECK-LABEL: acc.private.recipe @privatization_box_ptr_Uxi32 : !fir.box>> init { ! CHECK: ^bb0(%[[ARG0:.*]]: !fir.box>>): ! HLFIR: %[[C0:.*]] = arith.constant 0 : index @@ -35,8 +43,8 @@ ! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_50xf32 : !fir.ref> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<50xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<50xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } copy { @@ -55,8 +63,8 @@ ! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_100xf32 : !fir.ref> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } copy { @@ -87,16 +95,16 @@ ! CHECK-LABEL: acc.private.recipe @privatization_ref_50xf32 : !fir.ref> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<50xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<50xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } ! CHECK-LABEL: acc.private.recipe @privatization_ref_100xf32 : !fir.ref> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<100xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } @@ -251,3 +259,20 @@ subroutine acc_private_pointer_array(a, n) ! HLFIR: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box>>) -> !fir.ptr> ! HLFIR: %[[PRIVATE:.*]] = acc.private varPtr(%[[BOX_ADDR]] : !fir.ptr>) bounds(%{{.*}}) -> !fir.ptr> {name = "a"} ! HLFIR: acc.parallel private(@privatization_box_ptr_Uxi32 -> %[[PRIVATE]] : !fir.ptr>) + +subroutine acc_private_dynamic_extent(a, n) + integer :: n, i + integer :: a(n, n, 2) + + !$acc parallel loop private(a) + do i = 1, n + a(i, i, 1) = i + end do +end subroutine + +! CHECK-LABEL: func.func @_QPacc_private_dynamic_extent( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}, %[[ARG1:.*]]: !fir.ref {fir.bindc_name = "n"}) { +! HLFIR: %[[DECL_N:.*]]:2 = hlfir.declare %arg1 {uniq_name = "_QFacc_private_dynamic_extentEn"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! HLFIR: %[[DECL_A:.*]]:2 = hlfir.declare %[[ARG0]](%16) {uniq_name = "_QFacc_private_dynamic_extentEa"} : (!fir.ref>, !fir.shape<3>) -> (!fir.box>, !fir.ref>) +! HLFIR: %[[PRIV:.*]] = acc.private varPtr(%[[DECL_A]]#1 : !fir.ref>) bounds(%{{.*}}, %{{.*}}, %{{.*}}) -> !fir.ref> {name = "a"} +! HLFIR: acc.parallel private(@privatization_ref_UxUx2xi32 -> %[[PRIV]] : !fir.ref>) diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 index c9d556b91cb6c..523873325eed1 100644 --- a/flang/test/Lower/OpenACC/acc-serial-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -5,8 +5,8 @@ ! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_10xf32 : !fir.ref> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<1>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } copy { diff --git a/flang/test/Lower/OpenACC/acc-serial.f90 b/flang/test/Lower/OpenACC/acc-serial.f90 index e538cee1407a2..56952a37c9101 100644 --- a/flang/test/Lower/OpenACC/acc-serial.f90 +++ b/flang/test/Lower/OpenACC/acc-serial.f90 @@ -5,8 +5,8 @@ ! CHECK-LABEL: acc.firstprivate.recipe @firstprivatization_ref_10x10xf32 : !fir.ref> init { ! CHECK: ^bb0(%{{.*}}: !fir.ref>): -! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10x10xf32> ! HLFIR: %[[SHAPE:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2> +! CHECK: %[[ALLOCA:.*]] = fir.alloca !fir.array<10x10xf32> ! HLFIR: %[[DECLARE:.*]]:2 = hlfir.declare %[[ALLOCA]](%[[SHAPE]]) {uniq_name = "acc.private.init"} : (!fir.ref>, !fir.shape<2>) -> (!fir.ref>, !fir.ref>) ! HLFIR: acc.yield %[[DECLARE]]#0 : !fir.ref> ! CHECK: } copy {