2 * Copyright © 2015 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 * The nir_sweep() pass performs a mark and sweep pass over a nir_shader's associated
30 * memory - anything still connected to the program will be kept, and any dead memory
31 * we dropped on the floor will be freed.
33 * The expectation is that drivers should call this when finished compiling the shader
34 * (after any optimization, lowering, and so on). However, it's also fine to call it
35 * earlier, and even many times, trading CPU cycles for memory savings.
38 #define steal_list(mem_ctx, type, list) \
39 foreach_list_typed(type, obj, node, list) { ralloc_steal(mem_ctx, obj); }
41 static void sweep_cf_node(nir_shader
*nir
, nir_cf_node
*cf_node
);
44 sweep_src_indirect(nir_src
*src
, void *nir
)
46 if (!src
->is_ssa
&& src
->reg
.indirect
)
47 ralloc_steal(nir
, src
->reg
.indirect
);
53 sweep_dest_indirect(nir_dest
*dest
, void *nir
)
55 if (!dest
->is_ssa
&& dest
->reg
.indirect
)
56 ralloc_steal(nir
, dest
->reg
.indirect
);
62 sweep_block(nir_shader
*nir
, nir_block
*block
)
64 ralloc_steal(nir
, block
);
66 nir_foreach_instr(instr
, block
) {
67 ralloc_steal(nir
, instr
);
69 nir_foreach_src(instr
, sweep_src_indirect
, nir
);
70 nir_foreach_dest(instr
, sweep_dest_indirect
, nir
);
75 sweep_if(nir_shader
*nir
, nir_if
*iff
)
77 ralloc_steal(nir
, iff
);
79 foreach_list_typed(nir_cf_node
, cf_node
, node
, &iff
->then_list
) {
80 sweep_cf_node(nir
, cf_node
);
83 foreach_list_typed(nir_cf_node
, cf_node
, node
, &iff
->else_list
) {
84 sweep_cf_node(nir
, cf_node
);
89 sweep_loop(nir_shader
*nir
, nir_loop
*loop
)
91 ralloc_steal(nir
, loop
);
93 foreach_list_typed(nir_cf_node
, cf_node
, node
, &loop
->body
) {
94 sweep_cf_node(nir
, cf_node
);
99 sweep_cf_node(nir_shader
*nir
, nir_cf_node
*cf_node
)
101 switch (cf_node
->type
) {
102 case nir_cf_node_block
:
103 sweep_block(nir
, nir_cf_node_as_block(cf_node
));
106 sweep_if(nir
, nir_cf_node_as_if(cf_node
));
108 case nir_cf_node_loop
:
109 sweep_loop(nir
, nir_cf_node_as_loop(cf_node
));
112 unreachable("Invalid CF node type");
117 sweep_impl(nir_shader
*nir
, nir_function_impl
*impl
)
119 ralloc_steal(nir
, impl
);
121 ralloc_steal(nir
, impl
->params
);
122 for (unsigned i
= 0; i
< impl
->num_params
; i
++)
123 ralloc_steal(nir
, impl
->params
[i
]);
124 ralloc_steal(nir
, impl
->return_var
);
125 steal_list(nir
, nir_variable
, &impl
->locals
);
126 steal_list(nir
, nir_register
, &impl
->registers
);
128 foreach_list_typed(nir_cf_node
, cf_node
, node
, &impl
->body
) {
129 sweep_cf_node(nir
, cf_node
);
132 sweep_block(nir
, impl
->end_block
);
134 /* Wipe out all the metadata, if any. */
135 nir_metadata_preserve(impl
, nir_metadata_none
);
139 sweep_function(nir_shader
*nir
, nir_function
*f
)
141 ralloc_steal(nir
, f
);
142 ralloc_steal(nir
, f
->params
);
145 sweep_impl(nir
, f
->impl
);
149 nir_sweep(nir_shader
*nir
)
151 void *rubbish
= ralloc_context(NULL
);
153 /* The shader may not own shader_info so check first */
154 bool steal_info
= false;
155 if (nir
== ralloc_parent(nir
->info
))
158 /* First, move ownership of all the memory to a temporary context; assume dead. */
159 ralloc_adopt(rubbish
, nir
);
162 ralloc_steal(nir
, nir
->info
);
164 ralloc_steal(nir
, (char *)nir
->info
->name
);
165 if (nir
->info
->label
)
166 ralloc_steal(nir
, (char *)nir
->info
->label
);
168 /* Variables and registers are not dead. Steal them back. */
169 steal_list(nir
, nir_variable
, &nir
->uniforms
);
170 steal_list(nir
, nir_variable
, &nir
->inputs
);
171 steal_list(nir
, nir_variable
, &nir
->outputs
);
172 steal_list(nir
, nir_variable
, &nir
->shared
);
173 steal_list(nir
, nir_variable
, &nir
->globals
);
174 steal_list(nir
, nir_variable
, &nir
->system_values
);
175 steal_list(nir
, nir_register
, &nir
->registers
);
177 /* Recurse into functions, stealing their contents back. */
178 foreach_list_typed(nir_function
, func
, node
, &nir
->functions
) {
179 sweep_function(nir
, func
);
182 /* Free everything we didn't steal back. */
183 ralloc_free(rubbish
);