Skip to content

Commit a807149

Browse files
committed
[flang][OpenMP] Initialize allocatable members of derived types
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. To handle this, a new runtime function was added: InitializeClone. Lowering inserts a call to it for each privatized item that is a derived type with allocatable members. Fixes #114888 Fixes #114889
1 parent 70c5887 commit a807149

File tree

13 files changed

+270
-4
lines changed

13 files changed

+270
-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
@@ -556,8 +556,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
556556
return lookupSymbol(sym).getAddr();
557557
}
558558

559-
fir::ExtendedValue
560-
symBoxToExtendedValue(const Fortran::lower::SymbolBox &symBox) {
559+
fir::ExtendedValue symBoxToExtendedValue(
560+
const Fortran::lower::SymbolBox &symBox) override final {
561561
return symBox.match(
562562
[](const Fortran::lower::SymbolBox::Intrinsic &box)
563563
-> 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: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,31 @@ 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+
mlir::Type ty = addr.getType();
130+
131+
// Unwrap type
132+
while (auto eleTy = fir::dyn_cast_ptrOrBoxEleTy(ty))
133+
ty = eleTy;
134+
// For arrays, use its element type
135+
if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty))
136+
ty = seqTy.getEleTy();
137+
return fir::isRecordWithAllocatableMember(ty);
138+
};
139+
140+
if (needInitClone()) {
141+
Fortran::lower::initializeCloneAtRuntime(converter, *sym, symTable);
142+
callsInitClone = true;
143+
}
119144
}
120145

121146
void DataSharingProcessor::copyFirstPrivateSymbol(
@@ -165,8 +190,8 @@ bool DataSharingProcessor::needBarrier() {
165190
// variables.
166191
// Emit implicit barrier for linear clause. Maybe on somewhere else.
167192
for (const semantics::Symbol *sym : allPrivatizedSymbols) {
168-
if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate) &&
169-
sym->test(semantics::Symbol::Flag::OmpLastPrivate))
193+
if (sym->test(semantics::Symbol::Flag::OmpLastPrivate) &&
194+
(sym->test(semantics::Symbol::Flag::OmpFirstPrivate) || callsInitClone))
170195
return true;
171196
}
172197
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)