diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h --- a/flang/include/flang/Lower/OpenACC.h +++ b/flang/include/flang/Lower/OpenACC.h @@ -45,6 +45,7 @@ namespace lower { class AbstractConverter; +class StatementContext; namespace pft { struct Evaluation; @@ -55,7 +56,8 @@ pft::Evaluation &, const parser::OpenACCConstruct &); void genOpenACCDeclarativeConstruct( AbstractConverter &, Fortran::semantics::SemanticsContext &, - pft::Evaluation &, const parser::OpenACCDeclarativeConstruct &); + StatementContext &, pft::Evaluation &, + const parser::OpenACCDeclarativeConstruct &); /// Get a acc.private.recipe op for the given type or create it if it does not /// exist yet. diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -2230,7 +2230,7 @@ void genFIR(const Fortran::parser::OpenACCDeclarativeConstruct &accDecl) { mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint(); genOpenACCDeclarativeConstruct(*this, bridge.getSemanticsContext(), - getEval(), accDecl); + bridge.fctCtx(), getEval(), accDecl); for (Fortran::lower::pft::Evaluation &e : getEval().getNestedEvaluations()) genFIR(e); builder->restoreInsertionPoint(insertPt); 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 @@ -2397,6 +2397,7 @@ static void genDeclareInFunction(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &fctCtx, mlir::Location loc, const Fortran::parser::AccClauseList &accClauseList) { llvm::SmallVector dataClauseOperands, copyEntryOperands; @@ -2418,8 +2419,14 @@ TODO(clauseLocation, "clause on declare directive"); } } - builder.create(loc, dataClauseOperands); + + // Attach declare exit operation generation to function context. + fctCtx.attachCleanup([&builder, loc, copyEntryOperands]() { + builder.create(loc, copyEntryOperands); + genDataExitOperations( + builder, copyEntryOperands, /*structured=*/true, /*implicit=*/false); + }); } static void @@ -2465,6 +2472,7 @@ static void genACC(Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &fctCtx, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenACCStandaloneDeclarativeConstruct &declareConstruct) { @@ -2483,8 +2491,8 @@ auto funcOp = builder.getBlock()->getParent()->getParentOfType(); if (funcOp) - genDeclareInFunction(converter, semanticsContext, directiveLocation, - accClauseList); + genDeclareInFunction(converter, semanticsContext, fctCtx, + directiveLocation, accClauseList); else if (moduleOp) genDeclareInModule(converter, moduleOp, accClauseList); return; @@ -2532,6 +2540,7 @@ void Fortran::lower::genOpenACCDeclarativeConstruct( Fortran::lower::AbstractConverter &converter, Fortran::semantics::SemanticsContext &semanticsContext, + Fortran::lower::StatementContext &fctCtx, Fortran::lower::pft::Evaluation &eval, const Fortran::parser::OpenACCDeclarativeConstruct &accDeclConstruct) { @@ -2539,7 +2548,7 @@ common::visitors{ [&](const Fortran::parser::OpenACCStandaloneDeclarativeConstruct &standaloneDeclarativeConstruct) { - genACC(converter, semanticsContext, eval, + genACC(converter, semanticsContext, fctCtx, eval, standaloneDeclarativeConstruct); }, [&](const Fortran::parser::OpenACCRoutineConstruct diff --git a/flang/test/Lower/OpenACC/acc-declare.f90 b/flang/test/Lower/OpenACC/acc-declare.f90 --- a/flang/test/Lower/OpenACC/acc-declare.f90 +++ b/flang/test/Lower/OpenACC/acc-declare.f90 @@ -87,4 +87,12 @@ ! CHECK: %[[COPYIN:.*]] = acc.copyin varPtr(%[[ALLOCA]] : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {dataClause = #acc, name = "a"} ! CHECK: acc.declare_enter dataOperands(%[[COPYIN]] : !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%{{.*}} = %{{.*}}) -> (index, i32) { +! CHECK: } + +! CHECK: acc.declare_exit dataOperands(%[[COPYIN]] : !fir.ref>) +! CHECK: acc.copyout accPtr(%[[COPYIN]] : !fir.ref>) bounds(%[[BOUND]]) to varPtr(%[[ALLOCA]] : !fir.ref>) {dataClause = #acc, name = "a"} + +! CHECK: return + end module