1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2015 Intel Corporation
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the next
12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
13b8e80941Smrg * Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21b8e80941Smrg * IN THE SOFTWARE.
22b8e80941Smrg */
23b8e80941Smrg
24b8e80941Smrg#include "nir.h"
25b8e80941Smrg
26b8e80941Smrg/**
27b8e80941Smrg * \file nir_sweep.c
28b8e80941Smrg *
29b8e80941Smrg * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated
30b8e80941Smrg * memory - anything still connected to the program will be kept, and any dead memory
31b8e80941Smrg * we dropped on the floor will be freed.
32b8e80941Smrg *
33b8e80941Smrg * The expectation is that drivers should call this when finished compiling the shader
34b8e80941Smrg * (after any optimization, lowering, and so on).  However, it's also fine to call it
35b8e80941Smrg * earlier, and even many times, trading CPU cycles for memory savings.
36b8e80941Smrg */
37b8e80941Smrg
38b8e80941Smrg#define steal_list(mem_ctx, type, list) \
39b8e80941Smrg   foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); }
40b8e80941Smrg
41b8e80941Smrgstatic void sweep_cf_node(nir_shader *nir, nir_cf_node *cf_node);
42b8e80941Smrg
43b8e80941Smrgstatic bool
44b8e80941Smrgsweep_src_indirect(nir_src *src, void *nir)
45b8e80941Smrg{
46b8e80941Smrg   if (!src->is_ssa && src->reg.indirect)
47b8e80941Smrg      ralloc_steal(nir, src->reg.indirect);
48b8e80941Smrg
49b8e80941Smrg   return true;
50b8e80941Smrg}
51b8e80941Smrg
52b8e80941Smrgstatic bool
53b8e80941Smrgsweep_dest_indirect(nir_dest *dest, void *nir)
54b8e80941Smrg{
55b8e80941Smrg   if (!dest->is_ssa && dest->reg.indirect)
56b8e80941Smrg      ralloc_steal(nir, dest->reg.indirect);
57b8e80941Smrg
58b8e80941Smrg   return true;
59b8e80941Smrg}
60b8e80941Smrg
61b8e80941Smrgstatic void
62b8e80941Smrgsweep_block(nir_shader *nir, nir_block *block)
63b8e80941Smrg{
64b8e80941Smrg   ralloc_steal(nir, block);
65b8e80941Smrg
66b8e80941Smrg   /* sweep_impl will mark all metadata invalid.  We can safely release all of
67b8e80941Smrg    * this here.
68b8e80941Smrg    */
69b8e80941Smrg   ralloc_free(block->live_in);
70b8e80941Smrg   block->live_in = NULL;
71b8e80941Smrg
72b8e80941Smrg   ralloc_free(block->live_out);
73b8e80941Smrg   block->live_out = NULL;
74b8e80941Smrg
75b8e80941Smrg   nir_foreach_instr(instr, block) {
76b8e80941Smrg      ralloc_steal(nir, instr);
77b8e80941Smrg
78b8e80941Smrg      nir_foreach_src(instr, sweep_src_indirect, nir);
79b8e80941Smrg      nir_foreach_dest(instr, sweep_dest_indirect, nir);
80b8e80941Smrg   }
81b8e80941Smrg}
82b8e80941Smrg
83b8e80941Smrgstatic void
84b8e80941Smrgsweep_if(nir_shader *nir, nir_if *iff)
85b8e80941Smrg{
86b8e80941Smrg   ralloc_steal(nir, iff);
87b8e80941Smrg
88b8e80941Smrg   foreach_list_typed(nir_cf_node, cf_node, node, &iff->then_list) {
89b8e80941Smrg      sweep_cf_node(nir, cf_node);
90b8e80941Smrg   }
91b8e80941Smrg
92b8e80941Smrg   foreach_list_typed(nir_cf_node, cf_node, node, &iff->else_list) {
93b8e80941Smrg      sweep_cf_node(nir, cf_node);
94b8e80941Smrg   }
95b8e80941Smrg}
96b8e80941Smrg
97b8e80941Smrgstatic void
98b8e80941Smrgsweep_loop(nir_shader *nir, nir_loop *loop)
99b8e80941Smrg{
100b8e80941Smrg   ralloc_steal(nir, loop);
101b8e80941Smrg
102b8e80941Smrg   foreach_list_typed(nir_cf_node, cf_node, node, &loop->body) {
103b8e80941Smrg      sweep_cf_node(nir, cf_node);
104b8e80941Smrg   }
105b8e80941Smrg}
106b8e80941Smrg
107b8e80941Smrgstatic void
108b8e80941Smrgsweep_cf_node(nir_shader *nir, nir_cf_node *cf_node)
109b8e80941Smrg{
110b8e80941Smrg   switch (cf_node->type) {
111b8e80941Smrg   case nir_cf_node_block:
112b8e80941Smrg      sweep_block(nir, nir_cf_node_as_block(cf_node));
113b8e80941Smrg      break;
114b8e80941Smrg   case nir_cf_node_if:
115b8e80941Smrg      sweep_if(nir, nir_cf_node_as_if(cf_node));
116b8e80941Smrg      break;
117b8e80941Smrg   case nir_cf_node_loop:
118b8e80941Smrg      sweep_loop(nir, nir_cf_node_as_loop(cf_node));
119b8e80941Smrg      break;
120b8e80941Smrg   default:
121b8e80941Smrg      unreachable("Invalid CF node type");
122b8e80941Smrg   }
123b8e80941Smrg}
124b8e80941Smrg
125b8e80941Smrgstatic void
126b8e80941Smrgsweep_impl(nir_shader *nir, nir_function_impl *impl)
127b8e80941Smrg{
128b8e80941Smrg   ralloc_steal(nir, impl);
129b8e80941Smrg
130b8e80941Smrg   steal_list(nir, nir_variable, &impl->locals);
131b8e80941Smrg   steal_list(nir, nir_register, &impl->registers);
132b8e80941Smrg
133b8e80941Smrg   foreach_list_typed(nir_cf_node, cf_node, node, &impl->body) {
134b8e80941Smrg      sweep_cf_node(nir, cf_node);
135b8e80941Smrg   }
136b8e80941Smrg
137b8e80941Smrg   sweep_block(nir, impl->end_block);
138b8e80941Smrg
139b8e80941Smrg   /* Wipe out all the metadata, if any. */
140b8e80941Smrg   nir_metadata_preserve(impl, nir_metadata_none);
141b8e80941Smrg}
142b8e80941Smrg
143b8e80941Smrgstatic void
144b8e80941Smrgsweep_function(nir_shader *nir, nir_function *f)
145b8e80941Smrg{
146b8e80941Smrg   ralloc_steal(nir, f);
147b8e80941Smrg   ralloc_steal(nir, f->params);
148b8e80941Smrg
149b8e80941Smrg   if (f->impl)
150b8e80941Smrg      sweep_impl(nir, f->impl);
151b8e80941Smrg}
152b8e80941Smrg
153b8e80941Smrgvoid
154b8e80941Smrgnir_sweep(nir_shader *nir)
155b8e80941Smrg{
156b8e80941Smrg   void *rubbish = ralloc_context(NULL);
157b8e80941Smrg
158b8e80941Smrg   /* First, move ownership of all the memory to a temporary context; assume dead. */
159b8e80941Smrg   ralloc_adopt(rubbish, nir);
160b8e80941Smrg
161b8e80941Smrg   ralloc_steal(nir, (char *)nir->info.name);
162b8e80941Smrg   if (nir->info.label)
163b8e80941Smrg      ralloc_steal(nir, (char *)nir->info.label);
164b8e80941Smrg
165b8e80941Smrg   /* Variables and registers are not dead.  Steal them back. */
166b8e80941Smrg   steal_list(nir, nir_variable, &nir->uniforms);
167b8e80941Smrg   steal_list(nir, nir_variable, &nir->inputs);
168b8e80941Smrg   steal_list(nir, nir_variable, &nir->outputs);
169b8e80941Smrg   steal_list(nir, nir_variable, &nir->shared);
170b8e80941Smrg   steal_list(nir, nir_variable, &nir->globals);
171b8e80941Smrg   steal_list(nir, nir_variable, &nir->system_values);
172b8e80941Smrg
173b8e80941Smrg   /* Recurse into functions, stealing their contents back. */
174b8e80941Smrg   foreach_list_typed(nir_function, func, node, &nir->functions) {
175b8e80941Smrg      sweep_function(nir, func);
176b8e80941Smrg   }
177b8e80941Smrg
178b8e80941Smrg   ralloc_steal(nir, nir->constant_data);
179b8e80941Smrg
180b8e80941Smrg   /* Free everything we didn't steal back. */
181b8e80941Smrg   ralloc_free(rubbish);
182b8e80941Smrg}
183