Skip to content

Commit 83da8d0

Browse files
authored
[flang] Attach proper storage to [hl]fir.declare in lowering. (#155742)
As described in https://discourse.llvm.org/t/rfc-flang-representation-for-objects-inside-physical-storage/88026, `[hl]fir.declare` should carry information about the layout of COMMON/EQUIVALENCE variables within the physical storage. This patch modifes Flang lowering to attach this information.
1 parent 3dff9ac commit 83da8d0

40 files changed

+555
-280
lines changed

flang/include/flang/Lower/AbstractConverter.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,21 @@ class AbstractConverter {
108108
/// added or replaced at the inner-most level of the local symbol map.
109109
virtual void bindSymbol(SymbolRef sym, const fir::ExtendedValue &exval) = 0;
110110

111+
/// Binds the symbol's physical storage to a storage descriptor,
112+
/// which is the base address of the storage and the offset
113+
/// within the storage, where the symbol begins.
114+
/// The symbol binding will be added or replaced at the innermost level
115+
/// of the local symbol map.
116+
virtual void
117+
bindSymbolStorage(SymbolRef sym,
118+
Fortran::lower::SymMap::StorageDesc storage) = 0;
119+
120+
/// Returns the storage descriptor previously bound to this symbol.
121+
/// If there is no bound storage, the descriptor will contain
122+
/// nullptr base address.
123+
virtual Fortran::lower::SymMap::StorageDesc
124+
getSymbolStorage(SymbolRef sym) = 0;
125+
111126
/// Override lowering of expression with pre-lowered values.
112127
/// Associate mlir::Value to evaluate::Expr. All subsequent call to
113128
/// genExprXXX() will replace any occurrence of an overridden

flang/include/flang/Lower/ConvertVariable.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,14 @@ void defineCommonBlocks(
9292
/// The COMMON block is a global structure. \p commonValue is the base address
9393
/// of the COMMON block. As the offset from the symbol \p sym, generate the
9494
/// COMMON block member value (commonValue + offset) for the symbol.
95+
/// \p commonSize specifies the syze of the COMMON block in bytes.
96+
/// The size is used to represent a COMMON block reference as
97+
/// a !fir.ref<!fir.array<SIZExi8>>.
9598
mlir::Value genCommonBlockMember(AbstractConverter &converter,
9699
mlir::Location loc,
97100
const Fortran::semantics::Symbol &sym,
98-
mlir::Value commonValue);
101+
mlir::Value commonValue,
102+
std::size_t commonSize);
99103

100104
/// Lower a symbol attributes given an optional storage \p and add it to the
101105
/// provided symbol map. If \preAlloc is not provided, a temporary storage will

flang/include/flang/Lower/SymbolMap.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,22 @@ struct SymbolBox : public fir::details::matcher<SymbolBox> {
146146
class SymMap {
147147
public:
148148
using AcDoVar = llvm::StringRef;
149+
/// Descriptor of a symbol's storage consists of the base address
150+
/// of the storage and the offset within that storage.
151+
using StorageDesc = std::pair<mlir::Value, std::uint64_t>;
149152

150153
SymMap() { pushScope(); }
151154
SymMap(const SymMap &) = delete;
152155

153-
void pushScope() { symbolMapStack.emplace_back(); }
156+
void pushScope() {
157+
symbolMapStack.emplace_back();
158+
storageMapStack.emplace_back();
159+
}
154160
void popScope() {
155161
symbolMapStack.pop_back();
156162
assert(symbolMapStack.size() >= 1);
163+
storageMapStack.pop_back();
164+
assert(storageMapStack.size() >= 1);
157165
}
158166

159167
/// Add an extended value to the symbol table.
@@ -287,6 +295,8 @@ class SymMap {
287295
symbolMapStack.emplace_back();
288296
assert(symbolMapStack.size() == 1);
289297
impliedDoStack.clear();
298+
storageMapStack.clear();
299+
storageMapStack.emplace_back();
290300
}
291301

292302
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
@@ -315,6 +325,16 @@ class SymMap {
315325
return std::nullopt;
316326
}
317327

328+
/// Register the symbol's storage at the innermost level
329+
/// of the symbol table. If the storage is already registered,
330+
/// it will be replaced.
331+
void registerStorage(semantics::SymbolRef sym, StorageDesc storage);
332+
/// Lookup the symbol's storage at the innermost level of the symbol table.
333+
StorageDesc lookupStorage(semantics::SymbolRef sym);
334+
StorageDesc lookupStorage(const semantics::Symbol *sym) {
335+
return lookupStorage(*sym);
336+
}
337+
318338
private:
319339
/// Bind `box` to `symRef` in the symbol map.
320340
void makeSym(semantics::SymbolRef symRef, const SymbolBox &box,
@@ -332,6 +352,10 @@ class SymMap {
332352
// Implied DO induction variables are not represented as Se::Symbol in
333353
// Ev::Expr. Keep the variable markers in their own stack.
334354
llvm::SmallVector<std::pair<AcDoVar, mlir::Value>> impliedDoStack;
355+
356+
// A stack of maps between the symbols and their storage descriptors.
357+
llvm::SmallVector<llvm::DenseMap<const semantics::Symbol *, StorageDesc>>
358+
storageMapStack;
335359
};
336360

337361
/// RAII wrapper for SymMap.

flang/include/flang/Optimizer/Builder/HLFIRTools.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ fir::FortranVariableOpInterface
224224
genDeclare(mlir::Location loc, fir::FirOpBuilder &builder,
225225
const fir::ExtendedValue &exv, llvm::StringRef name,
226226
fir::FortranVariableFlagsAttr flags,
227-
mlir::Value dummyScope = nullptr,
227+
mlir::Value dummyScope = nullptr, mlir::Value storage = nullptr,
228+
std::uint64_t storageOffset = 0,
228229
cuf::DataAttributeAttr dataAttr = {});
229230

230231
/// Generate an hlfir.associate to build a variable from an expression value.

flang/include/flang/Optimizer/HLFIR/HLFIROps.td

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,12 @@ def hlfir_DeclareOp
109109
attr-dict `:` functional-type(operands, results)
110110
}];
111111

112-
let builders = [
113-
OpBuilder<(ins "mlir::Value":$memref, "llvm::StringRef":$uniq_name,
114-
CArg<"mlir::Value", "{}">:$shape, CArg<"mlir::ValueRange", "{}">:$typeparams,
112+
let builders = [OpBuilder<(ins "mlir::Value":$memref,
113+
"llvm::StringRef":$uniq_name, CArg<"mlir::Value", "{}">:$shape,
114+
CArg<"mlir::ValueRange", "{}">:$typeparams,
115115
CArg<"mlir::Value", "{}">:$dummy_scope,
116+
CArg<"mlir::Value", "{}">:$storage,
117+
CArg<"std::uint64_t", "0">:$storage_offset,
116118
CArg<"fir::FortranVariableFlagsAttr", "{}">:$fortran_attrs,
117119
CArg<"cuf::DataAttributeAttr", "{}">:$data_attr)>];
118120

flang/lib/Lower/Bridge.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,17 @@ class FirConverter : public Fortran::lower::AbstractConverter {
631631
addSymbol(sym, exval, /*forced=*/true);
632632
}
633633

634+
void bindSymbolStorage(
635+
Fortran::lower::SymbolRef sym,
636+
Fortran::lower::SymMap::StorageDesc storage) override final {
637+
localSymbols.registerStorage(sym, std::move(storage));
638+
}
639+
640+
Fortran::lower::SymMap::StorageDesc
641+
getSymbolStorage(Fortran::lower::SymbolRef sym) override final {
642+
return localSymbols.lookupStorage(sym);
643+
}
644+
634645
void
635646
overrideExprValues(const Fortran::lower::ExprToValueMap *map) override final {
636647
exprValueOverrides = map;

flang/lib/Lower/ConvertArrayConstructor.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,8 @@ class RuntimeTempStrategy : public StrategyBase {
315315
mlir::Value tempStorage = builder.createHeapTemporary(
316316
loc, declaredType, tempName, extents, lengths);
317317
mlir::Value shape = builder.genShape(loc, extents);
318-
declare = hlfir::DeclareOp::create(
319-
builder, loc, tempStorage, tempName, shape, lengths,
320-
/*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
318+
declare = hlfir::DeclareOp::create(builder, loc, tempStorage, tempName,
319+
shape, lengths);
321320
initialBoxValue =
322321
builder.createBox(loc, boxType, declare->getOriginalBase(), shape,
323322
/*slice=*/mlir::Value{}, lengths, /*tdesc=*/{});

flang/lib/Lower/ConvertExprToHLFIR.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,10 +1813,8 @@ class HlfirBuilder {
18131813
// Allocate scalar temporary that will be initialized
18141814
// with the values specified by the constructor.
18151815
mlir::Value storagePtr = builder.createTemporary(loc, recTy);
1816-
auto varOp = hlfir::EntityWithAttributes{hlfir::DeclareOp::create(
1817-
builder, loc, storagePtr, "ctor.temp", /*shape=*/nullptr,
1818-
/*typeparams=*/mlir::ValueRange{}, /*dummy_scope=*/nullptr,
1819-
fir::FortranVariableFlagsAttr{})};
1816+
auto varOp = hlfir::EntityWithAttributes{
1817+
hlfir::DeclareOp::create(builder, loc, storagePtr, "ctor.temp")};
18201818

18211819
// Initialize any components that need initialization.
18221820
mlir::Value box = builder.createBox(loc, fir::ExtendedValue{varOp});

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,7 @@ static void instantiateAlias(Fortran::lower::AbstractConverter &converter,
14131413
mlir::Value bytePtr = fir::CoordinateOp::create(
14141414
builder, loc, i8Ptr, storeAddr, mlir::ValueRange{offset});
14151415
mlir::Value typedPtr = castAliasToPointer(builder, loc, symType, bytePtr);
1416+
converter.bindSymbolStorage(sym, {storeAddr, off});
14161417
Fortran::lower::StatementContext stmtCtx;
14171418
mapSymbolAttributes(converter, var, symMap, stmtCtx, typedPtr);
14181419
// Default initialization is possible for equivalence members: see
@@ -1655,13 +1656,15 @@ void Fortran::lower::defineCommonBlocks(
16551656

16561657
mlir::Value Fortran::lower::genCommonBlockMember(
16571658
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
1658-
const Fortran::semantics::Symbol &sym, mlir::Value commonValue) {
1659+
const Fortran::semantics::Symbol &sym, mlir::Value commonValue,
1660+
std::size_t commonSize) {
16591661
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
16601662

16611663
std::size_t byteOffset = sym.GetUltimate().offset();
16621664
mlir::IntegerType i8Ty = builder.getIntegerType(8);
16631665
mlir::Type i8Ptr = builder.getRefType(i8Ty);
1664-
mlir::Type seqTy = builder.getRefType(builder.getVarLenSeqTy(i8Ty));
1666+
fir::SequenceType::Shape shape(1, commonSize);
1667+
mlir::Type seqTy = builder.getRefType(fir::SequenceType::get(shape, i8Ty));
16651668
mlir::Value base = builder.createConvert(loc, seqTy, commonValue);
16661669

16671670
mlir::Value offs =
@@ -1670,6 +1673,8 @@ mlir::Value Fortran::lower::genCommonBlockMember(
16701673
mlir::ValueRange{offs});
16711674
mlir::Type symType = converter.genType(sym);
16721675

1676+
converter.bindSymbolStorage(sym, {base, byteOffset});
1677+
16731678
return Fortran::semantics::FindEquivalenceSet(sym) != nullptr
16741679
? castAliasToPointer(builder, loc, symType, varAddr)
16751680
: builder.createConvert(loc, builder.getRefType(symType), varAddr);
@@ -1698,7 +1703,8 @@ static void instantiateCommon(Fortran::lower::AbstractConverter &converter,
16981703
symMap.addSymbol(common, commonAddr);
16991704
}
17001705

1701-
mlir::Value local = genCommonBlockMember(converter, loc, varSym, commonAddr);
1706+
mlir::Value local =
1707+
genCommonBlockMember(converter, loc, varSym, commonAddr, common.size());
17021708
Fortran::lower::StatementContext stmtCtx;
17031709
mapSymbolAttributes(converter, var, symMap, stmtCtx, local);
17041710
}
@@ -1970,7 +1976,8 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
19701976
// Declare a local pointer variable.
19711977
auto newBase = hlfir::DeclareOp::create(
19721978
builder, loc, boxAlloc, name, /*shape=*/nullptr, lenParams,
1973-
/*dummy_scope=*/nullptr, attributes);
1979+
/*dummy_scope=*/nullptr, /*storage=*/nullptr,
1980+
/*storage_offset=*/0, attributes);
19741981
mlir::Value nullAddr = builder.createNullConstant(
19751982
loc, llvm::cast<fir::BaseBoxType>(ptrBoxType).getEleTy());
19761983

@@ -2000,9 +2007,10 @@ static void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
20002007
mlir::Value dummyScope;
20012008
if (converter.isRegisteredDummySymbol(sym))
20022009
dummyScope = converter.dummyArgsScopeValue();
2003-
auto newBase =
2004-
hlfir::DeclareOp::create(builder, loc, base, name, shapeOrShift,
2005-
lenParams, dummyScope, attributes, dataAttr);
2010+
auto [storage, storageOffset] = converter.getSymbolStorage(sym);
2011+
auto newBase = hlfir::DeclareOp::create(
2012+
builder, loc, base, name, shapeOrShift, lenParams, dummyScope, storage,
2013+
storageOffset, attributes, dataAttr);
20062014
symMap.addVariableDefinition(sym, newBase, force);
20072015
return;
20082016
}
@@ -2060,8 +2068,10 @@ void Fortran::lower::genDeclareSymbol(
20602068
base = genPackArray(converter, sym, exv);
20612069
dummyScope = converter.dummyArgsScopeValue();
20622070
}
2063-
hlfir::EntityWithAttributes declare = hlfir::genDeclare(
2064-
loc, builder, base, name, attributes, dummyScope, dataAttr);
2071+
auto [storage, storageOffset] = converter.getSymbolStorage(sym);
2072+
hlfir::EntityWithAttributes declare =
2073+
hlfir::genDeclare(loc, builder, base, name, attributes, dummyScope,
2074+
storage, storageOffset, dataAttr);
20652075
symMap.addVariableDefinition(sym, declare.getIfVariableInterface(), force);
20662076
return;
20672077
}

flang/lib/Lower/OpenACC.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,12 +1212,10 @@ mlir::acc::FirstprivateRecipeOp Fortran::lower::createOrGetFirstprivateRecipe(
12121212

12131213
auto leftDeclOp = hlfir::DeclareOp::create(
12141214
builder, loc, recipe.getCopyRegion().getArgument(0), llvm::StringRef{},
1215-
shape, llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
1216-
fir::FortranVariableFlagsAttr{});
1215+
shape);
12171216
auto rightDeclOp = hlfir::DeclareOp::create(
12181217
builder, loc, recipe.getCopyRegion().getArgument(1), llvm::StringRef{},
1219-
shape, llvm::ArrayRef<mlir::Value>{}, /*dummy_scope=*/nullptr,
1220-
fir::FortranVariableFlagsAttr{});
1218+
shape);
12211219

12221220
hlfir::DesignateOp::Subscripts triplets =
12231221
getSubscriptsFromArgs(recipe.getCopyRegion().getArguments());
@@ -1523,14 +1521,10 @@ static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc,
15231521
auto shape =
15241522
genShapeFromBoundsOrArgs(loc, builder, seqTy, bounds,
15251523
recipe.getCombinerRegion().getArguments());
1526-
auto v1DeclareOp = hlfir::DeclareOp::create(
1527-
builder, loc, value1, llvm::StringRef{}, shape,
1528-
llvm::ArrayRef<mlir::Value>{},
1529-
/*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
1530-
auto v2DeclareOp = hlfir::DeclareOp::create(
1531-
builder, loc, value2, llvm::StringRef{}, shape,
1532-
llvm::ArrayRef<mlir::Value>{},
1533-
/*dummy_scope=*/nullptr, fir::FortranVariableFlagsAttr{});
1524+
auto v1DeclareOp = hlfir::DeclareOp::create(builder, loc, value1,
1525+
llvm::StringRef{}, shape);
1526+
auto v2DeclareOp = hlfir::DeclareOp::create(builder, loc, value2,
1527+
llvm::StringRef{}, shape);
15341528
hlfir::DesignateOp::Subscripts triplets = getTripletsFromArgs(recipe);
15351529

15361530
llvm::SmallVector<mlir::Value> lenParamsLeft;

0 commit comments

Comments
 (0)