summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-dominators.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-ir-dominators.cpp')
-rw-r--r--source/slang/slang-ir-dominators.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/source/slang/slang-ir-dominators.cpp b/source/slang/slang-ir-dominators.cpp
index 7960bcaf1..bae9f772f 100644
--- a/source/slang/slang-ir-dominators.cpp
+++ b/source/slang/slang-ir-dominators.cpp
@@ -34,6 +34,27 @@ bool IRDominatorTree::immediatelyDominates(IRBlock* dominator, IRBlock* dominate
bool IRDominatorTree::properlyDominates(IRBlock* dominator, IRBlock* dominated)
{
+ // We need to deal with the cases where `dominator` and/or
+ // `dominated` are unreachable, and thus not represtend
+ // in the nodes of the dominator tree we constructed.
+ //
+ // If `dominated` is unreachable, then there are zero
+ // control flow paths that can reach it, so that *all*
+ // of those (zero) control flow paths go through
+ // `dominator`.
+ //
+ if(isUnreachable(dominated))
+ return true;
+
+ // If `dominated` is reachable then there must exist at least
+ // one control-flow path to it. Thus if `dominator` is not
+ // reachable, it cannot be on that path, and thus must
+ // not be a dominator.
+ //
+ if(isUnreachable(dominator))
+ return false;
+
+
// Because of how we laid out the tree, we can test if one node
// properly dominates another in constant time.
//
@@ -67,6 +88,11 @@ bool IRDominatorTree::dominates(IRBlock* dominator, IRBlock* dominated)
IRBlock* IRDominatorTree::getImmediateDominator(IRBlock* block)
{
+ // An unreachable block has no immediate dominator.
+ //
+ if(isUnreachable(block))
+ return nullptr;
+
// The immediate dominator of a block is its parent
// in the dominator tree. Looking this up is straightforward,
// and we just need to be a bit careful to deal with
@@ -83,6 +109,11 @@ IRBlock* IRDominatorTree::getImmediateDominator(IRBlock* block)
IRDominatorTree::DominatedList IRDominatorTree::getImmediatelyDominatedBlocks(IRBlock* block)
{
+ // An unreachable block doesn't immediately dominate anything.
+ //
+ if(isUnreachable(block))
+ return DominatedList();
+
// Because of our representation, the immediately dominated blocks
// for a node are contiguous, and we store their range in the
// node already.
@@ -99,6 +130,13 @@ IRDominatorTree::DominatedList IRDominatorTree::getImmediatelyDominatedBlocks(IR
IRDominatorTree::DominatedList IRDominatorTree::getProperlyDominatedBlocks(IRBlock* block)
{
+ // Technically each unreachable block dominates all the other
+ // unreachable blocks, but setting things up to answer that
+ // query "correctly" would be a hassle.
+ //
+ if(isUnreachable(block))
+ return DominatedList();
+
// Because of our representation, the properly dominated blocks
// for a node are contiguous, and we store their range in the
// node already.
@@ -123,6 +161,12 @@ Int IRDominatorTree::getBlockIndex(IRBlock* block)
return index;
}
+bool IRDominatorTree::isUnreachable(IRBlock* block)
+{
+ return !mapBlockToIndex.ContainsKey(block);
+}
+
+
// IRDominatorTree::DominatedList
IRDominatorTree::DominatedList::DominatedList()
@@ -181,6 +225,12 @@ bool IRDominatorTree::DominatedList::Iterator::operator==(Iterator const& that)
return mIndex == that.mIndex;
}
+bool IRDominatorTree::DominatedList::Iterator::operator!=(Iterator const& that) const
+{
+ SLANG_ASSERT(mTree == that.mTree);
+ return mIndex != that.mIndex;
+}
+
//
// The dominance computation algorithm we are using relies on being able to compute
// a reverse postorder traversal of the nodes in the CFG, which is done using a depth-first