Skip to content

Commit 0e655bd

Browse files
committed
[flang] Adding lowering of TEAMs features to PRIF in MIF Dialect
CHANGE TEAM have a partial support for coarray associated list. PRIF require to use prif_alias_{create|destroy} for each coarray in this list. It will upstream later, when coarray allocation and alias procedure will be added.
1 parent a38e094 commit 0e655bd

File tree

18 files changed

+1103
-22
lines changed

18 files changed

+1103
-22
lines changed

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ struct IntrinsicLibrary {
270270
void genGetEnvironmentVariable(llvm::ArrayRef<fir::ExtendedValue>);
271271
mlir::Value genGetGID(mlir::Type resultType,
272272
llvm::ArrayRef<mlir::Value> args);
273+
mlir::Value genGetTeam(mlir::Type, llvm::ArrayRef<mlir::Value>);
273274
mlir::Value genGetUID(mlir::Type resultType,
274275
llvm::ArrayRef<mlir::Value> args);
275276
fir::ExtendedValue genHostnm(std::optional<mlir::Type> resultType,
@@ -425,6 +426,8 @@ struct IntrinsicLibrary {
425426
void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
426427
mlir::Value genTand(mlir::Type, llvm::ArrayRef<mlir::Value>);
427428
mlir::Value genTanpi(mlir::Type, llvm::ArrayRef<mlir::Value>);
429+
fir::ExtendedValue genTeamNumber(mlir::Type,
430+
llvm::ArrayRef<fir::ExtendedValue>);
428431
mlir::Value genTime(mlir::Type, llvm::ArrayRef<mlir::Value>);
429432
mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);
430433
fir::ExtendedValue genTransfer(mlir::Type,

flang/include/flang/Optimizer/Dialect/MIF/MIFOps.td

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ include "flang/Optimizer/Dialect/FIRAttr.td"
2121
class mif_Op<string mnemonic, list<Trait> traits>
2222
: Op<MIFDialect, mnemonic, traits>;
2323

24+
class region_Op<string mnemonic, list<Trait> traits = []>
25+
: mif_Op<mnemonic, !listconcat(traits, [RecursivelySpeculatable,
26+
RecursiveMemoryEffects])> {
27+
let hasCustomAssemblyFormat = 1;
28+
}
29+
2430
//===----------------------------------------------------------------------===//
2531
// Initialization and Finalization
2632
//===----------------------------------------------------------------------===//
@@ -174,6 +180,18 @@ def mif_SyncMemoryOp : mif_Op<"sync_memory", [AttrSizedOperandSegments]> {
174180
}];
175181
}
176182

183+
def mif_SyncTeamOp : mif_Op<"sync_team", [AttrSizedOperandSegments]> {
184+
let summary = "Performs a synchronization of the team, identified by `team`";
185+
186+
let arguments = (ins AnyRefOrBoxType:$team, Optional<AnyReferenceLike>:$stat,
187+
Optional<AnyRefOrBoxType>:$errmsg);
188+
let assemblyFormat = [{
189+
$team (`stat` $stat^ )?
190+
(`errmsg` $errmsg^ )?
191+
attr-dict `:` functional-type(operands, results)
192+
}];
193+
}
194+
177195
//===----------------------------------------------------------------------===//
178196
// Collective Operations
179197
//===----------------------------------------------------------------------===//
@@ -265,4 +283,141 @@ def mif_CoSumOp
265283
}];
266284
}
267285

286+
//===----------------------------------------------------------------------===//
287+
// Teams
288+
//===----------------------------------------------------------------------===//
289+
290+
def mif_FormTeamOp : mif_Op<"form_team", [AttrSizedOperandSegments]> {
291+
let summary =
292+
"Create a set of sibling teams whose parent team is the current team.";
293+
let description = [{
294+
Create a new team for each unique `team_number` value specified.
295+
Each executing image will belong to the team whose `team_number` is equal
296+
to the value of team-number on that image, and `team_var` becomes defined
297+
with a value that identifies that team.
298+
299+
If `new_index` is specified, the image index of the executing image will take
300+
this index in its new team. Otherwise, the new image index is processor
301+
dependent.
302+
303+
Arguments:
304+
- `team_number`: Shall be a positive integer.
305+
- `team_var` : Shall be a variable of type TEAM_TYPE from the intrinsic
306+
module ISO_FORTRAN_ENV.
307+
- `new_index`(optional): Shall be an integer that correspond to the index that
308+
the calling image will have in the new team.
309+
}];
310+
311+
let arguments = (ins AnyIntegerType:$team_number,
312+
Arg<fir_BoxType, "", [MemWrite]>:$team_var,
313+
Optional<AnyIntegerType>:$new_index,
314+
Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat,
315+
Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg);
316+
317+
let assemblyFormat = [{
318+
`team_number` $team_number `team_var` $team_var
319+
(`new_index` $new_index^ )?
320+
(`stat` $stat^ )?
321+
(`errmsg` $errmsg^ )?
322+
attr-dict `:` functional-type(operands, results)
323+
}];
324+
}
325+
326+
def mif_EndTeamOp : mif_Op<"end_team", [AttrSizedOperandSegments, Terminator,
327+
ParentOneOf<["ChangeTeamOp"]>]> {
328+
let summary = "Changes the current team to the parent team.";
329+
let description = [{
330+
The END TEAM operation completes the CHANGE TEAM construct and
331+
restores the current team to the team that was current before
332+
the CHANGE TEAM construct.
333+
}];
334+
335+
let arguments = (ins Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat,
336+
Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg);
337+
let builders = [OpBuilder<(ins), [{ /* do nothing */ }]>];
338+
339+
let assemblyFormat = [{
340+
(`stat` $stat^ )? (`errmsg` $errmsg^ )?
341+
attr-dict `:` functional-type(operands, results)
342+
}];
343+
}
344+
345+
//===----------------------------------------------------------------------===//
346+
// NOTE: The CHANGE TEAM region will take a coarray association list in
347+
// argument. However, coarray management and coarray alias creation are not
348+
// yet supported by the dialect. The argument is therefore not yet supported by
349+
// this operation and will be added later.
350+
//===----------------------------------------------------------------------===//
351+
def mif_ChangeTeamOp
352+
: region_Op<"change_team", [AttrSizedOperandSegments,
353+
SingleBlockImplicitTerminator<"EndTeamOp">]> {
354+
let summary = "Changes the current team.";
355+
let description = [{
356+
The CHANGE TEAM construct changes the current team to the specified new
357+
team, which must be a child team of the current team.
358+
359+
```
360+
mif.change_team %team {
361+
%x = fir.convert %i : (index) -> i32
362+
...
363+
mif.end_team
364+
}
365+
}];
366+
367+
let arguments = (ins AnyRefOrBoxType:$team,
368+
Arg<Optional<AnyReferenceLike>, "", [MemWrite]>:$stat,
369+
Arg<Optional<AnyRefOrBoxType>, "", [MemWrite]>:$errmsg);
370+
let regions = (region SizedRegion<1>:$region);
371+
372+
let skipDefaultBuilders = 1;
373+
let builders =
374+
[OpBuilder<(ins "mlir::Value":$team,
375+
CArg<"bool", "true">:$ensureTerminaison,
376+
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes)>,
377+
OpBuilder<(ins "mlir::Value":$team, "mlir::Value":$stat,
378+
"mlir::Value":$errmsg, CArg<"bool", "true">:$ensureTerminaison,
379+
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes)>];
380+
381+
let extraClassDeclaration = [{
382+
/// Get the body of the CHANGE TEAM construct
383+
mlir::Block *getBody() { return &getRegion().front(); }
384+
}];
385+
}
386+
387+
def mif_GetTeamOp : mif_Op<"get_team", []> {
388+
let summary = "Get the team value for the current or ancestor team.";
389+
let description = [{
390+
This operation gets the team value for the current or an ancestor team.
391+
`level`(optional): If provided, must equal one of the following constants :
392+
`INITIAL_TEAM`, `PARENT_TEAM` or `CURRENT_TEAM` from the module ISO_FORTRAN_ENV.
393+
If `level` isn't present or has the value `CURRENT_TEAM` the returned
394+
value is the current team.
395+
}];
396+
397+
let arguments = (ins Optional<AnyIntegerType>:$level);
398+
let results = (outs fir_BoxType:$team);
399+
400+
let assemblyFormat = [{
401+
(`level` $level^ )?
402+
attr-dict `:` functional-type(operands, results)
403+
}];
404+
}
405+
406+
def mif_TeamNumberOp : mif_Op<"team_number", []> {
407+
let summary = "Get the team number";
408+
let description = [{
409+
Argument: `team` is optional and shall be a scalar of type TEAM_TYPE from
410+
module ISO_FORTRAN_ENV and the value identifies the current or an ancestor team.
411+
If `team` is absent, the team specified is the current team.
412+
}];
413+
414+
let arguments = (ins Optional<AnyRefOrBoxType>:$team);
415+
let results = (outs I64);
416+
417+
let assemblyFormat = [{
418+
(`team` $team^ )?
419+
attr-dict `:` functional-type(operands, results)
420+
}];
421+
}
422+
268423
#endif // FORTRAN_DIALECT_MIF_MIF_OPS

flang/lib/Lower/Bridge.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3950,13 +3950,30 @@ class FirConverter : public Fortran::lower::AbstractConverter {
39503950
}
39513951

39523952
void genFIR(const Fortran::parser::ChangeTeamConstruct &construct) {
3953-
TODO(toLocation(), "coarray: ChangeTeamConstruct");
3953+
Fortran::lower::StatementContext stmtCtx;
3954+
pushActiveConstruct(getEval(), stmtCtx);
3955+
3956+
for (Fortran::lower::pft::Evaluation &e :
3957+
getEval().getNestedEvaluations()) {
3958+
if (e.getIf<Fortran::parser::ChangeTeamStmt>()) {
3959+
maybeStartBlock(e.block);
3960+
setCurrentPosition(e.position);
3961+
genFIR(e);
3962+
} else if (e.getIf<Fortran::parser::EndChangeTeamStmt>()) {
3963+
maybeStartBlock(e.block);
3964+
setCurrentPosition(e.position);
3965+
genFIR(e);
3966+
} else {
3967+
genFIR(e);
3968+
}
3969+
}
3970+
popActiveConstruct();
39543971
}
39553972
void genFIR(const Fortran::parser::ChangeTeamStmt &stmt) {
3956-
TODO(toLocation(), "coarray: ChangeTeamStmt");
3973+
genChangeTeamStmt(*this, getEval(), stmt);
39573974
}
39583975
void genFIR(const Fortran::parser::EndChangeTeamStmt &stmt) {
3959-
TODO(toLocation(), "coarray: EndChangeTeamStmt");
3976+
genEndChangeTeamStmt(*this, getEval(), stmt);
39603977
}
39613978

39623979
void genFIR(const Fortran::parser::CriticalConstruct &criticalConstruct) {

flang/lib/Lower/Coarray.cpp

Lines changed: 130 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "flang/Lower/SymbolMap.h"
1717
#include "flang/Optimizer/Builder/FIRBuilder.h"
1818
#include "flang/Optimizer/Builder/Todo.h"
19+
#include "flang/Optimizer/Dialect/MIF/MIFOps.h"
1920
#include "flang/Parser/parse-tree.h"
2021
#include "flang/Semantics/expression.h"
2122

@@ -33,21 +34,144 @@ void Fortran::lower::genChangeTeamConstruct(
3334
void Fortran::lower::genChangeTeamStmt(
3435
Fortran::lower::AbstractConverter &converter,
3536
Fortran::lower::pft::Evaluation &,
36-
const Fortran::parser::ChangeTeamStmt &) {
37-
TODO(converter.getCurrentLocation(), "coarray: CHANGE TEAM statement");
37+
const Fortran::parser::ChangeTeamStmt &stmt) {
38+
mlir::Location loc = converter.getCurrentLocation();
39+
converter.checkCoarrayEnabled();
40+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
41+
42+
mlir::Value errMsgAddr, statAddr, team;
43+
// Handle STAT and ERRMSG values
44+
Fortran::lower::StatementContext stmtCtx;
45+
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =
46+
std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);
47+
for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) {
48+
std::visit(Fortran::common::visitors{
49+
[&](const Fortran::parser::StatVariable &statVar) {
50+
const auto *expr = Fortran::semantics::GetExpr(statVar);
51+
statAddr = fir::getBase(
52+
converter.genExprAddr(loc, *expr, stmtCtx));
53+
},
54+
[&](const Fortran::parser::MsgVariable &errMsgVar) {
55+
const auto *expr = Fortran::semantics::GetExpr(errMsgVar);
56+
errMsgAddr = fir::getBase(
57+
converter.genExprBox(loc, *expr, stmtCtx));
58+
},
59+
},
60+
statOrErr.u);
61+
}
62+
63+
// TODO: Manage the list of coarrays associated in
64+
// `std::list<CoarrayAssociation>`. According to the PRIF specification, it is
65+
// necessary to call `prif_alias_{create|destroy}` for each coarray defined in
66+
// this list. Support will be added once lowering to this procedure is
67+
// possible.
68+
const std::list<Fortran::parser::CoarrayAssociation> &coarrayAssocList =
69+
std::get<std::list<Fortran::parser::CoarrayAssociation>>(stmt.t);
70+
if (coarrayAssocList.size())
71+
mlir::emitWarning(loc,
72+
"Coarrays provided in the association list are ignored.");
73+
74+
// Handle TEAM-VALUE
75+
const auto *teamExpr =
76+
Fortran::semantics::GetExpr(std::get<Fortran::parser::TeamValue>(stmt.t));
77+
team = fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx));
78+
79+
mif::ChangeTeamOp changeOp = mif::ChangeTeamOp::create(
80+
builder, loc, team, statAddr, errMsgAddr, /*terminator*/ false);
81+
builder.setInsertionPointToStart(changeOp.getBody());
3882
}
3983

4084
void Fortran::lower::genEndChangeTeamStmt(
4185
Fortran::lower::AbstractConverter &converter,
4286
Fortran::lower::pft::Evaluation &,
43-
const Fortran::parser::EndChangeTeamStmt &) {
44-
TODO(converter.getCurrentLocation(), "coarray: END CHANGE TEAM statement");
87+
const Fortran::parser::EndChangeTeamStmt &stmt) {
88+
converter.checkCoarrayEnabled();
89+
mlir::Location loc = converter.getCurrentLocation();
90+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
91+
92+
mlir::Value errMsgAddr, statAddr;
93+
// Handle STAT and ERRMSG values
94+
Fortran::lower::StatementContext stmtCtx;
95+
const std::list<Fortran::parser::StatOrErrmsg> &statOrErrList =
96+
std::get<std::list<Fortran::parser::StatOrErrmsg>>(stmt.t);
97+
for (const Fortran::parser::StatOrErrmsg &statOrErr : statOrErrList) {
98+
std::visit(Fortran::common::visitors{
99+
[&](const Fortran::parser::StatVariable &statVar) {
100+
const auto *expr = Fortran::semantics::GetExpr(statVar);
101+
statAddr = fir::getBase(
102+
converter.genExprAddr(loc, *expr, stmtCtx));
103+
},
104+
[&](const Fortran::parser::MsgVariable &errMsgVar) {
105+
const auto *expr = Fortran::semantics::GetExpr(errMsgVar);
106+
errMsgAddr = fir::getBase(
107+
converter.genExprBox(loc, *expr, stmtCtx));
108+
},
109+
},
110+
statOrErr.u);
111+
}
112+
113+
mif::EndTeamOp endOp =
114+
mif::EndTeamOp::create(builder, loc, statAddr, errMsgAddr);
115+
builder.setInsertionPointAfter(endOp.getParentOp());
45116
}
46117

47118
void Fortran::lower::genFormTeamStatement(
48119
Fortran::lower::AbstractConverter &converter,
49-
Fortran::lower::pft::Evaluation &, const Fortran::parser::FormTeamStmt &) {
50-
TODO(converter.getCurrentLocation(), "coarray: FORM TEAM statement");
120+
Fortran::lower::pft::Evaluation &,
121+
const Fortran::parser::FormTeamStmt &stmt) {
122+
converter.checkCoarrayEnabled();
123+
mlir::Location loc = converter.getCurrentLocation();
124+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
125+
126+
mlir::Value errMsgAddr, statAddr, newIndex, teamNumber, team;
127+
// Handle NEW_INDEX, STAT and ERRMSG
128+
std::list<Fortran::parser::StatOrErrmsg> statOrErrList{};
129+
Fortran::lower::StatementContext stmtCtx;
130+
const auto &formSpecList =
131+
std::get<std::list<Fortran::parser::FormTeamStmt::FormTeamSpec>>(stmt.t);
132+
for (const Fortran::parser::FormTeamStmt::FormTeamSpec &formSpec :
133+
formSpecList) {
134+
std::visit(
135+
Fortran::common::visitors{
136+
[&](const Fortran::parser::StatOrErrmsg &statOrErr) {
137+
std::visit(
138+
Fortran::common::visitors{
139+
[&](const Fortran::parser::StatVariable &statVar) {
140+
const auto *expr = Fortran::semantics::GetExpr(statVar);
141+
statAddr = fir::getBase(
142+
converter.genExprAddr(loc, *expr, stmtCtx));
143+
},
144+
[&](const Fortran::parser::MsgVariable &errMsgVar) {
145+
const auto *expr =
146+
Fortran::semantics::GetExpr(errMsgVar);
147+
errMsgAddr = fir::getBase(
148+
converter.genExprBox(loc, *expr, stmtCtx));
149+
},
150+
},
151+
statOrErr.u);
152+
},
153+
[&](const Fortran::parser::ScalarIntExpr &intExpr) {
154+
fir::ExtendedValue newIndexExpr = converter.genExprValue(
155+
loc, Fortran::semantics::GetExpr(intExpr), stmtCtx);
156+
newIndex = fir::getBase(newIndexExpr);
157+
},
158+
},
159+
formSpec.u);
160+
}
161+
162+
// Handle TEAM-NUMBER
163+
const auto *teamNumberExpr = Fortran::semantics::GetExpr(
164+
std::get<Fortran::parser::ScalarIntExpr>(stmt.t));
165+
teamNumber =
166+
fir::getBase(converter.genExprValue(loc, *teamNumberExpr, stmtCtx));
167+
168+
// Handle TEAM-VARIABLE
169+
const auto *teamExpr = Fortran::semantics::GetExpr(
170+
std::get<Fortran::parser::TeamVariable>(stmt.t));
171+
team = fir::getBase(converter.genExprBox(loc, *teamExpr, stmtCtx));
172+
173+
mif::FormTeamOp::create(builder, loc, teamNumber, team, newIndex, statAddr,
174+
errMsgAddr);
51175
}
52176

53177
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)