Skip to content

Commit 78eac46

Browse files
authored
[Flang][OpenMP][Lower] Use clause operand structures (#86802)
This patch updates Flang lowering to use the new set of OpenMP clause operand structures and their groupings into directive-specific sets of clause operands. It simplifies the passing of information from the clause processor and the creation of operations. The `DataSharingProcessor` is slightly modified to not hold delayed privatization state. Instead, optional arguments are added to `processStep1` which are only passed when delayed privatization is used. This enables using the clause operand structure for `private` and removes the need for the ad-hoc `DelayedPrivatizationInfo` structure. The processing of the `schedule` clause is updated to process the `chunk` modifier rather than requiring two separate calls to the `ClauseProcessor`. Lowering of a block-associated `ordered` construct is updated to emit a TODO error if the `simd` clause is specified, since it is not currently supported by the `ClauseProcessor` or later compilation stages. Removed processing of `schedule` from `omp.simdloop`, as it doesn't apply to `simd` constructs.
1 parent 8c0f52e commit 78eac46

File tree

8 files changed

+459
-562
lines changed

8 files changed

+459
-562
lines changed

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 134 additions & 139 deletions
Large diffs are not rendered by default.

flang/lib/Lower/OpenMP/ClauseProcessor.h

Lines changed: 49 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ namespace omp {
3737
/// corresponding clause if it is present in the clause list. Otherwise, they
3838
/// will return `false` to signal that the clause was not found.
3939
///
40-
/// The intended use is of this class is to move clause processing outside of
40+
/// The intended use of this class is to move clause processing outside of
4141
/// construct processing, since the same clauses can appear attached to
4242
/// different constructs and constructs can be combined, so that code
4343
/// duplication is minimized.
@@ -56,61 +56,51 @@ class ClauseProcessor {
5656
// 'Unique' clauses: They can appear at most once in the clause list.
5757
bool processCollapse(
5858
mlir::Location currentLocation, Fortran::lower::pft::Evaluation &eval,
59-
llvm::SmallVectorImpl<mlir::Value> &lowerBound,
60-
llvm::SmallVectorImpl<mlir::Value> &upperBound,
61-
llvm::SmallVectorImpl<mlir::Value> &step,
59+
mlir::omp::CollapseClauseOps &result,
6260
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> &iv) const;
6361
bool processDefault() const;
6462
bool processDevice(Fortran::lower::StatementContext &stmtCtx,
65-
mlir::Value &result) const;
66-
bool processDeviceType(mlir::omp::DeclareTargetDeviceType &result) const;
63+
mlir::omp::DeviceClauseOps &result) const;
64+
bool processDeviceType(mlir::omp::DeviceTypeClauseOps &result) const;
6765
bool processFinal(Fortran::lower::StatementContext &stmtCtx,
68-
mlir::Value &result) const;
66+
mlir::omp::FinalClauseOps &result) const;
6967
bool
70-
processHasDeviceAddr(llvm::SmallVectorImpl<mlir::Value> &operands,
68+
processHasDeviceAddr(mlir::omp::HasDeviceAddrClauseOps &result,
7169
llvm::SmallVectorImpl<mlir::Type> &isDeviceTypes,
7270
llvm::SmallVectorImpl<mlir::Location> &isDeviceLocs,
7371
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
7472
&isDeviceSymbols) const;
75-
bool processHint(mlir::IntegerAttr &result) const;
76-
bool processMergeable(mlir::UnitAttr &result) const;
77-
bool processNowait(mlir::UnitAttr &result) const;
73+
bool processHint(mlir::omp::HintClauseOps &result) const;
74+
bool processMergeable(mlir::omp::MergeableClauseOps &result) const;
75+
bool processNowait(mlir::omp::NowaitClauseOps &result) const;
7876
bool processNumTeams(Fortran::lower::StatementContext &stmtCtx,
79-
mlir::Value &result) const;
77+
mlir::omp::NumTeamsClauseOps &result) const;
8078
bool processNumThreads(Fortran::lower::StatementContext &stmtCtx,
81-
mlir::Value &result) const;
82-
bool processOrdered(mlir::IntegerAttr &result) const;
79+
mlir::omp::NumThreadsClauseOps &result) const;
80+
bool processOrdered(mlir::omp::OrderedClauseOps &result) const;
8381
bool processPriority(Fortran::lower::StatementContext &stmtCtx,
84-
mlir::Value &result) const;
85-
bool processProcBind(mlir::omp::ClauseProcBindKindAttr &result) const;
86-
bool processSafelen(mlir::IntegerAttr &result) const;
87-
bool processSchedule(mlir::omp::ClauseScheduleKindAttr &valAttr,
88-
mlir::omp::ScheduleModifierAttr &modifierAttr,
89-
mlir::UnitAttr &simdModifierAttr) const;
90-
bool processScheduleChunk(Fortran::lower::StatementContext &stmtCtx,
91-
mlir::Value &result) const;
92-
bool processSimdlen(mlir::IntegerAttr &result) const;
82+
mlir::omp::PriorityClauseOps &result) const;
83+
bool processProcBind(mlir::omp::ProcBindClauseOps &result) const;
84+
bool processSafelen(mlir::omp::SafelenClauseOps &result) const;
85+
bool processSchedule(Fortran::lower::StatementContext &stmtCtx,
86+
mlir::omp::ScheduleClauseOps &result) const;
87+
bool processSimdlen(mlir::omp::SimdlenClauseOps &result) const;
9388
bool processThreadLimit(Fortran::lower::StatementContext &stmtCtx,
94-
mlir::Value &result) const;
95-
bool processUntied(mlir::UnitAttr &result) const;
89+
mlir::omp::ThreadLimitClauseOps &result) const;
90+
bool processUntied(mlir::omp::UntiedClauseOps &result) const;
9691

9792
// 'Repeatable' clauses: They can appear multiple times in the clause list.
98-
bool
99-
processAllocate(llvm::SmallVectorImpl<mlir::Value> &allocatorOperands,
100-
llvm::SmallVectorImpl<mlir::Value> &allocateOperands) const;
93+
bool processAllocate(mlir::omp::AllocateClauseOps &result) const;
10194
bool processCopyin() const;
102-
bool processCopyPrivate(
103-
mlir::Location currentLocation,
104-
llvm::SmallVectorImpl<mlir::Value> &copyPrivateVars,
105-
llvm::SmallVectorImpl<mlir::Attribute> &copyPrivateFuncs) const;
106-
bool processDepend(llvm::SmallVectorImpl<mlir::Attribute> &dependTypeOperands,
107-
llvm::SmallVectorImpl<mlir::Value> &dependOperands) const;
95+
bool processCopyprivate(mlir::Location currentLocation,
96+
mlir::omp::CopyprivateClauseOps &result) const;
97+
bool processDepend(mlir::omp::DependClauseOps &result) const;
10898
bool
10999
processEnter(llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const;
110100
bool processIf(omp::clause::If::DirectiveNameModifier directiveName,
111-
mlir::Value &result) const;
101+
mlir::omp::IfClauseOps &result) const;
112102
bool
113-
processIsDevicePtr(llvm::SmallVectorImpl<mlir::Value> &operands,
103+
processIsDevicePtr(mlir::omp::IsDevicePtrClauseOps &result,
114104
llvm::SmallVectorImpl<mlir::Type> &isDeviceTypes,
115105
llvm::SmallVectorImpl<mlir::Location> &isDeviceLocs,
116106
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
@@ -119,43 +109,42 @@ class ClauseProcessor {
119109
processLink(llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const;
120110

121111
// This method is used to process a map clause.
122-
// The optional parameters - mapSymTypes, mapSymLocs & mapSymbols are used to
112+
// The optional parameters - mapSymTypes, mapSymLocs & mapSyms are used to
123113
// store the original type, location and Fortran symbol for the map operands.
124114
// They may be used later on to create the block_arguments for some of the
125115
// target directives that require it.
126-
bool processMap(mlir::Location currentLocation,
127-
const llvm::omp::Directive &directive,
128-
Fortran::lower::StatementContext &stmtCtx,
129-
llvm::SmallVectorImpl<mlir::Value> &mapOperands,
130-
llvm::SmallVectorImpl<mlir::Type> *mapSymTypes = nullptr,
131-
llvm::SmallVectorImpl<mlir::Location> *mapSymLocs = nullptr,
132-
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
133-
*mapSymbols = nullptr) const;
134-
bool
135-
processReduction(mlir::Location currentLocation,
136-
llvm::SmallVectorImpl<mlir::Value> &reductionVars,
137-
llvm::SmallVectorImpl<mlir::Type> &reductionTypes,
138-
llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols,
139-
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
140-
*reductionSymbols = nullptr) const;
141-
bool processSectionsReduction(mlir::Location currentLocation) const;
116+
bool processMap(
117+
mlir::Location currentLocation, const llvm::omp::Directive &directive,
118+
Fortran::lower::StatementContext &stmtCtx,
119+
mlir::omp::MapClauseOps &result,
120+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *mapSyms =
121+
nullptr,
122+
llvm::SmallVectorImpl<mlir::Location> *mapSymLocs = nullptr,
123+
llvm::SmallVectorImpl<mlir::Type> *mapSymTypes = nullptr) const;
124+
bool processReduction(
125+
mlir::Location currentLocation, mlir::omp::ReductionClauseOps &result,
126+
llvm::SmallVectorImpl<mlir::Type> *reductionTypes = nullptr,
127+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *reductionSyms =
128+
nullptr) const;
129+
bool processSectionsReduction(mlir::Location currentLocation,
130+
mlir::omp::ReductionClauseOps &result) const;
142131
bool processTo(llvm::SmallVectorImpl<DeclareTargetCapturePair> &result) const;
143132
bool
144-
processUseDeviceAddr(llvm::SmallVectorImpl<mlir::Value> &operands,
133+
processUseDeviceAddr(mlir::omp::UseDeviceClauseOps &result,
145134
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
146135
llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs,
147136
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
148-
&useDeviceSymbols) const;
137+
&useDeviceSyms) const;
149138
bool
150-
processUseDevicePtr(llvm::SmallVectorImpl<mlir::Value> &operands,
139+
processUseDevicePtr(mlir::omp::UseDeviceClauseOps &result,
151140
llvm::SmallVectorImpl<mlir::Type> &useDeviceTypes,
152141
llvm::SmallVectorImpl<mlir::Location> &useDeviceLocs,
153142
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
154-
&useDeviceSymbols) const;
143+
&useDeviceSyms) const;
155144

156145
template <typename T>
157146
bool processMotionClauses(Fortran::lower::StatementContext &stmtCtx,
158-
llvm::SmallVectorImpl<mlir::Value> &mapOperands);
147+
mlir::omp::MapClauseOps &result);
159148

160149
// Call this method for these clauses that should be supported but are not
161150
// implemented yet. It triggers a compilation error if any of the given
@@ -197,7 +186,7 @@ class ClauseProcessor {
197186
template <typename T>
198187
bool ClauseProcessor::processMotionClauses(
199188
Fortran::lower::StatementContext &stmtCtx,
200-
llvm::SmallVectorImpl<mlir::Value> &mapOperands) {
189+
mlir::omp::MapClauseOps &result) {
201190
return findRepeatableClause<T>(
202191
[&](const T &clause, const Fortran::parser::CharBlock &source) {
203192
mlir::Location clauseLocation = converter.genLocation(source);
@@ -239,7 +228,7 @@ bool ClauseProcessor::processMotionClauses(
239228
mapTypeBits),
240229
mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());
241230

242-
mapOperands.push_back(mapOp);
231+
result.mapVars.push_back(mapOp);
243232
}
244233
});
245234
}

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@ namespace Fortran {
2323
namespace lower {
2424
namespace omp {
2525

26-
void DataSharingProcessor::processStep1() {
26+
void DataSharingProcessor::processStep1(
27+
mlir::omp::PrivateClauseOps *clauseOps,
28+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) {
2729
collectSymbolsForPrivatization();
2830
collectDefaultSymbols();
29-
privatize();
30-
defaultPrivatize();
31+
privatize(clauseOps, privateSyms);
32+
defaultPrivatize(clauseOps, privateSyms);
3133
insertBarrier();
3234
}
3335

@@ -299,14 +301,16 @@ void DataSharingProcessor::collectDefaultSymbols() {
299301
}
300302
}
301303

302-
void DataSharingProcessor::privatize() {
304+
void DataSharingProcessor::privatize(
305+
mlir::omp::PrivateClauseOps *clauseOps,
306+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) {
303307
for (const Fortran::semantics::Symbol *sym : privatizedSymbols) {
304308
if (const auto *commonDet =
305309
sym->detailsIf<Fortran::semantics::CommonBlockDetails>()) {
306310
for (const auto &mem : commonDet->objects())
307-
doPrivatize(&*mem);
311+
doPrivatize(&*mem, clauseOps, privateSyms);
308312
} else
309-
doPrivatize(sym);
313+
doPrivatize(sym, clauseOps, privateSyms);
310314
}
311315
}
312316

@@ -323,19 +327,24 @@ void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) {
323327
}
324328
}
325329

326-
void DataSharingProcessor::defaultPrivatize() {
330+
void DataSharingProcessor::defaultPrivatize(
331+
mlir::omp::PrivateClauseOps *clauseOps,
332+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) {
327333
for (const Fortran::semantics::Symbol *sym : defaultSymbols) {
328334
if (!Fortran::semantics::IsProcedure(*sym) &&
329335
!sym->GetUltimate().has<Fortran::semantics::DerivedTypeDetails>() &&
330336
!sym->GetUltimate().has<Fortran::semantics::NamelistDetails>() &&
331337
!symbolsInNestedRegions.contains(sym) &&
332338
!symbolsInParentRegions.contains(sym) &&
333339
!privatizedSymbols.contains(sym))
334-
doPrivatize(sym);
340+
doPrivatize(sym, clauseOps, privateSyms);
335341
}
336342
}
337343

338-
void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
344+
void DataSharingProcessor::doPrivatize(
345+
const Fortran::semantics::Symbol *sym,
346+
mlir::omp::PrivateClauseOps *clauseOps,
347+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms) {
339348
if (!useDelayedPrivatization) {
340349
cloneSymbol(sym);
341350
copyFirstPrivateSymbol(sym);
@@ -419,10 +428,13 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
419428
return result;
420429
}();
421430

422-
delayedPrivatizationInfo.privatizers.push_back(
423-
mlir::SymbolRefAttr::get(privatizerOp));
424-
delayedPrivatizationInfo.originalAddresses.push_back(hsb.getAddr());
425-
delayedPrivatizationInfo.symbols.push_back(sym);
431+
if (clauseOps) {
432+
clauseOps->privatizers.push_back(mlir::SymbolRefAttr::get(privatizerOp));
433+
clauseOps->privateVars.push_back(hsb.getAddr());
434+
}
435+
436+
if (privateSyms)
437+
privateSyms->push_back(sym);
426438
}
427439

428440
} // namespace omp

flang/lib/Lower/OpenMP/DataSharingProcessor.h

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,17 @@
1919
#include "flang/Parser/parse-tree.h"
2020
#include "flang/Semantics/symbol.h"
2121

22+
namespace mlir {
23+
namespace omp {
24+
struct PrivateClauseOps;
25+
} // namespace omp
26+
} // namespace mlir
27+
2228
namespace Fortran {
2329
namespace lower {
2430
namespace omp {
2531

2632
class DataSharingProcessor {
27-
public:
28-
/// Collects all the information needed for delayed privatization. This can be
29-
/// used by ops with data-sharing clauses to properly generate their regions
30-
/// (e.g. add region arguments) and map the original SSA values to their
31-
/// corresponding OMP region operands.
32-
struct DelayedPrivatizationInfo {
33-
// The list of symbols referring to delayed privatizer ops (i.e.
34-
// `omp.private` ops).
35-
llvm::SmallVector<mlir::SymbolRefAttr> privatizers;
36-
// SSA values that correspond to "original" values being privatized.
37-
// "Original" here means the SSA value outside the OpenMP region from which
38-
// a clone is created inside the region.
39-
llvm::SmallVector<mlir::Value> originalAddresses;
40-
// Fortran symbols corresponding to the above SSA values.
41-
llvm::SmallVector<const Fortran::semantics::Symbol *> symbols;
42-
};
43-
4433
private:
4534
bool hasLastPrivateOp;
4635
mlir::OpBuilder::InsertPoint lastPrivIP;
@@ -57,7 +46,6 @@ class DataSharingProcessor {
5746
Fortran::lower::pft::Evaluation &eval;
5847
bool useDelayedPrivatization;
5948
Fortran::lower::SymMap *symTable;
60-
DelayedPrivatizationInfo delayedPrivatizationInfo;
6149

6250
bool needBarrier();
6351
void collectSymbols(Fortran::semantics::Symbol::Flag flag);
@@ -67,9 +55,16 @@ class DataSharingProcessor {
6755
void collectSymbolsForPrivatization();
6856
void insertBarrier();
6957
void collectDefaultSymbols();
70-
void privatize();
71-
void defaultPrivatize();
72-
void doPrivatize(const Fortran::semantics::Symbol *sym);
58+
void privatize(
59+
mlir::omp::PrivateClauseOps *clauseOps,
60+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms);
61+
void defaultPrivatize(
62+
mlir::omp::PrivateClauseOps *clauseOps,
63+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms);
64+
void doPrivatize(
65+
const Fortran::semantics::Symbol *sym,
66+
mlir::omp::PrivateClauseOps *clauseOps,
67+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *privateSyms);
7368
void copyLastPrivatize(mlir::Operation *op);
7469
void insertLastPrivateCompare(mlir::Operation *op);
7570
void cloneSymbol(const Fortran::semantics::Symbol *sym);
@@ -103,17 +98,15 @@ class DataSharingProcessor {
10398
// Step2 performs the copying for lastprivates and requires knowledge of the
10499
// MLIR operation to insert the last private update. Step2 adds
105100
// dealocation code as well.
106-
void processStep1();
101+
void processStep1(mlir::omp::PrivateClauseOps *clauseOps = nullptr,
102+
llvm::SmallVectorImpl<const Fortran::semantics::Symbol *>
103+
*privateSyms = nullptr);
107104
void processStep2(mlir::Operation *op, bool isLoop);
108105

109106
void setLoopIV(mlir::Value iv) {
110107
assert(!loopIV && "Loop iteration variable already set");
111108
loopIV = iv;
112109
}
113-
114-
const DelayedPrivatizationInfo &getDelayedPrivatizationInfo() const {
115-
return delayedPrivatizationInfo;
116-
}
117110
};
118111

119112
} // namespace omp

0 commit comments

Comments
 (0)