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_hierarchical_visitor
{
60 ir_copy_propagation_visitor(exec_list
*acp
)
67 virtual ir_visitor_status
visit(class ir_dereference_variable
*);
68 virtual ir_visitor_status
visit_enter(class ir_loop
*);
69 virtual ir_visitor_status
visit_enter(class ir_function_signature
*);
70 virtual ir_visitor_status
visit_enter(class ir_function
*);
71 virtual ir_visitor_status
visit_enter(class ir_assignment
*);
72 virtual ir_visitor_status
visit_enter(class ir_call
*);
73 virtual ir_visitor_status
visit_enter(class ir_if
*);
75 /** List of acp_entry */
79 /** Currently in the LHS of an assignment? */
85 ir_copy_propagation_visitor::visit_enter(ir_loop
*ir
)
88 return visit_continue_with_parent
;
92 ir_copy_propagation_visitor::visit_enter(ir_function_signature
*ir
)
95 return visit_continue_with_parent
;
99 ir_copy_propagation_visitor::visit_enter(ir_assignment
*ir
)
103 return visit_continue
;
107 ir_copy_propagation_visitor::visit_enter(ir_function
*ir
)
110 return visit_continue_with_parent
;
114 * Replaces dereferences of ACP RHS variables with ACP LHS variables.
116 * This is where the actual copy propagation occurs. Note that the
117 * rewriting of ir_dereference means that the ir_dereference instance
118 * must not be shared by multiple IR operations!
121 ir_copy_propagation_visitor::visit(ir_dereference_variable
*ir
)
123 /* Ignores the LHS. Don't want to rewrite the LHS to point at some
127 this->in_lhs
= false;
128 return visit_continue
;
131 ir_variable
*var
= ir
->variable_referenced();
133 foreach_iter(exec_list_iterator
, iter
, *this->acp
) {
134 acp_entry
*entry
= (acp_entry
*)iter
.get();
136 if (var
== entry
->lhs
) {
137 ir
->var
= entry
->rhs
;
138 this->progress
= true;
143 return visit_continue
;
148 ir_copy_propagation_visitor::visit_enter(ir_call
*ir
)
152 /* Note, if we were to do copy propagation to parameters of calls, we'd
153 * have to be careful about out params.
155 return visit_continue_with_parent
;
160 ir_copy_propagation_visitor::visit_enter(ir_if
*ir
)
162 ir
->condition
->accept(this);
164 /* Do not traverse into the body of the if-statement since that is a
165 * different basic block.
167 return visit_continue_with_parent
;
171 propagate_copies(ir_instruction
*ir
, exec_list
*acp
)
173 ir_copy_propagation_visitor
v(acp
);
181 kill_invalidated_copies(ir_assignment
*ir
, exec_list
*acp
)
183 ir_variable
*var
= ir
->lhs
->variable_referenced();
186 foreach_iter(exec_list_iterator
, iter
, *acp
) {
187 acp_entry
*entry
= (acp_entry
*)iter
.get();
189 if (entry
->lhs
== var
|| entry
->rhs
== var
) {
196 * Adds an entry to the available copy list if it's a plain assignment
197 * of a variable to a variable.
200 add_copy(ir_assignment
*ir
, exec_list
*acp
)
205 ir_constant
*condition
= ir
->condition
->as_constant();
206 if (!condition
|| !condition
->value
.b
[0])
210 ir_variable
*lhs_var
= ir
->lhs
->whole_variable_referenced();
211 ir_variable
*rhs_var
= ir
->rhs
->whole_variable_referenced();
213 if ((lhs_var
!= NULL
) && (rhs_var
!= NULL
)) {
214 entry
= new acp_entry(lhs_var
, rhs_var
);
215 acp
->push_tail(entry
);
220 copy_propagation_basic_block(ir_instruction
*first
,
221 ir_instruction
*last
,
225 /* List of avaialble_copy */
227 bool *out_progress
= (bool *)data
;
228 bool progress
= false;
230 for (ir
= first
;; ir
= (ir_instruction
*)ir
->next
) {
231 ir_assignment
*ir_assign
= ir
->as_assignment();
233 progress
= propagate_copies(ir
, &acp
) || progress
;
236 kill_invalidated_copies(ir_assign
, &acp
);
238 add_copy(ir_assign
, &acp
);
243 *out_progress
= progress
;
247 * Does a copy propagation pass on the code present in the instruction stream.
250 do_copy_propagation(exec_list
*instructions
)
252 bool progress
= false;
254 call_for_basic_blocks(instructions
, copy_propagation_basic_block
, &progress
);