}
}
+static bool
+vectorized_intrinsic(nir_intrinsic_instr *intr)
+{
+ const nir_intrinsic_info *info = &nir_intrinsic_infos[intr->intrinsic];
+
+ if (info->dest_components == 0)
+ return true;
+
+ for (unsigned i = 0; i < info->num_srcs; i++)
+ if (info->src_components[i] == 0)
+ return true;
+
+ return false;
+}
+
static void
validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state)
{
case nir_intrinsic_load_shared:
case nir_intrinsic_load_global:
case nir_intrinsic_load_scratch:
+ case nir_intrinsic_load_constant:
/* These memory load operations must have alignments */
validate_assert(state,
util_is_power_of_two_nonzero(nir_intrinsic_align_mul(instr)));
case nir_intrinsic_load_output:
case nir_intrinsic_load_per_vertex_output:
case nir_intrinsic_load_push_constant:
- case nir_intrinsic_load_constant:
/* All memory load operations must load at least a byte */
validate_assert(state, nir_dest_bit_size(instr->dest) >= 8);
break;
validate_dest(&instr->dest, state, dest_bit_size, components_written);
}
+
+ if (!vectorized_intrinsic(instr))
+ validate_assert(state, instr->num_components == 0);
}
static void
state->block->predecessors->entries);
}
+static void
+validate_jump_instr(nir_jump_instr *instr, validate_state *state)
+{
+ nir_block *block = state->block;
+ validate_assert(state, &instr->instr == nir_block_last_instr(block));
+
+ switch (instr->type) {
+ case nir_jump_return:
+ validate_assert(state, block->successors[0] == state->impl->end_block);
+ validate_assert(state, block->successors[1] == NULL);
+ validate_assert(state, instr->target == NULL);
+ validate_assert(state, instr->else_target == NULL);
+ break;
+
+ case nir_jump_break:
+ validate_assert(state, state->impl->structured);
+ validate_assert(state, state->loop != NULL);
+ if (state->loop) {
+ nir_block *after =
+ nir_cf_node_as_block(nir_cf_node_next(&state->loop->cf_node));
+ validate_assert(state, block->successors[0] == after);
+ }
+ validate_assert(state, block->successors[1] == NULL);
+ validate_assert(state, instr->target == NULL);
+ validate_assert(state, instr->else_target == NULL);
+ 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);
+ validate_assert(state, block->successors[0] == first);
+ }
+ validate_assert(state, block->successors[1] == NULL);
+ validate_assert(state, instr->target == NULL);
+ validate_assert(state, instr->else_target == NULL);
+ break;
+
+ case nir_jump_goto:
+ validate_assert(state, !state->impl->structured);
+ validate_assert(state, instr->target == block->successors[0]);
+ validate_assert(state, instr->target != NULL);
+ validate_assert(state, instr->else_target == NULL);
+ break;
+
+ case nir_jump_goto_if:
+ validate_assert(state, !state->impl->structured);
+ validate_assert(state, instr->target == block->successors[1]);
+ validate_assert(state, instr->else_target == block->successors[0]);
+ validate_src(&instr->condition, state, 0, 1);
+ validate_assert(state, instr->target != NULL);
+ validate_assert(state, instr->else_target != NULL);
+ break;
+
+ default:
+ validate_assert(state, !"Invalid jump instruction type");
+ break;
+ }
+}
+
static void
validate_instr(nir_instr *instr, validate_state *state)
{
break;
case nir_instr_type_jump:
+ validate_jump_instr(nir_instr_as_jump(instr), state);
break;
default:
return;
}
}
-
- abort();
+ validate_assert(state, !"Phi does not have a source corresponding to one "
+ "of its predecessor blocks");
}
static void
nir_instr_prev(instr)->type == nir_instr_type_phi);
}
- if (instr->type == nir_instr_type_jump) {
- validate_assert(state, instr == nir_block_last_instr(block));
- }
-
validate_instr(instr, state);
}
pred->successors[1] == block);
}
- if (!exec_list_is_empty(&block->instr_list) &&
- nir_block_last_instr(block)->type == nir_instr_type_jump) {
- validate_assert(state, block->successors[1] == NULL);
- nir_jump_instr *jump = nir_instr_as_jump(nir_block_last_instr(block));
- switch (jump->type) {
- case nir_jump_break: {
- nir_block *after =
- nir_cf_node_as_block(nir_cf_node_next(&state->loop->cf_node));
- validate_assert(state, block->successors[0] == after);
- break;
- }
-
- case nir_jump_continue: {
- nir_block *first = nir_loop_first_block(state->loop);
- validate_assert(state, block->successors[0] == first);
- break;
- }
-
- case nir_jump_return:
- validate_assert(state, block->successors[0] == state->impl->end_block);
- break;
-
- default:
- unreachable("bad jump type");
- }
- } else {
+ 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) {
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");
}
}
}
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));
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);
validate_assert(state, entry);
_mesa_set_remove(reg_state->uses, entry);
}
-
- if (reg_state->uses->entries != 0) {
- printf("extra entries in register uses:\n");
- set_foreach(reg_state->uses, entry)
- printf("%p\n", entry->key);
-
- abort();
- }
+ validate_assert(state, reg_state->uses->entries == 0);
nir_foreach_if_use(src, reg) {
struct set_entry *entry = _mesa_set_search(reg_state->if_uses, src);
validate_assert(state, entry);
_mesa_set_remove(reg_state->if_uses, entry);
}
-
- if (reg_state->if_uses->entries != 0) {
- printf("extra entries in register if_uses:\n");
- set_foreach(reg_state->if_uses, entry)
- printf("%p\n", entry->key);
-
- abort();
- }
+ validate_assert(state, reg_state->if_uses->entries == 0);
nir_foreach_def(src, reg) {
struct set_entry *entry = _mesa_set_search(reg_state->defs, src);
validate_assert(state, entry);
_mesa_set_remove(reg_state->defs, entry);
}
-
- if (reg_state->defs->entries != 0) {
- printf("extra entries in register defs:\n");
- set_foreach(reg_state->defs, entry)
- printf("%p\n", entry->key);
-
- abort();
- }
+ validate_assert(state, reg_state->defs->entries == 0);
}
static void
state->parent_node = &impl->cf_node;
exec_list_validate(&impl->locals);
- nir_foreach_variable(var, &impl->locals) {
+ nir_foreach_function_temp_variable(var, impl) {
validate_var_decl(var, nir_var_function_temp, state);
}
postvalidate_reg_decl(reg, state);
}
- if (state->ssa_srcs->entries != 0) {
- printf("extra dangling SSA sources:\n");
- set_foreach(state->ssa_srcs, entry)
- printf("%p\n", entry->key);
-
- abort();
- }
+ validate_assert(state, state->ssa_srcs->entries == 0);
+ _mesa_set_clear(state->ssa_srcs, NULL);
}
static void
state.shader = shader;
- exec_list_validate(&shader->uniforms);
- nir_foreach_variable(var, &shader->uniforms) {
- validate_var_decl(var, nir_var_uniform |
- nir_var_mem_ubo |
- nir_var_mem_ssbo,
- &state);
- }
-
- exec_list_validate(&shader->inputs);
- nir_foreach_variable(var, &shader->inputs) {
- validate_var_decl(var, nir_var_shader_in, &state);
- }
-
- exec_list_validate(&shader->outputs);
- nir_foreach_variable(var, &shader->outputs) {
- validate_var_decl(var, nir_var_shader_out, &state);
- }
-
- exec_list_validate(&shader->shared);
- nir_foreach_variable(var, &shader->shared) {
- validate_var_decl(var, nir_var_mem_shared, &state);
- }
-
- exec_list_validate(&shader->globals);
- nir_foreach_variable(var, &shader->globals) {
- validate_var_decl(var, nir_var_shader_temp, &state);
- }
-
- exec_list_validate(&shader->system_values);
- nir_foreach_variable(var, &shader->system_values) {
- validate_var_decl(var, nir_var_system_value, &state);
- }
+ nir_variable_mode valid_modes =
+ nir_var_shader_in |
+ nir_var_shader_out |
+ nir_var_shader_temp |
+ nir_var_uniform |
+ nir_var_mem_ubo |
+ nir_var_system_value |
+ nir_var_mem_ssbo |
+ nir_var_mem_shared;
+
+ exec_list_validate(&shader->variables);
+ nir_foreach_variable_in_shader(var, shader)
+ validate_var_decl(var, valid_modes, &state);
exec_list_validate(&shader->functions);
foreach_list_typed(nir_function, func, node, &shader->functions) {