2 * Copyright © 2010 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
21 * DEALINGS IN THE SOFTWARE.
25 * \file ir_dead_code.cpp
27 * Eliminates dead assignments and variable declarations from the code.
32 #include "ir_visitor.h"
33 #include "ir_expression_flattening.h"
34 #include "glsl_types.h"
36 class variable_entry
: public exec_node
39 variable_entry(ir_variable
*var
)
47 ir_variable
*var
; /* The key: the variable's pointer. */
48 ir_assignment
*assign
; /* An assignment to the variable, if any */
49 bool referenced
; /* If the variable has ever been referenced. */
50 bool declaration
; /* If the variable had a decl in the instruction stream */
53 class ir_dead_code_visitor
: public ir_visitor
{
59 * As typical for the visitor pattern, there must be one \c visit method for
60 * each concrete subclass of \c ir_instruction. Virtual base classes within
61 * the hierarchy should not have \c visit methods.
64 virtual void visit(ir_variable
*);
65 virtual void visit(ir_loop
*);
66 virtual void visit(ir_loop_jump
*);
67 virtual void visit(ir_function_signature
*);
68 virtual void visit(ir_function
*);
69 virtual void visit(ir_expression
*);
70 virtual void visit(ir_swizzle
*);
71 virtual void visit(ir_dereference
*);
72 virtual void visit(ir_assignment
*);
73 virtual void visit(ir_constant
*);
74 virtual void visit(ir_call
*);
75 virtual void visit(ir_return
*);
76 virtual void visit(ir_if
*);
79 variable_entry
*get_variable_entry(ir_variable
*var
);
81 bool (*predicate
)(ir_instruction
*ir
);
82 ir_instruction
*base_ir
;
84 /* List of variable_entry */
85 exec_list variable_list
;
89 ir_dead_code_visitor::get_variable_entry(ir_variable
*var
)
92 foreach_iter(exec_list_iterator
, iter
, this->variable_list
) {
93 variable_entry
*entry
= (variable_entry
*)iter
.get();
94 if (entry
->var
== var
)
98 variable_entry
*entry
= new variable_entry(var
);
99 this->variable_list
.push_tail(entry
);
104 find_dead_code(exec_list
*instructions
, ir_dead_code_visitor
*v
)
106 foreach_iter(exec_list_iterator
, iter
, *instructions
) {
107 ir_instruction
*ir
= (ir_instruction
*)iter
.get();
114 ir_dead_code_visitor::visit(ir_variable
*ir
)
116 variable_entry
*entry
= this->get_variable_entry(ir
);
118 entry
->declaration
= true;
124 ir_dead_code_visitor::visit(ir_loop
*ir
)
126 find_dead_code(&ir
->body_instructions
, this);
128 ir
->from
->accept(this);
130 ir
->to
->accept(this);
132 ir
->increment
->accept(this);
136 ir_dead_code_visitor::visit(ir_loop_jump
*ir
)
143 ir_dead_code_visitor::visit(ir_function_signature
*ir
)
145 find_dead_code(&ir
->body
, this);
149 ir_dead_code_visitor::visit(ir_function
*ir
)
155 ir_dead_code_visitor::visit(ir_expression
*ir
)
157 unsigned int operand
;
159 for (operand
= 0; operand
< ir
->get_num_operands(); operand
++) {
160 ir
->operands
[operand
]->accept(this);
166 ir_dead_code_visitor::visit(ir_swizzle
*ir
)
168 ir
->val
->accept(this);
173 ir_dead_code_visitor::visit(ir_dereference
*ir
)
177 if (ir
->mode
== ir_dereference::ir_reference_array
) {
178 ir
->selector
.array_index
->accept(this);
181 var
= ir
->var
->as_variable();
183 variable_entry
*entry
= this->get_variable_entry(var
);
184 entry
->referenced
= true;
186 ir
->var
->accept(this);
191 ir_dead_code_visitor::visit(ir_assignment
*ir
)
193 ir_instruction
*lhs
= ir
->lhs
;
195 /* Walk through the LHS and mark references for variables used in
196 * array indices but not for the assignment dereference.
199 if (lhs
->as_variable())
202 ir_dereference
*deref
= lhs
->as_dereference();
204 if (deref
->mode
== ir_dereference::ir_reference_array
)
205 deref
->selector
.array_index
->accept(this);
208 ir_swizzle
*swiz
= lhs
->as_swizzle();
214 ir
->rhs
->accept(this);
216 ir
->condition
->accept(this);
218 variable_entry
*entry
;
219 entry
= this->get_variable_entry(lhs
->as_variable());
221 if (entry
->assign
== NULL
)
228 ir_dead_code_visitor::visit(ir_constant
*ir
)
235 ir_dead_code_visitor::visit(ir_call
*ir
)
237 foreach_iter(exec_list_iterator
, iter
, *ir
) {
238 ir_rvalue
*param
= (ir_rvalue
*)iter
.get();
240 /* FINISHME: handle out values. */
244 /* Ignore the callee. Function bodies will get handled when they're
245 * encountered at the top level instruction stream and spawn their
246 * own dead code visitor.
252 ir_dead_code_visitor::visit(ir_return
*ir
)
254 ir
->get_value()->accept(this);
259 ir_dead_code_visitor::visit(ir_if
*ir
)
261 ir
->condition
->accept(this);
263 find_dead_code(&ir
->then_instructions
, this);
264 find_dead_code(&ir
->else_instructions
, this);
268 * Do a dead code pass over instructions and everything that instructions
271 * Note that this will remove assignments to globals, so it is not suitable
272 * for usage on an unlinked instruction stream.
275 do_dead_code(exec_list
*instructions
)
277 ir_dead_code_visitor v
;
278 bool progress
= false;
280 find_dead_code(instructions
, &v
);
282 foreach_iter(exec_list_iterator
, iter
, v
.variable_list
) {
283 variable_entry
*entry
= (variable_entry
*)iter
.get();
285 if (entry
->referenced
|| !entry
->declaration
)
289 /* Remove a single dead assignment to the variable we found.
290 * Don't do so if it's a shader output, though.
292 if (!entry
->var
->shader_out
) {
293 entry
->assign
->remove();
297 /* If there are no assignments or references to the variable left,
298 * then we can remove its declaration.
300 entry
->var
->remove();
308 * Does a dead code pass on the functions present in the instruction stream.
310 * This is suitable for use while the program is not linked, as it will
311 * ignore variable declarations (and the assignments to them) for variables
315 do_dead_code_unlinked(exec_list
*instructions
)
317 bool progress
= false;
319 foreach_iter(exec_list_iterator
, iter
, *instructions
) {
320 ir_instruction
*ir
= (ir_instruction
*)iter
.get();
321 ir_function
*f
= ir
->as_function();
323 foreach_iter(exec_list_iterator
, sigiter
, *f
) {
324 ir_function_signature
*sig
=
325 (ir_function_signature
*) sigiter
.get();
326 if (do_dead_code(&sig
->body
))