X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_remove_dead_variables.c;h=cfdd179629949bad410f658e529080ddaba34165;hb=60097cc840e33af8506d7d4d621fefdca1a77695;hp=f7429eb83da3095fba741ebc4bff3d5540d50f58;hpb=9464d8c49813aba77285e7465b96e92a91ed327c;p=mesa.git diff --git a/src/compiler/nir/nir_remove_dead_variables.c b/src/compiler/nir/nir_remove_dead_variables.c index f7429eb83da..cfdd1796299 100644 --- a/src/compiler/nir/nir_remove_dead_variables.c +++ b/src/compiler/nir/nir_remove_dead_variables.c @@ -27,67 +27,115 @@ #include "nir.h" -static void -add_var_use_intrinsic(nir_intrinsic_instr *instr, struct set *live) +static bool +deref_used_for_not_store(nir_deref_instr *deref) { - unsigned num_vars = nir_intrinsic_infos[instr->intrinsic].num_variables; - for (unsigned i = 0; i < num_vars; i++) { - nir_variable *var = instr->variables[i]->var; - _mesa_set_add(live, var); - } -} + nir_foreach_use(src, &deref->dest.ssa) { + switch (src->parent_instr->type) { + case nir_instr_type_deref: + if (deref_used_for_not_store(nir_instr_as_deref(src->parent_instr))) + return true; + break; + + case nir_instr_type_intrinsic: { + nir_intrinsic_instr *intrin = + nir_instr_as_intrinsic(src->parent_instr); + /* The first source of copy and store intrinsics is the deref to + * write. Don't record those. + */ + if ((intrin->intrinsic != nir_intrinsic_store_deref && + intrin->intrinsic != nir_intrinsic_copy_deref) || + src != &intrin->src[0]) + return true; + break; + } -static void -add_var_use_call(nir_call_instr *instr, struct set *live) -{ - if (instr->return_deref != NULL) { - nir_variable *var = instr->return_deref->var; - _mesa_set_add(live, var); + default: + /* If it's used by any other instruction type (most likely a texture + * or call instruction), consider it used. + */ + return true; + } } - for (unsigned i = 0; i < instr->num_params; i++) { - nir_variable *var = instr->params[i]->var; - _mesa_set_add(live, var); - } + return false; } static void -add_var_use_tex(nir_tex_instr *instr, struct set *live) +add_var_use_deref(nir_deref_instr *deref, struct set *live) { - if (instr->texture != NULL) { - nir_variable *var = instr->texture->var; - _mesa_set_add(live, var); - } - - if (instr->sampler != NULL) { - nir_variable *var = instr->sampler->var; - _mesa_set_add(live, var); - } + if (deref->deref_type != nir_deref_type_var) + return; + + /* If it's not a local that never escapes the shader, then any access at + * all means we need to keep it alive. + */ + assert(deref->mode == deref->var->data.mode); + if (!(deref->mode & (nir_var_function_temp | nir_var_shader_temp | nir_var_mem_shared)) || + deref_used_for_not_store(deref)) + _mesa_set_add(live, deref->var); } static void -add_var_use_shader(nir_shader *shader, struct set *live) +add_var_use_shader(nir_shader *shader, struct set *live, nir_variable_mode modes) { nir_foreach_function(function, shader) { if (function->impl) { nir_foreach_block(block, function->impl) { nir_foreach_instr(instr, block) { - switch(instr->type) { - case nir_instr_type_intrinsic: - add_var_use_intrinsic(nir_instr_as_intrinsic(instr), live); - break; + if (instr->type == nir_instr_type_deref) + add_var_use_deref(nir_instr_as_deref(instr), live); + } + } + } + } +} - case nir_instr_type_call: - add_var_use_call(nir_instr_as_call(instr), live); - break; +static void +remove_dead_var_writes(nir_shader *shader, struct set *live) +{ + nir_foreach_function(function, shader) { + if (!function->impl) + continue; + + nir_foreach_block(block, function->impl) { + nir_foreach_instr_safe(instr, block) { + switch (instr->type) { + case nir_instr_type_deref: { + nir_deref_instr *deref = nir_instr_as_deref(instr); + if (deref->deref_type == nir_deref_type_cast && + !nir_deref_instr_parent(deref)) + continue; + + nir_variable_mode parent_mode; + if (deref->deref_type == nir_deref_type_var) + parent_mode = deref->var->data.mode; + else + parent_mode = nir_deref_instr_parent(deref)->mode; + + /* If the parent mode is 0, then it references a dead variable. + * Flag this deref as dead and remove it. + */ + if (parent_mode == 0) { + deref->mode = 0; + nir_instr_remove(&deref->instr); + } + break; + } - case nir_instr_type_tex: - add_var_use_tex(nir_instr_as_tex(instr), live); + case nir_instr_type_intrinsic: { + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + if (intrin->intrinsic != nir_intrinsic_copy_deref && + intrin->intrinsic != nir_intrinsic_store_deref) break; - default: - break; - } + if (nir_src_as_deref(intrin->src[0])->mode == 0) + nir_instr_remove(instr); + break; + } + + default: + break; /* Nothing to do */ } } } @@ -102,8 +150,9 @@ remove_dead_vars(struct exec_list *var_list, struct set *live) foreach_list_typed_safe(nir_variable, var, node, var_list) { struct set_entry *entry = _mesa_set_search(live, var); if (entry == NULL) { + /* Mark this variable as used by setting the mode to 0 */ + var->data.mode = 0; exec_node_remove(&var->node); - ralloc_free(var); progress = true; } } @@ -115,10 +164,9 @@ bool nir_remove_dead_variables(nir_shader *shader, nir_variable_mode modes) { bool progress = false; - struct set *live = - _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal); + struct set *live = _mesa_pointer_set_create(NULL); - add_var_use_shader(shader, live); + add_var_use_shader(shader, live, modes); if (modes & nir_var_uniform) progress = remove_dead_vars(&shader->uniforms, live) || progress; @@ -129,21 +177,31 @@ nir_remove_dead_variables(nir_shader *shader, nir_variable_mode modes) if (modes & nir_var_shader_out) progress = remove_dead_vars(&shader->outputs, live) || progress; - if (modes & nir_var_global) + if (modes & nir_var_shader_temp) progress = remove_dead_vars(&shader->globals, live) || progress; if (modes & nir_var_system_value) progress = remove_dead_vars(&shader->system_values, live) || progress; - if (modes & nir_var_local) { + if (modes & nir_var_mem_shared) + progress = remove_dead_vars(&shader->shared, live) || progress; + + if (modes & nir_var_function_temp) { nir_foreach_function(function, shader) { if (function->impl) { - if (remove_dead_vars(&function->impl->locals, live)) { - nir_metadata_preserve(function->impl, nir_metadata_block_index | - nir_metadata_dominance | - nir_metadata_live_ssa_defs); + if (remove_dead_vars(&function->impl->locals, live)) progress = true; - } + } + } + } + + if (progress) { + remove_dead_var_writes(shader, live); + + nir_foreach_function(function, shader) { + if (function->impl) { + nir_metadata_preserve(function->impl, nir_metadata_block_index | + nir_metadata_dominance); } } }