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 /* sweep_impl will mark all metadata invalid. We can safely release all of
69 ralloc_free(block
->live_in
);
70 block
->live_in
= NULL
;
72 ralloc_free(block
->live_out
);
73 block
->live_out
= NULL
;
75 nir_foreach_instr(instr
, block
) {
76 ralloc_steal(nir
, instr
);
78 nir_foreach_src(instr
, sweep_src_indirect
, nir
);
79 nir_foreach_dest(instr
, sweep_dest_indirect
, nir
);
84 sweep_if(nir_shader
*nir
, nir_if
*iff
)
86 ralloc_steal(nir
, iff
);
88 foreach_list_typed(nir_cf_node
, cf_node
, node
, &iff
->then_list
) {
89 sweep_cf_node(nir
, cf_node
);
92 foreach_list_typed(nir_cf_node
, cf_node
, node
, &iff
->else_list
) {
93 sweep_cf_node(nir
, cf_node
);
98 sweep_loop(nir_shader
*nir
, nir_loop
*loop
)
100 ralloc_steal(nir
, loop
);
102 foreach_list_typed(nir_cf_node
, cf_node
, node
, &loop
->body
) {
103 sweep_cf_node(nir
, cf_node
);
108 sweep_cf_node(nir_shader
*nir
, nir_cf_node
*cf_node
)
110 switch (cf_node
->type
) {
111 case nir_cf_node_block
:
112 sweep_block(nir
, nir_cf_node_as_block(cf_node
));
115 sweep_if(nir
, nir_cf_node_as_if(cf_node
));
117 case nir_cf_node_loop
:
118 sweep_loop(nir
, nir_cf_node_as_loop(cf_node
));
121 unreachable("Invalid CF node type");
126 sweep_impl(nir_shader
*nir
, nir_function_impl
*impl
)
128 ralloc_steal(nir
, impl
);
130 steal_list(nir
, nir_variable
, &impl
->locals
);
131 steal_list(nir
, nir_register
, &impl
->registers
);
133 foreach_list_typed(nir_cf_node
, cf_node
, node
, &impl
->body
) {
134 sweep_cf_node(nir
, cf_node
);
137 sweep_block(nir
, impl
->end_block
);
139 /* Wipe out all the metadata, if any. */
140 nir_metadata_preserve(impl
, nir_metadata_none
);
144 sweep_function(nir_shader
*nir
, nir_function
*f
)
146 ralloc_steal(nir
, f
);
147 ralloc_steal(nir
, f
->params
);
150 sweep_impl(nir
, f
->impl
);
154 nir_sweep(nir_shader
*nir
)
156 void *rubbish
= ralloc_context(NULL
);
158 /* First, move ownership of all the memory to a temporary context; assume dead. */
159 ralloc_adopt(rubbish
, nir
);
161 ralloc_steal(nir
, (char *)nir
->info
.name
);
163 ralloc_steal(nir
, (char *)nir
->info
.label
);
165 /* Variables and registers are not dead. Steal them back. */
166 steal_list(nir
, nir_variable
, &nir
->uniforms
);
167 steal_list(nir
, nir_variable
, &nir
->inputs
);
168 steal_list(nir
, nir_variable
, &nir
->outputs
);
169 steal_list(nir
, nir_variable
, &nir
->shared
);
170 steal_list(nir
, nir_variable
, &nir
->globals
);
171 steal_list(nir
, nir_variable
, &nir
->system_values
);
173 /* Recurse into functions, stealing their contents back. */
174 foreach_list_typed(nir_function
, func
, node
, &nir
->functions
) {
175 sweep_function(nir
, func
);
178 ralloc_steal(nir
, nir
->constant_data
);
180 /* Free everything we didn't steal back. */
181 ralloc_free(rubbish
);