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 @@ -2404,7 +2404,7 @@ mlir::Location loc, const Fortran::parser::AccClauseList &accClauseList) { llvm::SmallVector dataClauseOperands, copyEntryOperands, - createEntryOperands; + createEntryOperands, copyoutEntryOperands; Fortran::lower::StatementContext stmtCtx; fir::FirOpBuilder &builder = converter.getFirOpBuilder(); for (const Fortran::parser::AccClause &clause : accClauseList.v) { @@ -2444,6 +2444,20 @@ Fortran::parser::AccDataModifier::Modifier::ReadOnly, dataClauseOperands, mlir::acc::DataClause::acc_copyin, mlir::acc::DataClause::acc_copyin_readonly, /*setDeclareAttr=*/true); + } else if (const auto *copyoutClause = + std::get_if( + &clause.u)) { + const Fortran::parser::AccObjectListWithModifier &listWithModifier = + copyoutClause->v; + const auto &accObjectList = + std::get(listWithModifier.t); + auto crtDataStart = dataClauseOperands.size(); + genDataOperandOperations( + accObjectList, converter, semanticsContext, stmtCtx, + dataClauseOperands, mlir::acc::DataClause::acc_copyout, + /*structured=*/true, /*setDeclareAttr=*/true); + copyoutEntryOperands.append(dataClauseOperands.begin() + crtDataStart, + dataClauseOperands.end()); } else { mlir::Location clauseLocation = converter.genLocation(clause.source); TODO(clauseLocation, "clause on declare directive"); @@ -2451,16 +2465,21 @@ } builder.create(loc, dataClauseOperands); - if (!createEntryOperands.empty() || !copyEntryOperands.empty()) { + if (!createEntryOperands.empty() || !copyEntryOperands.empty() || + !copyoutEntryOperands.empty()) { // Attach declare exit operation generation to function context. fctCtx.attachCleanup([&builder, loc, dataClauseOperands, - createEntryOperands, copyEntryOperands]() { + createEntryOperands, copyEntryOperands, + copyoutEntryOperands]() { builder.create(loc, dataClauseOperands); genDataExitOperations( builder, createEntryOperands, /*structured=*/true, /*implicit=*/false); genDataExitOperations( builder, copyEntryOperands, /*structured=*/true, /*implicit=*/false); + genDataExitOperations( + builder, copyoutEntryOperands, /*structured=*/true, + /*implicit=*/false); }); } } 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 @@ -155,4 +155,22 @@ ! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) ! CHECK-NOT: acc.declare_exit + subroutine acc_declare_copyout() + integer :: a(100), i + !$acc declare copyout(a) + + do i = 1, 100 + a(i) = i + end do + end subroutine + +! CHECK-LABEL: func.func @_QMacc_declarePacc_declare_copyout() +! CHECK: %[[A:.*]] = fir.alloca !fir.array<100xi32> {acc.declare = #acc.declare, bindc_name = "a", uniq_name = "_QMacc_declareFacc_declare_copyoutEa"} +! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[A]] : !fir.ref>) bounds(%{{.*}}) -> !fir.ref> {dataClause = #acc, name = "a"} +! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) +! CHECK: acc.declare_exit dataOperands(%[[CREATE]] : !fir.ref>) +! CHECK: acc.copyout accPtr(%[[CREATE]] : !fir.ref>) bounds(%{{.*}}) to varPtr(%[[A]] : !fir.ref>) {name = "a"} +! CHECK: return + end module