diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -478,6 +478,57 @@ } } +static mlir::acc::PrivateRecipeOp +createBasePrivateRecipeOp(fir::FirOpBuilder &builder, mlir::Value input, + llvm::StringRef recipeName, mlir::Location loc) { + mlir::ModuleOp mod = builder.getModule(); + mlir::OpBuilder modBuilder(mod.getBodyRegion()); + mlir::Type ty = input.getType(); + auto recipe = + modBuilder.create(loc, recipeName, ty); + builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(), + {ty}, {loc}); + builder.setInsertionPointToEnd(&recipe.getInitRegion().back()); + builder.create( + loc, recipe.getInitRegion().front().getArgument(0)); + return recipe; +} + +static void +genPrivatizations(const Fortran::parser::AccObjectList &objectList, + Fortran::lower::AbstractConverter &converter, + Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &stmtCtx, + llvm::SmallVectorImpl &dataOperands, + llvm::SmallVector &privatizations) { + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + mlir::ModuleOp mod = builder.getModule(); + for (const auto &accObject : objectList.v) { + llvm::SmallVector bounds; + std::stringstream asFortran; + mlir::Location operandLocation = genOperandLocation(converter, accObject); + mlir::Value baseAddr = gatherDataOperandAddrAndBounds( + converter, builder, semanticsContext, stmtCtx, accObject, + operandLocation, asFortran, bounds); + + std::string recipeName = fir::getTypeAsString( + baseAddr.getType(), converter.getKindMap(), "privatization"); + if (auto recipe = + mod.lookupSymbol(recipeName)) { + privatizations.push_back(mlir::SymbolRefAttr::get( + builder.getContext(), recipe.getSymName().str())); + } else { + auto crtPos = builder.saveInsertionPoint(); + mlir::acc::PrivateRecipeOp newRecipe = createBasePrivateRecipeOp( + builder, baseAddr, recipeName, operandLocation); + builder.restoreInsertionPoint(crtPos); + privatizations.push_back(mlir::SymbolRefAttr::get( + builder.getContext(), newRecipe.getSymName().str())); + } + dataOperands.push_back(baseAddr); + } +} + template static void genObjectListWithModifier( const Clause *x, Fortran::lower::AbstractConverter &converter, @@ -824,9 +875,9 @@ copyEntryOperands, copyoutEntryOperands, createEntryOperands, dataClauseOperands; - // TODO: need to more work/design. llvm::SmallVector reductionOperands, privateOperands, firstprivateOperands; + llvm::SmallVector privatizations; // Async, wait and self clause have optional values but can be present with // no value as well. When there is no value, the op has an attribute to @@ -973,8 +1024,8 @@ } else if (const auto *privateClause = std::get_if( &clause.u)) { - genObjectList(privateClause->v, converter, semanticsContext, stmtCtx, - privateOperands); + genPrivatizations(privateClause->v, converter, semanticsContext, stmtCtx, + privateOperands, privatizations); } else if (const auto *firstprivateClause = std::get_if( &clause.u)) { @@ -1019,6 +1070,12 @@ if (addSelfAttr) computeOp.setSelfAttrAttr(builder.getUnitAttr()); + if constexpr (!std::is_same_v) { + if (!privatizations.empty()) + computeOp.setPrivatizationsAttr( + mlir::ArrayAttr::get(builder.getContext(), privatizations)); + } + auto insPt = builder.saveInsertionPoint(); builder.setInsertionPointAfter(computeOp); diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 --- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -2,6 +2,13 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s +! CHECK-LABEL: acc.private.recipe @privatization_10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: acc.yield %{{.*}} : !fir.ref> +! CHECK: } + +! CHECK-LABEL: func.func @_QPacc_parallel_loop() + subroutine acc_parallel_loop integer :: i, j @@ -442,19 +449,18 @@ ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} -! TODO: will be updated after lowering change in privatization to MLIR -! !$acc parallel loop private(a) firstprivate(b) -! DO i = 1, n -! a(i) = b(i) -! END DO + !$acc parallel loop private(a) firstprivate(b) + DO i = 1, n + a(i) = b(i) + END DO -! TODO: acc.parallel firstprivate(%[[B]] : !fir.ref>) private(%[[A]] : !fir.ref>) { -! TODO: acc.loop private(%[[A]] : !fir.ref>) { -! TODO: fir.do_loop -! TODO: acc.yield -! TODO-NEXT: }{{$}} -! TODO: acc.yield -! TODO-NEXT: }{{$}} +! CHECK: acc.parallel firstprivate(%[[B]] : !fir.ref>) private(@privatization_10xf32 -> %[[A]] : !fir.ref>) { +! CHECK: acc.loop private(%[[A]] : !fir.ref>) { +! CHECK: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} !$acc parallel loop seq DO i = 1, n diff --git a/flang/test/Lower/OpenACC/acc-parallel.f90 b/flang/test/Lower/OpenACC/acc-parallel.f90 --- a/flang/test/Lower/OpenACC/acc-parallel.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel.f90 @@ -2,6 +2,13 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s +! CHECK-LABEL: acc.private.recipe @privatization_10x10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: acc.yield %{{.*}} : !fir.ref> +! CHECK: } + +! CHECK-LABEL: func.func @_QPacc_parallel() + subroutine acc_parallel integer :: i, j @@ -288,12 +295,11 @@ !CHECK: acc.detach accPtr(%[[ATTACH_D]] : !fir.ptr) {dataClause = 10 : i64, name = "d"} !CHECK: acc.detach accPtr(%[[ATTACH_E]] : !fir.ptr) {dataClause = 10 : i64, name = "e"} -! TODO: will be updated after lowering change in privatization to MLIR -! !$acc parallel private(a) firstprivate(b) private(c) -! !$acc end parallel +!$acc parallel private(a) firstprivate(b) private(c) +!$acc end parallel -!TODO: acc.parallel firstprivate(%[[B]] : !fir.ref>) private(%[[A]], %[[C]] : !fir.ref>, !fir.ref>) { -!TODO: acc.yield -!TODO-NEXT: }{{$}} +! CHECK: acc.parallel firstprivate(%[[B]] : !fir.ref>) private(@privatization_10x10xf32 -> %[[A]] : !fir.ref>, @privatization_10x10xf32 -> %[[C]] : !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} end subroutine acc_parallel diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 --- a/flang/test/Lower/OpenACC/acc-serial-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -2,6 +2,13 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s +! CHECK-LABEL: acc.private.recipe @privatization_10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: acc.yield %{{.*}} : !fir.ref> +! CHECK: } + +! CHECK-LABEL: func.func @_QPacc_serial_loop() + subroutine acc_serial_loop integer :: i, j @@ -358,19 +365,18 @@ ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} -! TODO: update when lowering is updated to new private design -! !$acc serial loop private(a) firstprivate(b) -! DO i = 1, n -! a(i) = b(i) -! END DO + !$acc serial loop private(a) firstprivate(b) + DO i = 1, n + a(i) = b(i) + END DO -! TODO: acc.serial firstprivate(%[[B]] : !fir.ref>) private(%[[A]] : !fir.ref>) { -! TODO: acc.loop private(%[[A]] : !fir.ref>) { -! TODO: fir.do_loop -! TODO: acc.yield -! TODO-NEXT: }{{$}} -! TODO: acc.yield -! TODO-NEXT: }{{$}} +! CHECK: acc.serial firstprivate(%[[B]] : !fir.ref>) private(@privatization_10xf32 -> %[[A]] : !fir.ref>) { +! CHECK: acc.loop private(%[[A]] : !fir.ref>) { +! CHECK: fir.do_loop +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} !$acc serial loop seq DO i = 1, n diff --git a/flang/test/Lower/OpenACC/acc-serial.f90 b/flang/test/Lower/OpenACC/acc-serial.f90 --- a/flang/test/Lower/OpenACC/acc-serial.f90 +++ b/flang/test/Lower/OpenACC/acc-serial.f90 @@ -2,6 +2,13 @@ ! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s +! CHECK-LABEL: acc.private.recipe @privatization_10x10xf32 : !fir.ref> init { +! CHECK: ^bb0(%{{.*}}: !fir.ref>): +! CHECK: acc.yield %{{.*}} : !fir.ref> +! CHECK: } + +! CHECK-LABEL: func.func @_QPacc_serial() + subroutine acc_serial integer :: i, j @@ -231,12 +238,11 @@ ! CHECK: acc.detach accPtr(%[[ATTACH_D]] : !fir.ptr) {dataClause = 10 : i64, name = "d"} ! CHECK: acc.detach accPtr(%[[ATTACH_E]] : !fir.ptr) {dataClause = 10 : i64, name = "e"} -! TODO: update when lowering is updated to new private design -! !$acc serial private(a) firstprivate(b) private(c) -! !$acc end serial + !$acc serial private(a) firstprivate(b) private(c) + !$acc end serial -! TODO: acc.serial firstprivate(%[[B]] : !fir.ref>) private(%[[A]], %[[C]] : !fir.ref>, !fir.ref>) { -! TODO: acc.yield -! TODO-NEXT: }{{$}} +! CHECK: acc.serial firstprivate(%[[B]] : !fir.ref>) private(@privatization_10x10xf32 -> %[[A]] : !fir.ref>, @privatization_10x10xf32 -> %[[C]] : !fir.ref>) { +! CHECK: acc.yield +! CHECK-NEXT: }{{$}} end subroutine