diff --git a/mlir/lib/Analysis/Dominance.cpp b/mlir/lib/Analysis/Dominance.cpp --- a/mlir/lib/Analysis/Dominance.cpp +++ b/mlir/lib/Analysis/Dominance.cpp @@ -183,17 +183,29 @@ // DominanceInfo //===----------------------------------------------------------------------===// -/// Return true if operation A properly dominates operation B. +/// Returns true if operation A properly dominates operation B. bool DominanceInfo::properlyDominates(Operation *a, Operation *b) { auto *aBlock = a->getBlock(), *bBlock = b->getBlock(); - // If a or b are not within a block, then a does not dominate b. + // If a or b are not within a block, then a does not properly dominate b. if (!aBlock || !bBlock) return false; // If the blocks are the same, then check if b is before a in the block. - if (aBlock == bBlock) - return a->isBeforeInBlock(b); + if (aBlock == bBlock) { + if (a->isBeforeInBlock(b)) + return true; + + // Even if b is before a in their block, if aBlock dominates all + // predecessors of aBlock, a dominates b. + + // Can't be equal for proper dominance. + if (a == b || aBlock->hasNoPredecessors()) + return false; + + return llvm::all_of(aBlock->getPredecessors(), + [&](Block *p) { return dominates(aBlock, p); }); + } // Traverse up b's hierarchy to check if b's block is contained in a's. if (auto *bAncestor = aBlock->findAncestorOpInBlock(*b)) { diff --git a/mlir/test/IR/dominance.mlir b/mlir/test/IR/dominance.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/IR/dominance.mlir @@ -0,0 +1,38 @@ +// RUN: mlir-opt %s | FileCheck %s + +// Verify dominance related functions in "cyclic" cases. +// CHECK-LABEL: func @dominance +func @dominance(%n: i32, %p : i1) -> i32 { + %x = addi %n, %n : i32 + return %x : i32 + + // Self loop. +^bar: + %y = addi %z, %x : i32 + // muli does dominate addi. + %z = muli %y, %y : i32 + br ^bar + + // abc and xyz cycle. +^abc: + %a = addi %b, %x : i32 + // muli does dominate addi. + %b = muli %a, %a : i32 + br ^xyz + +^xyz: + br ^abc + + // c1, c2, c3 are an SCC. +^c1: + %u = addi %v, %x : i32 + // muli does dominate addi. + %v = muli %u, %u : i32 + cond_br %p, ^c2, ^c3 + +^c2: + br ^c1 + +^c3: + br ^c1 +}