Skip to content

Commit 8c8d15a

Browse files
committed
[flang] Extend localization support for do concurrent (init regions)
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 6fe62e9 commit 8c8d15a

File tree

10 files changed

+163
-117
lines changed

10 files changed

+163
-117
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"
@@ -2038,44 +2037,38 @@ class FirConverter : public Fortran::lower::AbstractConverter {
20382037
bool useDelayedPriv =
20392038
enableDelayedPrivatizationStaging && doConcurrentLoopOp;
20402039
llvm::SetVector<const Fortran::semantics::Symbol *> allPrivatizedSymbols;
2040+
llvm::SmallSet<const Fortran::semantics::Symbol *, 16> mightHaveReadHostSym;
20412041

2042-
for (const Fortran::semantics::Symbol *sym : info.localSymList) {
2042+
for (const Fortran::semantics::Symbol *symToPrivatize : info.localSymList) {
20432043
if (useDelayedPriv) {
20442044
Fortran::lower::privatizeSymbol<fir::LocalitySpecifierOp>(
2045-
*this, this->getFirOpBuilder(), localSymbols,
2046-
[this](fir::LocalitySpecifierOp result, mlir::Type argType) {
2047-
TODO(this->toLocation(),
2048-
"Localizers that need init regions are not supported yet.");
2049-
},
2050-
allPrivatizedSymbols, sym, &privateClauseOps);
2045+
*this, this->getFirOpBuilder(), localSymbols, allPrivatizedSymbols,
2046+
mightHaveReadHostSym, symToPrivatize, &privateClauseOps);
20512047
continue;
20522048
}
20532049

2054-
createHostAssociateVarClone(*sym, /*skipDefaultInit=*/false);
2050+
createHostAssociateVarClone(*symToPrivatize, /*skipDefaultInit=*/false);
20552051
}
20562052

2057-
for (const Fortran::semantics::Symbol *sym : info.localInitSymList) {
2053+
for (const Fortran::semantics::Symbol *symToPrivatize :
2054+
info.localInitSymList) {
20582055
if (useDelayedPriv) {
20592056
Fortran::lower::privatizeSymbol<fir::LocalitySpecifierOp>(
2060-
*this, this->getFirOpBuilder(), localSymbols,
2061-
[this](fir::LocalitySpecifierOp result, mlir::Type argType) {
2062-
TODO(this->toLocation(),
2063-
"Localizers that need init regions are not supported yet.");
2064-
},
2065-
allPrivatizedSymbols, sym, &privateClauseOps);
2057+
*this, this->getFirOpBuilder(), localSymbols, allPrivatizedSymbols,
2058+
mightHaveReadHostSym, symToPrivatize, &privateClauseOps);
20662059
continue;
20672060
}
20682061

2069-
createHostAssociateVarClone(*sym, /*skipDefaultInit=*/true);
2062+
createHostAssociateVarClone(*symToPrivatize, /*skipDefaultInit=*/true);
20702063
const auto *hostDetails =
2071-
sym->detailsIf<Fortran::semantics::HostAssocDetails>();
2064+
symToPrivatize->detailsIf<Fortran::semantics::HostAssocDetails>();
20722065
assert(hostDetails && "missing locality spec host symbol");
20732066
const Fortran::semantics::Symbol *hostSym = &hostDetails->symbol();
20742067
Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
20752068
Fortran::evaluate::Assignment assign{
2076-
ea.Designate(Fortran::evaluate::DataRef{*sym}).value(),
2069+
ea.Designate(Fortran::evaluate::DataRef{*symToPrivatize}).value(),
20772070
ea.Designate(Fortran::evaluate::DataRef{*hostSym}).value()};
2078-
if (Fortran::semantics::IsPointer(*sym))
2071+
if (Fortran::semantics::IsPointer(*symToPrivatize))
20792072
assign.u = Fortran::evaluate::Assignment::BoundsSpec{};
20802073
genAssignment(assign);
20812074
}

flang/lib/Lower/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ add_flang_library(FortranLower
2828
OpenMP/DataSharingProcessor.cpp
2929
OpenMP/Decomposer.cpp
3030
OpenMP/OpenMP.cpp
31-
OpenMP/PrivateReductionUtils.cpp
3231
OpenMP/ReductionProcessor.cpp
3332
OpenMP/Utils.cpp
3433
PFTBuilder.cpp
3534
Runtime.cpp
35+
Support/PrivateReductionUtils.cpp
3636
Support/Utils.cpp
3737
SymbolMap.cpp
3838
VectorSubscripts.cpp

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

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

1313
#include "DataSharingProcessor.h"
1414

15-
#include "PrivateReductionUtils.h"
1615
#include "Utils.h"
1716
#include "flang/Lower/ConvertVariable.h"
1817
#include "flang/Lower/PFTBuilder.h"
18+
#include "flang/Lower/Support/PrivateReductionUtils.h"
1919
#include "flang/Lower/Support/Utils.h"
2020
#include "flang/Lower/SymbolMap.h"
2121
#include "flang/Optimizer/Builder/BoxValue.h"
@@ -537,38 +537,10 @@ void DataSharingProcessor::privatizeSymbol(
537537
return;
538538
}
539539

540-
auto initGen = [&](mlir::omp::PrivateClauseOp result, mlir::Type argType) {
541-
lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*symToPrivatize);
542-
assert(hsb && "Host symbol box not found");
543-
hlfir::Entity entity{hsb.getAddr()};
544-
bool cannotHaveNonDefaultLowerBounds =
545-
!entity.mayHaveNonDefaultLowerBounds();
546-
547-
mlir::Region &initRegion = result.getInitRegion();
548-
mlir::Location symLoc = hsb.getAddr().getLoc();
549-
mlir::Block *initBlock = firOpBuilder.createBlock(
550-
&initRegion, /*insertPt=*/{}, {argType, argType}, {symLoc, symLoc});
551-
552-
bool emitCopyRegion =
553-
symToPrivatize->test(semantics::Symbol::Flag::OmpFirstPrivate);
554-
555-
populateByRefInitAndCleanupRegions(
556-
converter, symLoc, argType, /*scalarInitValue=*/nullptr, initBlock,
557-
result.getInitPrivateArg(), result.getInitMoldArg(),
558-
result.getDeallocRegion(),
559-
emitCopyRegion ? omp::DeclOperationKind::FirstPrivate
560-
: omp::DeclOperationKind::Private,
561-
symToPrivatize, cannotHaveNonDefaultLowerBounds);
562-
// TODO: currently there are false positives from dead uses of the mold
563-
// arg
564-
if (result.initReadsFromMold())
565-
mightHaveReadHostSym.insert(symToPrivatize);
566-
};
567-
568540
Fortran::lower::privatizeSymbol<mlir::omp::PrivateClauseOp,
569541
mlir::omp::PrivateClauseOps>(
570-
converter, firOpBuilder, symTable, initGen, allPrivatizedSymbols,
571-
symToPrivatize, clauseOps);
542+
converter, firOpBuilder, symTable, allPrivatizedSymbols,
543+
mightHaveReadHostSym, symToPrivatize, clauseOps);
572544
}
573545
} // namespace omp
574546
} // 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(),
@@ -72,7 +73,10 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
7273
fir::MutableBoxValue mutableBox{converted, /*lenParameters=*/{},
7374
/*mutableProperties=*/{}};
7475
Fortran::lower::genDeallocateIfAllocated(converter, mutableBox, loc);
75-
builder.create<mlir::omp::YieldOp>(loc);
76+
if (isDoConcurrent)
77+
builder.create<fir::YieldOp>(loc);
78+
else
79+
builder.create<mlir::omp::YieldOp>(loc);
7680
return;
7781
}
7882
}
@@ -100,7 +104,10 @@ static void createCleanupRegion(Fortran::lower::AbstractConverter &converter,
100104
builder.create<fir::FreeMemOp>(loc, cast);
101105

102106
builder.setInsertionPointAfter(ifOp);
103-
builder.create<mlir::omp::YieldOp>(loc);
107+
if (isDoConcurrent)
108+
builder.create<fir::YieldOp>(loc);
109+
else
110+
builder.create<mlir::omp::YieldOp>(loc);
104111
return;
105112
}
106113

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

117124
builder.create<fir::FreeMemOp>(loc, addr);
118-
builder.create<mlir::omp::YieldOp>(loc);
125+
if (isDoConcurrent)
126+
builder.create<fir::YieldOp>(loc);
127+
else
128+
builder.create<mlir::omp::YieldOp>(loc);
129+
119130
return;
120131
}
121132

122133
typeError();
123134
}
124135

125-
fir::ShapeShiftOp Fortran::lower::omp::getShapeShift(
136+
fir::ShapeShiftOp Fortran::lower::getShapeShift(
126137
fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value box,
127138
bool cannotHaveNonDefaultLowerBounds, bool useDefaultLowerBounds) {
128139
fir::SequenceType sequenceType = mlir::cast<fir::SequenceType>(
@@ -262,7 +273,7 @@ static mlir::Value generateZeroShapeForRank(fir::FirOpBuilder &builder,
262273
}
263274

264275
namespace {
265-
using namespace Fortran::lower::omp;
276+
using namespace Fortran::lower;
266277
/// Class to store shared data so we don't have to maintain so many function
267278
/// arguments
268279
class PopulateInitAndCleanupRegionsHelper {
@@ -273,12 +284,13 @@ class PopulateInitAndCleanupRegionsHelper {
273284
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
274285
mlir::Block *initBlock, mlir::Region &cleanupRegion,
275286
DeclOperationKind kind, const Fortran::semantics::Symbol *sym,
276-
bool cannotHaveLowerBounds)
287+
bool cannotHaveLowerBounds, bool isDoConcurrent)
277288
: converter{converter}, builder{converter.getFirOpBuilder()}, loc{loc},
278289
argType{argType}, scalarInitValue{scalarInitValue},
279290
allocatedPrivVarArg{allocatedPrivVarArg}, moldArg{moldArg},
280291
initBlock{initBlock}, cleanupRegion{cleanupRegion}, kind{kind},
281-
sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds} {
292+
sym{sym}, cannotHaveNonDefaultLowerBounds{cannotHaveLowerBounds},
293+
isDoConcurrent{isDoConcurrent} {
282294
valType = fir::unwrapRefType(argType);
283295
}
284296

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

339+
bool isDoConcurrent;
340+
327341
void createYield(mlir::Value ret) {
328-
builder.create<mlir::omp::YieldOp>(loc, ret);
342+
if (isDoConcurrent)
343+
builder.create<fir::YieldOp>(loc, ret);
344+
else
345+
builder.create<mlir::omp::YieldOp>(loc, ret);
329346
}
330347

331348
void initTrivialType() {
@@ -429,11 +446,12 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedScalar(
429446
/*slice=*/mlir::Value{}, lenParams);
430447
initializeIfDerivedTypeBox(
431448
builder, loc, box, getLoadedMoldArg(), needsInitialization,
432-
/*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivate);
449+
/*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit);
433450
fir::StoreOp lastOp =
434451
builder.create<fir::StoreOp>(loc, box, allocatedPrivVarArg);
435452

436-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
453+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
454+
isDoConcurrent);
437455

438456
if (ifUnallocated)
439457
builder.setInsertionPointAfter(ifUnallocated);
@@ -470,13 +488,14 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
470488
allocatedArray, shape);
471489
initializeIfDerivedTypeBox(
472490
builder, loc, firClass, source, needsInitialization,
473-
/*isFirstprivate=*/kind == DeclOperationKind::FirstPrivate);
491+
/*isFirstprivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit);
474492
builder.create<fir::StoreOp>(loc, firClass, allocatedPrivVarArg);
475493
if (ifUnallocated)
476494
builder.setInsertionPointAfter(ifUnallocated);
477495
createYield(allocatedPrivVarArg);
478496
mlir::OpBuilder::InsertionGuard guard(builder);
479-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
497+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
498+
isDoConcurrent);
480499
return;
481500
}
482501

@@ -492,7 +511,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
492511
"createTempFromMold decides this statically");
493512
if (cstNeedsDealloc.has_value() && *cstNeedsDealloc != false) {
494513
mlir::OpBuilder::InsertionGuard guard(builder);
495-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
514+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
515+
isDoConcurrent);
496516
} else {
497517
assert(!isAllocatableOrPointer &&
498518
"Pointer-like arrays must be heap allocated");
@@ -520,7 +540,7 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxedArray(
520540

521541
initializeIfDerivedTypeBox(
522542
builder, loc, box, getLoadedMoldArg(), needsInitialization,
523-
/*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivate);
543+
/*isFirstPrivate=*/kind == DeclOperationKind::FirstPrivateOrLocalInit);
524544

525545
builder.create<fir::StoreOp>(loc, box, allocatedPrivVarArg);
526546
if (ifUnallocated)
@@ -548,7 +568,8 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupBoxchar(
548568
loc, eleTy, /*name=*/{}, /*shape=*/{}, /*lenParams=*/len);
549569
mlir::Value boxChar = charExprHelper.createEmboxChar(privateAddr, len);
550570

551-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
571+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
572+
isDoConcurrent);
552573

553574
builder.setInsertionPointToEnd(initBlock);
554575
createYield(boxChar);
@@ -563,10 +584,11 @@ void PopulateInitAndCleanupRegionsHelper::initAndCleanupUnboxedDerivedType(
563584
mlir::Value moldBox = builder.create<fir::EmboxOp>(loc, boxedTy, moldArg);
564585
initializeIfDerivedTypeBox(builder, loc, newBox, moldBox, needsInitialization,
565586
/*isFirstPrivate=*/kind ==
566-
DeclOperationKind::FirstPrivate);
587+
DeclOperationKind::FirstPrivateOrLocalInit);
567588

568589
if (sym && hasFinalization(*sym))
569-
createCleanupRegion(converter, loc, argType, cleanupRegion, sym);
590+
createCleanupRegion(converter, loc, argType, cleanupRegion, sym,
591+
isDoConcurrent);
570592

571593
builder.setInsertionPointToEnd(initBlock);
572594
createYield(allocatedPrivVarArg);
@@ -632,15 +654,17 @@ void PopulateInitAndCleanupRegionsHelper::populateByRefInitAndCleanupRegions() {
632654
"creating reduction/privatization init region for unsupported type");
633655
}
634656

635-
void Fortran::lower::omp::populateByRefInitAndCleanupRegions(
657+
void Fortran::lower::populateByRefInitAndCleanupRegions(
636658
Fortran::lower::AbstractConverter &converter, mlir::Location loc,
637659
mlir::Type argType, mlir::Value scalarInitValue, mlir::Block *initBlock,
638660
mlir::Value allocatedPrivVarArg, mlir::Value moldArg,
639661
mlir::Region &cleanupRegion, DeclOperationKind kind,
640-
const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds) {
662+
const Fortran::semantics::Symbol *sym, bool cannotHaveLowerBounds,
663+
bool isDoConcurrent) {
641664
PopulateInitAndCleanupRegionsHelper helper(
642665
converter, loc, argType, scalarInitValue, allocatedPrivVarArg, moldArg,
643-
initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds);
666+
initBlock, cleanupRegion, kind, sym, cannotHaveLowerBounds,
667+
isDoConcurrent);
644668
helper.populateByRefInitAndCleanupRegions();
645669

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

0 commit comments

Comments
 (0)