<p dir="ltr"><br>
On Apr 7, 2015 2:32 AM, "Kenneth Graunke" <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>> wrote:<br>
><br>
> This pass performs a mark and sweep pass over a nir_shader's associated<br>
> memory - anything still connected to the program will be kept, and any<br>
> dead memory we dropped on the floor will be freed.<br>
><br>
> The expectation is that this will be called when finished building and<br>
> optimizing the shader.  However, it's also fine to call it earlier, and<br>
> many times, to free up memory earlier.<br>
><br>
> v2: (feedback from Jason Ekstrand)<br>
> - Skip sweeping impl->start_block, as it's already in the CF list.<br>
> - Don't sweep SSA defs (they're owned by their defining instruction)<br>
> - Don't steal phi sources (they're owned by nir_phi_instr).<br>
> - Don't steal tex->src (it's owned by the tex_inst itself)<br>
> - Don't sweep dereference chains (top-level dereferences are owned by<br>
>   the instruction; sub-dereferences are owned by the parent deref).<br>
> - Don't sweep sources and destinations (SSA defs are handled as part of<br>
>   the defining instruction, and registers are handled as part of<br>
>   function implementations).<br>
> - Just steal instructions; don't walk them (no longer required).<br>
><br>
> Signed-off-by: Kenneth Graunke <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>><br>
> ---<br>
>  src/glsl/Makefile.sources |   1 +<br>
>  src/glsl/nir/nir.h        |   2 +<br>
>  src/glsl/nir/nir_sweep.c  | 151 ++++++++++++++++++++++++++++++++++++++++++++++<br>
>  3 files changed, 154 insertions(+)<br>
>  create mode 100644 src/glsl/nir/nir_sweep.c<br>
><br>
> This version is much simpler (= faster), thanks to the earlier changes.<br>
><br>
> diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources<br>
> index 9bdcb80..c471eca 100644<br>
> --- a/src/glsl/Makefile.sources<br>
> +++ b/src/glsl/Makefile.sources<br>
> @@ -59,6 +59,7 @@ NIR_FILES = \<br>
>         nir/nir_search.c \<br>
>         nir/nir_search.h \<br>
>         nir/nir_split_var_copies.c \<br>
> +       nir/nir_sweep.c \<br>
>         nir/nir_to_ssa.c \<br>
>         nir/nir_types.h \<br>
>         nir/nir_validate.c \<br>
> diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h<br>
> index e6b7684..0f72301 100644<br>
> --- a/src/glsl/nir/nir.h<br>
> +++ b/src/glsl/nir/nir.h<br>
> @@ -1650,6 +1650,8 @@ bool nir_opt_peephole_ffma(nir_shader *shader);<br>
><br>
>  bool nir_opt_remove_phis(nir_shader *shader);<br>
><br>
> +void nir_sweep(nir_shader *shader);<br>
> +<br>
>  #ifdef __cplusplus<br>
>  } /* extern "C" */<br>
>  #endif<br>
> diff --git a/src/glsl/nir/nir_sweep.c b/src/glsl/nir/nir_sweep.c<br>
> new file mode 100644<br>
> index 0000000..b33d624<br>
> --- /dev/null<br>
> +++ b/src/glsl/nir/nir_sweep.c<br>
> @@ -0,0 +1,151 @@<br>
> +/*<br>
> + * Copyright © 2015 Intel Corporation<br>
> + *<br>
> + * Permission is hereby granted, free of charge, to any person obtaining a<br>
> + * copy of this software and associated documentation files (the "Software"),<br>
> + * to deal in the Software without restriction, including without limitation<br>
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
> + * and/or sell copies of the Software, and to permit persons to whom the<br>
> + * Software is furnished to do so, subject to the following conditions:<br>
> + *<br>
> + * The above copyright notice and this permission notice (including the next<br>
> + * paragraph) shall be included in all copies or substantial portions of the<br>
> + * Software.<br>
> + *<br>
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
> + * IN THE SOFTWARE.<br>
> + */<br>
> +<br>
> +#include "nir.h"<br>
> +<br>
> +/**<br>
> + * \file nir_sweep.c<br>
> + *<br>
> + * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated<br>
> + * memory - anything still connected to the program will be kept, and any dead memory<br>
> + * we dropped on the floor will be freed.<br>
> + *<br>
> + * The expectation is that drivers should call this when finished compiling the shader<br>
> + * (after any optimization, lowering, and so on).  However, it's also fine to call it<br>
> + * earlier, and even many times, trading CPU cycles for memory savings.<br>
> + */<br>
> +<br>
> +#define steal_list(mem_ctx, type, list) \<br>
> +   foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); }<br>
> +<br>
> +static void sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node);<br>
> +<br>
> +static void<br>
> +sweep_block(nir_shader *nir, nir_block *block)<br>
> +{<br>
> +   ralloc_steal(nir, block);<br>
> +<br>
> +   nir_foreach_instr(block, instr) {<br>
> +      ralloc_steal(nir, instr);</p>
<p dir="ltr">We still need to walk the non-ssa sources and steal any indirect register uses.  Either that or ensure that they're allocated out of the instruction.</p>
<p dir="ltr">> +   }<br>
> +}<br>
> +<br>
> +static void<br>
> +sweep_if(nir_shader *nir, nir_if *iff)<br>
> +{<br>
> +   ralloc_steal(nir, iff);</p>
<p dir="ltr">If has a source that may have an indirect too.</p>
<p dir="ltr">With comments addressed, series is<br>
Reviewed-by: Jason Ekstrand <<a href="mailto:jason.ekstrand@intel.com">jason.ekstrand@intel.com</a>></p>
<p dir="ltr">> +<br>
> +   foreach_list_typed(nir_cf_node, cf_node, node, &iff->then_list) {<br>
> +      sweep_cf_node(nir, cf_node);<br>
> +   }<br>
> +<br>
> +   foreach_list_typed(nir_cf_node, cf_node, node, &iff->else_list) {<br>
> +      sweep_cf_node(nir, cf_node);<br>
> +   }<br>
> +}<br>
> +<br>
> +static void<br>
> +sweep_loop(nir_shader *nir, nir_loop *loop)<br>
> +{<br>
> +   ralloc_steal(nir, loop);<br>
> +<br>
> +   foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {<br>
> +      sweep_cf_node(nir, cf_node);<br>
> +   }<br>
> +}<br>
> +<br>
> +static void<br>
> +sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node)<br>
> +{<br>
> +   switch (cf_node->type) {<br>
> +   case nir_cf_node_block:<br>
> +      sweep_block(nir, nir_cf_node_as_block(cf_node));<br>
> +      break;<br>
> +   case nir_cf_node_if:<br>
> +      sweep_if(nir, nir_cf_node_as_if(cf_node));<br>
> +      break;<br>
> +   case nir_cf_node_loop:<br>
> +      sweep_loop(nir, nir_cf_node_as_loop(cf_node));<br>
> +      break;<br>
> +   default:<br>
> +      unreachable("Invalid CF node type");<br>
> +   }<br>
> +}<br>
> +<br>
> +static void<br>
> +sweep_impl(nir_shader *nir, nir_function_impl *impl)<br>
> +{<br>
> +   ralloc_steal(nir, impl);<br>
> +<br>
> +   ralloc_steal(nir, impl->params);<br>
> +   ralloc_steal(nir, impl->return_var);<br>
> +   steal_list(nir, nir_variable, &impl->locals);<br>
> +   steal_list(nir, nir_register, &impl->registers);<br>
> +<br>
> +   foreach_list_typed(nir_cf_node, cf_node, node, &impl->body) {<br>
> +      sweep_cf_node(nir, cf_node);<br>
> +   }<br>
> +<br>
> +   sweep_block(nir, impl->end_block);<br>
> +<br>
> +   /* Wipe out all the metadata, if any. */<br>
> +   nir_metadata_preserve(impl, nir_metadata_none);<br>
> +}<br>
> +<br>
> +static void<br>
> +sweep_function(nir_shader *nir, nir_function *f)<br>
> +{<br>
> +   ralloc_steal(nir, f);<br>
> +<br>
> +   foreach_list_typed(nir_function_overload, overload, node, &f->overload_list) {<br>
> +      ralloc_steal(nir, overload);<br>
> +      ralloc_steal(nir, overload->params);<br>
> +      if (overload->impl)<br>
> +         sweep_impl(nir, overload->impl);<br>
> +   }<br>
> +}<br>
> +<br>
> +void<br>
> +nir_sweep(nir_shader *nir)<br>
> +{<br>
> +   void *rubbish = ralloc_context(NULL);<br>
> +<br>
> +   /* First, move ownership of all the memory to a temporary context; assume dead. */<br>
> +   ralloc_adopt(rubbish, nir);<br>
> +<br>
> +   /* Variables and registers are not dead.  Steal them back. */<br>
> +   steal_list(nir, nir_variable, &nir->uniforms);<br>
> +   steal_list(nir, nir_variable, &nir->inputs);<br>
> +   steal_list(nir, nir_variable, &nir->outputs);<br>
> +   steal_list(nir, nir_variable, &nir->globals);<br>
> +   steal_list(nir, nir_variable, &nir->system_values);<br>
> +   steal_list(nir, nir_register, &nir->registers);<br>
> +<br>
> +   /* Recurse into functions, stealing their contents back. */<br>
> +   foreach_list_typed(nir_function, func, node, &nir->functions) {<br>
> +      sweep_function(nir, func);<br>
> +   }<br>
> +<br>
> +   /* Free everything we didn't steal back. */<br>
> +   ralloc_free(rubbish);<br>
> +}<br>
> --<br>
> 2.3.5<br>
><br>
> _______________________________________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</p>