Skip to content

Commit

Permalink
[flang][openacc] Add basic lowering for OpenACC declare construct in …
Browse files Browse the repository at this point in the history
…module

This patch adds the skeleton and the basic lowering for OpenACC declare
construct when located in the module declaration. This patch just lower the
create clause with or without modifier. Other clause and global descrutor
lowering will come in follow up patches to keep this one small enough for
review.

Reviewed By: razvanlupusoru

Differential Revision: https://reviews.llvm.org/D156266
  • Loading branch information
clementval committed Jul 26, 2023
1 parent e5df048 commit c217ff8
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 5 deletions.
4 changes: 2 additions & 2 deletions flang/include/flang/Lower/OpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ void genOpenACCConstruct(AbstractConverter &,
Fortran::semantics::SemanticsContext &,
pft::Evaluation &, const parser::OpenACCConstruct &);
void genOpenACCDeclarativeConstruct(
AbstractConverter &, pft::Evaluation &,
const parser::OpenACCDeclarativeConstruct &);
AbstractConverter &, Fortran::semantics::SemanticsContext &,
pft::Evaluation &, const parser::OpenACCDeclarativeConstruct &);

/// Get a acc.private.recipe op for the given type or create it if it does not
/// exist yet.
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Lower/Bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2229,7 +2229,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {

void genFIR(const Fortran::parser::OpenACCDeclarativeConstruct &accDecl) {
mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint();
genOpenACCDeclarativeConstruct(*this, getEval(), accDecl);
genOpenACCDeclarativeConstruct(*this, bridge.getSemanticsContext(),
getEval(), accDecl);
for (Fortran::lower::pft::Evaluation &e : getEval().getNestedEvaluations())
genFIR(e);
builder->restoreInsertionPoint(insertPt);
Expand Down
134 changes: 132 additions & 2 deletions flang/lib/Lower/OpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "flang/Common/idioms.h"
#include "flang/Lower/Bridge.h"
#include "flang/Lower/ConvertType.h"
#include "flang/Lower/Mangler.h"
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/StatementContext.h"
#include "flang/Lower/Support/Utils.h"
Expand Down Expand Up @@ -2282,6 +2283,134 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
waitOp.setAsyncAttr(firOpBuilder.getUnitAttr());
}

static void addDeclareAttr(fir::FirOpBuilder &builder, mlir::Operation *op,
mlir::acc::DataClause clause) {
op->setAttr(mlir::acc::getDeclareAttrName(),
mlir::acc::DeclareAttr::get(builder.getContext(),
mlir::acc::DataClauseAttr::get(
builder.getContext(), clause)));
}

static void genGlobalCtors(Fortran::lower::AbstractConverter &converter,
mlir::OpBuilder &modBuilder,
const Fortran::parser::AccObjectList &accObjectList,
mlir::acc::DataClause clause) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
for (const auto &accObject : accObjectList.v) {
mlir::Location operandLocation = genOperandLocation(converter, accObject);
std::visit(
Fortran::common::visitors{
[&](const Fortran::parser::Designator &designator) {
if (const auto *name =
Fortran::semantics::getDesignatorNameIfDataRef(
designator)) {
std::string globalName = converter.mangleName(*name->symbol);
fir::GlobalOp globalOp = builder.getNamedGlobal(globalName);
if (!globalOp)
llvm::report_fatal_error("could not retrieve global symbol");

// Create the new global constructor op after the FIR global.
std::stringstream globalCtorName;
globalCtorName << globalName << "_acc_ctor";
auto crtPos = builder.saveInsertionPoint();
addDeclareAttr(builder, globalOp.getOperation(), clause);
modBuilder.setInsertionPointAfter(globalOp);
auto globalCtor =
modBuilder.create<mlir::acc::GlobalConstructorOp>(
operandLocation, globalCtorName.str());
builder.createBlock(&globalCtor.getRegion(),
globalCtor.getRegion().end(), {}, {});
builder.setInsertionPointToEnd(&globalCtor.getRegion().back());

// Fill up the global constructor region.
fir::AddrOfOp addrOp = builder.create<fir::AddrOfOp>(
operandLocation,
fir::ReferenceType::get(globalOp.getType()),
globalOp.getSymbol());
addDeclareAttr(builder, addrOp.getOperation(), clause);
std::stringstream asFortran;
asFortran << Fortran::lower::mangle::demangleName(globalName);
llvm::SmallVector<mlir::Value> bounds;
mlir::acc::CreateOp entry =
createDataEntryOp<mlir::acc::CreateOp>(
builder, operandLocation, addrOp.getResTy(), asFortran,
bounds, true, clause, addrOp.getResTy().getType());
builder.create<mlir::acc::DeclareEnterOp>(
operandLocation, mlir::ValueRange{entry.getAccPtr()});
builder.create<mlir::acc::TerminatorOp>(operandLocation);
builder.restoreInsertionPoint(crtPos);

// TODO: global destructor.
}
},
[&](const Fortran::parser::Name &name) {
TODO(operandLocation, "OpenACC Global Ctor from parser::Name");
}},
accObject.u);
}
}

template <typename Clause>
static void
genGlobalCtorsWithModifier(Fortran::lower::AbstractConverter &converter,
mlir::OpBuilder &modBuilder, const Clause *x,
Fortran::parser::AccDataModifier::Modifier mod,
const mlir::acc::DataClause clause,
const mlir::acc::DataClause clauseWithModifier) {
const Fortran::parser::AccObjectListWithModifier &listWithModifier = x->v;
const auto &accObjectList =
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
const auto &modifier =
std::get<std::optional<Fortran::parser::AccDataModifier>>(
listWithModifier.t);
mlir::acc::DataClause dataClause =
(modifier && (*modifier).v == mod) ? clauseWithModifier : clause;
genGlobalCtors(converter, modBuilder, accObjectList, dataClause);
}

static void genACC(Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semanticsContext,
Fortran::lower::pft::Evaluation &eval,
const Fortran::parser::OpenACCStandaloneDeclarativeConstruct
&declareConstruct) {

const auto &declarativeDir =
std::get<Fortran::parser::AccDeclarativeDirective>(declareConstruct.t);
const auto &accClauseList =
std::get<Fortran::parser::AccClauseList>(declareConstruct.t);

if (declarativeDir.v == llvm::acc::Directive::ACCD_declare) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
llvm::SmallVector<mlir::Value> dataClauseOperands, copyEntryOperands,
copyoutEntryOperands, createEntryOperands;
Fortran::lower::StatementContext stmtCtx;
auto moduleOp =
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
auto funcOp =
builder.getBlock()->getParent()->getParentOfType<mlir::func::FuncOp>();
if (funcOp) {
TODO(funcOp.getLoc(), "OpenACC declare in function/subroutine");
} else if (moduleOp) {
mlir::OpBuilder modBuilder(moduleOp.getBodyRegion());
for (const Fortran::parser::AccClause &clause : accClauseList.v) {
mlir::Location clauseLocation = converter.genLocation(clause.source);
if (const auto *createClause =
std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
genGlobalCtorsWithModifier<Fortran::parser::AccClause::Create>(
converter, modBuilder, createClause,
Fortran::parser::AccDataModifier::Modifier::Zero,
mlir::acc::DataClause::acc_create,
mlir::acc::DataClause::acc_create_zero);
} else {
TODO(clauseLocation, "OpenACC declare clause");
}
}
}
return;
}
llvm_unreachable("unsupported declarative directive");
}

void Fortran::lower::genOpenACCConstruct(
Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semanticsContext,
Expand Down Expand Up @@ -2321,15 +2450,16 @@ void Fortran::lower::genOpenACCConstruct(

void Fortran::lower::genOpenACCDeclarativeConstruct(
Fortran::lower::AbstractConverter &converter,
Fortran::semantics::SemanticsContext &semanticsContext,
Fortran::lower::pft::Evaluation &eval,
const Fortran::parser::OpenACCDeclarativeConstruct &accDeclConstruct) {

std::visit(
common::visitors{
[&](const Fortran::parser::OpenACCStandaloneDeclarativeConstruct
&standaloneDeclarativeConstruct) {
TODO(converter.genLocation(standaloneDeclarativeConstruct.source),
"OpenACC Standalone Declarative construct not lowered yet!");
genACC(converter, semanticsContext, eval,
standaloneDeclarativeConstruct);
},
[&](const Fortran::parser::OpenACCRoutineConstruct
&routineConstruct) {
Expand Down
4 changes: 4 additions & 0 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ class AccAttributeVisitor : DirectiveAttributeVisitor<llvm::acc::Directive> {
bool Pre(const parser::OpenACCDeclarativeConstruct &);
void Post(const parser::OpenACCDeclarativeConstruct &) { PopContext(); }

void Post(const parser::AccDeclarativeDirective &) {
GetContext().withinConstruct = true;
}

bool Pre(const parser::OpenACCRoutineConstruct &);
bool Pre(const parser::AccBindClause &);
void Post(const parser::OpenACCStandaloneDeclarativeConstruct &);
Expand Down
27 changes: 27 additions & 0 deletions flang/test/Lower/OpenACC/acc-declare.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
! This test checks lowering of OpenACC declare directive.

! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s

module acc_declare_test
integer, parameter :: n = 100000
real, dimension(n) :: data1, data2
!$acc declare create(data1) create(zero: data2)
end module

! CHECK-LABEL: fir.global @_QMacc_declare_testEdata1 {acc.declare = #acc.declare<dataClause = acc_create>} : !fir.array<100000xf32>

! CHECK-LABEL: acc.global_ctor @_QMacc_declare_testEdata1_acc_ctor {
! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_testEdata1) {acc.declare = #acc.declare<dataClause = acc_create>} : !fir.ref<!fir.array<100000xf32>>
! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[GLOBAL_ADDR]] : !fir.ref<!fir.array<100000xf32>>) -> !fir.ref<!fir.array<100000xf32>> {name = "data1"}
! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100000xf32>>)
! CHECK: acc.terminator
! CHECK: }

! CHECK-LABEL: fir.global @_QMacc_declare_testEdata2 {acc.declare = #acc.declare<dataClause = acc_create_zero>} : !fir.array<100000xf32>

! CHECK-LABEL: acc.global_ctor @_QMacc_declare_testEdata2_acc_ctor {
! CHECK: %[[GLOBAL_ADDR:.*]] = fir.address_of(@_QMacc_declare_testEdata2) {acc.declare = #acc.declare<dataClause = acc_create_zero>} : !fir.ref<!fir.array<100000xf32>>
! CHECK: %[[CREATE:.*]] = acc.create varPtr(%[[GLOBAL_ADDR]] : !fir.ref<!fir.array<100000xf32>>) -> !fir.ref<!fir.array<100000xf32>> {dataClause = #acc<data_clause acc_create_zero>, name = "data2"}
! CHECK: acc.declare_enter dataOperands(%[[CREATE]] : !fir.ref<!fir.array<100000xf32>>)
! CHECK: acc.terminator
! CHECK: }

0 comments on commit c217ff8

Please sign in to comment.