Skip to content

Commit c3ff901

Browse files
committed
Use omp.single to handle CFG cases
1 parent 07a9eb3 commit c3ff901

File tree

1 file changed

+53
-24
lines changed

1 file changed

+53
-24
lines changed

flang/lib/Optimizer/OpenMP/LowerWorkshare.cpp

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
//
1717
//===----------------------------------------------------------------------===//
1818

19-
#include "flang/Optimizer/Builder/Todo.h"
2019
#include <flang/Optimizer/Builder/FIRBuilder.h>
2120
#include <flang/Optimizer/Dialect/FIROps.h>
2221
#include <flang/Optimizer/Dialect/FIRType.h>
@@ -39,7 +38,6 @@
3938
#include <mlir/IR/Visitors.h>
4039
#include <mlir/Interfaces/SideEffectInterfaces.h>
4140
#include <mlir/Support/LLVM.h>
42-
#include <mlir/Transforms/GreedyPatternRewriteDriver.h>
4341

4442
#include <variant>
4543

@@ -96,6 +94,12 @@ bool shouldUseWorkshareLowering(Operation *op) {
9694
if (isNestedIn<omp::SingleOp>(parentWorkshare, op))
9795
return false;
9896

97+
if (parentWorkshare.getRegion().getBlocks().size() != 1) {
98+
parentWorkshare->emitWarning(
99+
"omp workshare with unstructured control flow currently unsupported.");
100+
return false;
101+
}
102+
99103
return true;
100104
}
101105

@@ -408,15 +412,6 @@ LogicalResult lowerWorkshare(mlir::omp::WorkshareOp wsOp, DominanceInfo &di) {
408412

409413
OpBuilder rootBuilder(wsOp);
410414

411-
// This operation is just a placeholder which will be erased later. We need it
412-
// because our `parallelizeRegion` function works on regions and not blocks.
413-
omp::WorkshareOp newOp =
414-
rootBuilder.create<omp::WorkshareOp>(loc, omp::WorkshareOperands());
415-
if (!wsOp.getNowait())
416-
rootBuilder.create<omp::BarrierOp>(loc);
417-
418-
parallelizeRegion(wsOp.getRegion(), newOp.getRegion(), rootMapping, loc, di);
419-
420415
// FIXME Currently, we only support workshare constructs with structured
421416
// control flow. The transformation itself supports CFG, however, once we
422417
// transform the MLIR region in the omp.workshare, we need to inline that
@@ -427,19 +422,53 @@ LogicalResult lowerWorkshare(mlir::omp::WorkshareOp wsOp, DominanceInfo &di) {
427422
// time when fir ops get lowered to CFG. However, SCF is not registered in
428423
// flang so we cannot use it. Remove this requirement once we have
429424
// scf.execute_region or an alternative operation available.
430-
if (wsOp.getRegion().getBlocks().size() != 1)
431-
TODO(wsOp->getLoc(), "omp workshare with unstructured control flow");
432-
433-
// Inline the contents of the placeholder workshare op into its parent block.
434-
Block *theBlock = &newOp.getRegion().front();
435-
Operation *term = theBlock->getTerminator();
436-
Block *parentBlock = wsOp->getBlock();
437-
parentBlock->getOperations().splice(newOp->getIterator(),
438-
theBlock->getOperations());
439-
assert(term->getNumOperands() == 0);
440-
term->erase();
441-
newOp->erase();
442-
wsOp->erase();
425+
if (wsOp.getRegion().getBlocks().size() == 1) {
426+
// This operation is just a placeholder which will be erased later. We need
427+
// it because our `parallelizeRegion` function works on regions and not
428+
// blocks.
429+
omp::WorkshareOp newOp =
430+
rootBuilder.create<omp::WorkshareOp>(loc, omp::WorkshareOperands());
431+
if (!wsOp.getNowait())
432+
rootBuilder.create<omp::BarrierOp>(loc);
433+
434+
parallelizeRegion(wsOp.getRegion(), newOp.getRegion(), rootMapping, loc,
435+
di);
436+
437+
// Inline the contents of the placeholder workshare op into its parent
438+
// block.
439+
Block *theBlock = &newOp.getRegion().front();
440+
Operation *term = theBlock->getTerminator();
441+
Block *parentBlock = wsOp->getBlock();
442+
parentBlock->getOperations().splice(newOp->getIterator(),
443+
theBlock->getOperations());
444+
assert(term->getNumOperands() == 0);
445+
term->erase();
446+
newOp->erase();
447+
wsOp->erase();
448+
} else {
449+
// Otherwise just change the operation to an omp.single.
450+
451+
// `shouldUseWorkshareLowering` should have guaranteed that there are no
452+
// omp.workshare_loop_wrapper's that bind to this omp.workshare.
453+
assert(!wsOp->walk([&](Operation *op) {
454+
// Nested omp.workshare can have their own
455+
// omp.workshare_loop_wrapper's.
456+
if (isa<omp::WorkshareOp>(op))
457+
return WalkResult::skip();
458+
if (isa<omp::WorkshareLoopWrapperOp>(op))
459+
return WalkResult::interrupt();
460+
return WalkResult::advance();
461+
})
462+
.wasInterrupted());
463+
464+
omp::SingleOperands operands;
465+
operands.nowait = wsOp.getNowaitAttr();
466+
omp::SingleOp newOp = rootBuilder.create<omp::SingleOp>(loc, operands);
467+
468+
newOp.getRegion().getBlocks().splice(newOp.getRegion().getBlocks().begin(),
469+
wsOp.getRegion().getBlocks());
470+
wsOp->erase();
471+
}
443472
return success();
444473
}
445474

0 commit comments

Comments
 (0)