Skip to content

Commit 6d8995a

Browse files
authored
[MLIR][OpenMP] More robust support for target SPMD (#161)
This patch fixes `TargetOp::getInnermostCapturedOmpOp()` to avoid detecting as captured by the top target construct other constructs nested inside of a loop. This prevents the `omp.target` verifier from incorrectly flagging valid SPMD loops, like in the following example: ```f90 subroutine foo(n) implicit none integer, intent(in) :: n integer :: i, j !$omp target teams distribute parallel do do i=1,n !$omp simd do j=1,n call bar() enddo enddo end subroutine foo ```
1 parent 968dac4 commit 6d8995a

File tree

2 files changed

+14
-14
lines changed

2 files changed

+14
-14
lines changed

mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,13 +1127,16 @@ def TargetOp : OpenMP_Op<"target", traits = [
11271127
let hasVerifier = 1;
11281128

11291129
let extraClassDeclaration = [{
1130-
/// Returns the innermost OpenMP dialect operation nested inside of this
1131-
/// operation's region. For an operation to be detected as captured, it must
1132-
/// be inside a (possibly multi-level) nest of OpenMP dialect operation's
1130+
/// Returns the innermost OpenMP dialect operation captured by this target
1131+
/// construct. For an operation to be detected as captured, it must be
1132+
/// inside a (possibly multi-level) nest of OpenMP dialect operation's
11331133
/// regions where none of these levels contain other operations considered
11341134
/// not-allowed for these purposes (i.e. only terminator operations are
11351135
/// allowed from the OpenMP dialect, and other dialect's operations are
11361136
/// allowed as long as they don't have a memory write effect).
1137+
///
1138+
/// If there are omp.loop_nest operations in the sequence of nested
1139+
/// operations, the top level one will be the one captured.
11371140
Operation *getInnermostCapturedOmpOp();
11381141

11391142
/// Tells whether this target region represents a single worksharing loop

mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,13 @@ Operation *TargetOp::getInnermostCapturedOmpOp() {
15201520
if (op == *this)
15211521
return;
15221522

1523+
// Reset captured op if crossing through an omp.loop_nest, so that the top
1524+
// level one will be the one captured.
1525+
if (llvm::isa<LoopNestOp>(op)) {
1526+
capturedOp = nullptr;
1527+
capturedParentRegion = nullptr;
1528+
}
1529+
15231530
bool isOmpDialect = op->getDialect() == ompDialect;
15241531
bool hasRegions = op->getNumRegions() > 0;
15251532

@@ -1563,21 +1570,11 @@ Operation *TargetOp::getInnermostCapturedOmpOp() {
15631570

15641571
bool TargetOp::isTargetSPMDLoop() {
15651572
Operation *capturedOp = getInnermostCapturedOmpOp();
1566-
1567-
// Allow an omp.atomic_update to be captured inside of the loop and still
1568-
// consider the parent omp.target operation to be potentially defining an SPMD
1569-
// loop.
1570-
// TODO: Potentially accept other captured OpenMP dialect operations as well,
1571-
// if they are allowed inside of an SPMD loop.
1572-
if (isa_and_present<AtomicUpdateOp>(capturedOp))
1573-
capturedOp = capturedOp->getParentOp();
1574-
15751573
if (!isa_and_present<LoopNestOp>(capturedOp))
15761574
return false;
15771575

1578-
Operation *workshareOp = capturedOp->getParentOp();
1579-
15801576
// Accept optional SIMD leaf construct.
1577+
Operation *workshareOp = capturedOp->getParentOp();
15811578
if (isa_and_present<SimdOp>(workshareOp))
15821579
workshareOp = workshareOp->getParentOp();
15831580

0 commit comments

Comments
 (0)