16
16
//
17
17
// ===----------------------------------------------------------------------===//
18
18
19
- #include " flang/Optimizer/Builder/Todo.h"
20
19
#include < flang/Optimizer/Builder/FIRBuilder.h>
21
20
#include < flang/Optimizer/Dialect/FIROps.h>
22
21
#include < flang/Optimizer/Dialect/FIRType.h>
39
38
#include < mlir/IR/Visitors.h>
40
39
#include < mlir/Interfaces/SideEffectInterfaces.h>
41
40
#include < mlir/Support/LLVM.h>
42
- #include < mlir/Transforms/GreedyPatternRewriteDriver.h>
43
41
44
42
#include < variant>
45
43
@@ -96,6 +94,12 @@ bool shouldUseWorkshareLowering(Operation *op) {
96
94
if (isNestedIn<omp::SingleOp>(parentWorkshare, op))
97
95
return false ;
98
96
97
+ if (parentWorkshare.getRegion ().getBlocks ().size () != 1 ) {
98
+ parentWorkshare->emitWarning (
99
+ " omp workshare with unstructured control flow currently unsupported." );
100
+ return false ;
101
+ }
102
+
99
103
return true ;
100
104
}
101
105
@@ -408,15 +412,6 @@ LogicalResult lowerWorkshare(mlir::omp::WorkshareOp wsOp, DominanceInfo &di) {
408
412
409
413
OpBuilder rootBuilder (wsOp);
410
414
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
-
420
415
// FIXME Currently, we only support workshare constructs with structured
421
416
// control flow. The transformation itself supports CFG, however, once we
422
417
// 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) {
427
422
// time when fir ops get lowered to CFG. However, SCF is not registered in
428
423
// flang so we cannot use it. Remove this requirement once we have
429
424
// 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
+ }
443
472
return success ();
444
473
}
445
474
0 commit comments