From 5f85b93b237bab51d3582527c3f4f0076c3dc0f3 Mon Sep 17 00:00:00 2001 From: Razvan Lupusoru Date: Mon, 10 Feb 2025 09:58:15 -0800 Subject: [PATCH 1/3] [flang][acc] Ensure data exit action is generated for present & nocreate The acc.delete operation has semantics of decrementing present counter and deleting the data when the counter reaches zero. Since both acc.present and acc.nocreate are both intended to increment present counter, this matching exit action must be inserted. This is also what was specified in OpenACC dialect documentation: https://mlir.llvm.org/docs/Dialects/OpenACCDialect/#operation-categories --- flang/lib/Lower/OpenACC.cpp | 27 ++++++++++++++++--- flang/test/Lower/OpenACC/acc-kernels-loop.f90 | 4 +++ flang/test/Lower/OpenACC/acc-kernels.f90 | 6 +++++ .../test/Lower/OpenACC/acc-parallel-loop.f90 | 4 +++ flang/test/Lower/OpenACC/acc-parallel.f90 | 6 ++++- flang/test/Lower/OpenACC/acc-serial-loop.f90 | 4 +++ flang/test/Lower/OpenACC/acc-serial.f90 | 6 +++++ mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp | 1 + 8 files changed, 54 insertions(+), 4 deletions(-) diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index ac1a1c00eb145..da534107b15e4 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -2281,8 +2281,8 @@ static Op createComputeOp( mlir::Value selfCond; llvm::SmallVector waitOperands, attachEntryOperands, copyEntryOperands, copyinEntryOperands, copyoutEntryOperands, - createEntryOperands, dataClauseOperands, numGangs, numWorkers, - vectorLength, async; + createEntryOperands, nocreateEntryOperands, presentEntryOperands, + dataClauseOperands, numGangs, numWorkers, vectorLength, async; llvm::SmallVector numGangsDeviceTypes, numWorkersDeviceTypes, vectorLengthDeviceTypes, asyncDeviceTypes, asyncOnlyDeviceTypes, waitOperandsDeviceTypes, waitOnlyDeviceTypes; @@ -2457,19 +2457,25 @@ static Op createComputeOp( } else if (const auto *noCreateClause = std::get_if( &clause.u)) { + auto crtDataStart = dataClauseOperands.size(); genDataOperandOperations( noCreateClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_no_create, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, asyncOnlyDeviceTypes); + nocreateEntryOperands.append(dataClauseOperands.begin() + crtDataStart, + dataClauseOperands.end()); } else if (const auto *presentClause = std::get_if( &clause.u)) { + auto crtDataStart = dataClauseOperands.size(); genDataOperandOperations( presentClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_present, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, asyncOnlyDeviceTypes); + presentEntryOperands.append(dataClauseOperands.begin() + crtDataStart, + dataClauseOperands.end()); } else if (const auto *devicePtrClause = std::get_if( &clause.u)) { @@ -2634,6 +2640,10 @@ static Op createComputeOp( builder, attachEntryOperands, /*structured=*/true); genDataExitOperations( builder, createEntryOperands, /*structured=*/true); + genDataExitOperations( + builder, nocreateEntryOperands, /*structured=*/true); + genDataExitOperations( + builder, presentEntryOperands, /*structured=*/true); builder.restoreInsertionPoint(insPt); return computeOp; @@ -2648,7 +2658,8 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter, mlir::Value ifCond; llvm::SmallVector attachEntryOperands, createEntryOperands, copyEntryOperands, copyinEntryOperands, copyoutEntryOperands, - dataClauseOperands, waitOperands, async; + nocreateEntryOperands, presentEntryOperands, dataClauseOperands, + waitOperands, async; llvm::SmallVector asyncDeviceTypes, asyncOnlyDeviceTypes, waitOperandsDeviceTypes, waitOnlyDeviceTypes; llvm::SmallVector waitOperandsSegments; @@ -2745,19 +2756,25 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter, } else if (const auto *noCreateClause = std::get_if( &clause.u)) { + auto crtDataStart = dataClauseOperands.size(); genDataOperandOperations( noCreateClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_no_create, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, asyncOnlyDeviceTypes); + nocreateEntryOperands.append(dataClauseOperands.begin() + crtDataStart, + dataClauseOperands.end()); } else if (const auto *presentClause = std::get_if( &clause.u)) { + auto crtDataStart = dataClauseOperands.size(); genDataOperandOperations( presentClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_present, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, asyncOnlyDeviceTypes); + presentEntryOperands.append(dataClauseOperands.begin() + crtDataStart, + dataClauseOperands.end()); } else if (const auto *deviceptrClause = std::get_if( &clause.u)) { @@ -2837,6 +2854,10 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter, builder, attachEntryOperands, /*structured=*/true); genDataExitOperations( builder, createEntryOperands, /*structured=*/true); + genDataExitOperations( + builder, nocreateEntryOperands, /*structured=*/true); + genDataExitOperations( + builder, presentEntryOperands, /*structured=*/true); builder.restoreInsertionPoint(insPt); } diff --git a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 index 182b512f3931e..aa5d65afd57ec 100644 --- a/flang/test/Lower/OpenACC/acc-kernels-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-kernels-loop.f90 @@ -393,6 +393,8 @@ subroutine acc_kernels_loop ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[NOCREATE_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[NOCREATE_B]] : !fir.ref>) {dataClause = #acc, name = "b"} !$acc kernels loop present(a, b) DO i = 1, n @@ -407,6 +409,8 @@ subroutine acc_kernels_loop ! CHECK-NEXT: }{{$}} ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[PRESENT_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[PRESENT_B]] : !fir.ref>) {dataClause = #acc, name = "b"} !$acc kernels loop deviceptr(a) deviceptr(b) DO i = 1, n diff --git a/flang/test/Lower/OpenACC/acc-kernels.f90 b/flang/test/Lower/OpenACC/acc-kernels.f90 index f25a9d411098b..b333bb981a79b 100644 --- a/flang/test/Lower/OpenACC/acc-kernels.f90 +++ b/flang/test/Lower/OpenACC/acc-kernels.f90 @@ -253,6 +253,9 @@ subroutine acc_kernels ! CHECK: acc.kernels dataOperands(%[[NO_CREATE_A]], %[[NO_CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_C]] : !fir.ref>) {dataClause = #acc, name = "c"} +! CHECK: acc.delete accPtr(%[[NO_CREATE_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[NO_CREATE_B]] : !fir.ref>) {dataClause = #acc, name = "b"} !$acc kernels present(a, b, c) !$acc end kernels @@ -263,6 +266,9 @@ subroutine acc_kernels ! CHECK: acc.kernels dataOperands(%[[PRESENT_A]], %[[PRESENT_B]], %[[PRESENT_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { ! CHECK: acc.terminator ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[PRESENT_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[PRESENT_B]] : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[PRESENT_C]] : !fir.ref>) {dataClause = #acc, name = "c"} !$acc kernels deviceptr(a) deviceptr(c) !$acc end kernels diff --git a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 index 6f4409eaf5600..7a41da320b955 100644 --- a/flang/test/Lower/OpenACC/acc-parallel-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel-loop.f90 @@ -393,6 +393,8 @@ subroutine acc_parallel_loop ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[NOCREATE_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[NOCREATE_B]] : !fir.ref>) {dataClause = #acc, name = "b"} !$acc parallel loop present(a, b) DO i = 1, n @@ -407,6 +409,8 @@ subroutine acc_parallel_loop ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[PRESENT_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[PRESENT_B]] : !fir.ref>) {dataClause = #acc, name = "b"} !$acc parallel loop deviceptr(a) deviceptr(b) DO i = 1, n diff --git a/flang/test/Lower/OpenACC/acc-parallel.f90 b/flang/test/Lower/OpenACC/acc-parallel.f90 index 7a51be21e914d..e16c1b218878c 100644 --- a/flang/test/Lower/OpenACC/acc-parallel.f90 +++ b/flang/test/Lower/OpenACC/acc-parallel.f90 @@ -291,7 +291,8 @@ subroutine acc_parallel ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} ! CHECK: acc.delete accPtr(%[[CREATE_C]] : !fir.ref>) {dataClause = #acc, name = "c"} - +! CHECK: acc.delete accPtr(%[[NO_CREATE_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[NO_CREATE_B]] : !fir.ref>) {dataClause = #acc, name = "b"} !$acc parallel present(a, b, c) !$acc end parallel @@ -302,6 +303,9 @@ subroutine acc_parallel ! CHECK: acc.parallel dataOperands(%[[PRESENT_A]], %[[PRESENT_B]], %[[PRESENT_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[PRESENT_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[PRESENT_B]] : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[PRESENT_C]] : !fir.ref>) {dataClause = #acc, name = "c"} !$acc parallel deviceptr(a) deviceptr(c) !$acc end parallel diff --git a/flang/test/Lower/OpenACC/acc-serial-loop.f90 b/flang/test/Lower/OpenACC/acc-serial-loop.f90 index 66cde19ef09af..a94f0e8e8583e 100644 --- a/flang/test/Lower/OpenACC/acc-serial-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-serial-loop.f90 @@ -334,6 +334,8 @@ subroutine acc_serial_loop ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[NOCREATE_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[NOCREATE_B]] : !fir.ref>) {dataClause = #acc, name = "b"} !$acc serial loop present(a, b) DO i = 1, n @@ -348,6 +350,8 @@ subroutine acc_serial_loop ! CHECK-NEXT: }{{$}} ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[PRESENT_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[PRESENT_B]] : !fir.ref>) {dataClause = #acc, name = "b"} !$acc serial loop deviceptr(a) deviceptr(b) DO i = 1, n diff --git a/flang/test/Lower/OpenACC/acc-serial.f90 b/flang/test/Lower/OpenACC/acc-serial.f90 index 88b801a82ee68..f2f73876af877 100644 --- a/flang/test/Lower/OpenACC/acc-serial.f90 +++ b/flang/test/Lower/OpenACC/acc-serial.f90 @@ -227,6 +227,9 @@ subroutine acc_serial ! CHECK: acc.serial dataOperands(%[[NO_CREATE_A]], %[[NO_CREATE_B]], %[[CREATE_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[CREATE_C]] : !fir.ref>) {dataClause = #acc, name = "c"} +! CHECK: acc.delete accPtr(%[[NO_CREATE_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[NO_CREATE_B]] : !fir.ref>) {dataClause = #acc, name = "b"} !$acc serial present(a, b, c) !$acc end serial @@ -237,6 +240,9 @@ subroutine acc_serial ! CHECK: acc.serial dataOperands(%[[PRESENT_A]], %[[PRESENT_B]], %[[PRESENT_C]] : !fir.ref>, !fir.ref>, !fir.ref>) { ! CHECK: acc.yield ! CHECK-NEXT: }{{$}} +! CHECK: acc.delete accPtr(%[[PRESENT_A]] : !fir.ref>) {dataClause = #acc, name = "a"} +! CHECK: acc.delete accPtr(%[[PRESENT_B]] : !fir.ref>) {dataClause = #acc, name = "b"} +! CHECK: acc.delete accPtr(%[[PRESENT_C]] : !fir.ref>) {dataClause = #acc, name = "c"} !$acc serial deviceptr(a) deviceptr(c) !$acc end serial diff --git a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp index aaa3db22110ac..8f150cb33e6f3 100644 --- a/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp +++ b/mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp @@ -580,6 +580,7 @@ LogicalResult acc::DeleteOp::verify() { getDataClause() != acc::DataClause::acc_copyin && getDataClause() != acc::DataClause::acc_copyin_readonly && getDataClause() != acc::DataClause::acc_present && + getDataClause() != acc::DataClause::acc_no_create && getDataClause() != acc::DataClause::acc_declare_device_resident && getDataClause() != acc::DataClause::acc_declare_link) return emitError( From fed14e2d5d01d182e1d69a19bf650ef160417285 Mon Sep 17 00:00:00 2001 From: Razvan Lupusoru Date: Mon, 10 Feb 2025 10:04:36 -0800 Subject: [PATCH 2/3] Fix formatting --- flang/lib/Lower/OpenACC.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index da534107b15e4..bbca4cab589b4 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -2464,7 +2464,7 @@ static Op createComputeOp( /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, asyncOnlyDeviceTypes); nocreateEntryOperands.append(dataClauseOperands.begin() + crtDataStart, - dataClauseOperands.end()); + dataClauseOperands.end()); } else if (const auto *presentClause = std::get_if( &clause.u)) { @@ -2475,7 +2475,7 @@ static Op createComputeOp( /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, asyncOnlyDeviceTypes); presentEntryOperands.append(dataClauseOperands.begin() + crtDataStart, - dataClauseOperands.end()); + dataClauseOperands.end()); } else if (const auto *devicePtrClause = std::get_if( &clause.u)) { @@ -2763,7 +2763,7 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, asyncOnlyDeviceTypes); nocreateEntryOperands.append(dataClauseOperands.begin() + crtDataStart, - dataClauseOperands.end()); + dataClauseOperands.end()); } else if (const auto *presentClause = std::get_if( &clause.u)) { @@ -2774,7 +2774,7 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter, /*structured=*/true, /*implicit=*/false, async, asyncDeviceTypes, asyncOnlyDeviceTypes); presentEntryOperands.append(dataClauseOperands.begin() + crtDataStart, - dataClauseOperands.end()); + dataClauseOperands.end()); } else if (const auto *deviceptrClause = std::get_if( &clause.u)) { From 01ba4d3656acfa839e2ea378ee3a2d5e05ec6e68 Mon Sep 17 00:00:00 2001 From: Razvan Lupusoru Date: Mon, 10 Feb 2025 10:36:58 -0800 Subject: [PATCH 3/3] Add support for exit action for present used in acc declare --- flang/lib/Lower/OpenACC.cpp | 14 ++++++++++---- .../OpenACC/acc-declare-unwrap-defaultbounds.f90 | 4 +++- flang/test/Lower/OpenACC/acc-declare.f90 | 4 +++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index bbca4cab589b4..a11a2c824bf9e 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -3835,7 +3835,7 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter, const Fortran::parser::AccClauseList &accClauseList) { llvm::SmallVector dataClauseOperands, copyEntryOperands, copyinEntryOperands, createEntryOperands, copyoutEntryOperands, - deviceResidentEntryOperands; + presentEntryOperands, deviceResidentEntryOperands; Fortran::lower::StatementContext stmtCtx; fir::FirOpBuilder &builder = converter.getFirOpBuilder(); @@ -3866,11 +3866,14 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter, } else if (const auto *presentClause = std::get_if( &clause.u)) { + auto crtDataStart = dataClauseOperands.size(); genDeclareDataOperandOperations( + mlir::acc::DeleteOp>( presentClause->v, converter, semanticsContext, stmtCtx, dataClauseOperands, mlir::acc::DataClause::acc_present, /*structured=*/true, /*implicit=*/false); + presentEntryOperands.append(dataClauseOperands.begin() + crtDataStart, + dataClauseOperands.end()); } else if (const auto *copyinClause = std::get_if(&clause.u)) { auto crtDataStart = dataClauseOperands.size(); @@ -3949,14 +3952,15 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter, openAccCtx.attachCleanup([&builder, loc, createEntryOperands, copyEntryOperands, copyinEntryOperands, - copyoutEntryOperands, deviceResidentEntryOperands, - declareToken]() { + copyoutEntryOperands, presentEntryOperands, + deviceResidentEntryOperands, declareToken]() { llvm::SmallVector operands; operands.append(createEntryOperands); operands.append(deviceResidentEntryOperands); operands.append(copyEntryOperands); operands.append(copyinEntryOperands); operands.append(copyoutEntryOperands); + operands.append(presentEntryOperands); mlir::func::FuncOp funcOp = builder.getFunction(); auto ops = funcOp.getOps(); @@ -3978,6 +3982,8 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter, builder, copyinEntryOperands, /*structured=*/true); genDataExitOperations( builder, copyoutEntryOperands, /*structured=*/true); + genDataExitOperations( + builder, presentEntryOperands, /*structured=*/true); }); } diff --git a/flang/test/Lower/OpenACC/acc-declare-unwrap-defaultbounds.f90 b/flang/test/Lower/OpenACC/acc-declare-unwrap-defaultbounds.f90 index 0b7c8664abd9f..065033431137d 100644 --- a/flang/test/Lower/OpenACC/acc-declare-unwrap-defaultbounds.f90 +++ b/flang/test/Lower/OpenACC/acc-declare-unwrap-defaultbounds.f90 @@ -65,8 +65,10 @@ subroutine acc_declare_present(a) ! CHECK-DAG: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_presentEa"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%{{.*}} : index) startIdx(%[[C1]] : index) ! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[DECL]]#0 : !fir.ref>) bounds(%[[BOUND]]) -> !fir.ref> {name = "a"} -! CHECK: acc.declare_enter dataOperands(%[[PRESENT]] : !fir.ref>) +! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[PRESENT]] : !fir.ref>) ! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) +! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[PRESENT]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref>) bounds(%[[BOUND]]) {dataClause = #acc, name = "a"} subroutine acc_declare_copyin() integer :: a(100), b(10), i diff --git a/flang/test/Lower/OpenACC/acc-declare.f90 b/flang/test/Lower/OpenACC/acc-declare.f90 index 9f03bc3c2b481..8727c0722e474 100644 --- a/flang/test/Lower/OpenACC/acc-declare.f90 +++ b/flang/test/Lower/OpenACC/acc-declare.f90 @@ -59,8 +59,10 @@ subroutine acc_declare_present(a) ! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}) ! CHECK: %[[DECL:.*]]:2 = hlfir.declare %[[ARG0]](%{{.*}}) dummy_scope %{{[0-9]+}} {acc.declare = #acc.declare, uniq_name = "_QMacc_declareFacc_declare_presentEa"} : (!fir.ref>, !fir.shape<1>, !fir.dscope) -> (!fir.ref>, !fir.ref>) ! CHECK: %[[PRESENT:.*]] = acc.present varPtr(%[[DECL]]#0 : !fir.ref>) -> !fir.ref> {name = "a"} -! CHECK: acc.declare_enter dataOperands(%[[PRESENT]] : !fir.ref>) +! CHECK: %[[TOKEN:.*]] = acc.declare_enter dataOperands(%[[PRESENT]] : !fir.ref>) ! CHECK: %{{.*}}:2 = fir.do_loop %{{.*}} = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%arg{{.*}} = %{{.*}}) -> (index, i32) +! CHECK: acc.declare_exit token(%[[TOKEN]]) dataOperands(%[[PRESENT]] : !fir.ref>) +! CHECK: acc.delete accPtr(%[[PRESENT]] : !fir.ref>) {dataClause = #acc, name = "a"} subroutine acc_declare_copyin() integer :: a(100), b(10), i