block->imm_dom = NULL;
block->num_dom_children = 0;
+ /* See nir_block_dominates */
+ block->dom_pre_index = INT16_MAX;
+ block->dom_post_index = -1;
+
set_foreach(block->dom_frontier, entry) {
_mesa_set_remove(block->dom_frontier, entry);
}
{
void *mem_ctx = ralloc_parent(impl);
- nir_foreach_block(block, impl) {
+ nir_foreach_block_unstructured(block, impl) {
if (block->imm_dom)
block->imm_dom->num_dom_children++;
}
- nir_foreach_block(block, impl) {
+ nir_foreach_block_unstructured(block, impl) {
block->dom_children = ralloc_array(mem_ctx, nir_block *,
block->num_dom_children);
block->num_dom_children = 0;
}
- nir_foreach_block(block, impl) {
+ nir_foreach_block_unstructured(block, impl) {
if (block->imm_dom) {
block->imm_dom->dom_children[block->imm_dom->num_dom_children++]
= block;
nir_metadata_require(impl, nir_metadata_block_index);
- nir_foreach_block(block, impl) {
+ nir_foreach_block_unstructured(block, impl) {
init_block(block, impl);
}
bool progress = true;
while (progress) {
progress = false;
- nir_foreach_block(block, impl) {
+ nir_foreach_block_unstructured(block, impl) {
if (block != nir_start_block(impl))
progress |= calc_dominance(block);
}
}
- nir_foreach_block(block, impl) {
+ nir_foreach_block_unstructured(block, impl) {
calc_dom_frontier(block);
}
}
}
+static nir_block *
+block_return_if_reachable(nir_block *b)
+{
+ return (b && nir_block_is_reachable(b)) ? b : NULL;
+}
+
/**
- * Computes the least common anscestor of two blocks. If one of the blocks
- * is null, the other block is returned.
+ * Computes the least common ancestor of two blocks. If one of the blocks
+ * is null or unreachable, the other block is returned or NULL if it's
+ * unreachable.
*/
nir_block *
nir_dominance_lca(nir_block *b1, nir_block *b2)
{
- if (b1 == NULL)
- return b2;
+ if (b1 == NULL || !nir_block_is_reachable(b1))
+ return block_return_if_reachable(b2);
- if (b2 == NULL)
- return b1;
+ if (b2 == NULL || !nir_block_is_reachable(b2))
+ return block_return_if_reachable(b1);
assert(nir_cf_node_get_function(&b1->cf_node) ==
nir_cf_node_get_function(&b2->cf_node));
}
/**
- * Returns true if parent dominates child
+ * Returns true if parent dominates child according to the following
+ * definition:
+ *
+ * "The block A dominates the block B if every path from the start block
+ * to block B passes through A."
+ *
+ * This means, in particular, that any unreachable block is dominated by every
+ * other block and an unreachable block does not dominate anything except
+ * another unreachable block.
*/
bool
nir_block_dominates(nir_block *parent, nir_block *child)
assert(nir_cf_node_get_function(&parent->cf_node)->valid_metadata &
nir_metadata_dominance);
+ /* If a block is unreachable, then nir_block::dom_pre_index == INT16_MAX
+ * and nir_block::dom_post_index == -1. This allows us to trivially handle
+ * unreachable blocks here with zero extra work.
+ */
return child->dom_pre_index >= parent->dom_pre_index &&
child->dom_post_index <= parent->dom_post_index;
}
+bool
+nir_block_is_unreachable(nir_block *block)
+{
+ assert(nir_cf_node_get_function(&block->cf_node)->valid_metadata &
+ nir_metadata_dominance);
+ assert(nir_cf_node_get_function(&block->cf_node)->valid_metadata &
+ nir_metadata_block_index);
+
+ /* Unreachable blocks have no dominator. The only reachable block with no
+ * dominator is the start block which has index 0.
+ */
+ return block->index > 0 && block->imm_dom == NULL;
+}
+
void
nir_dump_dom_tree_impl(nir_function_impl *impl, FILE *fp)
{
fprintf(fp, "digraph doms_%s {\n", impl->function->name);
- nir_foreach_block(block, impl) {
+ nir_foreach_block_unstructured(block, impl) {
if (block->imm_dom)
fprintf(fp, "\t%u -> %u\n", block->imm_dom->index, block->index);
}
void
nir_dump_dom_frontier_impl(nir_function_impl *impl, FILE *fp)
{
- nir_foreach_block(block, impl) {
+ nir_foreach_block_unstructured(block, impl) {
fprintf(fp, "DF(%u) = {", block->index);
set_foreach(block->dom_frontier, entry) {
nir_block *df = (nir_block *) entry->key;
{
fprintf(fp, "digraph cfg_%s {\n", impl->function->name);
- nir_foreach_block(block, impl) {
+ nir_foreach_block_unstructured(block, impl) {
if (block->successors[0])
fprintf(fp, "\t%u -> %u\n", block->index, block->successors[0]->index);
if (block->successors[1])