Skip to content

Commit 1fcb6a9

Browse files
authored
[flang][OpenMP] Initialize allocatable members of derived types (#120295)
Allocatable members of privatized derived types must be allocated, with the same bounds as the original object, whenever that member is also allocated in it, but Flang was not performing such initialization. The `Initialize` runtime function can't perform this task unless its signature is changed to receive an additional parameter, the original object, that is needed to find out which allocatable members, with their bounds, must also be allocated in the clone. As `Initialize` is used not only for privatization, sometimes this other object won't even exist, so this new parameter would need to be optional. Because of this, it seemed better to add a new runtime function: `InitializeClone`. To avoid unnecessary calls, lowering inserts a call to it only for privatized items that are derived types with allocatable members. Fixes #114888 Fixes #114889
1 parent bdf2555 commit 1fcb6a9

File tree

13 files changed

+262
-4
lines changed

13 files changed

+262
-4
lines changed

flang/include/flang/Lower/AbstractConverter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ class AbstractConverter {
8888
/// Get the mlir instance of a symbol.
8989
virtual mlir::Value getSymbolAddress(SymbolRef sym) = 0;
9090

91+
virtual fir::ExtendedValue
92+
symBoxToExtendedValue(const Fortran::lower::SymbolBox &symBox) = 0;
93+
9194
virtual fir::ExtendedValue
9295
getSymbolExtendedValue(const Fortran::semantics::Symbol &sym,
9396
Fortran::lower::SymMap *symMap = nullptr) = 0;

flang/include/flang/Lower/ConvertVariable.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ void defaultInitializeAtRuntime(Fortran::lower::AbstractConverter &converter,
7070
const Fortran::semantics::Symbol &sym,
7171
Fortran::lower::SymMap &symMap);
7272

73+
/// Call clone initialization runtime routine to initialize \p sym's value.
74+
void initializeCloneAtRuntime(Fortran::lower::AbstractConverter &converter,
75+
const Fortran::semantics::Symbol &sym,
76+
Fortran::lower::SymMap &symMap);
77+
7378
/// Create a fir::GlobalOp given a module variable definition. This is intended
7479
/// to be used when lowering a module definition, not when lowering variables
7580
/// used from a module. For used variables instantiateVariable must directly be

flang/include/flang/Optimizer/Builder/Runtime/Derived.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ namespace fir::runtime {
2626
void genDerivedTypeInitialize(fir::FirOpBuilder &builder, mlir::Location loc,
2727
mlir::Value box);
2828

29+
/// Generate call to derived type clone initialization runtime routine to
30+
/// initialize \p newBox from \p box.
31+
void genDerivedTypeInitializeClone(fir::FirOpBuilder &builder,
32+
mlir::Location loc, mlir::Value newBox,
33+
mlir::Value box);
34+
2935
/// Generate call to derived type destruction runtime routine to
3036
/// destroy \p box.
3137
void genDerivedTypeDestroy(fir::FirOpBuilder &builder, mlir::Location loc,

flang/include/flang/Runtime/derived-api.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ extern "C" {
3232
void RTDECL(Initialize)(
3333
const Descriptor &, const char *sourceFile = nullptr, int sourceLine = 0);
3434

35+
// Initializes an object clone from the original object.
36+
// Each allocatable member of the clone is allocated with the same bounds as
37+
// in the original object, if it is also allocated in it.
38+
// The descriptor must be initialized and non-null.
39+
void RTDECL(InitializeClone)(const Descriptor &, const Descriptor &,
40+
const char *sourceFile = nullptr, int sourceLine = 0);
41+
3542
// Finalizes an object and its components. Deallocates any
3643
// allocatable/automatic components. Does not deallocate the descriptor's
3744
// storage.

flang/lib/Lower/Bridge.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
557557
return lookupSymbol(sym).getAddr();
558558
}
559559

560-
fir::ExtendedValue
561-
symBoxToExtendedValue(const Fortran::lower::SymbolBox &symBox) {
560+
fir::ExtendedValue symBoxToExtendedValue(
561+
const Fortran::lower::SymbolBox &symBox) override final {
562562
return symBox.match(
563563
[](const Fortran::lower::SymbolBox::Intrinsic &box)
564564
-> fir::ExtendedValue { return box.getAddr(); },

flang/lib/Lower/ConvertVariable.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,20 @@ void Fortran::lower::defaultInitializeAtRuntime(
798798
}
799799
}
800800

801+
/// Call clone initialization runtime routine to initialize \p sym's value.
802+
void Fortran::lower::initializeCloneAtRuntime(
803+
Fortran::lower::AbstractConverter &converter,
804+
const Fortran::semantics::Symbol &sym, Fortran::lower::SymMap &symMap) {
805+
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
806+
mlir::Location loc = converter.getCurrentLocation();
807+
fir::ExtendedValue exv = converter.getSymbolExtendedValue(sym, &symMap);
808+
mlir::Value newBox = builder.createBox(loc, exv);
809+
lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(sym);
810+
fir::ExtendedValue hexv = converter.symBoxToExtendedValue(hsb);
811+
mlir::Value box = builder.createBox(loc, hexv);
812+
fir::runtime::genDerivedTypeInitializeClone(builder, loc, newBox, box);
813+
}
814+
801815
enum class VariableCleanUp { Finalize, Deallocate };
802816
/// Check whether a local variable needs to be finalized according to clause
803817
/// 7.5.6.3 point 3 or if it is an allocatable that must be deallocated. Note

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,23 @@ void DataSharingProcessor::cloneSymbol(const semantics::Symbol *sym) {
116116
*sym, /*skipDefaultInit=*/isFirstPrivate);
117117
(void)success;
118118
assert(success && "Privatization failed due to existing binding");
119+
120+
// Initialize clone from original object if it has any allocatable member.
121+
auto needInitClone = [&] {
122+
if (isFirstPrivate)
123+
return false;
124+
125+
SymbolBox sb = symTable.lookupSymbol(sym);
126+
assert(sb);
127+
mlir::Value addr = sb.getAddr();
128+
assert(addr);
129+
return hlfir::mayHaveAllocatableComponent(addr.getType());
130+
};
131+
132+
if (needInitClone()) {
133+
Fortran::lower::initializeCloneAtRuntime(converter, *sym, symTable);
134+
callsInitClone = true;
135+
}
119136
}
120137

121138
void DataSharingProcessor::copyFirstPrivateSymbol(
@@ -165,8 +182,8 @@ bool DataSharingProcessor::needBarrier() {
165182
// variables.
166183
// Emit implicit barrier for linear clause. Maybe on somewhere else.
167184
for (const semantics::Symbol *sym : allPrivatizedSymbols) {
168-
if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate) &&
169-
sym->test(semantics::Symbol::Flag::OmpLastPrivate))
185+
if (sym->test(semantics::Symbol::Flag::OmpLastPrivate) &&
186+
(sym->test(semantics::Symbol::Flag::OmpFirstPrivate) || callsInitClone))
170187
return true;
171188
}
172189
return false;

flang/lib/Lower/OpenMP/DataSharingProcessor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class DataSharingProcessor {
8686
lower::pft::Evaluation &eval;
8787
bool shouldCollectPreDeterminedSymbols;
8888
bool useDelayedPrivatization;
89+
bool callsInitClone = false;
8990
lower::SymMap &symTable;
9091
OMPConstructSymbolVisitor visitor;
9192

flang/lib/Optimizer/Builder/Runtime/Derived.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,21 @@ void fir::runtime::genDerivedTypeInitialize(fir::FirOpBuilder &builder,
2929
builder.create<fir::CallOp>(loc, func, args);
3030
}
3131

32+
void fir::runtime::genDerivedTypeInitializeClone(fir::FirOpBuilder &builder,
33+
mlir::Location loc,
34+
mlir::Value newBox,
35+
mlir::Value box) {
36+
auto func =
37+
fir::runtime::getRuntimeFunc<mkRTKey(InitializeClone)>(loc, builder);
38+
auto fTy = func.getFunctionType();
39+
auto sourceFile = fir::factory::locationToFilename(builder, loc);
40+
auto sourceLine =
41+
fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
42+
auto args = fir::runtime::createArguments(builder, loc, fTy, newBox, box,
43+
sourceFile, sourceLine);
44+
builder.create<fir::CallOp>(loc, func, args);
45+
}
46+
3247
void fir::runtime::genDerivedTypeDestroy(fir::FirOpBuilder &builder,
3348
mlir::Location loc, mlir::Value box) {
3449
auto func = fir::runtime::getRuntimeFunc<mkRTKey(Destroy)>(loc, builder);

flang/runtime/derived-api.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ void RTDEF(Initialize)(
3131
}
3232
}
3333

34+
void RTDEF(InitializeClone)(const Descriptor &clone, const Descriptor &orig,
35+
const char *sourceFile, int sourceLine) {
36+
if (const DescriptorAddendum * addendum{clone.Addendum()}) {
37+
if (const auto *derived{addendum->derivedType()}) {
38+
Terminator terminator{sourceFile, sourceLine};
39+
InitializeClone(clone, orig, *derived, terminator);
40+
}
41+
}
42+
}
43+
3444
void RTDEF(Destroy)(const Descriptor &descriptor) {
3545
if (const DescriptorAddendum * addendum{descriptor.Addendum()}) {
3646
if (const auto *derived{addendum->derivedType()}) {

0 commit comments

Comments
 (0)