On Tue, Dec 16, 2014 at 1:11 AM, Jason Ekstrand <ja...@jlekstrand.net> wrote:
> --- > src/glsl/Makefile.sources | 1 + > src/glsl/nir/nir.h | 2 + > src/glsl/nir/nir_lower_global_vars_to_local.c | 107 > ++++++++++++++++++++++++++ > 3 files changed, 110 insertions(+) > create mode 100644 src/glsl/nir/nir_lower_global_vars_to_local.c > > diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources > index 53c3e98..3f5c0bd 100644 > --- a/src/glsl/Makefile.sources > +++ b/src/glsl/Makefile.sources > @@ -22,6 +22,7 @@ NIR_FILES = \ > $(GLSL_SRCDIR)/nir/nir_intrinsics.h \ > $(GLSL_SRCDIR)/nir/nir_live_variables.c \ > $(GLSL_SRCDIR)/nir/nir_lower_atomics.c \ > + $(GLSL_SRCDIR)/nir/nir_lower_global_vars_to_local.c \ > $(GLSL_SRCDIR)/nir/nir_lower_locals_to_regs.c \ > $(GLSL_SRCDIR)/nir/nir_lower_io.c \ > $(GLSL_SRCDIR)/nir/nir_lower_samplers.cpp \ > diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h > index ec9ce07..30146d6 100644 > --- a/src/glsl/nir/nir.h > +++ b/src/glsl/nir/nir.h > @@ -1358,6 +1358,8 @@ void nir_dump_cfg(nir_shader *shader, FILE *fp); > > void nir_split_var_copies(nir_shader *shader); > > +void nir_lower_global_vars_to_local(nir_shader *shader); > + > void nir_lower_locals_to_regs(nir_shader *shader); > > void nir_lower_io(nir_shader *shader); > diff --git a/src/glsl/nir/nir_lower_global_vars_to_local.c > b/src/glsl/nir/nir_lower_global_vars_to_local.c > new file mode 100644 > index 0000000..ec23a0a > --- /dev/null > +++ b/src/glsl/nir/nir_lower_global_vars_to_local.c > @@ -0,0 +1,107 @@ > +/* > + * Copyright © 2014 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the > "Software"), > + * to deal in the Software without restriction, including without > limitation > + * the rights to use, copy, modify, merge, publish, distribute, > sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the > next > + * paragraph) shall be included in all copies or substantial portions of > the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT > SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR > OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > DEALINGS > + * IN THE SOFTWARE. > + * > + * Authors: > + * Jason Ekstrand (ja...@jlekstrand.net) > + * > + */ > + > +/* > + * This lowering pass detects when a global variable is only being used by > + * one function and makes it local to that function > + */ > + > +#include "nir.h" > + > +struct global_to_local_state { > + nir_function_impl *impl; > + /* A hash table keyed on variable pointers that stores the unique > + * nir_function_impl that uses the given variable. If a variable is > + * used in multiple functions, the data for the given key will be NULL. > + */ > + struct hash_table *var_func_table; > +}; > + > +static bool > +mark_global_var_uses_block(nir_block *block, void *void_state) > +{ > + struct global_to_local_state *state = void_state; > + > + nir_foreach_instr(block, instr) { > + if (instr->type != nir_instr_type_intrinsic) > + continue; > + > + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); > + unsigned num_vars = > nir_intrinsic_infos[intrin->intrinsic].num_variables; > + > + for (unsigned i = 0; i < num_vars; i++) { > + nir_variable *var = intrin->variables[i]->var; > + if (var->data.mode != nir_var_global) > + continue; > + > + uint32_t hash = _mesa_hash_pointer(var); > + struct hash_entry *entry = > + _mesa_hash_table_search(state->var_func_table, hash, var); > + > + if (entry) { > + if (entry->data != state->impl) > + entry->data = NULL; > + } > + > + _mesa_hash_table_insert(state->var_func_table, hash, var, > state->impl); > I think you should be doing: if (entry) { ... } else { _mesa_hash_table_insert(state->var_func_table, hash, var, state->impl); } > + } > + } > + > + return true; > +} > + > +void > +nir_lower_global_vars_to_local(nir_shader *shader) > +{ > + struct global_to_local_state state; > + > + state.var_func_table = _mesa_hash_table_create(NULL, > + > _mesa_key_pointer_equal); > + > + nir_foreach_overload(shader, overload) { > + if (overload->impl) { > + state.impl = overload->impl; > + nir_foreach_block(overload->impl, mark_global_var_uses_block, > &state); > + } > + } > + > + struct hash_entry *entry; > + hash_table_foreach(state.var_func_table, entry) { > + nir_variable *var = (void *)entry->key; > + nir_function_impl *impl = entry->data; > + > + assert(var->data.mode == nir_var_global); > + > + if (impl != NULL) { > + exec_node_remove(&var->node); > + var->data.mode = nir_var_local; > + exec_list_push_tail(&impl->locals, &var->node); > + } > + } > + > + _mesa_hash_table_destroy(state.var_func_table, NULL); > +} > -- > 2.2.0 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev