nir/dominance: Better handle unreachable blocks

v2: Fix minor comments (Ken)

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4636>
This commit is contained in:
Jason Ekstrand 2017-01-17 18:38:35 -08:00 committed by Marge Bot
parent 425558bfd5
commit 4d083b52c0
2 changed files with 38 additions and 8 deletions

View file

@ -2406,13 +2406,20 @@ typedef struct nir_block {
* dom_pre_index and dom_post_index for this block, which makes testing if
* a given block is dominated by another block an O(1) operation.
*/
unsigned dom_pre_index, dom_post_index;
int16_t dom_pre_index, dom_post_index;
/* live in and out for this block; used for liveness analysis */
BITSET_WORD *live_in;
BITSET_WORD *live_out;
} nir_block;
static inline bool
nir_block_is_reachable(nir_block *b)
{
/* See also nir_block_dominates */
return b->dom_post_index != -1;
}
static inline nir_instr *
nir_block_first_instr(nir_block *block)
{

View file

@ -42,6 +42,10 @@ init_block(nir_block *block, nir_function_impl *impl)
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);
}
@ -201,18 +205,25 @@ nir_calc_dominance(nir_shader *shader)
}
}
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));
@ -224,7 +235,15 @@ nir_dominance_lca(nir_block *b1, nir_block *b2)
}
/**
* 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)
@ -235,6 +254,10 @@ 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;
}