Skip to content

Commit 128ce22

Browse files
committed
FORALL lowering
This is a major restructuring of how FORALL loops are lowered in the bridge from parse trees to FIR. Previously, FORALL loops had been lowered like any other structured control-flow loops and then as a more dynamic form of array expression. This refactoring is a middle road approach where the FORALL context is analyzed and then lowered in the bridge. This allows lowering to create loop nests that correctly deal with impure expressions and pure masking expressions, which were not aligned with array expressions. Lowering of assignment statements in the FORALL context is then done within the pre-built context by expression lowering. Secondly, expression lowering is refactored into a new "scalar array" traversal and code gen that works with array values as instantiated by the bridge in the earlier loop generation phase. Switching to this structure allows the array expression framework to be simplified since it no longer is required to deal with "special" scalar expressions and try to raise them into an array form. Allocatable arrays and pointer assignments are supported. User-defined ASSIGNMENT in (scalar) FORALL contexts is supported. This also introduces several correctness fixes. This does not correct known problems with arrays of CHARACTER, incomplete information with respect to derived types, elemental user-defined ASSIGNMENT in array expressions, PDTs, etc.
1 parent 53d598b commit 128ce22

File tree

14 files changed

+2535
-2494
lines changed

14 files changed

+2535
-2494
lines changed

flang/include/flang/Lower/ConvertExpr.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "flang/Evaluate/shape.h"
2121
#include "flang/Optimizer/Builder/BoxValue.h"
22+
#include "flang/Optimizer/Builder/FIRBuilder.h"
2223

2324
namespace mlir {
2425
class Location;
@@ -176,6 +177,14 @@ createSomeArrayBox(AbstractConverter &converter,
176177
const evaluate::Expr<evaluate::SomeType> &expr,
177178
SymMap &symMap, StatementContext &stmtCtx);
178179

180+
// Attribute for an alloca that is a trivial adaptor for converting a value to
181+
// pass-by-ref semantics for a VALUE parameter. The optimizer may be able to
182+
// eliminate these.
183+
inline mlir::NamedAttribute getAdaptToByRefAttr(fir::FirOpBuilder &builder) {
184+
return {mlir::Identifier::get("adapt.valuebyref", builder.getContext()),
185+
builder.getUnitAttr()};
186+
}
187+
179188
} // namespace Fortran::lower
180189

181190
#endif // FORTRAN_LOWER_CONVERTEXPR_H

flang/include/flang/Optimizer/Builder/FIRBuilder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ class FirOpBuilder : public mlir::OpBuilder {
338338
mlir::Value genIsNotNull(mlir::Location loc, mlir::Value addr);
339339

340340
private:
341-
const fir::KindMapping &kindMap;
341+
const KindMapping &kindMap;
342342
};
343343

344344
} // namespace fir

flang/include/flang/Optimizer/Dialect/FIRType.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,12 @@ inline mlir::Type unwrapSequenceType(mlir::Type t) {
163163
return t;
164164
}
165165

166+
inline mlir::Type unwrapRefType(mlir::Type t) {
167+
if (auto eleTy = dyn_cast_ptrEleTy(t))
168+
return eleTy;
169+
return t;
170+
}
171+
166172
/// If `t` conforms with a pass-by-reference type (box, ref, ptr, etc.) then
167173
/// return the element type of `t`. Otherwise, return `t`.
168174
inline mlir::Type unwrapPassByRefType(mlir::Type t) {
@@ -193,6 +199,13 @@ bool isUnlimitedPolymorphicType(mlir::Type ty);
193199
/// Return true iff `ty` is a RecordType with members that are allocatable.
194200
bool isRecordWithAllocatableMember(mlir::Type ty);
195201

202+
/// Return true iff `ty` is a RecordType with type parameters.
203+
inline bool isRecordWithTypeParameters(mlir::Type ty) {
204+
if (auto recTy = ty.dyn_cast_or_null<fir::RecordType>())
205+
return recTy.getNumLenParams() != 0;
206+
return false;
207+
}
208+
196209
/// Apply the components specified by `path` to `rootTy` to determine the type
197210
/// of the resulting component element. `rootTy` should be an aggregate type.
198211
/// Returns null on error.

flang/include/flang/Optimizer/Transforms/Factory.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ class Value;
2727

2828
namespace fir::factory {
2929

30+
constexpr llvm::StringRef attrFortranArrayOffsets() {
31+
return "Fortran.offsets";
32+
}
33+
3034
/// Generate a character copy with optimized forms.
3135
///
3236
/// If the lengths are constant and equal, use load/store rather than a loop.
@@ -137,14 +141,27 @@ void genCharacterCopy(mlir::Value src, mlir::Value srcLen, mlir::Value dst,
137141
builder.restoreInsertionPoint(insPt);
138142
}
139143

144+
/// Get extents from fir.shape/fir.shape_shift op. Empty result if
145+
/// \p shapeVal is empty or is a fir.shift.
146+
inline std::vector<mlir::Value> getExtents(mlir::Value shapeVal) {
147+
if (shapeVal)
148+
if (auto *shapeOp = shapeVal.getDefiningOp()) {
149+
if (auto shOp = mlir::dyn_cast<fir::ShapeOp>(shapeOp))
150+
return shOp.getExtents();
151+
if (auto shOp = mlir::dyn_cast<fir::ShapeShiftOp>(shapeOp))
152+
return shOp.getExtents();
153+
}
154+
return {};
155+
}
156+
140157
/// Get origins from fir.shape_shift/fir.shift op. Empty result if
141158
/// \p shapeVal is empty or is a fir.shape.
142159
inline std::vector<mlir::Value> getOrigins(mlir::Value shapeVal) {
143160
if (shapeVal)
144161
if (auto *shapeOp = shapeVal.getDefiningOp()) {
145162
if (auto shOp = mlir::dyn_cast<fir::ShapeShiftOp>(shapeOp))
146163
return shOp.getOrigins();
147-
else if (auto shOp = mlir::dyn_cast<fir::ShiftOp>(shapeOp))
164+
if (auto shOp = mlir::dyn_cast<fir::ShiftOp>(shapeOp))
148165
return shOp.getOrigins();
149166
}
150167
return {};

0 commit comments

Comments
 (0)