Skip to content

Commit 61d3ad3

Browse files
committed
[flang][OpenMP] Convert DataSharingProcessor to omp::Clause
1 parent 1299d51 commit 61d3ad3

File tree

1 file changed

+149
-154
lines changed

1 file changed

+149
-154
lines changed

flang/lib/Lower/OpenMP.cpp

Lines changed: 149 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,14 +1278,15 @@ class DataSharingProcessor {
12781278
llvm::SetVector<const Fortran::semantics::Symbol *> symbolsInNestedRegions;
12791279
llvm::SetVector<const Fortran::semantics::Symbol *> symbolsInParentRegions;
12801280
Fortran::lower::AbstractConverter &converter;
1281+
Fortran::semantics::SemanticsContext &semaCtx;
12811282
fir::FirOpBuilder &firOpBuilder;
1282-
const Fortran::parser::OmpClauseList &opClauseList;
1283+
omp::List<omp::Clause> clauses;
12831284
Fortran::lower::pft::Evaluation &eval;
12841285

12851286
bool needBarrier();
12861287
void collectSymbols(Fortran::semantics::Symbol::Flag flag);
12871288
void collectOmpObjectListSymbol(
1288-
const Fortran::parser::OmpObjectList &ompObjectList,
1289+
const omp::ObjectList &objects,
12891290
llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet);
12901291
void collectSymbolsForPrivatization();
12911292
void insertBarrier();
@@ -1302,11 +1303,12 @@ class DataSharingProcessor {
13021303

13031304
public:
13041305
DataSharingProcessor(Fortran::lower::AbstractConverter &converter,
1306+
Fortran::semantics::SemanticsContext &semaCtx,
13051307
const Fortran::parser::OmpClauseList &opClauseList,
13061308
Fortran::lower::pft::Evaluation &eval)
1307-
: hasLastPrivateOp(false), converter(converter),
1308-
firOpBuilder(converter.getFirOpBuilder()), opClauseList(opClauseList),
1309-
eval(eval) {}
1309+
: hasLastPrivateOp(false), converter(converter), semaCtx(semaCtx),
1310+
firOpBuilder(converter.getFirOpBuilder()),
1311+
clauses(omp::makeList(opClauseList, semaCtx)), eval(eval) {}
13101312
// Privatisation is split into two steps.
13111313
// Step1 performs cloning of all privatisation clauses and copying for
13121314
// firstprivates. Step1 is performed at the place where process/processStep1
@@ -1384,30 +1386,28 @@ void DataSharingProcessor::copyLastPrivateSymbol(
13841386
}
13851387

13861388
void DataSharingProcessor::collectOmpObjectListSymbol(
1387-
const Fortran::parser::OmpObjectList &ompObjectList,
1389+
const omp::ObjectList &objects,
13881390
llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet) {
1389-
for (const Fortran::parser::OmpObject &ompObject : ompObjectList.v) {
1390-
Fortran::semantics::Symbol *sym = getOmpObjectSymbol(ompObject);
1391+
for (const omp::Object &object : objects) {
1392+
Fortran::semantics::Symbol *sym = object.sym;
13911393
symbolSet.insert(sym);
13921394
}
13931395
}
13941396

13951397
void DataSharingProcessor::collectSymbolsForPrivatization() {
13961398
bool hasCollapse = false;
1397-
for (const Fortran::parser::OmpClause &clause : opClauseList.v) {
1399+
for (const omp::Clause &clause : clauses) {
13981400
if (const auto &privateClause =
1399-
std::get_if<Fortran::parser::OmpClause::Private>(&clause.u)) {
1401+
std::get_if<omp::clause::Private>(&clause.u)) {
14001402
collectOmpObjectListSymbol(privateClause->v, privatizedSymbols);
14011403
} else if (const auto &firstPrivateClause =
1402-
std::get_if<Fortran::parser::OmpClause::Firstprivate>(
1403-
&clause.u)) {
1404+
std::get_if<omp::clause::Firstprivate>(&clause.u)) {
14041405
collectOmpObjectListSymbol(firstPrivateClause->v, privatizedSymbols);
14051406
} else if (const auto &lastPrivateClause =
1406-
std::get_if<Fortran::parser::OmpClause::Lastprivate>(
1407-
&clause.u)) {
1407+
std::get_if<omp::clause::Lastprivate>(&clause.u)) {
14081408
collectOmpObjectListSymbol(lastPrivateClause->v, privatizedSymbols);
14091409
hasLastPrivateOp = true;
1410-
} else if (std::get_if<Fortran::parser::OmpClause::Collapse>(&clause.u)) {
1410+
} else if (std::get_if<omp::clause::Collapse>(&clause.u)) {
14111411
hasCollapse = true;
14121412
}
14131413
}
@@ -1440,138 +1440,135 @@ void DataSharingProcessor::insertBarrier() {
14401440
void DataSharingProcessor::insertLastPrivateCompare(mlir::Operation *op) {
14411441
bool cmpCreated = false;
14421442
mlir::OpBuilder::InsertPoint localInsPt = firOpBuilder.saveInsertionPoint();
1443-
for (const Fortran::parser::OmpClause &clause : opClauseList.v) {
1444-
if (std::get_if<Fortran::parser::OmpClause::Lastprivate>(&clause.u)) {
1445-
// TODO: Add lastprivate support for simd construct
1446-
if (mlir::isa<mlir::omp::SectionOp>(op)) {
1447-
if (&eval == &eval.parentConstruct->getLastNestedEvaluation()) {
1448-
// For `omp.sections`, lastprivatized variables occur in
1449-
// lexically final `omp.section` operation. The following FIR
1450-
// shall be generated for the same:
1451-
//
1452-
// omp.sections lastprivate(...) {
1453-
// omp.section {...}
1454-
// omp.section {...}
1455-
// omp.section {
1456-
// fir.allocate for `private`/`firstprivate`
1457-
// <More operations here>
1458-
// fir.if %true {
1459-
// ^%lpv_update_blk
1460-
// }
1461-
// }
1462-
// }
1463-
//
1464-
// To keep code consistency while handling privatization
1465-
// through this control flow, add a `fir.if` operation
1466-
// that always evaluates to true, in order to create
1467-
// a dedicated sub-region in `omp.section` where
1468-
// lastprivate FIR can reside. Later canonicalizations
1469-
// will optimize away this operation.
1470-
if (!eval.lowerAsUnstructured()) {
1471-
auto ifOp = firOpBuilder.create<fir::IfOp>(
1472-
op->getLoc(),
1473-
firOpBuilder.createIntegerConstant(
1474-
op->getLoc(), firOpBuilder.getIntegerType(1), 0x1),
1475-
/*else*/ false);
1476-
firOpBuilder.setInsertionPointToStart(
1477-
&ifOp.getThenRegion().front());
1478-
1479-
const Fortran::parser::OpenMPConstruct *parentOmpConstruct =
1480-
eval.parentConstruct->getIf<Fortran::parser::OpenMPConstruct>();
1481-
assert(parentOmpConstruct &&
1482-
"Expected a valid enclosing OpenMP construct");
1483-
const Fortran::parser::OpenMPSectionsConstruct *sectionsConstruct =
1484-
std::get_if<Fortran::parser::OpenMPSectionsConstruct>(
1485-
&parentOmpConstruct->u);
1486-
assert(sectionsConstruct &&
1487-
"Expected an enclosing omp.sections construct");
1488-
const Fortran::parser::OmpClauseList &sectionsEndClauseList =
1489-
std::get<Fortran::parser::OmpClauseList>(
1490-
std::get<Fortran::parser::OmpEndSectionsDirective>(
1491-
sectionsConstruct->t)
1492-
.t);
1493-
for (const Fortran::parser::OmpClause &otherClause :
1494-
sectionsEndClauseList.v)
1495-
if (std::get_if<Fortran::parser::OmpClause::Nowait>(
1496-
&otherClause.u))
1497-
// Emit implicit barrier to synchronize threads and avoid data
1498-
// races on post-update of lastprivate variables when `nowait`
1499-
// clause is present.
1500-
firOpBuilder.create<mlir::omp::BarrierOp>(
1501-
converter.getCurrentLocation());
1502-
firOpBuilder.setInsertionPointToStart(
1503-
&ifOp.getThenRegion().front());
1504-
lastPrivIP = firOpBuilder.saveInsertionPoint();
1505-
firOpBuilder.setInsertionPoint(ifOp);
1506-
insPt = firOpBuilder.saveInsertionPoint();
1507-
} else {
1508-
// Lastprivate operation is inserted at the end
1509-
// of the lexically last section in the sections
1510-
// construct
1511-
mlir::OpBuilder::InsertPoint unstructuredSectionsIP =
1512-
firOpBuilder.saveInsertionPoint();
1513-
mlir::Operation *lastOper = op->getRegion(0).back().getTerminator();
1514-
firOpBuilder.setInsertionPoint(lastOper);
1515-
lastPrivIP = firOpBuilder.saveInsertionPoint();
1516-
firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP);
1517-
}
1518-
}
1519-
} else if (mlir::isa<mlir::omp::WsLoopOp>(op)) {
1520-
// Update the original variable just before exiting the worksharing
1521-
// loop. Conversion as follows:
1443+
for (const omp::Clause &clause : clauses) {
1444+
if (clause.id != llvm::omp::OMPC_lastprivate)
1445+
continue;
1446+
// TODO: Add lastprivate support for simd construct
1447+
if (mlir::isa<mlir::omp::SectionOp>(op)) {
1448+
if (&eval == &eval.parentConstruct->getLastNestedEvaluation()) {
1449+
// For `omp.sections`, lastprivatized variables occur in
1450+
// lexically final `omp.section` operation. The following FIR
1451+
// shall be generated for the same:
15221452
//
1523-
// omp.wsloop {
1524-
// omp.wsloop { ...
1525-
// ... store
1526-
// store ===> %v = arith.addi %iv, %step
1527-
// omp.yield %cmp = %step < 0 ? %v < %ub : %v > %ub
1528-
// } fir.if %cmp {
1529-
// fir.store %v to %loopIV
1530-
// ^%lpv_update_blk:
1531-
// }
1532-
// omp.yield
1533-
// }
1453+
// omp.sections lastprivate(...) {
1454+
// omp.section {...}
1455+
// omp.section {...}
1456+
// omp.section {
1457+
// fir.allocate for `private`/`firstprivate`
1458+
// <More operations here>
1459+
// fir.if %true {
1460+
// ^%lpv_update_blk
1461+
// }
1462+
// }
1463+
// }
15341464
//
1535-
1536-
// Only generate the compare once in presence of multiple LastPrivate
1537-
// clauses.
1538-
if (cmpCreated)
1539-
continue;
1540-
cmpCreated = true;
1541-
1542-
mlir::Location loc = op->getLoc();
1543-
mlir::Operation *lastOper = op->getRegion(0).back().getTerminator();
1544-
firOpBuilder.setInsertionPoint(lastOper);
1545-
1546-
mlir::Value iv = op->getRegion(0).front().getArguments()[0];
1547-
mlir::Value ub =
1548-
mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getUpperBound()[0];
1549-
mlir::Value step = mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getStep()[0];
1550-
1551-
// v = iv + step
1552-
// cmp = step < 0 ? v < ub : v > ub
1553-
mlir::Value v = firOpBuilder.create<mlir::arith::AddIOp>(loc, iv, step);
1554-
mlir::Value zero =
1555-
firOpBuilder.createIntegerConstant(loc, step.getType(), 0);
1556-
mlir::Value negativeStep = firOpBuilder.create<mlir::arith::CmpIOp>(
1557-
loc, mlir::arith::CmpIPredicate::slt, step, zero);
1558-
mlir::Value vLT = firOpBuilder.create<mlir::arith::CmpIOp>(
1559-
loc, mlir::arith::CmpIPredicate::slt, v, ub);
1560-
mlir::Value vGT = firOpBuilder.create<mlir::arith::CmpIOp>(
1561-
loc, mlir::arith::CmpIPredicate::sgt, v, ub);
1562-
mlir::Value cmpOp = firOpBuilder.create<mlir::arith::SelectOp>(
1563-
loc, negativeStep, vLT, vGT);
1564-
1565-
auto ifOp = firOpBuilder.create<fir::IfOp>(loc, cmpOp, /*else*/ false);
1566-
firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front());
1567-
assert(loopIV && "loopIV was not set");
1568-
firOpBuilder.create<fir::StoreOp>(op->getLoc(), v, loopIV);
1569-
lastPrivIP = firOpBuilder.saveInsertionPoint();
1570-
} else {
1571-
TODO(converter.getCurrentLocation(),
1572-
"lastprivate clause in constructs other than "
1573-
"simd/worksharing-loop");
1465+
// To keep code consistency while handling privatization
1466+
// through this control flow, add a `fir.if` operation
1467+
// that always evaluates to true, in order to create
1468+
// a dedicated sub-region in `omp.section` where
1469+
// lastprivate FIR can reside. Later canonicalizations
1470+
// will optimize away this operation.
1471+
if (!eval.lowerAsUnstructured()) {
1472+
auto ifOp = firOpBuilder.create<fir::IfOp>(
1473+
op->getLoc(),
1474+
firOpBuilder.createIntegerConstant(
1475+
op->getLoc(), firOpBuilder.getIntegerType(1), 0x1),
1476+
/*else*/ false);
1477+
firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front());
1478+
1479+
const Fortran::parser::OpenMPConstruct *parentOmpConstruct =
1480+
eval.parentConstruct->getIf<Fortran::parser::OpenMPConstruct>();
1481+
assert(parentOmpConstruct &&
1482+
"Expected a valid enclosing OpenMP construct");
1483+
const Fortran::parser::OpenMPSectionsConstruct *sectionsConstruct =
1484+
std::get_if<Fortran::parser::OpenMPSectionsConstruct>(
1485+
&parentOmpConstruct->u);
1486+
assert(sectionsConstruct &&
1487+
"Expected an enclosing omp.sections construct");
1488+
const Fortran::parser::OmpClauseList &sectionsEndClauseList =
1489+
std::get<Fortran::parser::OmpClauseList>(
1490+
std::get<Fortran::parser::OmpEndSectionsDirective>(
1491+
sectionsConstruct->t)
1492+
.t);
1493+
for (const Fortran::parser::OmpClause &otherClause :
1494+
sectionsEndClauseList.v)
1495+
if (std::get_if<Fortran::parser::OmpClause::Nowait>(&otherClause.u))
1496+
// Emit implicit barrier to synchronize threads and avoid data
1497+
// races on post-update of lastprivate variables when `nowait`
1498+
// clause is present.
1499+
firOpBuilder.create<mlir::omp::BarrierOp>(
1500+
converter.getCurrentLocation());
1501+
firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front());
1502+
lastPrivIP = firOpBuilder.saveInsertionPoint();
1503+
firOpBuilder.setInsertionPoint(ifOp);
1504+
insPt = firOpBuilder.saveInsertionPoint();
1505+
} else {
1506+
// Lastprivate operation is inserted at the end
1507+
// of the lexically last section in the sections
1508+
// construct
1509+
mlir::OpBuilder::InsertPoint unstructuredSectionsIP =
1510+
firOpBuilder.saveInsertionPoint();
1511+
mlir::Operation *lastOper = op->getRegion(0).back().getTerminator();
1512+
firOpBuilder.setInsertionPoint(lastOper);
1513+
lastPrivIP = firOpBuilder.saveInsertionPoint();
1514+
firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP);
1515+
}
15741516
}
1517+
} else if (mlir::isa<mlir::omp::WsLoopOp>(op)) {
1518+
// Update the original variable just before exiting the worksharing
1519+
// loop. Conversion as follows:
1520+
//
1521+
// omp.wsloop {
1522+
// omp.wsloop { ...
1523+
// ... store
1524+
// store ===> %v = arith.addi %iv, %step
1525+
// omp.yield %cmp = %step < 0 ? %v < %ub : %v > %ub
1526+
// } fir.if %cmp {
1527+
// fir.store %v to %loopIV
1528+
// ^%lpv_update_blk:
1529+
// }
1530+
// omp.yield
1531+
// }
1532+
//
1533+
1534+
// Only generate the compare once in presence of multiple LastPrivate
1535+
// clauses.
1536+
if (cmpCreated)
1537+
continue;
1538+
cmpCreated = true;
1539+
1540+
mlir::Location loc = op->getLoc();
1541+
mlir::Operation *lastOper = op->getRegion(0).back().getTerminator();
1542+
firOpBuilder.setInsertionPoint(lastOper);
1543+
1544+
mlir::Value iv = op->getRegion(0).front().getArguments()[0];
1545+
mlir::Value ub =
1546+
mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getUpperBound()[0];
1547+
mlir::Value step = mlir::dyn_cast<mlir::omp::WsLoopOp>(op).getStep()[0];
1548+
1549+
// v = iv + step
1550+
// cmp = step < 0 ? v < ub : v > ub
1551+
mlir::Value v = firOpBuilder.create<mlir::arith::AddIOp>(loc, iv, step);
1552+
mlir::Value zero =
1553+
firOpBuilder.createIntegerConstant(loc, step.getType(), 0);
1554+
mlir::Value negativeStep = firOpBuilder.create<mlir::arith::CmpIOp>(
1555+
loc, mlir::arith::CmpIPredicate::slt, step, zero);
1556+
mlir::Value vLT = firOpBuilder.create<mlir::arith::CmpIOp>(
1557+
loc, mlir::arith::CmpIPredicate::slt, v, ub);
1558+
mlir::Value vGT = firOpBuilder.create<mlir::arith::CmpIOp>(
1559+
loc, mlir::arith::CmpIPredicate::sgt, v, ub);
1560+
mlir::Value cmpOp = firOpBuilder.create<mlir::arith::SelectOp>(
1561+
loc, negativeStep, vLT, vGT);
1562+
1563+
auto ifOp = firOpBuilder.create<fir::IfOp>(loc, cmpOp, /*else*/ false);
1564+
firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front());
1565+
assert(loopIV && "loopIV was not set");
1566+
firOpBuilder.create<fir::StoreOp>(op->getLoc(), v, loopIV);
1567+
lastPrivIP = firOpBuilder.saveInsertionPoint();
1568+
} else {
1569+
TODO(converter.getCurrentLocation(),
1570+
"lastprivate clause in constructs other than "
1571+
"simd/worksharing-loop");
15751572
}
15761573
}
15771574
firOpBuilder.restoreInsertionPoint(localInsPt);
@@ -1595,14 +1592,12 @@ void DataSharingProcessor::collectSymbols(
15951592
}
15961593

15971594
void DataSharingProcessor::collectDefaultSymbols() {
1598-
for (const Fortran::parser::OmpClause &clause : opClauseList.v) {
1599-
if (const auto &defaultClause =
1600-
std::get_if<Fortran::parser::OmpClause::Default>(&clause.u)) {
1601-
if (defaultClause->v.v ==
1602-
Fortran::parser::OmpDefaultClause::Type::Private)
1595+
for (const omp::Clause &clause : clauses) {
1596+
if (const auto *defaultClause =
1597+
std::get_if<omp::clause::Default>(&clause.u)) {
1598+
if (defaultClause->v == omp::clause::Default::Type::Private)
16031599
collectSymbols(Fortran::semantics::Symbol::Flag::OmpPrivate);
1604-
else if (defaultClause->v.v ==
1605-
Fortran::parser::OmpDefaultClause::Type::Firstprivate)
1600+
else if (defaultClause->v == omp::clause::Default::Type::Firstprivate)
16061601
collectSymbols(Fortran::semantics::Symbol::Flag::OmpFirstPrivate);
16071602
}
16081603
}
@@ -3447,7 +3442,7 @@ static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) {
34473442
std::optional<DataSharingProcessor> tempDsp;
34483443
if (privatize) {
34493444
if (!info.dsp) {
3450-
tempDsp.emplace(info.converter, *info.clauses, info.eval);
3445+
tempDsp.emplace(info.converter, info.semaCtx, *info.clauses, info.eval);
34513446
tempDsp->processStep1();
34523447
}
34533448
}
@@ -4393,7 +4388,7 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
43934388
const Fortran::parser::OmpClauseList &loopOpClauseList,
43944389
mlir::Location loc) {
43954390
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
4396-
DataSharingProcessor dsp(converter, loopOpClauseList, eval);
4391+
DataSharingProcessor dsp(converter, semaCtx, loopOpClauseList, eval);
43974392
dsp.processStep1();
43984393

43994394
Fortran::lower::StatementContext stmtCtx;
@@ -4450,7 +4445,7 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter,
44504445
const Fortran::parser::OmpClauseList *endClauseList,
44514446
mlir::Location loc) {
44524447
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
4453-
DataSharingProcessor dsp(converter, beginClauseList, eval);
4448+
DataSharingProcessor dsp(converter, semaCtx, beginClauseList, eval);
44544449
dsp.processStep1();
44554450

44564451
Fortran::lower::StatementContext stmtCtx;

0 commit comments

Comments
 (0)