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_copy_propagation.cpp
27 * Moves usage of recently-copied variables to the previous copy of
28 * the variable within basic blocks.
30 * This should reduce the number of MOV instructions in the generated
31 * programs unless copy propagation is also done on the LIR, and may
32 * help anyway by triggering other optimizations that live in the HIR.
37 #include "ir_visitor.h"
38 #include "ir_print_visitor.h"
39 #include "ir_basic_block.h"
40 #include "ir_optimization.h"
41 #include "glsl_types.h"
43 class acp_entry
: public exec_node
46 acp_entry(ir_variable
*lhs
, ir_variable
*rhs
)
58 class ir_copy_propagation_visitor
: public ir_visitor
{
60 ir_copy_propagation_visitor(exec_list
*acp
)
69 * As typical for the visitor pattern, there must be one \c visit method for
70 * each concrete subclass of \c ir_instruction. Virtual base classes within
71 * the hierarchy should not have \c visit methods.
74 virtual void visit(ir_variable
*);
75 virtual void visit(ir_loop
*);
76 virtual void visit(ir_loop_jump
*);
77 virtual void visit(ir_function_signature
*);
78 virtual void visit(ir_function
*);
79 virtual void visit(ir_expression
*);
80 virtual void visit(ir_swizzle
*);
81 virtual void visit(ir_dereference
*);
82 virtual void visit(ir_assignment
*);
83 virtual void visit(ir_constant
*);
84 virtual void visit(ir_call
*);
85 virtual void visit(ir_return
*);
86 virtual void visit(ir_if
*);
89 /** List of acp_entry */
96 ir_copy_propagation_visitor::visit(ir_variable
*ir
)
103 ir_copy_propagation_visitor::visit(ir_loop
*ir
)
109 ir_copy_propagation_visitor::visit(ir_loop_jump
*ir
)
116 ir_copy_propagation_visitor::visit(ir_function_signature
*ir
)
122 ir_copy_propagation_visitor::visit(ir_function
*ir
)
128 ir_copy_propagation_visitor::visit(ir_expression
*ir
)
130 unsigned int operand
;
132 for (operand
= 0; operand
< ir
->get_num_operands(); operand
++) {
133 ir
->operands
[operand
]->accept(this);
139 ir_copy_propagation_visitor::visit(ir_swizzle
*ir
)
141 ir
->val
->accept(this);
145 * Replaces dereferences of ACP RHS variables with ACP LHS variables.
147 * This is where the actual copy propagation occurs. Note that the
148 * rewriting of ir_dereference means that the ir_dereference instance
149 * must not be shared by multiple IR operations!
152 ir_copy_propagation_visitor::visit(ir_dereference
*ir
)
156 if (ir
->mode
== ir_dereference::ir_reference_array
) {
157 ir
->selector
.array_index
->accept(this);
160 var
= ir
->var
->as_variable();
162 foreach_iter(exec_list_iterator
, iter
, *this->acp
) {
163 acp_entry
*entry
= (acp_entry
*)iter
.get();
165 if (var
== entry
->lhs
) {
166 ir
->var
= entry
->rhs
;
167 this->progress
= true;
172 ir
->var
->accept(this);
177 ir_copy_propagation_visitor::visit(ir_assignment
*ir
)
180 ir
->condition
->accept(this);
182 /* Ignores the LHS. Don't want to rewrite the LHS to point at some
186 ir
->rhs
->accept(this);
191 ir_copy_propagation_visitor::visit(ir_constant
*ir
)
198 ir_copy_propagation_visitor::visit(ir_call
*ir
)
202 /* Note, if we were to do copy propagation to parameters of calls, we'd
203 * have to be careful about out params.
209 ir_copy_propagation_visitor::visit(ir_return
*ir
)
211 ir_rvalue
*val
= ir
->get_value();
219 ir_copy_propagation_visitor::visit(ir_if
*ir
)
221 ir
->condition
->accept(this);
225 propagate_copies(ir_instruction
*ir
, exec_list
*acp
)
227 ir_copy_propagation_visitor
v(acp
);
235 kill_invalidated_copies(ir_assignment
*ir
, exec_list
*acp
)
237 ir_instruction
*current
= ir
->lhs
;
239 /* Walk down the dereference chain to find the variable at the end
240 * of it that we're actually modifying.
242 while (current
!= NULL
) {
244 ir_dereference
*deref
;
246 if ((swiz
= current
->as_swizzle())) {
248 } else if ((deref
= current
->as_dereference())) {
249 current
= deref
->var
;
251 ir_variable
*var
= current
->as_variable();
254 foreach_iter(exec_list_iterator
, iter
, *acp
) {
255 acp_entry
*entry
= (acp_entry
*)iter
.get();
257 if (entry
->lhs
== var
|| entry
->rhs
== var
) {
268 * Adds an entry to the available copy list if it's a plain assignment
269 * of a variable to a variable.
272 add_copy(ir_assignment
*ir
, exec_list
*acp
)
277 ir_constant
*condition
= ir
->condition
->as_constant();
278 if (!condition
|| !condition
->value
.b
[0])
282 ir_dereference
*lhs_deref
= ir
->lhs
->as_dereference();
283 if (!lhs_deref
|| lhs_deref
->mode
!= ir_dereference::ir_reference_variable
)
285 ir_variable
*lhs_var
= lhs_deref
->var
->as_variable();
287 ir_dereference
*rhs_deref
= ir
->rhs
->as_dereference();
288 if (!rhs_deref
|| rhs_deref
->mode
!= ir_dereference::ir_reference_variable
)
290 ir_variable
*rhs_var
= rhs_deref
->var
->as_variable();
292 entry
= new acp_entry(lhs_var
, rhs_var
);
293 acp
->push_tail(entry
);
297 copy_propagation_basic_block(ir_instruction
*first
,
298 ir_instruction
*last
,
302 /* List of avaialble_copy */
304 bool *out_progress
= (bool *)data
;
305 bool progress
= false;
307 for (ir
= first
;; ir
= (ir_instruction
*)ir
->next
) {
308 ir_assignment
*ir_assign
= ir
->as_assignment();
310 progress
= propagate_copies(ir
, &acp
) || progress
;
313 kill_invalidated_copies(ir_assign
, &acp
);
315 add_copy(ir_assign
, &acp
);
320 *out_progress
= progress
;
324 * Does a copy propagation pass on the code present in the instruction stream.
327 do_copy_propagation(exec_list
*instructions
)
329 bool progress
= false;
331 call_for_basic_blocks(instructions
, copy_propagation_basic_block
, &progress
);