Skip to content

Commit 6227665

Browse files
committed
Lower elemental subroutine calls (outside of user assignment case)
Use the array lowering framework to lower elemental subroutine. This required: - Splitting the part of genIterSpace that creates the implicit loops into a new genImplicitLoops function. genIterspace deals with the destination and other explicit contexts set-ups that do not matter in the subroutine case (there is no destination). Other than having no destination, a big difference is that there is no threaded innerArg. genImplicitLoops handles this variation. - Fixing a bug in the iteration shape determination. The code was assuming there would always be at least one array_load, which is not true if there are only RefTransparent operands. This is always true in the subroutine case, but was actually also an issue for things like `print *, elem_func(array)` with the previous code (compile crash). Add a new ArrayOperands structure to keep track of what matters to later deduce the shape of the array expression instead of keeping track of array_loads for that purpose. - Elemental subroutine with intent(out)/intent(inout) arguments must be applied "in array element order" (15.8.3). It turns out this is also the case for impure elemental functions (10.1.4 p5). Instead of always creating loops as "unordered=true" add an unordered field to the ArrayExprLowering class. It is set to true by default, but will be set to false if any impure elemental function is lowered, or in case of intent(out)/intent(inout) arguments in elemental subroutines. - Last, instead of using createFirExpr to lowering subroutine calls, use a new createSubroutineCall that deals with the array/scalar dispatching. A TODO is added for the user defined elemental assignment, because overlap analysis between RHS/LHS must be done, and this require somehow plugging this special and very restricted case of elemental calls into the array_load/array_update/array_merge framework or some ad-hoc lowering.
1 parent 63130d8 commit 6227665

File tree

7 files changed

+380
-90
lines changed

7 files changed

+380
-90
lines changed

flang/include/flang/Lower/ConvertExpr.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,16 @@ createSomeArrayBox(AbstractConverter &converter,
186186
const evaluate::Expr<evaluate::SomeType> &expr,
187187
SymMap &symMap, StatementContext &stmtCtx);
188188

189+
/// Lower a subroutine call. This handles both elemental and non elemental
190+
/// subroutines. \p isUserDefAssignment must be set if this is called in the
191+
/// context of a user defined assignment. For subroutines with alternate
192+
/// returns, the returned value indicates which label the code should jump to.
193+
/// The returned value is null otherwise.
194+
mlir::Value createSubroutineCall(AbstractConverter &converter,
195+
const evaluate::Expr<evaluate::SomeType> &call,
196+
SymMap &symMap, StatementContext &stmtCtx,
197+
bool isUserDefAssignment);
198+
189199
// Attribute for an alloca that is a trivial adaptor for converting a value to
190200
// pass-by-ref semantics for a VALUE parameter. The optimizer may be able to
191201
// eliminate these.

flang/lib/Lower/Bridge.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
662662
assert(stmt.typedCall && "Call was not analyzed");
663663
// Call statement lowering shares code with function call lowering.
664664
Fortran::semantics::SomeExpr expr{*stmt.typedCall};
665-
auto res = createFIRExpr(toLocation(), &expr, stmtCtx);
665+
auto res = Fortran::lower::createSubroutineCall(
666+
*this, expr, localSymbols, stmtCtx, /*isUserDefAssignment=*/false);
666667
if (!res)
667668
return; // "Normal" subroutine call.
668669
// Call with alternate return specifiers.
@@ -1939,11 +1940,13 @@ class FirConverter : public Fortran::lower::AbstractConverter {
19391940
[&](const Fortran::evaluate::ProcedureRef &procRef) {
19401941
if (implicitIterationSpace())
19411942
TODO(loc, "user defined assignment within WHERE");
1943+
19421944
Fortran::semantics::SomeExpr expr{procRef};
1943-
createFIRExpr(toLocation(), &expr,
1944-
explicitIterationSpace()
1945-
? explicitIterSpace.stmtContext()
1946-
: stmtCtx);
1945+
auto &ctx = explicitIterationSpace()
1946+
? explicitIterSpace.stmtContext()
1947+
: stmtCtx;
1948+
Fortran::lower::createSubroutineCall(
1949+
*this, expr, localSymbols, ctx, /*isUserDefAssignment=*/true);
19471950
},
19481951

19491952
// [3] Pointer assignment with possibly empty bounds-spec. R1035: a

0 commit comments

Comments
 (0)