@@ -521,7 +521,7 @@ struct OpWithBodyGenInfo {
521
521
// / \param [in] op - the operation the body belongs to.
522
522
// / \param [in] info - options controlling code-gen for the construction.
523
523
template <typename Op>
524
- static void createBodyOfOp (Op &op, OpWithBodyGenInfo &info) {
524
+ static void createBodyOfOp (mlir::Operation &op, OpWithBodyGenInfo &info) {
525
525
fir::FirOpBuilder &firOpBuilder = info.converter .getFirOpBuilder ();
526
526
527
527
auto insertMarker = [](fir::FirOpBuilder &builder) {
@@ -537,10 +537,10 @@ static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) {
537
537
auto regionArgs =
538
538
[&]() -> llvm::SmallVector<const Fortran::semantics::Symbol *> {
539
539
if (info.genRegionEntryCB != nullptr ) {
540
- return info.genRegionEntryCB (op);
540
+ return info.genRegionEntryCB (& op);
541
541
}
542
542
543
- firOpBuilder.createBlock (&op.getRegion ());
543
+ firOpBuilder.createBlock (&op.getRegion (0 ));
544
544
return {};
545
545
}();
546
546
// Mark the earliest insertion point.
@@ -556,7 +556,7 @@ static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) {
556
556
// Start with privatization, so that the lowering of the nested
557
557
// code will use the right symbols.
558
558
constexpr bool isLoop = std::is_same_v<Op, mlir::omp::WsloopOp> ||
559
- std::is_same_v<Op, mlir::omp::SimdLoopOp >;
559
+ std::is_same_v<Op, mlir::omp::SimdOp >;
560
560
bool privatize = info.clauses && !info.outerCombined ;
561
561
562
562
firOpBuilder.setInsertionPoint (marker);
@@ -582,9 +582,9 @@ static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) {
582
582
// a lot of complications for our approach if the terminator generation
583
583
// is delayed past this point. Insert a temporary terminator here, then
584
584
// delete it.
585
- firOpBuilder.setInsertionPointToEnd (&op.getRegion ().back ());
586
- auto *temp = Fortran::lower::genOpenMPTerminator (
587
- firOpBuilder, op. getOperation () , info.loc );
585
+ firOpBuilder.setInsertionPointToEnd (&op.getRegion (0 ).back ());
586
+ auto *temp =
587
+ Fortran::lower::genOpenMPTerminator ( firOpBuilder, &op , info.loc );
588
588
firOpBuilder.setInsertionPointAfter (marker);
589
589
genNestedEvaluations (info.converter , info.eval );
590
590
temp->erase ();
@@ -626,23 +626,36 @@ static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) {
626
626
return exit;
627
627
};
628
628
629
- if (auto *exitBlock = getUniqueExit (op.getRegion ())) {
629
+ if (auto *exitBlock = getUniqueExit (op.getRegion (0 ))) {
630
630
firOpBuilder.setInsertionPointToEnd (exitBlock);
631
- auto *term = Fortran::lower::genOpenMPTerminator (
632
- firOpBuilder, op. getOperation () , info.loc );
631
+ auto *term =
632
+ Fortran::lower::genOpenMPTerminator ( firOpBuilder, &op , info.loc );
633
633
// Only insert lastprivate code when there actually is an exit block.
634
634
// Such a block may not exist if the nested code produced an infinite
635
635
// loop (this may not make sense in production code, but a user could
636
636
// write that and we should handle it).
637
637
firOpBuilder.setInsertionPoint (term);
638
638
if (privatize) {
639
+ // DataSharingProcessor::processStep2() may create operations before/after
640
+ // the one passed as argument. We need to treat loop wrappers and their
641
+ // nested loop as a unit, so we need to pass the top level wrapper (if
642
+ // present). Otherwise, these operations will be inserted within a
643
+ // wrapper region.
644
+ mlir::Operation *privatizationTopLevelOp = &op;
645
+ if (auto loopNest = llvm::dyn_cast<mlir::omp::LoopNestOp>(op)) {
646
+ llvm::SmallVector<mlir::omp::LoopWrapperInterface> wrappers;
647
+ loopNest.gatherWrappers (wrappers);
648
+ if (!wrappers.empty ())
649
+ privatizationTopLevelOp = &*wrappers.back ();
650
+ }
651
+
639
652
if (!info.dsp ) {
640
653
assert (tempDsp.has_value ());
641
- tempDsp->processStep2 (op , isLoop);
654
+ tempDsp->processStep2 (privatizationTopLevelOp , isLoop);
642
655
} else {
643
656
if (isLoop && regionArgs.size () > 0 )
644
657
info.dsp ->setLoopIV (info.converter .getSymbolAddress (*regionArgs[0 ]));
645
- info.dsp ->processStep2 (op , isLoop);
658
+ info.dsp ->processStep2 (privatizationTopLevelOp , isLoop);
646
659
}
647
660
}
648
661
}
@@ -719,7 +732,7 @@ template <typename OpTy, typename... Args>
719
732
static OpTy genOpWithBody (OpWithBodyGenInfo &info, Args &&...args) {
720
733
auto op = info.converter .getFirOpBuilder ().create <OpTy>(
721
734
info.loc , std::forward<Args>(args)...);
722
- createBodyOfOp<OpTy>(op, info);
735
+ createBodyOfOp<OpTy>(* op, info);
723
736
return op;
724
737
}
725
738
@@ -1689,13 +1702,12 @@ genLoopAndReductionVars(
1689
1702
return llvm::SmallVector<const Fortran::semantics::Symbol *>(loopArgs);
1690
1703
}
1691
1704
1692
- static void
1693
- createSimdLoop (Fortran::lower::AbstractConverter &converter,
1694
- Fortran::semantics::SemanticsContext &semaCtx,
1695
- Fortran::lower::pft::Evaluation &eval,
1696
- llvm::omp::Directive ompDirective,
1697
- const Fortran::parser::OmpClauseList &loopOpClauseList,
1698
- mlir::Location loc) {
1705
+ static void createSimd (Fortran::lower::AbstractConverter &converter,
1706
+ Fortran::semantics::SemanticsContext &semaCtx,
1707
+ Fortran::lower::pft::Evaluation &eval,
1708
+ llvm::omp::Directive ompDirective,
1709
+ const Fortran::parser::OmpClauseList &loopOpClauseList,
1710
+ mlir::Location loc) {
1699
1711
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
1700
1712
DataSharingProcessor dsp (converter, semaCtx, loopOpClauseList, eval);
1701
1713
dsp.processStep1 ();
@@ -1720,11 +1732,20 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
1720
1732
cp.processTODO <clause::Aligned, clause::Allocate, clause::Linear,
1721
1733
clause::Nontemporal, clause::Order>(loc, ompDirective);
1722
1734
1735
+ // Create omp.simd wrapper.
1723
1736
mlir::TypeRange resultType;
1724
- auto simdLoopOp = firOpBuilder.create <mlir::omp::SimdLoopOp>(
1725
- loc, resultType, lowerBound, upperBound, step, alignedVars,
1726
- /* alignment_values=*/ nullptr , ifClauseOperand, nontemporalVars,
1727
- orderClauseOperand, simdlenClauseOperand, safelenClauseOperand,
1737
+ auto simdOp = firOpBuilder.create <mlir::omp::SimdOp>(
1738
+ loc, resultType, alignedVars, /* alignment_values=*/ nullptr ,
1739
+ ifClauseOperand, nontemporalVars, orderClauseOperand,
1740
+ simdlenClauseOperand, safelenClauseOperand);
1741
+
1742
+ firOpBuilder.createBlock (&simdOp.getRegion ());
1743
+ firOpBuilder.setInsertionPoint (
1744
+ Fortran::lower::genOpenMPTerminator (firOpBuilder, simdOp, loc));
1745
+
1746
+ // Create nested omp.loop_nest and fill body with loop contents.
1747
+ auto loopOp = firOpBuilder.create <mlir::omp::LoopNestOp>(
1748
+ loc, lowerBound, upperBound, step,
1728
1749
/* inclusive=*/ firOpBuilder.getUnitAttr ());
1729
1750
1730
1751
auto *nestedEval = getCollapsedLoopEval (
@@ -1734,11 +1755,11 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,
1734
1755
return genLoopVars (op, converter, loc, iv);
1735
1756
};
1736
1757
1737
- createBodyOfOp<mlir::omp::SimdLoopOp >(
1738
- simdLoopOp , OpWithBodyGenInfo (converter, semaCtx, loc, *nestedEval)
1739
- .setClauses (&loopOpClauseList)
1740
- .setDataSharingProcessor (&dsp)
1741
- .setGenRegionEntryCb (ivCallback));
1758
+ createBodyOfOp<mlir::omp::SimdOp >(
1759
+ *loopOp , OpWithBodyGenInfo (converter, semaCtx, loc, *nestedEval)
1760
+ .setClauses (&loopOpClauseList)
1761
+ .setDataSharingProcessor (&dsp)
1762
+ .setGenRegionEntryCb (ivCallback));
1742
1763
}
1743
1764
1744
1765
static void createWsloop (Fortran::lower::AbstractConverter &converter,
@@ -1819,11 +1840,11 @@ static void createWsloop(Fortran::lower::AbstractConverter &converter,
1819
1840
};
1820
1841
1821
1842
createBodyOfOp<mlir::omp::WsloopOp>(
1822
- wsLoopOp, OpWithBodyGenInfo (converter, semaCtx, loc, *nestedEval)
1823
- .setClauses (&beginClauseList)
1824
- .setDataSharingProcessor (&dsp)
1825
- .setReductions (&reductionSymbols, &reductionTypes)
1826
- .setGenRegionEntryCb (ivCallback));
1843
+ * wsLoopOp, OpWithBodyGenInfo (converter, semaCtx, loc, *nestedEval)
1844
+ .setClauses (&beginClauseList)
1845
+ .setDataSharingProcessor (&dsp)
1846
+ .setReductions (&reductionSymbols, &reductionTypes)
1847
+ .setGenRegionEntryCb (ivCallback));
1827
1848
}
1828
1849
1829
1850
static void createSimdWsloop (
@@ -2200,7 +2221,7 @@ genOMP(Fortran::lower::AbstractConverter &converter,
2200
2221
global.getSymName ()));
2201
2222
}();
2202
2223
auto genInfo = OpWithBodyGenInfo (converter, semaCtx, currentLocation, eval);
2203
- createBodyOfOp<mlir::omp::CriticalOp>(criticalOp, genInfo);
2224
+ createBodyOfOp<mlir::omp::CriticalOp>(* criticalOp, genInfo);
2204
2225
}
2205
2226
2206
2227
static void
@@ -2285,8 +2306,8 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
2285
2306
2286
2307
} else if (llvm::omp::allSimdSet.test (ompDirective)) {
2287
2308
// 2.9.3.1 SIMD construct
2288
- createSimdLoop (converter, semaCtx, eval, ompDirective, loopOpClauseList,
2289
- currentLocation);
2309
+ createSimd (converter, semaCtx, eval, ompDirective, loopOpClauseList,
2310
+ currentLocation);
2290
2311
genOpenMPReduction (converter, semaCtx, loopOpClauseList);
2291
2312
} else {
2292
2313
createWsloop (converter, semaCtx, eval, ompDirective, loopOpClauseList,
@@ -2410,10 +2431,9 @@ mlir::Operation *Fortran::lower::genOpenMPTerminator(fir::FirOpBuilder &builder,
2410
2431
mlir::Operation *op,
2411
2432
mlir::Location loc) {
2412
2433
if (mlir::isa<mlir::omp::WsloopOp, mlir::omp::DeclareReductionOp,
2413
- mlir::omp::AtomicUpdateOp, mlir::omp::SimdLoopOp >(op))
2434
+ mlir::omp::AtomicUpdateOp, mlir::omp::LoopNestOp >(op))
2414
2435
return builder.create <mlir::omp::YieldOp>(loc);
2415
- else
2416
- return builder.create <mlir::omp::TerminatorOp>(loc);
2436
+ return builder.create <mlir::omp::TerminatorOp>(loc);
2417
2437
}
2418
2438
2419
2439
void Fortran::lower::genOpenMPConstruct (
0 commit comments