Skip to content

Commit 1bffc75

Browse files
committed
Upstream support for POINTER assignment in FORALL.
Reviewed By: vdonaldson, PeteSteinfeld Differential Revision: https://reviews.llvm.org/D125140
1 parent 102bc63 commit 1bffc75

File tree

22 files changed

+2004
-480
lines changed

22 files changed

+2004
-480
lines changed

flang/include/flang/Lower/AbstractConverter.h

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -103,37 +103,51 @@ class AbstractConverter {
103103
// Expressions
104104
//===--------------------------------------------------------------------===//
105105

106-
/// Generate the address of the location holding the expression, someExpr.
107-
virtual fir::ExtendedValue genExprAddr(const SomeExpr &, StatementContext &,
106+
/// Generate the address of the location holding the expression, \p expr.
107+
/// If \p expr is a Designator that is not compile time contiguous, the
108+
/// address returned is the one of a contiguous temporary storage holding the
109+
/// expression value. The clean-up for this temporary is added to \p context.
110+
virtual fir::ExtendedValue genExprAddr(const SomeExpr &expr,
111+
StatementContext &context,
108112
mlir::Location *loc = nullptr) = 0;
109-
/// Generate the address of the location holding the expression, someExpr
110-
fir::ExtendedValue genExprAddr(const SomeExpr *someExpr,
111-
StatementContext &stmtCtx,
112-
mlir::Location loc) {
113-
return genExprAddr(*someExpr, stmtCtx, &loc);
113+
114+
/// Generate the address of the location holding the expression, \p expr.
115+
fir::ExtendedValue genExprAddr(mlir::Location loc, const SomeExpr *expr,
116+
StatementContext &stmtCtx) {
117+
return genExprAddr(*expr, stmtCtx, &loc);
118+
}
119+
fir::ExtendedValue genExprAddr(mlir::Location loc, const SomeExpr &expr,
120+
StatementContext &stmtCtx) {
121+
return genExprAddr(expr, stmtCtx, &loc);
114122
}
115123

116-
/// Generate the computations of the expression to produce a value
117-
virtual fir::ExtendedValue genExprValue(const SomeExpr &, StatementContext &,
124+
/// Generate the computations of the expression to produce a value.
125+
virtual fir::ExtendedValue genExprValue(const SomeExpr &expr,
126+
StatementContext &context,
118127
mlir::Location *loc = nullptr) = 0;
119-
/// Generate the computations of the expression, someExpr, to produce a value
120-
fir::ExtendedValue genExprValue(const SomeExpr *someExpr,
121-
StatementContext &stmtCtx,
122-
mlir::Location loc) {
123-
return genExprValue(*someExpr, stmtCtx, &loc);
128+
129+
/// Generate the computations of the expression, \p expr, to produce a value.
130+
fir::ExtendedValue genExprValue(mlir::Location loc, const SomeExpr *expr,
131+
StatementContext &stmtCtx) {
132+
return genExprValue(*expr, stmtCtx, &loc);
133+
}
134+
fir::ExtendedValue genExprValue(mlir::Location loc, const SomeExpr &expr,
135+
StatementContext &stmtCtx) {
136+
return genExprValue(expr, stmtCtx, &loc);
124137
}
125138

126139
/// Generate or get a fir.box describing the expression. If SomeExpr is
127140
/// a Designator, the fir.box describes an entity over the Designator base
128141
/// storage without making a temporary.
129-
virtual fir::ExtendedValue genExprBox(const SomeExpr &, StatementContext &,
130-
mlir::Location) = 0;
142+
virtual fir::ExtendedValue genExprBox(mlir::Location loc,
143+
const SomeExpr &expr,
144+
StatementContext &stmtCtx) = 0;
131145

132146
/// Generate the address of the box describing the variable designated
133147
/// by the expression. The expression must be an allocatable or pointer
134148
/// designator.
135149
virtual fir::MutableBoxValue genExprMutableBox(mlir::Location loc,
136-
const SomeExpr &) = 0;
150+
const SomeExpr &expr) = 0;
137151

138152
/// Get FoldingContext that is required for some expression
139153
/// analysis.

flang/include/flang/Lower/Allocatable.h

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef FORTRAN_LOWER_ALLOCATABLE_H
1414
#define FORTRAN_LOWER_ALLOCATABLE_H
1515

16+
#include "flang/Lower/AbstractConverter.h"
1617
#include "flang/Optimizer/Builder/MutableBox.h"
1718
#include "llvm/ADT/StringRef.h"
1819

@@ -23,55 +24,55 @@ class Location;
2324
} // namespace mlir
2425

2526
namespace fir {
26-
class MutableBoxValue;
27-
}
27+
class FirOpBuilder;
28+
} // namespace fir
2829

29-
namespace Fortran::parser {
30+
namespace Fortran {
31+
namespace parser {
3032
struct AllocateStmt;
3133
struct DeallocateStmt;
32-
} // namespace Fortran::parser
34+
} // namespace parser
3335

34-
namespace Fortran::evaluate {
35-
template <typename T>
36-
class Expr;
37-
struct SomeType;
38-
} // namespace Fortran::evaluate
36+
namespace lower {
37+
struct SymbolBox;
3938

40-
namespace Fortran::lower {
41-
class AbstractConverter;
4239
class StatementContext;
4340

44-
namespace pft {
45-
struct Variable;
46-
}
41+
bool isArraySectionWithoutVectorSubscript(const SomeExpr &expr);
4742

4843
/// Lower an allocate statement to fir.
49-
void genAllocateStmt(Fortran::lower::AbstractConverter &,
50-
const Fortran::parser::AllocateStmt &, mlir::Location);
44+
void genAllocateStmt(AbstractConverter &converter,
45+
const parser::AllocateStmt &stmt, mlir::Location loc);
5146

5247
/// Lower a deallocate statement to fir.
53-
void genDeallocateStmt(Fortran::lower::AbstractConverter &,
54-
const Fortran::parser::DeallocateStmt &, mlir::Location);
48+
void genDeallocateStmt(AbstractConverter &converter,
49+
const parser::DeallocateStmt &stmt, mlir::Location loc);
5550

5651
/// Create a MutableBoxValue for an allocatable or pointer entity.
5752
/// If the variables is a local variable that is not a dummy, it will be
5853
/// initialized to unallocated/diassociated status.
59-
fir::MutableBoxValue createMutableBox(Fortran::lower::AbstractConverter &,
60-
mlir::Location,
61-
const Fortran::lower::pft::Variable &var,
54+
fir::MutableBoxValue createMutableBox(AbstractConverter &converter,
55+
mlir::Location loc,
56+
const pft::Variable &var,
6257
mlir::Value boxAddr,
6358
mlir::ValueRange nonDeferredParams);
6459

65-
/// Update a MutableBoxValue to describe the entity designated by the expression
66-
/// \p source. This version takes care of \p source lowering.
67-
/// If \lbounds is not empty, it is used to defined the MutableBoxValue
68-
/// lower bounds, otherwise, the lower bounds from \p source are used.
69-
void associateMutableBox(
70-
Fortran::lower::AbstractConverter &, mlir::Location,
71-
const fir::MutableBoxValue &,
72-
const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &source,
73-
mlir::ValueRange lbounds, Fortran::lower::StatementContext &);
74-
75-
} // namespace Fortran::lower
60+
/// Assign a boxed value to a boxed variable, \p box (known as a
61+
/// MutableBoxValue). Expression \p source will be lowered to build the
62+
/// assignment. If \p lbounds is not empty, it is used to define the result's
63+
/// lower bounds. Otherwise, the lower bounds from \p source will be used.
64+
void associateMutableBox(AbstractConverter &converter, mlir::Location loc,
65+
const fir::MutableBoxValue &box,
66+
const SomeExpr &source, mlir::ValueRange lbounds,
67+
StatementContext &stmtCtx);
68+
69+
/// Is \p expr a reference to an entity with the ALLOCATABLE attribute?
70+
bool isWholeAllocatable(const SomeExpr &expr);
71+
72+
/// Is \p expr a reference to an entity with the POINTER attribute?
73+
bool isWholePointer(const SomeExpr &expr);
74+
75+
} // namespace lower
76+
} // namespace Fortran
7677

7778
#endif // FORTRAN_LOWER_ALLOCATABLE_H

flang/include/flang/Lower/ComponentPath.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ class ImplicitSubscripts {};
2727

2828
using PathComponent =
2929
std::variant<const evaluate::ArrayRef *, const evaluate::Component *,
30-
const Fortran::evaluate::ComplexPart *,
31-
details::ImplicitSubscripts>;
30+
const evaluate::ComplexPart *, details::ImplicitSubscripts>;
3231

3332
/// Collection of components.
3433
///
@@ -37,17 +36,24 @@ using PathComponent =
3736
/// arguments.
3837
class ComponentPath {
3938
public:
39+
using ExtendRefFunc = std::function<mlir::Value(const mlir::Value &)>;
40+
4041
ComponentPath(bool isImplicit) { setPC(isImplicit); }
4142
ComponentPath(bool isImplicit, const evaluate::Substring *ss)
4243
: substring(ss) {
4344
setPC(isImplicit);
4445
}
4546
ComponentPath() = delete;
4647

47-
bool isSlice() { return !trips.empty() || hasComponents(); }
48-
bool hasComponents() { return !suffixComponents.empty(); }
48+
bool isSlice() const { return !trips.empty() || hasComponents(); }
49+
bool hasComponents() const { return !suffixComponents.empty(); }
4950
void clear();
5051

52+
bool hasExtendCoorRef() const { return extendCoorRef.hasValue(); }
53+
ExtendRefFunc getExtendCoorRef() const;
54+
void resetExtendCoorRef() { extendCoorRef = llvm::None; }
55+
void resetPC();
56+
5157
llvm::SmallVector<PathComponent> reversePath;
5258
const evaluate::Substring *substring = nullptr;
5359
bool applied = false;
@@ -57,6 +63,13 @@ class ComponentPath {
5763
llvm::SmallVector<mlir::Value> suffixComponents;
5864
std::function<IterationSpace(const IterationSpace &)> pc;
5965

66+
/// In the case where a path of components involves members that are POINTER
67+
/// or ALLOCATABLE, a dereference is required in FIR for semantic correctness.
68+
/// This optional continuation allows the generation of those dereferences.
69+
/// These accesses are always on Fortran entities of record types, which are
70+
/// implicitly in-memory objects.
71+
llvm::Optional<ExtendRefFunc> extendCoorRef = llvm::None;
72+
6073
private:
6174
void setPC(bool isImplicit);
6275
};

flang/include/flang/Lower/ConvertExpr.h

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -164,22 +164,6 @@ void createAnyMaskedArrayAssignment(AbstractConverter &converter,
164164
ImplicitIterSpace &implicitIterSpace,
165165
SymMap &symMap, StatementContext &stmtCtx);
166166

167-
/// In the context of a FORALL, a pointer assignment is allowed. The pointer
168-
/// assignment can be elementwise on an array of pointers. The bounds
169-
/// expressions as well as the component path may contain references to the
170-
/// concurrent control variables. The explicit iteration space must be defined.
171-
void createAnyArrayPointerAssignment(
172-
AbstractConverter &converter, const SomeExpr &lhs, const SomeExpr &rhs,
173-
const evaluate::Assignment::BoundsSpec &bounds,
174-
ExplicitIterSpace &explicitIterSpace, ImplicitIterSpace &implicitIterSpace,
175-
SymMap &symMap);
176-
/// Support the bounds remapping flavor of pointer assignment.
177-
void createAnyArrayPointerAssignment(
178-
AbstractConverter &converter, const SomeExpr &lhs, const SomeExpr &rhs,
179-
const evaluate::Assignment::BoundsRemapping &bounds,
180-
ExplicitIterSpace &explicitIterSpace, ImplicitIterSpace &implicitIterSpace,
181-
SymMap &symMap);
182-
183167
/// Lower an assignment to an allocatable array, allocating the array if
184168
/// it is not allocated yet or reallocation it if it does not conform
185169
/// with the right hand side.
@@ -190,6 +174,17 @@ void createAllocatableArrayAssignment(AbstractConverter &converter,
190174
SymMap &symMap,
191175
StatementContext &stmtCtx);
192176

177+
/// Lower a pointer assignment in an explicit iteration space. The explicit
178+
/// space iterates over a data structure with a type of `!fir.array<...
179+
/// !fir.box<!fir.ptr<T>> ...>`. Lower the assignment by copying the rhs box
180+
/// value to each array element.
181+
void createArrayOfPointerAssignment(
182+
AbstractConverter &converter, const SomeExpr &lhs, const SomeExpr &rhs,
183+
ExplicitIterSpace &explicitIterSpace, ImplicitIterSpace &implicitIterSpace,
184+
const llvm::SmallVector<mlir::Value> &lbounds,
185+
llvm::Optional<llvm::SmallVector<mlir::Value>> ubounds, SymMap &symMap,
186+
StatementContext &stmtCtx);
187+
193188
/// Lower an array expression with "parallel" semantics. Such a rhs expression
194189
/// is fully evaluated prior to being assigned back to a temporary array.
195190
fir::ExtendedValue createSomeArrayTempValue(AbstractConverter &converter,

flang/include/flang/Lower/Support/Utils.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,17 @@ ignoreEvConvert(const Fortran::evaluate::Expr<Fortran::evaluate::Type<
7979
return std::visit([](const auto &v) { return ignoreEvConvert(v); }, x.u);
8080
}
8181

82+
/// Zip two containers of the same size together and flatten the pairs. `flatZip
83+
/// [1;2] [3;4]` yields `[1;3;2;4]`.
84+
template <typename A>
85+
A flatZip(const A &container1, const A &container2) {
86+
assert(container1.size() == container2.size());
87+
A result;
88+
for (auto [e1, e2] : llvm::zip(container1, container2)) {
89+
result.emplace_back(e1);
90+
result.emplace_back(e2);
91+
}
92+
return result;
93+
}
94+
8295
#endif // FORTRAN_LOWER_SUPPORT_UTILS_H

0 commit comments

Comments
 (0)