Skip to content

Commit b81ebd1

Browse files
committed
[flang] Extend localization support for do concurrent (init regions) (llvm#142564)
Extends support for locality specifiers in `do concurrent` by supporting data types that need `init` regions. This further unifies the paths taken by the compiler for OpenMP privatization clauses and `do concurrent` locality specifiers.
1 parent c491482 commit b81ebd1

File tree

10 files changed

+133
-98
lines changed

10 files changed

+133
-98
lines changed

flang/lib/Lower/OpenMP/PrivateReductionUtils.h renamed to flang/include/flang/Lower/Support/PrivateReductionUtils.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ namespace Fortran {
3535
namespace lower {
3636
class AbstractConverter;
3737

38-
namespace omp {
39-
40-
enum class DeclOperationKind { Private, FirstPrivate, Reduction };
38+
enum class DeclOperationKind {
39+
PrivateOrLocal,
40+
FirstPrivateOrLocalInit,
41+
Reduction
42+
};
4143
inline bool isPrivatization(DeclOperationKind kind) {
42-
return (kind == DeclOperationKind::FirstPrivate) ||
43-
(kind == DeclOperationKind::Private);
44+
return (kind == DeclOperationKind::FirstPrivateOrLocalInit) ||
45+
(kind == DeclOperationKind::PrivateOrLocal);
4446
}
4547
inline bool isReduction(DeclOperationKind kind) {
4648
return kind == DeclOperationKind::Reduction;
@@ -56,7 +58,7 @@ void populateByRefInitAndCleanupRegions(
5658
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
5759
mlir::Region &cleanupRegion, DeclOperationKind kind,
5860
const Fortran::semantics::Symbol *sym = nullptr,
59-
bool cannotHaveNonDefaultLowerBounds = false);
61+
bool cannotHaveNonDefaultLowerBounds = false, bool isDoConcurrent = false);
6062

6163
/// Generate a fir::ShapeShift op describing the provided boxed array.
6264
/// `cannotHaveNonDefaultLowerBounds` should be set if `box` is known to have
@@ -69,7 +71,6 @@ fir::ShapeShiftOp getShapeShift(fir::FirOpBuilder &builder, mlir::Location loc,
6971
bool cannotHaveNonDefaultLowerBounds = false,
7072
bool useDefaultLowerBounds = false);
7173

72-
} // namespace omp
7374
} // namespace lower
7475
} // namespace Fortran
7576

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "mlir/Dialect/Arith/IR/Arith.h"
2121
#include "mlir/Dialect/Func/IR/FuncOps.h"
2222
#include "mlir/IR/BuiltinAttributes.h"
23+
#include "llvm/ADT/SmallSet.h"
2324
#include "llvm/ADT/StringRef.h"
2425

2526
namespace Fortran::lower {
@@ -98,8 +99,9 @@ bool isEqual(const Fortran::lower::ExplicitIterSpace::ArrayBases &x,
9899
template <typename OpType, typename OperandsStructType>
99100
void privatizeSymbol(
100101
lower::AbstractConverter &converter, fir::FirOpBuilder &firOpBuilder,
101-
lower::SymMap &symTable, std::function<void(OpType, mlir::Type)> initGen,
102+
lower::SymMap &symTable,
102103
llvm::SetVector<const semantics::Symbol *> &allPrivatizedSymbols,
104+
llvm::SmallSet<const semantics::Symbol *, 16> &mightHaveReadHostSym,
103105
const semantics::Symbol *symToPrivatize, OperandsStructType *clauseOps);
104106

105107
} // end namespace Fortran::lower

flang/lib/Lower/Bridge.cpp

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
#include "flang/Lower/Bridge.h"
1414

15-
#include "OpenMP/DataSharingProcessor.h"
1615
#include "flang/Lower/Allocatable.h"
1716
#include "flang/Lower/CallInterface.h"
1817
#include "flang/Lower/Coarray.h"
@@ -2059,44 +2058,38 @@ class FirConverter : public Fortran::lower::AbstractConverter {
20592058
bool useDelayedPriv =
20602059
enableDelayedPrivatizationStaging && doConcurrentLoopOp;
20612060
llvm::SetVector<const Fortran::semantics::Symbol *> allPrivatizedSymbols;
2061+
llvm::SmallSet<const Fortran::semantics::Symbol *, 16> mightHaveReadHostSym;
20622062

2063-
for (const Fortran::semantics::Symbol *sym : info.localSymList) {
2063+
for (const Fortran::semantics::Symbol *symToPrivatize : info.localSymList) {
20642064
if (useDelayedPriv) {
20652065
Fortran::lower::privatizeSymbol<fir::LocalitySpecifierOp>(
2066-
*this, this->getFirOpBuilder(), localSymbols,
2067-
[this](fir::LocalitySpecifierOp result, mlir::Type argType) {
2068-
TODO(this->toLocation(),
2069-
"Localizers that need init regions are not supported yet.");
2070-
},
2071-
allPrivatizedSymbols, sym, &privateClauseOps);
2066+
*this, this->getFirOpBuilder(), localSymbols, allPrivatizedSymbols,
2067+
mightHaveReadHostSym, symToPrivatize, &privateClauseOps);
20722068
continue;
20732069
}
20742070

2075-
createHostAssociateVarClone(*sym, /*skipDefaultInit=*/false);
2071+
createHostAssociateVarClone(*symToPrivatize, /*skipDefaultInit=*/false);
20762072
}
20772073

2078-
for (const Fortran::semantics::Symbol *sym : info.localInitSymList) {
2074+
for (const Fortran::semantics::Symbol *symToPrivatize :
2075+
info.localInitSymList) {
20792076
if (useDelayedPriv) {
20802077
Fortran::lower::privatizeSymbol<fir::LocalitySpecifierOp>(
2081-
*this, this->getFirOpBuilder(), localSymbols,
2082-
[this](fir::LocalitySpecifierOp result, mlir::Type argType) {
2083-
TODO(this->toLocation(),
2084-
"Localizers that need init regions are not supported yet.");
2085-
},
2086-
allPrivatizedSymbols, sym, &privateClauseOps);
2078+
*this, this->getFirOpBuilder(), localSymbols, allPrivatizedSymbols,
2079+
mightHaveReadHostSym, symToPrivatize, &privateClauseOps);
20872080
continue;
20882081
}
20892082

2090-
createHostAssociateVarClone(*sym, /*skipDefaultInit=*/true);
2083+
createHostAssociateVarClone(*symToPrivatize, /*skipDefaultInit=*/true);
20912084
const auto *hostDetails =
2092-
sym->detailsIf<Fortran::semantics::HostAssocDetails>();
2085+
symToPrivatize->detailsIf<Fortran::semantics::HostAssocDetails>();
20932086
assert(hostDetails && "missing locality spec host symbol");
20942087
const Fortran::semantics::Symbol *hostSym = &hostDetails->symbol();
20952088
Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
20962089
Fortran::evaluate::Assignment assign{
2097-
ea.Designate(Fortran::evaluate::DataRef{*sym}).value(),
2090+
ea.Designate(Fortran::evaluate::DataRef{*symToPrivatize}).value(),
20982091
ea.Designate(Fortran::evaluate::DataRef{*hostSym}).value()};
2099-
if (Fortran::semantics::IsPointer(*sym))
2092+
if (Fortran::semantics::IsPointer(*symToPrivatize))
21002093
assign.u = Fortran::evaluate::Assignment::BoundsSpec{};
21012094
genAssignment(assign);
21022095
}

flang/lib/Lower/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ add_flang_library(FortranLower
2929
OpenMP/DataSharingProcessor.cpp
3030
OpenMP/Decomposer.cpp
3131
OpenMP/OpenMP.cpp
32-
OpenMP/PrivateReductionUtils.cpp
3332
OpenMP/ReductionProcessor.cpp
3433
OpenMP/Utils.cpp
3534
PFTBuilder.cpp
3635
Runtime.cpp
36+
Support/PrivateReductionUtils.cpp
3737
Support/Utils.cpp
3838
SymbolMap.cpp
3939
VectorSubscripts.cpp

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212

1313
#include "DataSharingProcessor.h"
1414

15-
#include "PrivateReductionUtils.h"
15+
#include "Utils.h"
1616
#include "flang/Lower/ConvertVariable.h"
1717
#include "flang/Lower/OpenMP/Utils.h"
1818
#include "flang/Lower/PFTBuilder.h"
19+
#include "flang/Lower/Support/PrivateReductionUtils.h"
1920
#include "flang/Lower/Support/Utils.h"
2021
#include "flang/Lower/SymbolMap.h"
2122
#include "flang/Optimizer/Builder/BoxValue.h"
@@ -604,38 +605,10 @@ void DataSharingProcessor::privatizeSymbol(
604605
return;
605606
}
606607

607-
auto initGen = [&](mlir::omp::PrivateClauseOp result, mlir::Type argType) {
608-
lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*symToPrivatize);
609-
assert(hsb && "Host symbol box not found");
610-
hlfir::Entity entity{hsb.getAddr()};
611-
bool cannotHaveNonDefaultLowerBounds =
612-
!entity.mayHaveNonDefaultLowerBounds();
613-
614-
mlir::Region &initRegion = result.getInitRegion();
615-
mlir::Location symLoc = hsb.getAddr().getLoc();
616-
mlir::Block *initBlock = firOpBuilder.createBlock(
617-
&initRegion, /*insertPt=*/{}, {argType, argType}, {symLoc, symLoc});
618-
619-
bool emitCopyRegion =
620-
symToPrivatize->test(semantics::Symbol::Flag::OmpFirstPrivate);
621-
622-
populateByRefInitAndCleanupRegions(
623-
converter, symLoc, argType, /*scalarInitValue=*/nullptr, initBlock,
624-
result.getInitPrivateArg(), result.getInitMoldArg(),
625-
result.getDeallocRegion(),
626-
emitCopyRegion ? omp::DeclOperationKind::FirstPrivate
627-
: omp::DeclOperationKind::Private,
628-
symToPrivatize, cannotHaveNonDefaultLowerBounds);
629-
// TODO: currently there are false positives from dead uses of the mold
630-
// arg
631-
if (result.initReadsFromMold())
632-
mightHaveReadHostSym.insert(symToPrivatize);
633-
};
634-
635608
Fortran::lower::privatizeSymbol<mlir::omp::PrivateClauseOp,
636609
mlir::omp::PrivateClauseOps>(
637-
converter, firOpBuilder, symTable, initGen, allPrivatizedSymbols,
638-
symToPrivatize, clauseOps);
610+
converter, firOpBuilder, symTable, allPrivatizedSymbols,
611+
mightHaveReadHostSym, symToPrivatize, clauseOps);
639612
}
640613
} // namespace omp
641614
} // namespace lower

flang/lib/Lower/OpenMP/ReductionProcessor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
#include "ReductionProcessor.h"
1414

15-
#include "PrivateReductionUtils.h"
1615
#include "flang/Lower/AbstractConverter.h"
1716
#include "flang/Lower/ConvertType.h"
17+
#include "flang/Lower/Support/PrivateReductionUtils.h"
1818
#include "flang/Lower/SymbolMap.h"
1919
#include "flang/Optimizer/Builder/Complex.h"
2020
#include "flang/Optimizer/Builder/HLFIRTools.h"

flang/lib/Lower/OpenMP/PrivateReductionUtils.cpp renamed to flang/lib/Lower/Support/PrivateReductionUtils.cpp

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#include "PrivateReductionUtils.h"
13+
#include "flang/Lower/Support/PrivateReductionUtils.h"
1414

1515
#include "flang/Lower/AbstractConverter.h"
1616
#include "flang/Lower/Allocatable.h"
@@ -42,7 +42,8 @@ static bool hasFinalization(const Fortran::semantics::Symbol &sym) {
4242
static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
4343
mlir::Location loc, mlir::Type argType,
4444
mlir::Region &cleanupRegion,
45-
const Fortran::semantics::Symbol *sym) {
45+
const Fortran::semantics::Symbol *sym,
46+
bool isDoConcurrent) {
4647
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
4748
assert(cleanupRegion.empty());
4849
mlir::Block *block = builder.createBlock(&cleanupRegion, cleanupRegion.end(),
@@ -73,7 +74,10 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
7374
fir::MutableBoxValue mutableBox{converted, /*lenParameters=*/{},
7475
/*mutableProperties=*/{}};
7576
Fortran::lower::genDeallocateIfAllocated(converter, mutableBox, loc);
76-
builder.create<mlir::omp::YieldOp>(loc);
77+
if (isDoConcurrent)
78+
builder.create<fir::YieldOp>(loc);
79+
else
80+
builder.create<mlir::omp::YieldOp>(loc);
7781
return;
7882
}
7983
}
@@ -101,7 +105,10 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
101105
builder.create<fir::FreeMemOp>(loc, cast);
102106

103107
builder.setInsertionPointAfter(ifOp);
104-
builder.create<mlir::omp::YieldOp>(loc);
108+
if (isDoConcurrent)
109+
builder.create<fir::YieldOp>(loc);
110+
else
111+
builder.create<mlir::omp::YieldOp>(loc);
105112
return;
106113
}
107114

@@ -116,14 +123,18 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
116123
addr = builder.createConvert(loc, heapTy, addr);
117124

118125
builder.create<fir::FreeMemOp>(loc, addr);
119-
builder.create<mlir::omp::YieldOp>(loc);
126+
if (isDoConcurrent)
127+
builder.create<fir::YieldOp>(loc);
128+
else
129+
builder.create<mlir::omp::YieldOp>(loc);
130+
120131
return;
121132
}
122133

123134
typeError();
124135
}
125136

126-
fir::ShapeShiftOp Fortran::lower::omp::getShapeShift(
137+
fir::ShapeShiftOp Fortran::lower::getShapeShift(
127138
fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value box,
128139
bool cannotHaveNonDefaultLowerBounds, bool useDefaultLowerBounds) {
129140
fir::SequenceType sequenceType = mlir::cast<fir::SequenceType>(
@@ -263,7 +274,7 @@ static mlir::Value generateZeroShapeForRank(fir::FirOpBuilder &builder,
263274
}
264275

265276
namespace {
266-
using namespace Fortran::lower::omp;
277+
using namespace Fortran::lower;
267278
/// Class to store shared data so we don't have to maintain so many function
268279
/// arguments
269280
class PopulateInitAndCleanupRegionsHelper {
@@ -274,12 +285,13 @@ class PopulateInitAndCleanupRegionsHelper {
274285
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
275286
mlir::Block *initBlock, mlir::Region &cleanupRegion,
276287
DeclOperationKind kind, const Fortran::semantics::Symbol *sym,
277-
bool cannotHaveLowerBounds)
288+
bool cannotHaveLowerBounds, bool isDoConcurrent)
278289
: converter{converter}, builder{converter.getFirOpBuilder()}, loc{loc},
279290
argType{argType}, scalarInitValue{scalarInitValue},
280291
allocatedPrivVarArg{allocatedPrivVarArg}, moldArg{moldArg},
281292
initBlock{initBlock}, cleanupRegion{cleanupRegion}, kind{kind},
282-
sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds} {
293+
sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds},
294+
isDoConcurrent{isDoConcurrent} {
283295
valType = fir::unwrapRefType(argType);
284296
}
285297

@@ -325,8 +337,13 @@ class PopulateInitAndCleanupRegionsHelper {
325337
/// lower bounds then we don't need to generate code to read them.
326338
bool cannotHaveNonDefaultLowerBounds;
327339

340+
bool isDoConcurrent;
341+
328342
void createYield(mlir::Value ret) {
329-
builder.create<mlir::omp::YieldOp>(loc, ret);
343+
if (isDoConcurrent)
344+
builder.create<fir::YieldOp>(loc, ret);
345+
else
346+
builder.create<mlir::omp::YieldOp>(loc, ret);
330347
}
331348

332349
void initTrivialType() {
@@ -430,11 +447,12 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedScalar(
430447
/*slice=*/mlir::Value{}, lenParams);
431448
initializeIfDerivedTypeBox(
432449
builder, loc, box, getLoadedMoldArg(), needsInitialization,
433-
/*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivate);
450+
/*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit);
434451
fir::StoreOp lastOp =
435452
builder.create<fir::StoreOp>(loc, box, allocatedPrivVarArg);
436453

437-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
454+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
455+
isDoConcurrent);
438456

439457
if (ifUnallocated)
440458
builder.setInsertionPointAfter(ifUnallocated);
@@ -471,13 +489,14 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
471489
allocatedArray, shape);
472490
initializeIfDerivedTypeBox(
473491
builder, loc, firClass, source, needsInitialization,
474-
/*isFirstprivate=*/kind == DeclOperationKind::FirstPrivate);
492+
/*isFirstprivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit);
475493
builder.create<fir::StoreOp>(loc, firClass, allocatedPrivVarArg);
476494
if (ifUnallocated)
477495
builder.setInsertionPointAfter(ifUnallocated);
478496
createYield(allocatedPrivVarArg);
479497
mlir::OpBuilder::InsertionGuard guard(builder);
480-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
498+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
499+
isDoConcurrent);
481500
return;
482501
}
483502

@@ -502,7 +521,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
502521
"createTempFromMold decides this statically");
503522
if (cstNeedsDealloc.has_value() && *cstNeedsDealloc != false) {
504523
mlir::OpBuilder::InsertionGuard guard(builder);
505-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
524+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
525+
isDoConcurrent);
506526
} else {
507527
assert(!isAllocatableOrPointer &&
508528
"Pointer-like arrays must be heap allocated");
@@ -530,7 +550,7 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
530550

531551
initializeIfDerivedTypeBox(
532552
builder, loc, box, getLoadedMoldArg(), needsInitialization,
533-
/*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivate);
553+
/*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit);
534554

535555
builder.create<fir::StoreOp>(loc, box, allocatedPrivVarArg);
536556
if (ifUnallocated)
@@ -558,7 +578,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxchar(
558578
loc, eleTy, /*name=*/{}, /*shape=*/{}, /*lenParams=*/len);
559579
mlir::Value boxChar = charExprHelper.createEmboxChar(privateAddr, len);
560580

561-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
581+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
582+
isDoConcurrent);
562583

563584
builder.setInsertionPointToEnd(initBlock);
564585
createYield(boxChar);
@@ -573,10 +594,11 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupUnboxedDerivedType(
573594
mlir::Value moldBox = builder.create<fir::EmboxOp>(loc, boxedTy, moldArg);
574595
initializeIfDerivedTypeBox(builder, loc, newBox, moldBox, needsInitialization,
575596
/*isFirstPrivate=*/kind ==
576-
DeclOperationKind::FirstPrivate);
597+
DeclOperationKind::FirstPrivateOrLocalInit);
577598

578599
if (sym && hasFinalization(*sym))
579-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
600+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
601+
isDoConcurrent);
580602

581603
builder.setInsertionPointToEnd(initBlock);
582604
createYield(allocatedPrivVarArg);
@@ -642,15 +664,17 @@ void PopulateInitAndCleanupRegionsHelper::populateByRefInitAndCleanupRegions() {
642664
"creating reduction/privatization init region for unsupported type");
643665
}
644666

645-
void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
667+
void Fortran::lower::populateByRefInitAndCleanupRegions(
646668
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
647669
mlir::Type argType, mlir::Value scalarInitValue, mlir::Block *initBlock,
648670
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
649671
mlir::Region &cleanupRegion, DeclOperationKind kind,
650-
const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds) {
672+
const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds,
673+
bool isDoConcurrent) {
651674
PopulateInitAndCleanupRegionsHelper helper(
652675
converter, loc, argType, scalarInitValue, allocatedPrivVarArg, moldArg,
653-
initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds);
676+
initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds,
677+
isDoConcurrent);
654678
helper.populateByRefInitAndCleanupRegions();
655679

656680
// Often we load moldArg to check something (e.g. length parameters, shape)

0 commit comments

Comments
 (0)