2
* Copyright © 2014 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
24
* Connor Abbott (cwabbott0@gmail.com)
31
deref_used_for_not_store(nir_deref_instr *deref)
33
nir_foreach_use(src, &deref->dest.ssa) {
34
switch (src->parent_instr->type) {
35
case nir_instr_type_deref:
36
if (deref_used_for_not_store(nir_instr_as_deref(src->parent_instr)))
40
case nir_instr_type_intrinsic: {
41
nir_intrinsic_instr *intrin =
42
nir_instr_as_intrinsic(src->parent_instr);
43
/* The first source of copy and store intrinsics is the deref to
44
* write. Don't record those.
46
if ((intrin->intrinsic != nir_intrinsic_store_deref &&
47
intrin->intrinsic != nir_intrinsic_copy_deref) ||
48
src != &intrin->src[0])
54
/* If it's used by any other instruction type (most likely a texture
55
* or call instruction), consider it used.
65
add_var_use_deref(nir_deref_instr *deref, struct set *live)
67
if (deref->deref_type != nir_deref_type_var)
70
/* Since these local variables don't escape the shader, writing doesn't
71
* make them live. Only keep them if they are used by some intrinsic.
73
if ((deref->var->data.mode & (nir_var_function_temp |
74
nir_var_shader_temp)) &&
75
!deref_used_for_not_store(deref))
79
* Shared memory blocks (interface type) alias each other, so be
80
* conservative in that case.
82
if ((deref->var->data.mode & nir_var_mem_shared) &&
83
!glsl_type_is_interface(deref->var->type) &&
84
!deref_used_for_not_store(deref))
87
nir_variable *var = deref->var;
89
_mesa_set_add(live, var);
90
/* Also mark the chain of variables used to initialize it. */
91
var = var->pointer_initializer;
96
add_var_use_shader(nir_shader *shader, struct set *live, nir_variable_mode modes)
98
nir_foreach_function(function, shader) {
100
nir_foreach_block(block, function->impl) {
101
nir_foreach_instr(instr, block) {
102
if (instr->type == nir_instr_type_deref)
103
add_var_use_deref(nir_instr_as_deref(instr), live);
111
remove_dead_var_writes(nir_shader *shader)
113
nir_foreach_function(function, shader) {
117
nir_foreach_block(block, function->impl) {
118
nir_foreach_instr_safe(instr, block) {
119
switch (instr->type) {
120
case nir_instr_type_deref: {
121
nir_deref_instr *deref = nir_instr_as_deref(instr);
122
if (deref->deref_type == nir_deref_type_cast &&
123
!nir_deref_instr_parent(deref))
126
nir_variable_mode parent_modes;
127
if (deref->deref_type == nir_deref_type_var)
128
parent_modes = deref->var->data.mode;
130
parent_modes = nir_deref_instr_parent(deref)->modes;
132
/* If the parent mode is 0, then it references a dead variable.
133
* Flag this deref as dead and remove it.
135
if (parent_modes == 0) {
137
nir_instr_remove(&deref->instr);
142
case nir_instr_type_intrinsic: {
143
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
144
if (intrin->intrinsic != nir_intrinsic_copy_deref &&
145
intrin->intrinsic != nir_intrinsic_store_deref)
148
if (nir_src_as_deref(intrin->src[0])->modes == 0)
149
nir_instr_remove(instr);
154
break; /* Nothing to do */
162
remove_dead_vars(struct exec_list *var_list, nir_variable_mode modes,
163
struct set *live, const nir_remove_dead_variables_options *opts)
165
bool progress = false;
167
nir_foreach_variable_in_list_safe(var, var_list) {
168
if (!(var->data.mode & modes))
171
if (opts && opts->can_remove_var &&
172
!opts->can_remove_var(var, opts->can_remove_var_data))
175
struct set_entry *entry = _mesa_set_search(live, var);
177
/* Mark this variable as used by setting the mode to 0 */
179
exec_node_remove(&var->node);
188
nir_remove_dead_variables(nir_shader *shader, nir_variable_mode modes,
189
const nir_remove_dead_variables_options *opts)
191
bool progress = false;
192
struct set *live = _mesa_pointer_set_create(NULL);
194
add_var_use_shader(shader, live, modes);
196
if (modes & ~nir_var_function_temp) {
197
progress = remove_dead_vars(&shader->variables, modes,
198
live, opts) || progress;
201
if (modes & nir_var_function_temp) {
202
nir_foreach_function(function, shader) {
203
if (function->impl) {
204
if (remove_dead_vars(&function->impl->locals,
205
nir_var_function_temp,
212
_mesa_set_destroy(live, NULL);
214
nir_foreach_function(function, shader) {
219
remove_dead_var_writes(shader);
220
nir_metadata_preserve(function->impl, nir_metadata_block_index |
221
nir_metadata_dominance);
223
nir_metadata_preserve(function->impl, nir_metadata_all);