@@ -1278,14 +1278,15 @@ class DataSharingProcessor {
1278
1278
llvm::SetVector<const Fortran::semantics::Symbol *> symbolsInNestedRegions;
1279
1279
llvm::SetVector<const Fortran::semantics::Symbol *> symbolsInParentRegions;
1280
1280
Fortran::lower::AbstractConverter &converter;
1281
+ Fortran::semantics::SemanticsContext &semaCtx;
1281
1282
fir::FirOpBuilder &firOpBuilder;
1282
- const Fortran::parser::OmpClauseList &opClauseList ;
1283
+ omp::List<omp::Clause> clauses ;
1283
1284
Fortran::lower::pft::Evaluation &eval;
1284
1285
1285
1286
bool needBarrier ();
1286
1287
void collectSymbols (Fortran::semantics::Symbol::Flag flag);
1287
1288
void collectOmpObjectListSymbol (
1288
- const Fortran::parser::OmpObjectList &ompObjectList ,
1289
+ const omp::ObjectList &objects ,
1289
1290
llvm::SetVector<const Fortran::semantics::Symbol *> &symbolSet);
1290
1291
void collectSymbolsForPrivatization ();
1291
1292
void insertBarrier ();
@@ -1302,11 +1303,12 @@ class DataSharingProcessor {
1302
1303
1303
1304
public:
1304
1305
DataSharingProcessor (Fortran::lower::AbstractConverter &converter,
1306
+ Fortran::semantics::SemanticsContext &semaCtx,
1305
1307
const Fortran::parser::OmpClauseList &opClauseList,
1306
1308
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) {}
1310
1312
// Privatisation is split into two steps.
1311
1313
// Step1 performs cloning of all privatisation clauses and copying for
1312
1314
// firstprivates. Step1 is performed at the place where process/processStep1
@@ -1384,30 +1386,28 @@ void DataSharingProcessor::copyLastPrivateSymbol(
1384
1386
}
1385
1387
1386
1388
void DataSharingProcessor::collectOmpObjectListSymbol (
1387
- const Fortran::parser::OmpObjectList &ompObjectList ,
1389
+ const omp::ObjectList &objects ,
1388
1390
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 ;
1391
1393
symbolSet.insert (sym);
1392
1394
}
1393
1395
}
1394
1396
1395
1397
void DataSharingProcessor::collectSymbolsForPrivatization () {
1396
1398
bool hasCollapse = false ;
1397
- for (const Fortran::parser::OmpClause &clause : opClauseList. v ) {
1399
+ for (const omp::Clause &clause : clauses ) {
1398
1400
if (const auto &privateClause =
1399
- std::get_if<Fortran::parser::OmpClause ::Private>(&clause.u )) {
1401
+ std::get_if<omp::clause ::Private>(&clause.u )) {
1400
1402
collectOmpObjectListSymbol (privateClause->v , privatizedSymbols);
1401
1403
} 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 )) {
1404
1405
collectOmpObjectListSymbol (firstPrivateClause->v , privatizedSymbols);
1405
1406
} 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 )) {
1408
1408
collectOmpObjectListSymbol (lastPrivateClause->v , privatizedSymbols);
1409
1409
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 )) {
1411
1411
hasCollapse = true ;
1412
1412
}
1413
1413
}
@@ -1440,138 +1440,135 @@ void DataSharingProcessor::insertBarrier() {
1440
1440
void DataSharingProcessor::insertLastPrivateCompare (mlir::Operation *op) {
1441
1441
bool cmpCreated = false ;
1442
1442
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 §ionsEndClauseList =
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:
1522
1452
//
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
+ // }
1534
1464
//
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 §ionsEndClauseList =
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
+ }
1574
1516
}
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" );
1575
1572
}
1576
1573
}
1577
1574
firOpBuilder.restoreInsertionPoint (localInsPt);
@@ -1595,14 +1592,12 @@ void DataSharingProcessor::collectSymbols(
1595
1592
}
1596
1593
1597
1594
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)
1603
1599
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)
1606
1601
collectSymbols (Fortran::semantics::Symbol::Flag::OmpFirstPrivate);
1607
1602
}
1608
1603
}
@@ -3447,7 +3442,7 @@ static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) {
3447
3442
std::optional<DataSharingProcessor> tempDsp;
3448
3443
if (privatize) {
3449
3444
if (!info.dsp ) {
3450
- tempDsp.emplace (info.converter , *info.clauses , info.eval );
3445
+ tempDsp.emplace (info.converter , info. semaCtx , *info.clauses , info.eval );
3451
3446
tempDsp->processStep1 ();
3452
3447
}
3453
3448
}
@@ -4393,7 +4388,7 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
4393
4388
const Fortran::parser::OmpClauseList &loopOpClauseList,
4394
4389
mlir::Location loc) {
4395
4390
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
4396
- DataSharingProcessor dsp (converter, loopOpClauseList, eval);
4391
+ DataSharingProcessor dsp (converter, semaCtx, loopOpClauseList, eval);
4397
4392
dsp.processStep1 ();
4398
4393
4399
4394
Fortran::lower::StatementContext stmtCtx;
@@ -4450,7 +4445,7 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter,
4450
4445
const Fortran::parser::OmpClauseList *endClauseList,
4451
4446
mlir::Location loc) {
4452
4447
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
4453
- DataSharingProcessor dsp (converter, beginClauseList, eval);
4448
+ DataSharingProcessor dsp (converter, semaCtx, beginClauseList, eval);
4454
4449
dsp.processStep1 ();
4455
4450
4456
4451
Fortran::lower::StatementContext stmtCtx;
0 commit comments