Skip to content

Commit 69a6bd5

Browse files
committed
[flang][openacc] Lower acc routine with function name
The routine directive can appear in the specification part of a subroutine, function or module and therefore appear before the function or subroutine is lowered. We keep track of the created routine info attribute and attach them to the function at the end of the lowering if the directive appeared before the function was lowered. Reviewed By: razvanlupusoru Differential Revision: https://reviews.llvm.org/D158204
1 parent 1f7d034 commit 69a6bd5

File tree

4 files changed

+105
-24
lines changed

4 files changed

+105
-24
lines changed

flang/include/flang/Lower/OpenACC.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class StringRef;
2424
namespace mlir {
2525
class Location;
2626
class Type;
27+
class ModuleOp;
2728
class OpBuilder;
2829
class Value;
2930
} // namespace mlir
@@ -52,6 +53,9 @@ namespace pft {
5253
struct Evaluation;
5354
} // namespace pft
5455

56+
using AccRoutineInfoMappingList =
57+
llvm::SmallVector<std::pair<std::string, mlir::SymbolRefAttr>>;
58+
5559
static constexpr llvm::StringRef declarePostAllocSuffix =
5660
"_acc_declare_update_desc_post_alloc";
5761
static constexpr llvm::StringRef declarePreDeallocSuffix =
@@ -62,10 +66,14 @@ static constexpr llvm::StringRef declarePostDeallocSuffix =
6266
void genOpenACCConstruct(AbstractConverter &,
6367
Fortran::semantics::SemanticsContext &,
6468
pft::Evaluation &, const parser::OpenACCConstruct &);
65-
void genOpenACCDeclarativeConstruct(
66-
AbstractConverter &, Fortran::semantics::SemanticsContext &,
67-
StatementContext &, pft::Evaluation &,
68-
const parser::OpenACCDeclarativeConstruct &);
69+
void genOpenACCDeclarativeConstruct(AbstractConverter &,
70+
Fortran::semantics::SemanticsContext &,
71+
StatementContext &, pft::Evaluation &,
72+
const parser::OpenACCDeclarativeConstruct &,
73+
AccRoutineInfoMappingList &);
74+
75+
void finalizeOpenACCRoutineAttachment(mlir::ModuleOp &,
76+
AccRoutineInfoMappingList &);
6977

7078
/// Get a acc.private.recipe op for the given type or create it if it does not
7179
/// exist yet.

flang/lib/Lower/Bridge.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
350350
fir::runtime::genEnvironmentDefaults(*builder, toLocation(),
351351
bridge.getEnvironmentDefaults());
352352
});
353+
354+
finalizeOpenACCLowering();
353355
}
354356

355357
/// Declare a function.
@@ -2248,7 +2250,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
22482250
void genFIR(const Fortran::parser::OpenACCDeclarativeConstruct &accDecl) {
22492251
mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint();
22502252
genOpenACCDeclarativeConstruct(*this, bridge.getSemanticsContext(),
2251-
bridge.fctCtx(), getEval(), accDecl);
2253+
bridge.fctCtx(), getEval(), accDecl,
2254+
accRoutineInfos);
22522255
for (Fortran::lower::pft::Evaluation &e : getEval().getNestedEvaluations())
22532256
genFIR(e);
22542257
builder->restoreInsertionPoint(insertPt);
@@ -4683,6 +4686,13 @@ class FirConverter : public Fortran::lower::AbstractConverter {
46834686
expr.u);
46844687
}
46854688

4689+
/// Performing OpenACC lowering action that were deferred to the end of
4690+
/// lowering.
4691+
void finalizeOpenACCLowering() {
4692+
Fortran::lower::finalizeOpenACCRoutineAttachment(getModuleOp(),
4693+
accRoutineInfos);
4694+
}
4695+
46864696
//===--------------------------------------------------------------------===//
46874697

46884698
Fortran::lower::LoweringBridge &bridge;
@@ -4726,6 +4736,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
47264736

47274737
/// A counter for uniquing names in `literalNamesMap`.
47284738
std::uint64_t uniqueLitId = 0;
4739+
4740+
/// Deferred OpenACC routine attachment.
4741+
Fortran::lower::AccRoutineInfoMappingList accRoutineInfos;
47294742
};
47304743

47314744
} // namespace

flang/lib/Lower/OpenACC.cpp

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2925,29 +2925,53 @@ GetConstExpr(Fortran::semantics::SemanticsContext &semanticsContext,
29252925
return std::nullopt;
29262926
}
29272927

2928+
static void attachRoutineInfo(mlir::func::FuncOp func,
2929+
mlir::SymbolRefAttr routineAttr) {
2930+
llvm::SmallVector<mlir::SymbolRefAttr> routines;
2931+
if (func.getOperation()->hasAttr(mlir::acc::getRoutineInfoAttrName())) {
2932+
auto routineInfo =
2933+
func.getOperation()->getAttrOfType<mlir::acc::RoutineInfoAttr>(
2934+
mlir::acc::getRoutineInfoAttrName());
2935+
routines.append(routineInfo.getAccRoutines().begin(),
2936+
routineInfo.getAccRoutines().end());
2937+
}
2938+
routines.push_back(routineAttr);
2939+
func.getOperation()->setAttr(
2940+
mlir::acc::getRoutineInfoAttrName(),
2941+
mlir::acc::RoutineInfoAttr::get(func.getContext(), routines));
2942+
}
2943+
29282944
static void
29292945
genACC(Fortran::lower::AbstractConverter &converter,
29302946
Fortran::semantics::SemanticsContext &semanticsContext,
29312947
Fortran::lower::pft::Evaluation &eval,
2932-
const Fortran::parser::OpenACCRoutineConstruct &routineConstruct) {
2948+
const Fortran::parser::OpenACCRoutineConstruct &routineConstruct,
2949+
Fortran::lower::AccRoutineInfoMappingList &accRoutineInfos) {
29332950
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
29342951
mlir::Location loc = converter.genLocation(routineConstruct.source);
29352952
std::optional<Fortran::parser::Name> name =
29362953
std::get<std::optional<Fortran::parser::Name>>(routineConstruct.t);
29372954
const auto &clauses =
29382955
std::get<Fortran::parser::AccClauseList>(routineConstruct.t);
2939-
if (name)
2940-
TODO(loc, "acc routine with name");
29412956

2942-
mlir::func::FuncOp func = builder.getFunction();
29432957
mlir::ModuleOp mod = builder.getModule();
2958+
mlir::func::FuncOp funcOp;
2959+
std::string funcName;
2960+
if (name) {
2961+
funcName = converter.mangleName(*name->symbol);
2962+
funcOp = builder.getNamedFunction(funcName);
2963+
} else {
2964+
funcOp = builder.getFunction();
2965+
funcName = funcOp.getName();
2966+
}
2967+
29442968
mlir::OpBuilder modBuilder(mod.getBodyRegion());
29452969
std::stringstream routineOpName;
29462970
routineOpName << accRoutinePrefix.str() << routineCounter++;
29472971
auto routineOp = modBuilder.create<mlir::acc::RoutineOp>(
2948-
loc, routineOpName.str(), func.getName(), mlir::StringAttr{},
2972+
loc, routineOpName.str(), funcName, mlir::StringAttr{}, mlir::UnitAttr{},
29492973
mlir::UnitAttr{}, mlir::UnitAttr{}, mlir::UnitAttr{}, mlir::UnitAttr{},
2950-
mlir::UnitAttr{}, mlir::UnitAttr{}, mlir::IntegerAttr{});
2974+
mlir::UnitAttr{}, mlir::IntegerAttr{});
29512975

29522976
for (const Fortran::parser::AccClause &clause : clauses.v) {
29532977
if (std::get_if<Fortran::parser::AccClause::Seq>(&clause.u)) {
@@ -2994,18 +3018,27 @@ genACC(Fortran::lower::AbstractConverter &converter,
29943018
}
29953019
}
29963020

2997-
llvm::SmallVector<mlir::SymbolRefAttr> routines;
2998-
if (func.getOperation()->hasAttr(mlir::acc::getRoutineInfoAttrName())) {
2999-
auto routineInfo =
3000-
func.getOperation()->getAttrOfType<mlir::acc::RoutineInfoAttr>(
3001-
mlir::acc::getRoutineInfoAttrName());
3002-
routines.append(routineInfo.getAccRoutines().begin(),
3003-
routineInfo.getAccRoutines().end());
3021+
if (funcOp)
3022+
attachRoutineInfo(funcOp, builder.getSymbolRefAttr(routineOpName.str()));
3023+
else
3024+
// FuncOp is not lowered yet. Keep the information so the routine info
3025+
// can be attached later to the funcOp.
3026+
accRoutineInfos.push_back(std::make_pair(
3027+
funcName, builder.getSymbolRefAttr(routineOpName.str())));
3028+
}
3029+
3030+
void Fortran::lower::finalizeOpenACCRoutineAttachment(
3031+
mlir::ModuleOp &mod,
3032+
Fortran::lower::AccRoutineInfoMappingList &accRoutineInfos) {
3033+
for (auto &mapping : accRoutineInfos) {
3034+
mlir::func::FuncOp funcOp =
3035+
mod.lookupSymbol<mlir::func::FuncOp>(mapping.first);
3036+
if (!funcOp)
3037+
llvm::report_fatal_error(
3038+
"could not find function to attach OpenACC routine information.");
3039+
attachRoutineInfo(funcOp, mapping.second);
30043040
}
3005-
routines.push_back(builder.getSymbolRefAttr(routineOpName.str()));
3006-
func.getOperation()->setAttr(
3007-
mlir::acc::getRoutineInfoAttrName(),
3008-
mlir::acc::RoutineInfoAttr::get(builder.getContext(), routines));
3041+
accRoutineInfos.clear();
30093042
}
30103043

30113044
void Fortran::lower::genOpenACCConstruct(
@@ -3050,7 +3083,8 @@ void Fortran::lower::genOpenACCDeclarativeConstruct(
30503083
Fortran::semantics::SemanticsContext &semanticsContext,
30513084
Fortran::lower::StatementContext &fctCtx,
30523085
Fortran::lower::pft::Evaluation &eval,
3053-
const Fortran::parser::OpenACCDeclarativeConstruct &accDeclConstruct) {
3086+
const Fortran::parser::OpenACCDeclarativeConstruct &accDeclConstruct,
3087+
Fortran::lower::AccRoutineInfoMappingList &accRoutineInfos) {
30543088

30553089
std::visit(
30563090
common::visitors{
@@ -3061,7 +3095,8 @@ void Fortran::lower::genOpenACCDeclarativeConstruct(
30613095
},
30623096
[&](const Fortran::parser::OpenACCRoutineConstruct
30633097
&routineConstruct) {
3064-
genACC(converter, semanticsContext, eval, routineConstruct);
3098+
genACC(converter, semanticsContext, eval, routineConstruct,
3099+
accRoutineInfos);
30653100
},
30663101
},
30673102
accDeclConstruct.u);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
! This test checks lowering of OpenACC routine directive.
2+
3+
! RUN: bbc -fopenacc -emit-fir %s -o - | FileCheck %s
4+
5+
module acc_routines
6+
7+
! CHECK: acc.routine @acc_routine_1 func(@_QMacc_routinesPacc2)
8+
! CHECK: acc.routine @acc_routine_0 func(@_QMacc_routinesPacc1) seq
9+
10+
!$acc routine(acc1) seq
11+
12+
contains
13+
14+
subroutine acc1()
15+
end subroutine
16+
17+
! CHECK-LABEL: func.func @_QMacc_routinesPacc1() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_0]>}
18+
19+
subroutine acc2()
20+
!$acc routine(acc2)
21+
end subroutine
22+
23+
! CHECK-LABEL: func.func @_QMacc_routinesPacc2() attributes {acc.routine_info = #acc.routine_info<[@acc_routine_1]>}
24+
25+
end module

0 commit comments

Comments
 (0)