[flang-commits] [flang] 672a2c4 - [flang][openacc] Generate declare pre/post dealloc function
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Thu Aug 10 11:06:03 PDT 2023
Author: Valentin Clement
Date: 2023-08-10T10:55:12-07:00
New Revision: 672a2c4a5aa1310a4ad63137857f064b4ab439c5
URL: https://github.com/llvm/llvm-project/commit/672a2c4a5aa1310a4ad63137857f064b4ab439c5
DIFF: https://github.com/llvm/llvm-project/commit/672a2c4a5aa1310a4ad63137857f064b4ab439c5.diff
LOG: [flang][openacc] Generate declare pre/post dealloc function
Generate the function dealing with the action on deallocation (pre/post) of
a declare variable.
Reviewed By: razvanlupusoru
Differential Revision: https://reviews.llvm.org/D157530
Added:
Modified:
flang/include/flang/Lower/OpenACC.h
flang/lib/Lower/OpenACC.cpp
flang/test/Lower/OpenACC/acc-declare.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Lower/OpenACC.h b/flang/include/flang/Lower/OpenACC.h
index ef0360be439c4f..c551b69f2b2754 100644
--- a/flang/include/flang/Lower/OpenACC.h
+++ b/flang/include/flang/Lower/OpenACC.h
@@ -51,6 +51,11 @@ namespace pft {
struct Evaluation;
} // namespace pft
+static constexpr llvm::StringRef declarePreDeallocSuffix =
+ "_acc_declare_update_desc_pre_dealloc";
+static constexpr llvm::StringRef declarePostDeallocSuffix =
+ "_acc_declare_update_desc_post_dealloc";
+
void genOpenACCConstruct(AbstractConverter &,
Fortran::semantics::SemanticsContext &,
pft::Evaluation &, const parser::OpenACCConstruct &);
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index f899590336a715..97691232192b31 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -2392,6 +2392,86 @@ static void createRegisterFunc(mlir::OpBuilder &modBuilder,
modBuilder.setInsertionPointAfter(registerFuncOp);
}
+static mlir::func::FuncOp createDeclareFunc(mlir::OpBuilder &modBuilder,
+ fir::FirOpBuilder &builder,
+ mlir::Location loc,
+ llvm::StringRef funcName) {
+ auto funcTy = mlir::FunctionType::get(modBuilder.getContext(), {}, {});
+ auto funcOp = modBuilder.create<mlir::func::FuncOp>(loc, funcName, funcTy);
+ funcOp.setVisibility(mlir::SymbolTable::Visibility::Private);
+ builder.createBlock(&funcOp.getRegion(), funcOp.getRegion().end(), {}, {});
+ builder.setInsertionPointToEnd(&funcOp.getRegion().back());
+ builder.create<mlir::func::ReturnOp>(loc);
+ builder.setInsertionPointToStart(&funcOp.getRegion().back());
+ return funcOp;
+}
+
+/// Action to be performed on deallocation are split in two distinct functions.
+/// - Pre deallocation function includes all the action to be performed before
+/// the actual deallocation is done on the host side.
+/// - Post deallocation function includes update to the descriptor.
+template <typename ExitOp>
+static void createDeclareDeallocFunc(mlir::OpBuilder &modBuilder,
+ fir::FirOpBuilder &builder,
+ mlir::Location loc,
+ fir::GlobalOp &globalOp,
+ mlir::acc::DataClause clause) {
+
+ // Generate the pre dealloc function.
+ std::stringstream preDeallocFuncName;
+ preDeallocFuncName << globalOp.getSymName().str()
+ << Fortran::lower::declarePreDeallocSuffix.str();
+ auto preDeallocOp =
+ createDeclareFunc(modBuilder, builder, loc, preDeallocFuncName.str());
+ fir::AddrOfOp addrOp = builder.create<fir::AddrOfOp>(
+ loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol());
+ auto loadOp = builder.create<fir::LoadOp>(loc, addrOp.getResult());
+ fir::BoxAddrOp boxAddrOp = builder.create<fir::BoxAddrOp>(loc, loadOp);
+ addDeclareAttr(builder, boxAddrOp.getOperation(), clause);
+
+ std::stringstream asFortran;
+ asFortran << Fortran::lower::mangle::demangleName(globalOp.getSymName());
+ llvm::SmallVector<mlir::Value> bounds;
+ mlir::acc::GetDevicePtrOp entryOp =
+ createDataEntryOp<mlir::acc::GetDevicePtrOp>(
+ builder, loc, boxAddrOp.getResult(), asFortran, bounds,
+ /*structured=*/false, /*implicit=*/false, clause,
+ boxAddrOp.getType());
+
+ builder.create<mlir::acc::DeclareExitOp>(
+ loc, mlir::ValueRange(entryOp.getAccPtr()));
+
+ mlir::Value varPtr;
+ if constexpr (std::is_same_v<ExitOp, mlir::acc::CopyoutOp> ||
+ std::is_same_v<ExitOp, mlir::acc::UpdateHostOp>)
+ varPtr = entryOp.getVarPtr();
+ builder.create<ExitOp>(entryOp.getLoc(), entryOp.getAccPtr(), varPtr,
+ entryOp.getBounds(), entryOp.getDataClause(),
+ /*structured=*/false, /*implicit=*/false,
+ builder.getStringAttr(*entryOp.getName()));
+
+ // Generate the post dealloc function.
+ modBuilder.setInsertionPointAfter(preDeallocOp);
+ std::stringstream postDeallocFuncName;
+ postDeallocFuncName << globalOp.getSymName().str()
+ << Fortran::lower::declarePostDeallocSuffix.str();
+ auto postDeallocOp =
+ createDeclareFunc(modBuilder, builder, loc, postDeallocFuncName.str());
+
+ addrOp = builder.create<fir::AddrOfOp>(
+ loc, fir::ReferenceType::get(globalOp.getType()), globalOp.getSymbol());
+ asFortran << "_desc";
+ mlir::acc::UpdateDeviceOp updateDeviceOp =
+ createDataEntryOp<mlir::acc::UpdateDeviceOp>(
+ builder, loc, addrOp, asFortran, bounds,
+ /*structured=*/false, /*implicit=*/true,
+ mlir::acc::DataClause::acc_update_device, addrOp.getType());
+ llvm::SmallVector<int32_t> operandSegments{0, 0, 0, 0, 0, 1};
+ llvm::SmallVector<mlir::Value> operands{updateDeviceOp.getResult()};
+ createSimpleOp<mlir::acc::UpdateOp>(builder, loc, operands, operandSegments);
+ modBuilder.setInsertionPointAfter(postDeallocOp);
+}
+
template <typename EntryOp, typename ExitOp>
static void genGlobalCtors(Fortran::lower::AbstractConverter &converter,
mlir::OpBuilder &modBuilder,
@@ -2422,6 +2502,9 @@ static void genGlobalCtors(Fortran::lower::AbstractConverter &converter,
/*implicit=*/true);
createRegisterFunc<EntryOp>(
modBuilder, builder, operandLocation, globalOp, clause);
+ if constexpr (!std::is_same_v<EntryOp, ExitOp>)
+ createDeclareDeallocFunc<ExitOp>(
+ modBuilder, builder, operandLocation, globalOp, clause);
} else {
createDeclareGlobalOp<mlir::acc::GlobalConstructorOp, EntryOp,
mlir::acc::DeclareEnterOp, ExitOp>(
diff --git a/flang/test/Lower/OpenACC/acc-declare.f90 b/flang/test/Lower/OpenACC/acc-declare.f90
index 2d1a52bd01ab7f..b253294ab33cf0 100644
--- a/flang/test/Lower/OpenACC/acc-declare.f90
+++ b/flang/test/Lower/OpenACC/acc-declare.f90
@@ -282,6 +282,23 @@ module acc_declare_allocatable_test
! CHECK: return
! CHECK: }
+! CHECK-LABEL: func.func private @_QMacc_declare_allocatable_testEdata1_acc_declare_update_desc_pre_dealloc() {
+! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK: %[[LOAD]] = fir.load %[[GLOBAL_ADDR]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK: %[[BOXADDR:.*]] = fir.box_addr %[[LOAD]] {acc.declare = #acc.declare<dataClause = acc_create>} : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+! CHECK: %[[DEVPTR:.*]] = acc.getdeviceptr varPtr(%[[BOXADDR]] : !fir.heap<!fir.array<?xi32>>) -> !fir.heap<!fir.array<?xi32>> {dataClause = #acc<data_clause acc_create>, name = "data1", structured = false}
+! CHECK: acc.declare_exit dataOperands(%[[DEVICEPTR]] : !fir.heap<!fir.array<?xi32>>)
+! CHECK: acc.delete accPtr(%[[DEVPTR]] : !fir.heap<!fir.array<?xi32>>) {dataClause = #acc<data_clause acc_create>, name = "data1", structured = false}
+! CHECK: return
+! CHECK: }
+
+! CHECK-LABEL: func.func private @_QMacc_declare_allocatable_testEdata1_acc_declare_update_desc_post_dealloc() {
+! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+! CHECK: %[[UPDATE:.*]] = acc.update_device varPtr(%[[GLOBAL_ADDR]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {implicit = true, name = "data1_desc", structured = false}
+! CHECK: acc.update dataOperands(%[[UPDATE]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>)
+! CHECK: return
+! CHECK: }
+
! CHECK-LABEL: acc.global_dtor @_QMacc_declare_allocatable_testEdata1_acc_dtor {
! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_allocatable_testEdata1) {acc.declare = #acc.declare<dataClause = acc_create>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK: %[[DEVICEPTR:.*]] = acc.getdeviceptr varPtr(%[[GLOBAL_ADDR]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>> {dataClause = #acc<data_clause acc_create>, name = "data1", structured = false}
More information about the flang-commits
mailing list