summaryrefslogtreecommitdiffstats
path: root/src/glsl/nir/nir_dominance.c
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2015-02-06 12:45:43 -0800
committerJason Ekstrand <[email protected]>2015-02-19 17:06:17 -0800
commitf481a9425cb8d70bc61c6303268a465f5a05896b (patch)
tree5045a7422e40089ff9036b774d60b7814a12bd5b /src/glsl/nir/nir_dominance.c
parentb4c5489c8ac12eb2c9881ba2d8bb745203affb7b (diff)
nir/dominance: Add a constant-time mechanism for comparing blocks
This is mostly thanks to Connor. The idea is to do a depth-first search that computes pre and post indices for all the blocks. We can then figure out if one block dominates another in constant time by two simple comparison operations. Reviewed-by: Connor Abbott <[email protected]>
Diffstat (limited to 'src/glsl/nir/nir_dominance.c')
-rw-r--r--src/glsl/nir/nir_dominance.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/glsl/nir/nir_dominance.c b/src/glsl/nir/nir_dominance.c
index 29589cbce23..2f50db1c1f6 100644
--- a/src/glsl/nir/nir_dominance.c
+++ b/src/glsl/nir/nir_dominance.c
@@ -177,6 +177,17 @@ calc_dom_children(nir_function_impl* impl)
nir_foreach_block(impl, block_add_child, NULL);
}
+static void
+calc_dfs_indicies(nir_block *block, unsigned *index)
+{
+ block->dom_pre_index = (*index)++;
+
+ for (unsigned i = 0; i < block->num_dom_children; i++)
+ calc_dfs_indicies(block->dom_children[i], index);
+
+ block->dom_post_index = (*index)++;
+}
+
void
nir_calc_dominance_impl(nir_function_impl *impl)
{
@@ -201,6 +212,9 @@ nir_calc_dominance_impl(nir_function_impl *impl)
impl->start_block->imm_dom = NULL;
calc_dom_children(impl);
+
+ unsigned dfs_index = 0;
+ calc_dfs_indicies(impl->start_block, &dfs_index);
}
void
@@ -234,6 +248,22 @@ nir_dominance_lca(nir_block *b1, nir_block *b2)
return intersect(b1, b2);
}
+/**
+ * Returns true if parent dominates child
+ */
+bool
+nir_block_dominates(nir_block *parent, nir_block *child)
+{
+ assert(nir_cf_node_get_function(&parent->cf_node) ==
+ nir_cf_node_get_function(&child->cf_node));
+
+ assert(nir_cf_node_get_function(&parent->cf_node)->valid_metadata &
+ nir_metadata_dominance);
+
+ return child->dom_pre_index >= parent->dom_pre_index &&
+ child->dom_post_index <= parent->dom_post_index;
+}
+
static bool
dump_block_dom(nir_block *block, void *state)
{