From 4768ea1a77ad7559004949d0cf1eb7af9a4499d9 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Wed, 23 Oct 2019 20:42:40 +0200 Subject: [PATCH] nir: Add a structured flag to nir_shader v2 (Jason Ekstrand): - Make "structured" a property of nir_function_impl not nir_shader - More validation and asserts Signed-off-by: Karol Herbst Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/nir/nir.c | 5 +++++ src/compiler/nir/nir.h | 6 ++++++ src/compiler/nir/nir_serialize.c | 4 ++++ src/compiler/nir/nir_validate.c | 16 +++++++++++++--- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index e17b11cdd4a..070c2751a5b 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -295,6 +295,7 @@ nir_function_impl_create_bare(nir_shader *shader) impl->reg_alloc = 0; impl->ssa_alloc = 0; impl->valid_metadata = nir_metadata_none; + impl->structured = true; /* create start & end blocks */ nir_block *start_block = nir_block_create(shader); @@ -1600,6 +1601,8 @@ nir_block_cf_tree_next(nir_block *block) return NULL; } + assert(nir_cf_node_get_function(&block->cf_node)->structured); + nir_cf_node *cf_next = nir_cf_node_next(&block->cf_node); if (cf_next) return nir_cf_node_cf_tree_first(cf_next); @@ -1636,6 +1639,8 @@ nir_block_cf_tree_prev(nir_block *block) return NULL; } + assert(nir_cf_node_get_function(&block->cf_node)->structured); + nir_cf_node *cf_prev = nir_cf_node_prev(&block->cf_node); if (cf_prev) return nir_cf_node_cf_tree_last(cf_prev); diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 0f3578e7f8a..281a5b17898 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -2775,6 +2775,12 @@ typedef struct { /* total number of basic blocks, only valid when block_index_dirty = false */ unsigned num_blocks; + /** True if this nir_function_impl uses structured control-flow + * + * Structured nir_function_impls have different validation rules. + */ + bool structured; + nir_metadata valid_metadata; } nir_function_impl; diff --git a/src/compiler/nir/nir_serialize.c b/src/compiler/nir/nir_serialize.c index 8baa735def0..b2b3afb151e 100644 --- a/src/compiler/nir/nir_serialize.c +++ b/src/compiler/nir/nir_serialize.c @@ -1901,6 +1901,8 @@ read_cf_list(read_ctx *ctx, struct exec_list *cf_list) static void write_function_impl(write_ctx *ctx, const nir_function_impl *fi) { + blob_write_uint8(ctx->blob, fi->structured); + write_var_list(ctx, &fi->locals); write_reg_list(ctx, &fi->registers); blob_write_uint32(ctx->blob, fi->reg_alloc); @@ -1915,6 +1917,8 @@ read_function_impl(read_ctx *ctx, nir_function *fxn) nir_function_impl *fi = nir_function_impl_create_bare(ctx->nir); fi->function = fxn; + fi->structured = blob_read_uint8(ctx->blob); + read_var_list(ctx, &fi->locals); read_reg_list(ctx, &fi->registers); fi->reg_alloc = blob_read_uint32(ctx->blob); diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index 6d498b0b154..2f6e312826e 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -780,6 +780,7 @@ validate_jump_instr(nir_jump_instr *instr, validate_state *state) break; case nir_jump_break: + validate_assert(state, state->impl->structured); validate_assert(state, state->loop != NULL); if (state->loop) { nir_block *after = @@ -790,6 +791,7 @@ validate_jump_instr(nir_jump_instr *instr, validate_state *state) break; case nir_jump_continue: + validate_assert(state, state->impl->structured); validate_assert(state, state->loop != NULL); if (state->loop) { nir_block *first = nir_loop_first_block(state->loop); @@ -926,7 +928,9 @@ validate_block(nir_block *block, validate_state *state) pred->successors[1] == block); } - if (!nir_block_ends_in_jump(block)) { + if (!state->impl->structured) { + validate_assert(state, nir_block_ends_in_jump(block)); + } else if (!nir_block_ends_in_jump(block)) { nir_cf_node *next = nir_cf_node_next(&block->cf_node); if (next == NULL) { switch (state->parent_node->type) { @@ -962,12 +966,14 @@ validate_block(nir_block *block, validate_state *state) nir_if_first_then_block(if_stmt)); validate_assert(state, block->successors[1] == nir_if_first_else_block(if_stmt)); - } else { - validate_assert(state, next->type == nir_cf_node_loop); + } else if (next->type == nir_cf_node_loop) { nir_loop *loop = nir_cf_node_as_loop(next); validate_assert(state, block->successors[0] == nir_loop_first_block(loop)); validate_assert(state, block->successors[1] == NULL); + } else { + validate_assert(state, + !"Structured NIR cannot have consecutive blocks"); } } } @@ -976,6 +982,8 @@ validate_block(nir_block *block, validate_state *state) static void validate_if(nir_if *if_stmt, validate_state *state) { + validate_assert(state, state->impl->structured); + state->if_stmt = if_stmt; validate_assert(state, !exec_node_is_head_sentinel(if_stmt->cf_node.node.prev)); @@ -1011,6 +1019,8 @@ validate_if(nir_if *if_stmt, validate_state *state) static void validate_loop(nir_loop *loop, validate_state *state) { + validate_assert(state, state->impl->structured); + validate_assert(state, !exec_node_is_head_sentinel(loop->cf_node.node.prev)); nir_cf_node *prev_node = nir_cf_node_prev(&loop->cf_node); validate_assert(state, prev_node->type == nir_cf_node_block); -- 2.30.2