1784695442c415cf0be882434a25671ecfb635d34Eric Anholt/*
2784695442c415cf0be882434a25671ecfb635d34Eric Anholt * Copyright © 2010 Intel Corporation
3784695442c415cf0be882434a25671ecfb635d34Eric Anholt *
4784695442c415cf0be882434a25671ecfb635d34Eric Anholt * Permission is hereby granted, free of charge, to any person obtaining a
5784695442c415cf0be882434a25671ecfb635d34Eric Anholt * copy of this software and associated documentation files (the "Software"),
6784695442c415cf0be882434a25671ecfb635d34Eric Anholt * to deal in the Software without restriction, including without limitation
7784695442c415cf0be882434a25671ecfb635d34Eric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8784695442c415cf0be882434a25671ecfb635d34Eric Anholt * and/or sell copies of the Software, and to permit persons to whom the
9784695442c415cf0be882434a25671ecfb635d34Eric Anholt * Software is furnished to do so, subject to the following conditions:
10784695442c415cf0be882434a25671ecfb635d34Eric Anholt *
11784695442c415cf0be882434a25671ecfb635d34Eric Anholt * The above copyright notice and this permission notice (including the next
12784695442c415cf0be882434a25671ecfb635d34Eric Anholt * paragraph) shall be included in all copies or substantial portions of the
13784695442c415cf0be882434a25671ecfb635d34Eric Anholt * Software.
14784695442c415cf0be882434a25671ecfb635d34Eric Anholt *
15784695442c415cf0be882434a25671ecfb635d34Eric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16784695442c415cf0be882434a25671ecfb635d34Eric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17784695442c415cf0be882434a25671ecfb635d34Eric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18784695442c415cf0be882434a25671ecfb635d34Eric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19784695442c415cf0be882434a25671ecfb635d34Eric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20784695442c415cf0be882434a25671ecfb635d34Eric Anholt * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21784695442c415cf0be882434a25671ecfb635d34Eric Anholt * DEALINGS IN THE SOFTWARE.
22784695442c415cf0be882434a25671ecfb635d34Eric Anholt */
23784695442c415cf0be882434a25671ecfb635d34Eric Anholt
24784695442c415cf0be882434a25671ecfb635d34Eric Anholt/**
25df883eb1575a740bf91e01cbe2eaa4dbc1f9f154Chad Versace * \file opt_tree_grafting.cpp
26784695442c415cf0be882434a25671ecfb635d34Eric Anholt *
27784695442c415cf0be882434a25671ecfb635d34Eric Anholt * Takes assignments to variables that are dereferenced only once and
28784695442c415cf0be882434a25671ecfb635d34Eric Anholt * pastes the RHS expression into where the variable is dereferenced.
29784695442c415cf0be882434a25671ecfb635d34Eric Anholt *
30784695442c415cf0be882434a25671ecfb635d34Eric Anholt * In the process of various operations like function inlining and
31784695442c415cf0be882434a25671ecfb635d34Eric Anholt * tertiary op handling, we'll end up with our expression trees having
32784695442c415cf0be882434a25671ecfb635d34Eric Anholt * been chopped up into a series of assignments of short expressions
33784695442c415cf0be882434a25671ecfb635d34Eric Anholt * to temps.  Other passes like ir_algebraic.cpp would prefer to see
34784695442c415cf0be882434a25671ecfb635d34Eric Anholt * the deepest expression trees they can to try to optimize them.
35784695442c415cf0be882434a25671ecfb635d34Eric Anholt *
36784695442c415cf0be882434a25671ecfb635d34Eric Anholt * This is a lot like copy propagaton.  In comparison, copy
37784695442c415cf0be882434a25671ecfb635d34Eric Anholt * propagation only acts on plain copies, not arbitrary expressions on
38784695442c415cf0be882434a25671ecfb635d34Eric Anholt * the RHS.  Generally, we wouldn't want to go pasting some
39784695442c415cf0be882434a25671ecfb635d34Eric Anholt * complicated expression everywhere it got used, though, so we don't
40784695442c415cf0be882434a25671ecfb635d34Eric Anholt * handle expressions in that pass.
41784695442c415cf0be882434a25671ecfb635d34Eric Anholt *
42784695442c415cf0be882434a25671ecfb635d34Eric Anholt * The hard part is making sure we don't move an expression across
43784695442c415cf0be882434a25671ecfb635d34Eric Anholt * some other assignments that would change the value of the
44784695442c415cf0be882434a25671ecfb635d34Eric Anholt * expression.  So we split this into two passes: First, find the
45784695442c415cf0be882434a25671ecfb635d34Eric Anholt * variables in our scope which are written to once and read once, and
46784695442c415cf0be882434a25671ecfb635d34Eric Anholt * then go through basic blocks seeing if we find an opportunity to
47784695442c415cf0be882434a25671ecfb635d34Eric Anholt * move those expressions safely.
48784695442c415cf0be882434a25671ecfb635d34Eric Anholt */
49784695442c415cf0be882434a25671ecfb635d34Eric Anholt
50784695442c415cf0be882434a25671ecfb635d34Eric Anholt#include "ir.h"
51784695442c415cf0be882434a25671ecfb635d34Eric Anholt#include "ir_visitor.h"
52784695442c415cf0be882434a25671ecfb635d34Eric Anholt#include "ir_variable_refcount.h"
53784695442c415cf0be882434a25671ecfb635d34Eric Anholt#include "ir_basic_block.h"
54784695442c415cf0be882434a25671ecfb635d34Eric Anholt#include "ir_optimization.h"
55784695442c415cf0be882434a25671ecfb635d34Eric Anholt#include "glsl_types.h"
56784695442c415cf0be882434a25671ecfb635d34Eric Anholt
57337d9c955b070224f7278524af54ddacd8bb0f17Eric Anholtnamespace {
58337d9c955b070224f7278524af54ddacd8bb0f17Eric Anholt
59784695442c415cf0be882434a25671ecfb635d34Eric Anholtstatic bool debug = false;
60784695442c415cf0be882434a25671ecfb635d34Eric Anholt
61784695442c415cf0be882434a25671ecfb635d34Eric Anholtclass ir_tree_grafting_visitor : public ir_hierarchical_visitor {
62784695442c415cf0be882434a25671ecfb635d34Eric Anholtpublic:
63784695442c415cf0be882434a25671ecfb635d34Eric Anholt   ir_tree_grafting_visitor(ir_assignment *graft_assign,
64784695442c415cf0be882434a25671ecfb635d34Eric Anholt			    ir_variable *graft_var)
65784695442c415cf0be882434a25671ecfb635d34Eric Anholt   {
66784695442c415cf0be882434a25671ecfb635d34Eric Anholt      this->progress = false;
67784695442c415cf0be882434a25671ecfb635d34Eric Anholt      this->graft_assign = graft_assign;
68784695442c415cf0be882434a25671ecfb635d34Eric Anholt      this->graft_var = graft_var;
69784695442c415cf0be882434a25671ecfb635d34Eric Anholt   }
70784695442c415cf0be882434a25671ecfb635d34Eric Anholt
71784695442c415cf0be882434a25671ecfb635d34Eric Anholt   virtual ir_visitor_status visit_leave(class ir_assignment *);
72784695442c415cf0be882434a25671ecfb635d34Eric Anholt   virtual ir_visitor_status visit_enter(class ir_call *);
73784695442c415cf0be882434a25671ecfb635d34Eric Anholt   virtual ir_visitor_status visit_enter(class ir_expression *);
74784695442c415cf0be882434a25671ecfb635d34Eric Anholt   virtual ir_visitor_status visit_enter(class ir_function *);
75784695442c415cf0be882434a25671ecfb635d34Eric Anholt   virtual ir_visitor_status visit_enter(class ir_function_signature *);
76784695442c415cf0be882434a25671ecfb635d34Eric Anholt   virtual ir_visitor_status visit_enter(class ir_if *);
77784695442c415cf0be882434a25671ecfb635d34Eric Anholt   virtual ir_visitor_status visit_enter(class ir_loop *);
78784695442c415cf0be882434a25671ecfb635d34Eric Anholt   virtual ir_visitor_status visit_enter(class ir_swizzle *);
79784695442c415cf0be882434a25671ecfb635d34Eric Anholt   virtual ir_visitor_status visit_enter(class ir_texture *);
80784695442c415cf0be882434a25671ecfb635d34Eric Anholt
813c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke   ir_visitor_status check_graft(ir_instruction *ir, ir_variable *var);
823c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke
83784695442c415cf0be882434a25671ecfb635d34Eric Anholt   bool do_graft(ir_rvalue **rvalue);
84784695442c415cf0be882434a25671ecfb635d34Eric Anholt
85784695442c415cf0be882434a25671ecfb635d34Eric Anholt   bool progress;
86784695442c415cf0be882434a25671ecfb635d34Eric Anholt   ir_variable *graft_var;
87784695442c415cf0be882434a25671ecfb635d34Eric Anholt   ir_assignment *graft_assign;
88784695442c415cf0be882434a25671ecfb635d34Eric Anholt};
89784695442c415cf0be882434a25671ecfb635d34Eric Anholt
90784695442c415cf0be882434a25671ecfb635d34Eric Anholtstruct find_deref_info {
91784695442c415cf0be882434a25671ecfb635d34Eric Anholt   ir_variable *var;
92784695442c415cf0be882434a25671ecfb635d34Eric Anholt   bool found;
93784695442c415cf0be882434a25671ecfb635d34Eric Anholt};
94784695442c415cf0be882434a25671ecfb635d34Eric Anholt
95784695442c415cf0be882434a25671ecfb635d34Eric Anholtvoid
96784695442c415cf0be882434a25671ecfb635d34Eric Anholtdereferences_variable_callback(ir_instruction *ir, void *data)
97784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
98784695442c415cf0be882434a25671ecfb635d34Eric Anholt   struct find_deref_info *info = (struct find_deref_info *)data;
99c314c8f2310fa0ac51b8953e139f9504e08eb48fEric Anholt   ir_dereference_variable *deref = ir->as_dereference_variable();
100784695442c415cf0be882434a25671ecfb635d34Eric Anholt
101c314c8f2310fa0ac51b8953e139f9504e08eb48fEric Anholt   if (deref && deref->var == info->var)
102784695442c415cf0be882434a25671ecfb635d34Eric Anholt      info->found = true;
103784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
104784695442c415cf0be882434a25671ecfb635d34Eric Anholt
105784695442c415cf0be882434a25671ecfb635d34Eric Anholtstatic bool
106784695442c415cf0be882434a25671ecfb635d34Eric Anholtdereferences_variable(ir_instruction *ir, ir_variable *var)
107784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
108784695442c415cf0be882434a25671ecfb635d34Eric Anholt   struct find_deref_info info;
109784695442c415cf0be882434a25671ecfb635d34Eric Anholt
110784695442c415cf0be882434a25671ecfb635d34Eric Anholt   info.var = var;
111784695442c415cf0be882434a25671ecfb635d34Eric Anholt   info.found = false;
112784695442c415cf0be882434a25671ecfb635d34Eric Anholt
113784695442c415cf0be882434a25671ecfb635d34Eric Anholt   visit_tree(ir, dereferences_variable_callback, &info);
114784695442c415cf0be882434a25671ecfb635d34Eric Anholt
115784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return info.found;
116784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
117784695442c415cf0be882434a25671ecfb635d34Eric Anholt
118784695442c415cf0be882434a25671ecfb635d34Eric Anholtbool
119784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_tree_grafting_visitor::do_graft(ir_rvalue **rvalue)
120784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
121784695442c415cf0be882434a25671ecfb635d34Eric Anholt   if (!*rvalue)
122784695442c415cf0be882434a25671ecfb635d34Eric Anholt      return false;
123784695442c415cf0be882434a25671ecfb635d34Eric Anholt
124784695442c415cf0be882434a25671ecfb635d34Eric Anholt   ir_dereference_variable *deref = (*rvalue)->as_dereference_variable();
125784695442c415cf0be882434a25671ecfb635d34Eric Anholt
126784695442c415cf0be882434a25671ecfb635d34Eric Anholt   if (!deref || deref->var != this->graft_var)
127784695442c415cf0be882434a25671ecfb635d34Eric Anholt      return false;
128784695442c415cf0be882434a25671ecfb635d34Eric Anholt
129784695442c415cf0be882434a25671ecfb635d34Eric Anholt   if (debug) {
130784695442c415cf0be882434a25671ecfb635d34Eric Anholt      printf("GRAFTING:\n");
131c314c8f2310fa0ac51b8953e139f9504e08eb48fEric Anholt      this->graft_assign->print();
132784695442c415cf0be882434a25671ecfb635d34Eric Anholt      printf("\n");
133784695442c415cf0be882434a25671ecfb635d34Eric Anholt      printf("TO:\n");
134784695442c415cf0be882434a25671ecfb635d34Eric Anholt      (*rvalue)->print();
135784695442c415cf0be882434a25671ecfb635d34Eric Anholt      printf("\n");
136784695442c415cf0be882434a25671ecfb635d34Eric Anholt   }
137784695442c415cf0be882434a25671ecfb635d34Eric Anholt
138784695442c415cf0be882434a25671ecfb635d34Eric Anholt   this->graft_assign->remove();
139784695442c415cf0be882434a25671ecfb635d34Eric Anholt   *rvalue = this->graft_assign->rhs;
140784695442c415cf0be882434a25671ecfb635d34Eric Anholt
141784695442c415cf0be882434a25671ecfb635d34Eric Anholt   this->progress = true;
142784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return true;
143784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
144784695442c415cf0be882434a25671ecfb635d34Eric Anholt
145784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_visitor_status
146784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_tree_grafting_visitor::visit_enter(ir_loop *ir)
147784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
148784695442c415cf0be882434a25671ecfb635d34Eric Anholt   (void)ir;
149784695442c415cf0be882434a25671ecfb635d34Eric Anholt   /* Do not traverse into the body of the loop since that is a
150784695442c415cf0be882434a25671ecfb635d34Eric Anholt    * different basic block.
151784695442c415cf0be882434a25671ecfb635d34Eric Anholt    */
152784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return visit_stop;
153784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
154784695442c415cf0be882434a25671ecfb635d34Eric Anholt
1553c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke/**
1563c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke * Check if we can continue grafting after writing to a variable.  If the
1573c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke * expression we're trying to graft references the variable, we must stop.
1583c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke *
1593c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke * \param ir   An instruction that writes to a variable.
1603c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke * \param var  The variable being updated.
1613c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke */
162784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_visitor_status
1633c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunkeir_tree_grafting_visitor::check_graft(ir_instruction *ir, ir_variable *var)
164784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
1653c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke   if (dereferences_variable(this->graft_assign->rhs, var)) {
166784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (debug) {
167784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 printf("graft killed by: ");
168784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 ir->print();
169784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 printf("\n");
170784695442c415cf0be882434a25671ecfb635d34Eric Anholt      }
171784695442c415cf0be882434a25671ecfb635d34Eric Anholt      return visit_stop;
172784695442c415cf0be882434a25671ecfb635d34Eric Anholt   }
173784695442c415cf0be882434a25671ecfb635d34Eric Anholt
174784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return visit_continue;
175784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
176784695442c415cf0be882434a25671ecfb635d34Eric Anholt
177784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_visitor_status
1783c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunkeir_tree_grafting_visitor::visit_leave(ir_assignment *ir)
1793c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke{
1803c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke   if (do_graft(&ir->rhs) ||
1813c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke       do_graft(&ir->condition))
1823c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke      return visit_stop;
1833c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke
1843c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke   /* If this assignment updates a variable used in the assignment
1853c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke    * we're trying to graft, then we're done.
1863c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke    */
1873c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke   return check_graft(ir, ir->lhs->variable_referenced());
1883c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke}
1893c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke
1903c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunkeir_visitor_status
191784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_tree_grafting_visitor::visit_enter(ir_function *ir)
192784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
193784695442c415cf0be882434a25671ecfb635d34Eric Anholt   (void) ir;
194784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return visit_continue_with_parent;
195784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
196784695442c415cf0be882434a25671ecfb635d34Eric Anholt
197784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_visitor_status
198784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_tree_grafting_visitor::visit_enter(ir_function_signature *ir)
199784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
200784695442c415cf0be882434a25671ecfb635d34Eric Anholt   (void)ir;
201784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return visit_continue_with_parent;
202784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
203784695442c415cf0be882434a25671ecfb635d34Eric Anholt
204784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_visitor_status
205784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_tree_grafting_visitor::visit_enter(ir_call *ir)
206784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
20782065fa20ee3f2880a070f1f4f75509b910ceddeKenneth Graunke   exec_list_iterator sig_iter = ir->callee->parameters.iterator();
208784695442c415cf0be882434a25671ecfb635d34Eric Anholt   /* Reminder: iterating ir_call iterates its parameters. */
209784695442c415cf0be882434a25671ecfb635d34Eric Anholt   foreach_iter(exec_list_iterator, iter, *ir) {
210137b8397fa5cc5d70e86a4b14d6be9326340f584Eric Anholt      ir_variable *sig_param = (ir_variable *)sig_iter.get();
211784695442c415cf0be882434a25671ecfb635d34Eric Anholt      ir_rvalue *ir = (ir_rvalue *)iter.get();
212784695442c415cf0be882434a25671ecfb635d34Eric Anholt      ir_rvalue *new_ir = ir;
213784695442c415cf0be882434a25671ecfb635d34Eric Anholt
2143c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke      if (sig_param->mode != ir_var_in && sig_param->mode != ir_var_const_in) {
2153c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke	 if (check_graft(ir, sig_param) == visit_stop)
2163c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke	    return visit_stop;
217137b8397fa5cc5d70e86a4b14d6be9326340f584Eric Anholt	 continue;
2183c22e3516527ccb83f2667abfa0e6518c5938df8Kenneth Graunke      }
219137b8397fa5cc5d70e86a4b14d6be9326340f584Eric Anholt
220784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (do_graft(&new_ir)) {
221784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 ir->replace_with(new_ir);
222784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 return visit_stop;
223784695442c415cf0be882434a25671ecfb635d34Eric Anholt      }
224ea709696185846c876581e1c41a21921826823ecEric Anholt      sig_iter.next();
225784695442c415cf0be882434a25671ecfb635d34Eric Anholt   }
226784695442c415cf0be882434a25671ecfb635d34Eric Anholt
227d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke   if (ir->return_deref && check_graft(ir, ir->return_deref->var) == visit_stop)
228d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke      return visit_stop;
229d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke
230784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return visit_continue;
231784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
232784695442c415cf0be882434a25671ecfb635d34Eric Anholt
233784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_visitor_status
234784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_tree_grafting_visitor::visit_enter(ir_expression *ir)
235784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
236784695442c415cf0be882434a25671ecfb635d34Eric Anholt   for (unsigned int i = 0; i < ir->get_num_operands(); i++) {
237784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (do_graft(&ir->operands[i]))
238784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 return visit_stop;
239784695442c415cf0be882434a25671ecfb635d34Eric Anholt   }
240784695442c415cf0be882434a25671ecfb635d34Eric Anholt
241784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return visit_continue;
242784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
243784695442c415cf0be882434a25671ecfb635d34Eric Anholt
244784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_visitor_status
245784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_tree_grafting_visitor::visit_enter(ir_if *ir)
246784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
247784695442c415cf0be882434a25671ecfb635d34Eric Anholt   if (do_graft(&ir->condition))
248784695442c415cf0be882434a25671ecfb635d34Eric Anholt      return visit_stop;
249784695442c415cf0be882434a25671ecfb635d34Eric Anholt
250784695442c415cf0be882434a25671ecfb635d34Eric Anholt   /* Do not traverse into the body of the if-statement since that is a
251784695442c415cf0be882434a25671ecfb635d34Eric Anholt    * different basic block.
252784695442c415cf0be882434a25671ecfb635d34Eric Anholt    */
253784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return visit_continue_with_parent;
254784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
255784695442c415cf0be882434a25671ecfb635d34Eric Anholt
256784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_visitor_status
257784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_tree_grafting_visitor::visit_enter(ir_swizzle *ir)
258784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
259784695442c415cf0be882434a25671ecfb635d34Eric Anholt   if (do_graft(&ir->val))
260784695442c415cf0be882434a25671ecfb635d34Eric Anholt      return visit_stop;
261784695442c415cf0be882434a25671ecfb635d34Eric Anholt
262784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return visit_continue;
263784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
264784695442c415cf0be882434a25671ecfb635d34Eric Anholt
265784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_visitor_status
266784695442c415cf0be882434a25671ecfb635d34Eric Anholtir_tree_grafting_visitor::visit_enter(ir_texture *ir)
267784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
268784695442c415cf0be882434a25671ecfb635d34Eric Anholt   if (do_graft(&ir->coordinate) ||
269784695442c415cf0be882434a25671ecfb635d34Eric Anholt       do_graft(&ir->projector) ||
270c5a27b5939427bdc95c926b450ed3de1ff4baafbKenneth Graunke       do_graft(&ir->offset) ||
271784695442c415cf0be882434a25671ecfb635d34Eric Anholt       do_graft(&ir->shadow_comparitor))
272784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 return visit_stop;
273784695442c415cf0be882434a25671ecfb635d34Eric Anholt
274784695442c415cf0be882434a25671ecfb635d34Eric Anholt   switch (ir->op) {
275784695442c415cf0be882434a25671ecfb635d34Eric Anholt   case ir_tex:
276784695442c415cf0be882434a25671ecfb635d34Eric Anholt      break;
277784695442c415cf0be882434a25671ecfb635d34Eric Anholt   case ir_txb:
278784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (do_graft(&ir->lod_info.bias))
279784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 return visit_stop;
280784695442c415cf0be882434a25671ecfb635d34Eric Anholt      break;
281784695442c415cf0be882434a25671ecfb635d34Eric Anholt   case ir_txf:
282784695442c415cf0be882434a25671ecfb635d34Eric Anholt   case ir_txl:
2831e3bcbdf31f09666ba358f35ff9486faee3642caKenneth Graunke   case ir_txs:
284784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (do_graft(&ir->lod_info.lod))
285784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 return visit_stop;
286784695442c415cf0be882434a25671ecfb635d34Eric Anholt      break;
287784695442c415cf0be882434a25671ecfb635d34Eric Anholt   case ir_txd:
288784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (do_graft(&ir->lod_info.grad.dPdx) ||
289784695442c415cf0be882434a25671ecfb635d34Eric Anholt	  do_graft(&ir->lod_info.grad.dPdy))
290784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 return visit_stop;
291784695442c415cf0be882434a25671ecfb635d34Eric Anholt      break;
292784695442c415cf0be882434a25671ecfb635d34Eric Anholt   }
293784695442c415cf0be882434a25671ecfb635d34Eric Anholt
294784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return visit_continue;
295784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
296784695442c415cf0be882434a25671ecfb635d34Eric Anholt
297784695442c415cf0be882434a25671ecfb635d34Eric Anholtstruct tree_grafting_info {
298784695442c415cf0be882434a25671ecfb635d34Eric Anholt   ir_variable_refcount_visitor *refs;
299784695442c415cf0be882434a25671ecfb635d34Eric Anholt   bool progress;
300784695442c415cf0be882434a25671ecfb635d34Eric Anholt};
301784695442c415cf0be882434a25671ecfb635d34Eric Anholt
302784695442c415cf0be882434a25671ecfb635d34Eric Anholtstatic bool
303784695442c415cf0be882434a25671ecfb635d34Eric Anholttry_tree_grafting(ir_assignment *start,
304784695442c415cf0be882434a25671ecfb635d34Eric Anholt		  ir_variable *lhs_var,
305784695442c415cf0be882434a25671ecfb635d34Eric Anholt		  ir_instruction *bb_last)
306784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
307784695442c415cf0be882434a25671ecfb635d34Eric Anholt   ir_tree_grafting_visitor v(start, lhs_var);
308784695442c415cf0be882434a25671ecfb635d34Eric Anholt
309784695442c415cf0be882434a25671ecfb635d34Eric Anholt   if (debug) {
310784695442c415cf0be882434a25671ecfb635d34Eric Anholt      printf("trying to graft: ");
311784695442c415cf0be882434a25671ecfb635d34Eric Anholt      lhs_var->print();
312784695442c415cf0be882434a25671ecfb635d34Eric Anholt      printf("\n");
313784695442c415cf0be882434a25671ecfb635d34Eric Anholt   }
314784695442c415cf0be882434a25671ecfb635d34Eric Anholt
315784695442c415cf0be882434a25671ecfb635d34Eric Anholt   for (ir_instruction *ir = (ir_instruction *)start->next;
316784695442c415cf0be882434a25671ecfb635d34Eric Anholt	ir != bb_last->next;
317784695442c415cf0be882434a25671ecfb635d34Eric Anholt	ir = (ir_instruction *)ir->next) {
318784695442c415cf0be882434a25671ecfb635d34Eric Anholt
319784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (debug) {
320784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 printf("- ");
321784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 ir->print();
322784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 printf("\n");
323784695442c415cf0be882434a25671ecfb635d34Eric Anholt      }
324784695442c415cf0be882434a25671ecfb635d34Eric Anholt
325784695442c415cf0be882434a25671ecfb635d34Eric Anholt      ir_visitor_status s = ir->accept(&v);
326784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (s == visit_stop)
327784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 return v.progress;
328784695442c415cf0be882434a25671ecfb635d34Eric Anholt   }
329784695442c415cf0be882434a25671ecfb635d34Eric Anholt
330784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return false;
331784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
332784695442c415cf0be882434a25671ecfb635d34Eric Anholt
333784695442c415cf0be882434a25671ecfb635d34Eric Anholtstatic void
334784695442c415cf0be882434a25671ecfb635d34Eric Anholttree_grafting_basic_block(ir_instruction *bb_first,
335784695442c415cf0be882434a25671ecfb635d34Eric Anholt			  ir_instruction *bb_last,
336784695442c415cf0be882434a25671ecfb635d34Eric Anholt			  void *data)
337784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
338784695442c415cf0be882434a25671ecfb635d34Eric Anholt   struct tree_grafting_info *info = (struct tree_grafting_info *)data;
339784695442c415cf0be882434a25671ecfb635d34Eric Anholt   ir_instruction *ir, *next;
340784695442c415cf0be882434a25671ecfb635d34Eric Anholt
341784695442c415cf0be882434a25671ecfb635d34Eric Anholt   for (ir = bb_first, next = (ir_instruction *)ir->next;
342784695442c415cf0be882434a25671ecfb635d34Eric Anholt	ir != bb_last->next;
343784695442c415cf0be882434a25671ecfb635d34Eric Anholt	ir = next, next = (ir_instruction *)ir->next) {
344784695442c415cf0be882434a25671ecfb635d34Eric Anholt      ir_assignment *assign = ir->as_assignment();
345784695442c415cf0be882434a25671ecfb635d34Eric Anholt
346784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (!assign)
347784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 continue;
348784695442c415cf0be882434a25671ecfb635d34Eric Anholt
3495a7758efbe14dee026245a4f4f4fb3ccf7b2c23bIan Romanick      ir_variable *lhs_var = assign->whole_variable_written();
350784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (!lhs_var)
351784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 continue;
352784695442c415cf0be882434a25671ecfb635d34Eric Anholt
353b259eb28049fc06ebc75a7714834b9ed037a3454Eric Anholt      if (lhs_var->mode == ir_var_out ||
354b259eb28049fc06ebc75a7714834b9ed037a3454Eric Anholt	  lhs_var->mode == ir_var_inout)
355b259eb28049fc06ebc75a7714834b9ed037a3454Eric Anholt	 continue;
356b259eb28049fc06ebc75a7714834b9ed037a3454Eric Anholt
357e3b520049675f78065eccbc25c001ea77861c129Kenneth Graunke      ir_variable_refcount_entry *entry = info->refs->get_variable_entry(lhs_var);
358784695442c415cf0be882434a25671ecfb635d34Eric Anholt
359784695442c415cf0be882434a25671ecfb635d34Eric Anholt      if (!entry->declaration ||
360784695442c415cf0be882434a25671ecfb635d34Eric Anholt	  entry->assigned_count != 1 ||
361784695442c415cf0be882434a25671ecfb635d34Eric Anholt	  entry->referenced_count != 2)
362784695442c415cf0be882434a25671ecfb635d34Eric Anholt	 continue;
363784695442c415cf0be882434a25671ecfb635d34Eric Anholt
364784695442c415cf0be882434a25671ecfb635d34Eric Anholt      assert(assign == entry->assign);
365784695442c415cf0be882434a25671ecfb635d34Eric Anholt
366784695442c415cf0be882434a25671ecfb635d34Eric Anholt      /* Found a possibly graftable assignment.  Now, walk through the
367784695442c415cf0be882434a25671ecfb635d34Eric Anholt       * rest of the BB seeing if the deref is here, and if nothing interfered with
368784695442c415cf0be882434a25671ecfb635d34Eric Anholt       * pasting its expression's values in between.
369784695442c415cf0be882434a25671ecfb635d34Eric Anholt       */
370784695442c415cf0be882434a25671ecfb635d34Eric Anholt      info->progress |= try_tree_grafting(assign, lhs_var, bb_last);
371784695442c415cf0be882434a25671ecfb635d34Eric Anholt   }
372784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
373784695442c415cf0be882434a25671ecfb635d34Eric Anholt
374337d9c955b070224f7278524af54ddacd8bb0f17Eric Anholt} /* unnamed namespace */
375337d9c955b070224f7278524af54ddacd8bb0f17Eric Anholt
376784695442c415cf0be882434a25671ecfb635d34Eric Anholt/**
377784695442c415cf0be882434a25671ecfb635d34Eric Anholt * Does a copy propagation pass on the code present in the instruction stream.
378784695442c415cf0be882434a25671ecfb635d34Eric Anholt */
379784695442c415cf0be882434a25671ecfb635d34Eric Anholtbool
380784695442c415cf0be882434a25671ecfb635d34Eric Anholtdo_tree_grafting(exec_list *instructions)
381784695442c415cf0be882434a25671ecfb635d34Eric Anholt{
382784695442c415cf0be882434a25671ecfb635d34Eric Anholt   ir_variable_refcount_visitor refs;
383784695442c415cf0be882434a25671ecfb635d34Eric Anholt   struct tree_grafting_info info;
384784695442c415cf0be882434a25671ecfb635d34Eric Anholt
385784695442c415cf0be882434a25671ecfb635d34Eric Anholt   info.progress = false;
386784695442c415cf0be882434a25671ecfb635d34Eric Anholt   info.refs = &refs;
387784695442c415cf0be882434a25671ecfb635d34Eric Anholt
388784695442c415cf0be882434a25671ecfb635d34Eric Anholt   visit_list_elements(info.refs, instructions);
389784695442c415cf0be882434a25671ecfb635d34Eric Anholt
390784695442c415cf0be882434a25671ecfb635d34Eric Anholt   call_for_basic_blocks(instructions, tree_grafting_basic_block, &info);
391784695442c415cf0be882434a25671ecfb635d34Eric Anholt
392784695442c415cf0be882434a25671ecfb635d34Eric Anholt   return info.progress;
393784695442c415cf0be882434a25671ecfb635d34Eric Anholt}
394