Mesa (master): nir/validate: Improve the validation of blocks

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Sep 30 17:01:59 UTC 2020


Module: Mesa
Branch: master
Commit: 6f134a622b186df8a8b3b25d98cee70c78d1992a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=6f134a622b186df8a8b3b25d98cee70c78d1992a

Author: Jason Ekstrand <jason at jlekstrand.net>
Date:   Tue Sep 15 11:28:43 2020 -0500

nir/validate: Improve the validation of blocks

This commit adds a number of new validation checks:

 1. We now check that every block pointer in the IR points to a block
    that actually exists in a block list that's reachable from the
    nir_function_impl.

 2. We assert that nir_function_impl::body is non-empty

 3. We assert that the start block has no predecessors.  This is
    important because we tend to put run-once code there.

 4. We now validate some stuff on the end block.

Reviewed-by: Karol Herbst <kherbst at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6750>

---

 src/compiler/nir/nir_validate.c | 100 ++++++++++++++++++++++++++++++++--------
 1 file changed, 80 insertions(+), 20 deletions(-)

diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c
index 0be74297858..57f7e365158 100644
--- a/src/compiler/nir/nir_validate.c
+++ b/src/compiler/nir/nir_validate.c
@@ -81,6 +81,9 @@ typedef struct {
    /* the current function implementation being validated */
    nir_function_impl *impl;
 
+   /* Set of all blocks in the list */
+   struct set *blocks;
+
    /* Set of seen SSA sources */
    struct set *ssa_srcs;
 
@@ -932,8 +935,63 @@ validate_phi_srcs(nir_block *block, nir_block *succ, validate_state *state)
    }
 }
 
+static void
+collect_blocks(struct exec_list *cf_list, validate_state *state)
+{
+   exec_list_validate(cf_list);
+   foreach_list_typed(nir_cf_node, node, node, cf_list) {
+      switch (node->type) {
+      case nir_cf_node_block:
+         _mesa_set_add(state->blocks, nir_cf_node_as_block(node));
+         break;
+
+      case nir_cf_node_if:
+         collect_blocks(&nir_cf_node_as_if(node)->then_list, state);
+         collect_blocks(&nir_cf_node_as_if(node)->else_list, state);
+         break;
+
+      case nir_cf_node_loop:
+         collect_blocks(&nir_cf_node_as_loop(node)->body, state);
+         break;
+
+      default:
+         unreachable("Invalid CF node type");
+      }
+   }
+}
+
 static void validate_cf_node(nir_cf_node *node, validate_state *state);
 
+static void
+validate_block_predecessors(nir_block *block, validate_state *state)
+{
+   for (unsigned i = 0; i < 2; i++) {
+      if (block->successors[i] == NULL)
+         continue;
+
+      /* The block has to exist in the nir_function_impl */
+      validate_assert(state, _mesa_set_search(state->blocks,
+                                              block->successors[i]));
+
+      /* And we have to be in our successor's predecessors set */
+      validate_assert(state,
+         _mesa_set_search(block->successors[i]->predecessors, block));
+
+      validate_phi_srcs(block, block->successors[i], state);
+   }
+
+   /* The start block cannot have any predecessors */
+   if (block == nir_start_block(state->impl))
+      validate_assert(state, block->predecessors->entries == 0);
+
+   set_foreach(block->predecessors, entry) {
+      const nir_block *pred = entry->key;
+      validate_assert(state, _mesa_set_search(state->blocks, pred));
+      validate_assert(state, pred->successors[0] == block ||
+                             pred->successors[1] == block);
+   }
+}
+
 static void
 validate_block(nir_block *block, validate_state *state)
 {
@@ -953,22 +1011,7 @@ validate_block(nir_block *block, validate_state *state)
 
    validate_assert(state, block->successors[0] != NULL);
    validate_assert(state, block->successors[0] != block->successors[1]);
-
-   for (unsigned i = 0; i < 2; i++) {
-      if (block->successors[i] != NULL) {
-         struct set_entry *entry =
-            _mesa_set_search(block->successors[i]->predecessors, block);
-         validate_assert(state, entry);
-
-         validate_phi_srcs(block, block->successors[i], state);
-      }
-   }
-
-   set_foreach(block->predecessors, entry) {
-      const nir_block *pred = entry->key;
-      validate_assert(state, pred->successors[0] == block ||
-             pred->successors[1] == block);
-   }
+   validate_block_predecessors(block, state);
 
    if (!state->impl->structured) {
       validate_assert(state, nir_block_ends_in_jump(block));
@@ -1021,6 +1064,20 @@ validate_block(nir_block *block, validate_state *state)
    }
 }
 
+
+static void
+validate_end_block(nir_block *block, validate_state *state)
+{
+   validate_assert(state, block->cf_node.parent == &state->impl->cf_node);
+
+   exec_list_validate(&block->instr_list);
+   validate_assert(state, exec_list_is_empty(&block->instr_list));
+
+   validate_assert(state, block->successors[0] == NULL);
+   validate_assert(state, block->successors[1] == NULL);
+   validate_block_predecessors(block, state);
+}
+
 static void
 validate_if(nir_if *if_stmt, validate_state *state)
 {
@@ -1044,12 +1101,10 @@ validate_if(nir_if *if_stmt, validate_state *state)
    nir_cf_node *old_parent = state->parent_node;
    state->parent_node = &if_stmt->cf_node;
 
-   exec_list_validate(&if_stmt->then_list);
    foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->then_list) {
       validate_cf_node(cf_node, state);
    }
 
-   exec_list_validate(&if_stmt->else_list);
    foreach_list_typed(nir_cf_node, cf_node, node, &if_stmt->else_list) {
       validate_cf_node(cf_node, state);
    }
@@ -1078,7 +1133,6 @@ validate_loop(nir_loop *loop, validate_state *state)
    nir_loop *old_loop = state->loop;
    state->loop = loop;
 
-   exec_list_validate(&loop->body);
    foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {
       validate_cf_node(cf_node, state);
    }
@@ -1301,10 +1355,15 @@ validate_function_impl(nir_function_impl *impl, validate_state *state)
                                     BITSET_WORD, BITSET_WORDS(impl->ssa_alloc));
    memset(state->ssa_defs_found, 0, BITSET_WORDS(impl->ssa_alloc) *
                                     sizeof(BITSET_WORD));
-   exec_list_validate(&impl->body);
+
+   _mesa_set_clear(state->blocks, NULL);
+   collect_blocks(&impl->body, state);
+   _mesa_set_add(state->blocks, impl->end_block);
+   validate_assert(state, !exec_list_is_empty(&impl->body));
    foreach_list_typed(nir_cf_node, node, node, &impl->body) {
       validate_cf_node(node, state);
    }
+   validate_end_block(impl->end_block, state);
 
    foreach_list_typed(nir_register, reg, node, &impl->registers) {
       postvalidate_reg_decl(reg, state);
@@ -1339,6 +1398,7 @@ init_validate_state(validate_state *state)
    state->ssa_srcs = _mesa_pointer_set_create(state->mem_ctx);
    state->ssa_defs_found = NULL;
    state->regs_found = NULL;
+   state->blocks = _mesa_pointer_set_create(state->mem_ctx);
    state->var_defs = _mesa_pointer_hash_table_create(state->mem_ctx);
    state->errors = _mesa_pointer_hash_table_create(state->mem_ctx);
 



More information about the mesa-commit mailing list