Skip to content

Commit 158901f

Browse files
committed
[flang][OpenMP] Convert DataSharingProcessor to omp::Clause
1 parent 7e785c4 commit 158901f

File tree

3 files changed

+146
-150
lines changed

3 files changed

+146
-150
lines changed

flang/lib/Lower/OpenMP/DataSharingProcessor.cpp

Lines changed: 135 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -79,30 +79,28 @@ void DataSharingProcessor::copyLastPrivateSymbol(
7979
}
8080

8181
void DataSharingProcessor::collectOmpObjectListSymbol(
82-
const Fortran::parser::OmpObjectList &ompObjectList,
82+
const omp::ObjectList &objects,
8383
llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet) {
84-
for (const Fortran::parser::OmpObject &ompObject : ompObjectList.v) {
85-
Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject);
84+
for (const omp::Object &object : objects) {
85+
Fortran::semantics::Symbol *sym = object.id();
8686
symbolSet.insert(sym);
8787
}
8888
}
8989

9090
void DataSharingProcessor::collectSymbolsForPrivatization() {
9191
bool hasCollapse = false;
92-
for (const Fortran::parser::OmpClause &clause : opClauseList.v) {
92+
for (const omp::Clause &clause : clauses) {
9393
if (const auto &privateClause =
94-
std::get_if<Fortran::parser::OmpClause::Private>(&clause.u)) {
94+
std::get_if<omp::clause::Private>(&clause.u)) {
9595
collectOmpObjectListSymbol(privateClause->v, privatizedSymbols);
9696
} else if (const auto &firstPrivateClause =
97-
std::get_if<Fortran::parser::OmpClause::Firstprivate>(
98-
&clause.u)) {
97+
std::get_if<omp::clause::Firstprivate>(&clause.u)) {
9998
collectOmpObjectListSymbol(firstPrivateClause->v, privatizedSymbols);
10099
} else if (const auto &lastPrivateClause =
101-
std::get_if<Fortran::parser::OmpClause::Lastprivate>(
102-
&clause.u)) {
100+
std::get_if<omp::clause::Lastprivate>(&clause.u)) {
103101
collectOmpObjectListSymbol(lastPrivateClause->v, privatizedSymbols);
104102
hasLastPrivateOp = true;
105-
} else if (std::get_if<Fortran::parser::OmpClause::Collapse>(&clause.u)) {
103+
} else if (std::get_if<omp::clause::Collapse>(&clause.u)) {
106104
hasCollapse = true;
107105
}
108106
}
@@ -135,138 +133,135 @@ void DataSharingProcessor::insertBarrier() {
135133
void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {
136134
bool cmpCreated = false;
137135
mlir::OpBuilder::InsertPoint localInsPt = firOpBuilder.saveInsertionPoint();
138-
for (const Fortran::parser::OmpClause &clause : opClauseList.v) {
139-
if (std::get_if<Fortran::parser::OmpClause::Lastprivate>(&clause.u)) {
140-
// TODO: Add lastprivate support for simd construct
141-
if (mlir::isa<mlir::omp::SectionOp>(op)) {
142-
if (&eval == &eval.parentConstruct->getLastNestedEvaluation()) {
143-
// For `omp.sections`, lastprivatized variables occur in
144-
// lexically final `omp.section` operation. The following FIR
145-
// shall be generated for the same:
146-
//
147-
// omp.sections lastprivate(...) {
148-
// omp.section {...}
149-
// omp.section {...}
150-
// omp.section {
151-
// fir.allocate for `private`/`firstprivate`
152-
// <More operations here>
153-
// fir.if %true {
154-
// ^%lpv_update_blk
155-
// }
156-
// }
157-
// }
158-
//
159-
// To keep code consistency while handling privatization
160-
// through this control flow, add a `fir.if` operation
161-
// that always evaluates to true, in order to create
162-
// a dedicated sub-region in `omp.section` where
163-
// lastprivate FIR can reside. Later canonicalizations
164-
// will optimize away this operation.
165-
if (!eval.lowerAsUnstructured()) {
166-
auto ifOp = firOpBuilder.create<fir::IfOp>(
167-
op->getLoc(),
168-
firOpBuilder.createIntegerConstant(
169-
op->getLoc(), firOpBuilder.getIntegerType(1), 0x1),
170-
/*else*/ false);
171-
firOpBuilder.setInsertionPointToStart(
172-
&ifOp.getThenRegion().front());
173-
174-
const Fortran::parser::OpenMPConstruct *parentOmpConstruct =
175-
eval.parentConstruct->getIf<Fortran::parser::OpenMPConstruct>();
176-
assert(parentOmpConstruct &&
177-
"Expected a valid enclosing OpenMP construct");
178-
const Fortran::parser::OpenMPSectionsConstruct *sectionsConstruct =
179-
std::get_if<Fortran::parser::OpenMPSectionsConstruct>(
180-
&parentOmpConstruct->u);
181-
assert(sectionsConstruct &&
182-
"Expected an enclosing omp.sections construct");
183-
const Fortran::parser::OmpClauseList &sectionsEndClauseList =
184-
std::get<Fortran::parser::OmpClauseList>(
185-
std::get<Fortran::parser::OmpEndSectionsDirective>(
186-
sectionsConstruct->t)
187-
.t);
188-
for (const Fortran::parser::OmpClause &otherClause :
189-
sectionsEndClauseList.v)
190-
if (std::get_if<Fortran::parser::OmpClause::Nowait>(
191-
&otherClause.u))
192-
// Emit implicit barrier to synchronize threads and avoid data
193-
// races on post-update of lastprivate variables when `nowait`
194-
// clause is present.
195-
firOpBuilder.create<mlir::omp::BarrierOp>(
196-
converter.getCurrentLocation());
197-
firOpBuilder.setInsertionPointToStart(
198-
&ifOp.getThenRegion().front());
199-
lastPrivIP = firOpBuilder.saveInsertionPoint();
200-
firOpBuilder.setInsertionPoint(ifOp);
201-
insPt = firOpBuilder.saveInsertionPoint();
202-
} else {
203-
// Lastprivate operation is inserted at the end
204-
// of the lexically last section in the sections
205-
// construct
206-
mlir::OpBuilder::InsertPoint unstructuredSectionsIP =
207-
firOpBuilder.saveInsertionPoint();
208-
mlir::Operation *lastOper = op->getRegion(0).back().getTerminator();
209-
firOpBuilder.setInsertionPoint(lastOper);
210-
lastPrivIP = firOpBuilder.saveInsertionPoint();
211-
firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP);
212-
}
213-
}
214-
} else if (mlir::isa<mlir::omp::WsLoopOp>(op)) {
215-
// Update the original variable just before exiting the worksharing
216-
// loop. Conversion as follows:
136+
for (const omp::Clause &clause : clauses) {
137+
if (clause.id != llvm::omp::OMPC_lastprivate)
138+
continue;
139+
// TODO: Add lastprivate support for simd construct
140+
if (mlir::isa<mlir::omp::SectionOp>(op)) {
141+
if (&eval == &eval.parentConstruct->getLastNestedEvaluation()) {
142+
// For `omp.sections`, lastprivatized variables occur in
143+
// lexically final `omp.section` operation. The following FIR
144+
// shall be generated for the same:
217145
//
218-
// omp.wsloop {
219-
// omp.wsloop { ...
220-
// ... store
221-
// store ===> %v = arith.addi %iv, %step
222-
// omp.yield %cmp = %step < 0 ? %v < %ub : %v > %ub
223-
// } fir.if %cmp {
224-
// fir.store %v to %loopIV
225-
// ^%lpv_update_blk:
226-
// }
227-
// omp.yield
228-
// }
146+
// omp.sections lastprivate(...) {
147+
// omp.section {...}
148+
// omp.section {...}
149+
// omp.section {
150+
// fir.allocate for `private`/`firstprivate`
151+
// <More operations here>
152+
// fir.if %true {
153+
// ^%lpv_update_blk
154+
// }
155+
// }
156+
// }
229157
//
158+
// To keep code consistency while handling privatization
159+
// through this control flow, add a `fir.if` operation
160+
// that always evaluates to true, in order to create
161+
// a dedicated sub-region in `omp.section` where
162+
// lastprivate FIR can reside. Later canonicalizations
163+
// will optimize away this operation.
164+
if (!eval.lowerAsUnstructured()) {
165+
auto ifOp = firOpBuilder.create<fir::IfOp>(
166+
op->getLoc(),
167+
firOpBuilder.createIntegerConstant(
168+
op->getLoc(), firOpBuilder.getIntegerType(1), 0x1),
169+
/*else*/ false);
170+
firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front());
230171

231-
// Only generate the compare once in presence of multiple LastPrivate
232-
// clauses.
233-
if (cmpCreated)
234-
continue;
235-
cmpCreated = true;
172+
const Fortran::parser::OpenMPConstruct *parentOmpConstruct =
173+
eval.parentConstruct->getIf<Fortran::parser::OpenMPConstruct>();
174+
assert(parentOmpConstruct &&
175+
"Expected a valid enclosing OpenMP construct");
176+
const Fortran::parser::OpenMPSectionsConstruct *sectionsConstruct =
177+
std::get_if<Fortran::parser::OpenMPSectionsConstruct>(
178+
&parentOmpConstruct->u);
179+
assert(sectionsConstruct &&
180+
"Expected an enclosing omp.sections construct");
181+
const Fortran::parser::OmpClauseList &sectionsEndClauseList =
182+
std::get<Fortran::parser::OmpClauseList>(
183+
std::get<Fortran::parser::OmpEndSectionsDirective>(
184+
sectionsConstruct->t)
185+
.t);
186+
for (const Fortran::parser::OmpClause &otherClause :
187+
sectionsEndClauseList.v)
188+
if (std::get_if<Fortran::parser::OmpClause::Nowait>(&otherClause.u))
189+
// Emit implicit barrier to synchronize threads and avoid data
190+
// races on post-update of lastprivate variables when `nowait`
191+
// clause is present.
192+
firOpBuilder.create<mlir::omp::BarrierOp>(
193+
converter.getCurrentLocation());
194+
firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front());
195+
lastPrivIP = firOpBuilder.saveInsertionPoint();
196+
firOpBuilder.setInsertionPoint(ifOp);
197+
insPt = firOpBuilder.saveInsertionPoint();
198+
} else {
199+
// Lastprivate operation is inserted at the end
200+
// of the lexically last section in the sections
201+
// construct
202+
mlir::OpBuilder::InsertPoint unstructuredSectionsIP =
203+
firOpBuilder.saveInsertionPoint();
204+
mlir::Operation *lastOper = op->getRegion(0).back().getTerminator();
205+
firOpBuilder.setInsertionPoint(lastOper);
206+
lastPrivIP = firOpBuilder.saveInsertionPoint();
207+
firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP);
208+
}
209+
}
210+
} else if (mlir::isa<mlir::omp::WsLoopOp>(op)) {
211+
// Update the original variable just before exiting the worksharing
212+
// loop. Conversion as follows:
213+
//
214+
// omp.wsloop {
215+
// omp.wsloop { ...
216+
// ... store
217+
// store ===> %v = arith.addi %iv, %step
218+
// omp.yield %cmp = %step < 0 ? %v < %ub : %v > %ub
219+
// } fir.if %cmp {
220+
// fir.store %v to %loopIV
221+
// ^%lpv_update_blk:
222+
// }
223+
// omp.yield
224+
// }
225+
//
236226

237-
mlir::Location loc = op->getLoc();
238-
mlir::Operation *lastOper = op->getRegion(0).back().getTerminator();
239-
firOpBuilder.setInsertionPoint(lastOper);
227+
// Only generate the compare once in presence of multiple LastPrivate
228+
// clauses.
229+
if (cmpCreated)
230+
continue;
231+
cmpCreated = true;
240232

241-
mlir::Value iv = op->getRegion(0).front().getArguments()[0];
242-
mlir::Value ub =
243-
mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getUpperBound()[0];
244-
mlir::Value step = mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getStep()[0];
233+
mlir::Location loc = op->getLoc();
234+
mlir::Operation *lastOper = op->getRegion(0).back().getTerminator();
235+
firOpBuilder.setInsertionPoint(lastOper);
245236

246-
// v = iv + step
247-
// cmp = step < 0 ? v < ub : v > ub
248-
mlir::Value v = firOpBuilder.create<mlir::arith::AddIOp>(loc, iv, step);
249-
mlir::Value zero =
250-
firOpBuilder.createIntegerConstant(loc, step.getType(), 0);
251-
mlir::Value negativeStep = firOpBuilder.create<mlir::arith::CmpIOp>(
252-
loc, mlir::arith::CmpIPredicate::slt, step, zero);
253-
mlir::Value vLT = firOpBuilder.create<mlir::arith::CmpIOp>(
254-
loc, mlir::arith::CmpIPredicate::slt, v, ub);
255-
mlir::Value vGT = firOpBuilder.create<mlir::arith::CmpIOp>(
256-
loc, mlir::arith::CmpIPredicate::sgt, v, ub);
257-
mlir::Value cmpOp = firOpBuilder.create<mlir::arith::SelectOp>(
258-
loc, negativeStep, vLT, vGT);
237+
mlir::Value iv = op->getRegion(0).front().getArguments()[0];
238+
mlir::Value ub =
239+
mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getUpperBound()[0];
240+
mlir::Value step = mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getStep()[0];
259241

260-
auto ifOp = firOpBuilder.create<fir::IfOp>(loc, cmpOp, /*else*/ false);
261-
firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front());
262-
assert(loopIV && "loopIV was not set");
263-
firOpBuilder.create<fir::StoreOp>(op->getLoc(), v, loopIV);
264-
lastPrivIP = firOpBuilder.saveInsertionPoint();
265-
} else {
266-
TODO(converter.getCurrentLocation(),
267-
"lastprivate clause in constructs other than "
268-
"simd/worksharing-loop");
269-
}
242+
// v = iv + step
243+
// cmp = step < 0 ? v < ub : v > ub
244+
mlir::Value v = firOpBuilder.create<mlir::arith::AddIOp>(loc, iv, step);
245+
mlir::Value zero =
246+
firOpBuilder.createIntegerConstant(loc, step.getType(), 0);
247+
mlir::Value negativeStep = firOpBuilder.create<mlir::arith::CmpIOp>(
248+
loc, mlir::arith::CmpIPredicate::slt, step, zero);
249+
mlir::Value vLT = firOpBuilder.create<mlir::arith::CmpIOp>(
250+
loc, mlir::arith::CmpIPredicate::slt, v, ub);
251+
mlir::Value vGT = firOpBuilder.create<mlir::arith::CmpIOp>(
252+
loc, mlir::arith::CmpIPredicate::sgt, v, ub);
253+
mlir::Value cmpOp = firOpBuilder.create<mlir::arith::SelectOp>(
254+
loc, negativeStep, vLT, vGT);
255+
256+
auto ifOp = firOpBuilder.create<fir::IfOp>(loc, cmpOp, /*else*/ false);
257+
firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front());
258+
assert(loopIV && "loopIV was not set");
259+
firOpBuilder.create<fir::StoreOp>(op->getLoc(), v, loopIV);
260+
lastPrivIP = firOpBuilder.saveInsertionPoint();
261+
} else {
262+
TODO(converter.getCurrentLocation(),
263+
"lastprivate clause in constructs other than "
264+
"simd/worksharing-loop");
270265
}
271266
}
272267
firOpBuilder.restoreInsertionPoint(localInsPt);
@@ -290,14 +285,12 @@ void DataSharingProcessor::collectSymbols(
290285
}
291286

292287
void DataSharingProcessor::collectDefaultSymbols() {
293-
for (const Fortran::parser::OmpClause &clause : opClauseList.v) {
294-
if (const auto &defaultClause =
295-
std::get_if<Fortran::parser::OmpClause::Default>(&clause.u)) {
296-
if (defaultClause->v.v ==
297-
Fortran::parser::OmpDefaultClause::Type::Private)
288+
for (const omp::Clause &clause : clauses) {
289+
if (const auto *defaultClause =
290+
std::get_if<omp::clause::Default>(&clause.u)) {
291+
if (defaultClause->v == omp::clause::Default::Type::Private)
298292
collectSymbols(Fortran::semantics::Symbol::Flag::OmpPrivate);
299-
else if (defaultClause->v.v ==
300-
Fortran::parser::OmpDefaultClause::Type::Firstprivate)
293+
else if (defaultClause->v == omp::clause::Default::Type::Firstprivate)
301294
collectSymbols(Fortran::semantics::Symbol::Flag::OmpFirstPrivate);
302295
}
303296
}

flang/lib/Lower/OpenMP/DataSharingProcessor.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#ifndef FORTRAN_LOWER_DATASHARINGPROCESSOR_H
1313
#define FORTRAN_LOWER_DATASHARINGPROCESSOR_H
1414

15+
#include "Clauses.h"
1516
#include "flang/Lower/AbstractConverter.h"
1617
#include "flang/Lower/OpenMP.h"
1718
#include "flang/Optimizer/Builder/FIRBuilder.h"
@@ -33,14 +34,15 @@ class DataSharingProcessor {
3334
llvm::SetVector<const Fortran::semantics::Symbol *> symbolsInNestedRegions;
3435
llvm::SetVector<const Fortran::semantics::Symbol *> symbolsInParentRegions;
3536
Fortran::lower::AbstractConverter &converter;
37+
Fortran::semantics::SemanticsContext &semaCtx;
3638
fir::FirOpBuilder &firOpBuilder;
37-
const Fortran::parser::OmpClauseList &opClauseList;
39+
omp::List<omp::Clause> clauses;
3840
Fortran::lower::pft::Evaluation &eval;
3941

4042
bool needBarrier();
4143
void collectSymbols(Fortran::semantics::Symbol::Flag flag);
4244
void collectOmpObjectListSymbol(
43-
const Fortran::parser::OmpObjectList &ompObjectList,
45+
const omp::ObjectList &objects,
4446
llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet);
4547
void collectSymbolsForPrivatization();
4648
void insertBarrier();
@@ -57,11 +59,12 @@ class DataSharingProcessor {
5759

5860
public:
5961
DataSharingProcessor(Fortran::lower::AbstractConverter &converter,
62+
Fortran::semantics::SemanticsContext &semaCtx,
6063
const Fortran::parser::OmpClauseList &opClauseList,
6164
Fortran::lower::pft::Evaluation &eval)
62-
: hasLastPrivateOp(false), converter(converter),
63-
firOpBuilder(converter.getFirOpBuilder()), opClauseList(opClauseList),
64-
eval(eval) {}
65+
: hasLastPrivateOp(false), converter(converter), semaCtx(semaCtx),
66+
firOpBuilder(converter.getFirOpBuilder()),
67+
clauses(omp::makeList(opClauseList, semaCtx)), eval(eval) {}
6568
// Privatisation is split into two steps.
6669
// Step1 performs cloning of all privatisation clauses and copying for
6770
// firstprivates. Step1 is performed at the place where process/processStep1

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) {
372372
std::optional<DataSharingProcessor> tempDsp;
373373
if (privatize) {
374374
if (!info.dsp) {
375-
tempDsp.emplace(info.converter, *info.clauses, info.eval);
375+
tempDsp.emplace(info.converter, info.semaCtx, *info.clauses, info.eval);
376376
tempDsp->processStep1();
377377
}
378378
}
@@ -1383,7 +1383,7 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
13831383
const Fortran::parser::OmpClauseList &loopOpClauseList,
13841384
mlir::Location loc) {
13851385
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1386-
DataSharingProcessor dsp(converter, loopOpClauseList, eval);
1386+
DataSharingProcessor dsp(converter, semaCtx, loopOpClauseList, eval);
13871387
dsp.processStep1();
13881388

13891389
Fortran::lower::StatementContext stmtCtx;
@@ -1439,7 +1439,7 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter,
14391439
const Fortran::parser::OmpClauseList *endClauseList,
14401440
mlir::Location loc) {
14411441
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
1442-
DataSharingProcessor dsp(converter, beginClauseList, eval);
1442+
DataSharingProcessor dsp(converter, semaCtx, beginClauseList, eval);
14431443
dsp.processStep1();
14441444

14451445
Fortran::lower::StatementContext stmtCtx;

0 commit comments

Comments
 (0)