11591693c7b415e9869157c711fe11263c95d74eDavid Li/*
21591693c7b415e9869157c711fe11263c95d74eDavid Li * Copyright © 2010 Intel Corporation
31591693c7b415e9869157c711fe11263c95d74eDavid Li *
41591693c7b415e9869157c711fe11263c95d74eDavid Li * Permission is hereby granted, free of charge, to any person obtaining a
51591693c7b415e9869157c711fe11263c95d74eDavid Li * copy of this software and associated documentation files (the "Software"),
61591693c7b415e9869157c711fe11263c95d74eDavid Li * to deal in the Software without restriction, including without limitation
71591693c7b415e9869157c711fe11263c95d74eDavid Li * the rights to use, copy, modify, merge, publish, distribute, sublicense,
81591693c7b415e9869157c711fe11263c95d74eDavid Li * and/or sell copies of the Software, and to permit persons to whom the
91591693c7b415e9869157c711fe11263c95d74eDavid Li * Software is furnished to do so, subject to the following conditions:
101591693c7b415e9869157c711fe11263c95d74eDavid Li *
111591693c7b415e9869157c711fe11263c95d74eDavid Li * The above copyright notice and this permission notice (including the next
121591693c7b415e9869157c711fe11263c95d74eDavid Li * paragraph) shall be included in all copies or substantial portions of the
131591693c7b415e9869157c711fe11263c95d74eDavid Li * Software.
141591693c7b415e9869157c711fe11263c95d74eDavid Li *
151591693c7b415e9869157c711fe11263c95d74eDavid Li * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161591693c7b415e9869157c711fe11263c95d74eDavid Li * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171591693c7b415e9869157c711fe11263c95d74eDavid Li * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
181591693c7b415e9869157c711fe11263c95d74eDavid Li * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191591693c7b415e9869157c711fe11263c95d74eDavid Li * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
201591693c7b415e9869157c711fe11263c95d74eDavid Li * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
211591693c7b415e9869157c711fe11263c95d74eDavid Li * DEALINGS IN THE SOFTWARE.
221591693c7b415e9869157c711fe11263c95d74eDavid Li */
231591693c7b415e9869157c711fe11263c95d74eDavid Li
241591693c7b415e9869157c711fe11263c95d74eDavid Li/**
251591693c7b415e9869157c711fe11263c95d74eDavid Li * \file opt_tree_grafting.cpp
261591693c7b415e9869157c711fe11263c95d74eDavid Li *
271591693c7b415e9869157c711fe11263c95d74eDavid Li * Takes assignments to variables that are dereferenced only once and
281591693c7b415e9869157c711fe11263c95d74eDavid Li * pastes the RHS expression into where the variable is dereferenced.
291591693c7b415e9869157c711fe11263c95d74eDavid Li *
301591693c7b415e9869157c711fe11263c95d74eDavid Li * In the process of various operations like function inlining and
311591693c7b415e9869157c711fe11263c95d74eDavid Li * tertiary op handling, we'll end up with our expression trees having
321591693c7b415e9869157c711fe11263c95d74eDavid Li * been chopped up into a series of assignments of short expressions
331591693c7b415e9869157c711fe11263c95d74eDavid Li * to temps.  Other passes like ir_algebraic.cpp would prefer to see
341591693c7b415e9869157c711fe11263c95d74eDavid Li * the deepest expression trees they can to try to optimize them.
351591693c7b415e9869157c711fe11263c95d74eDavid Li *
361591693c7b415e9869157c711fe11263c95d74eDavid Li * This is a lot like copy propagaton.  In comparison, copy
371591693c7b415e9869157c711fe11263c95d74eDavid Li * propagation only acts on plain copies, not arbitrary expressions on
381591693c7b415e9869157c711fe11263c95d74eDavid Li * the RHS.  Generally, we wouldn't want to go pasting some
391591693c7b415e9869157c711fe11263c95d74eDavid Li * complicated expression everywhere it got used, though, so we don't
401591693c7b415e9869157c711fe11263c95d74eDavid Li * handle expressions in that pass.
411591693c7b415e9869157c711fe11263c95d74eDavid Li *
421591693c7b415e9869157c711fe11263c95d74eDavid Li * The hard part is making sure we don't move an expression across
431591693c7b415e9869157c711fe11263c95d74eDavid Li * some other assignments that would change the value of the
441591693c7b415e9869157c711fe11263c95d74eDavid Li * expression.  So we split this into two passes: First, find the
451591693c7b415e9869157c711fe11263c95d74eDavid Li * variables in our scope which are written to once and read once, and
461591693c7b415e9869157c711fe11263c95d74eDavid Li * then go through basic blocks seeing if we find an opportunity to
471591693c7b415e9869157c711fe11263c95d74eDavid Li * move those expressions safely.
481591693c7b415e9869157c711fe11263c95d74eDavid Li */
491591693c7b415e9869157c711fe11263c95d74eDavid Li
501591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir.h"
511591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_visitor.h"
521591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_variable_refcount.h"
531591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_basic_block.h"
541591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_optimization.h"
551591693c7b415e9869157c711fe11263c95d74eDavid Li#include "glsl_types.h"
561591693c7b415e9869157c711fe11263c95d74eDavid Li
571591693c7b415e9869157c711fe11263c95d74eDavid Listatic bool debug = false;
581591693c7b415e9869157c711fe11263c95d74eDavid Li
591591693c7b415e9869157c711fe11263c95d74eDavid Liclass ir_tree_grafting_visitor : public ir_hierarchical_visitor {
601591693c7b415e9869157c711fe11263c95d74eDavid Lipublic:
611591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_tree_grafting_visitor(ir_assignment *graft_assign,
621591693c7b415e9869157c711fe11263c95d74eDavid Li			    ir_variable *graft_var)
631591693c7b415e9869157c711fe11263c95d74eDavid Li   {
641591693c7b415e9869157c711fe11263c95d74eDavid Li      this->progress = false;
651591693c7b415e9869157c711fe11263c95d74eDavid Li      this->graft_assign = graft_assign;
661591693c7b415e9869157c711fe11263c95d74eDavid Li      this->graft_var = graft_var;
671591693c7b415e9869157c711fe11263c95d74eDavid Li   }
681591693c7b415e9869157c711fe11263c95d74eDavid Li
691591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(class ir_assignment *);
701591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_call *);
711591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_expression *);
721591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_function *);
731591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_function_signature *);
741591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_if *);
751591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_loop *);
761591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_swizzle *);
771591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(class ir_texture *);
781591693c7b415e9869157c711fe11263c95d74eDavid Li
791591693c7b415e9869157c711fe11263c95d74eDavid Li   bool do_graft(ir_rvalue **rvalue);
801591693c7b415e9869157c711fe11263c95d74eDavid Li
811591693c7b415e9869157c711fe11263c95d74eDavid Li   bool progress;
821591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable *graft_var;
831591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_assignment *graft_assign;
841591693c7b415e9869157c711fe11263c95d74eDavid Li};
851591693c7b415e9869157c711fe11263c95d74eDavid Li
861591693c7b415e9869157c711fe11263c95d74eDavid Listruct find_deref_info {
871591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable *var;
881591693c7b415e9869157c711fe11263c95d74eDavid Li   bool found;
891591693c7b415e9869157c711fe11263c95d74eDavid Li};
901591693c7b415e9869157c711fe11263c95d74eDavid Li
911591693c7b415e9869157c711fe11263c95d74eDavid Livoid
921591693c7b415e9869157c711fe11263c95d74eDavid Lidereferences_variable_callback(ir_instruction *ir, void *data)
931591693c7b415e9869157c711fe11263c95d74eDavid Li{
941591693c7b415e9869157c711fe11263c95d74eDavid Li   struct find_deref_info *info = (struct find_deref_info *)data;
951591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference_variable *deref = ir->as_dereference_variable();
961591693c7b415e9869157c711fe11263c95d74eDavid Li
971591693c7b415e9869157c711fe11263c95d74eDavid Li   if (deref && deref->var == info->var)
981591693c7b415e9869157c711fe11263c95d74eDavid Li      info->found = true;
991591693c7b415e9869157c711fe11263c95d74eDavid Li}
1001591693c7b415e9869157c711fe11263c95d74eDavid Li
1011591693c7b415e9869157c711fe11263c95d74eDavid Listatic bool
1021591693c7b415e9869157c711fe11263c95d74eDavid Lidereferences_variable(ir_instruction *ir, ir_variable *var)
1031591693c7b415e9869157c711fe11263c95d74eDavid Li{
1041591693c7b415e9869157c711fe11263c95d74eDavid Li   struct find_deref_info info;
1051591693c7b415e9869157c711fe11263c95d74eDavid Li
1061591693c7b415e9869157c711fe11263c95d74eDavid Li   info.var = var;
1071591693c7b415e9869157c711fe11263c95d74eDavid Li   info.found = false;
1081591693c7b415e9869157c711fe11263c95d74eDavid Li
1091591693c7b415e9869157c711fe11263c95d74eDavid Li   visit_tree(ir, dereferences_variable_callback, &info);
1101591693c7b415e9869157c711fe11263c95d74eDavid Li
1111591693c7b415e9869157c711fe11263c95d74eDavid Li   return info.found;
1121591693c7b415e9869157c711fe11263c95d74eDavid Li}
1131591693c7b415e9869157c711fe11263c95d74eDavid Li
1141591693c7b415e9869157c711fe11263c95d74eDavid Libool
1151591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::do_graft(ir_rvalue **rvalue)
1161591693c7b415e9869157c711fe11263c95d74eDavid Li{
1171591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!*rvalue)
1181591693c7b415e9869157c711fe11263c95d74eDavid Li      return false;
1191591693c7b415e9869157c711fe11263c95d74eDavid Li
1201591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference_variable *deref = (*rvalue)->as_dereference_variable();
1211591693c7b415e9869157c711fe11263c95d74eDavid Li
1221591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!deref || deref->var != this->graft_var)
1231591693c7b415e9869157c711fe11263c95d74eDavid Li      return false;
1241591693c7b415e9869157c711fe11263c95d74eDavid Li
1251591693c7b415e9869157c711fe11263c95d74eDavid Li   if (debug) {
1261591693c7b415e9869157c711fe11263c95d74eDavid Li      printf("GRAFTING:\n");
1271591693c7b415e9869157c711fe11263c95d74eDavid Li      this->graft_assign->print();
1281591693c7b415e9869157c711fe11263c95d74eDavid Li      printf("\n");
1291591693c7b415e9869157c711fe11263c95d74eDavid Li      printf("TO:\n");
1301591693c7b415e9869157c711fe11263c95d74eDavid Li      (*rvalue)->print();
1311591693c7b415e9869157c711fe11263c95d74eDavid Li      printf("\n");
1321591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1331591693c7b415e9869157c711fe11263c95d74eDavid Li
1341591693c7b415e9869157c711fe11263c95d74eDavid Li   this->graft_assign->remove();
1351591693c7b415e9869157c711fe11263c95d74eDavid Li   *rvalue = this->graft_assign->rhs;
1361591693c7b415e9869157c711fe11263c95d74eDavid Li
1371591693c7b415e9869157c711fe11263c95d74eDavid Li   this->progress = true;
1381591693c7b415e9869157c711fe11263c95d74eDavid Li   return true;
1391591693c7b415e9869157c711fe11263c95d74eDavid Li}
1401591693c7b415e9869157c711fe11263c95d74eDavid Li
1411591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1421591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::visit_enter(ir_loop *ir)
1431591693c7b415e9869157c711fe11263c95d74eDavid Li{
1441591693c7b415e9869157c711fe11263c95d74eDavid Li   (void)ir;
1451591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Do not traverse into the body of the loop since that is a
1461591693c7b415e9869157c711fe11263c95d74eDavid Li    * different basic block.
1471591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1481591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_stop;
1491591693c7b415e9869157c711fe11263c95d74eDavid Li}
1501591693c7b415e9869157c711fe11263c95d74eDavid Li
1511591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1521591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::visit_leave(ir_assignment *ir)
1531591693c7b415e9869157c711fe11263c95d74eDavid Li{
1541591693c7b415e9869157c711fe11263c95d74eDavid Li   if (do_graft(&ir->rhs) ||
1551591693c7b415e9869157c711fe11263c95d74eDavid Li       do_graft(&ir->condition))
1561591693c7b415e9869157c711fe11263c95d74eDavid Li      return visit_stop;
1571591693c7b415e9869157c711fe11263c95d74eDavid Li
1581591693c7b415e9869157c711fe11263c95d74eDavid Li   /* If this assignment updates a variable used in the assignment
1591591693c7b415e9869157c711fe11263c95d74eDavid Li    * we're trying to graft, then we're done.
1601591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1611591693c7b415e9869157c711fe11263c95d74eDavid Li   if (dereferences_variable(this->graft_assign->rhs,
1621591693c7b415e9869157c711fe11263c95d74eDavid Li			     ir->lhs->variable_referenced())) {
1631591693c7b415e9869157c711fe11263c95d74eDavid Li      if (debug) {
1641591693c7b415e9869157c711fe11263c95d74eDavid Li	 printf("graft killed by: ");
1651591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir->print();
1661591693c7b415e9869157c711fe11263c95d74eDavid Li	 printf("\n");
1671591693c7b415e9869157c711fe11263c95d74eDavid Li      }
1681591693c7b415e9869157c711fe11263c95d74eDavid Li      return visit_stop;
1691591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1701591693c7b415e9869157c711fe11263c95d74eDavid Li
1711591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
1721591693c7b415e9869157c711fe11263c95d74eDavid Li}
1731591693c7b415e9869157c711fe11263c95d74eDavid Li
1741591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1751591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::visit_enter(ir_function *ir)
1761591693c7b415e9869157c711fe11263c95d74eDavid Li{
1771591693c7b415e9869157c711fe11263c95d74eDavid Li   (void) ir;
1781591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue_with_parent;
1791591693c7b415e9869157c711fe11263c95d74eDavid Li}
1801591693c7b415e9869157c711fe11263c95d74eDavid Li
1811591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1821591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::visit_enter(ir_function_signature *ir)
1831591693c7b415e9869157c711fe11263c95d74eDavid Li{
1841591693c7b415e9869157c711fe11263c95d74eDavid Li   (void)ir;
1851591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue_with_parent;
1861591693c7b415e9869157c711fe11263c95d74eDavid Li}
1871591693c7b415e9869157c711fe11263c95d74eDavid Li
1881591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1891591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::visit_enter(ir_call *ir)
1901591693c7b415e9869157c711fe11263c95d74eDavid Li{
1911591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
1921591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Reminder: iterating ir_call iterates its parameters. */
1931591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, iter, *ir) {
1941591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_variable *sig_param = (ir_variable *)sig_iter.get();
1951591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_rvalue *ir = (ir_rvalue *)iter.get();
1961591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_rvalue *new_ir = ir;
1971591693c7b415e9869157c711fe11263c95d74eDavid Li
1981591693c7b415e9869157c711fe11263c95d74eDavid Li      if (sig_param->mode != ir_var_in)
1991591693c7b415e9869157c711fe11263c95d74eDavid Li	 continue;
2001591693c7b415e9869157c711fe11263c95d74eDavid Li
2011591693c7b415e9869157c711fe11263c95d74eDavid Li      if (do_graft(&new_ir)) {
2021591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir->replace_with(new_ir);
2031591693c7b415e9869157c711fe11263c95d74eDavid Li	 return visit_stop;
2041591693c7b415e9869157c711fe11263c95d74eDavid Li      }
2051591693c7b415e9869157c711fe11263c95d74eDavid Li      sig_iter.next();
2061591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2071591693c7b415e9869157c711fe11263c95d74eDavid Li
2081591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
2091591693c7b415e9869157c711fe11263c95d74eDavid Li}
2101591693c7b415e9869157c711fe11263c95d74eDavid Li
2111591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2121591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::visit_enter(ir_expression *ir)
2131591693c7b415e9869157c711fe11263c95d74eDavid Li{
2141591693c7b415e9869157c711fe11263c95d74eDavid Li   for (unsigned int i = 0; i < ir->get_num_operands(); i++) {
2151591693c7b415e9869157c711fe11263c95d74eDavid Li      if (do_graft(&ir->operands[i]))
2161591693c7b415e9869157c711fe11263c95d74eDavid Li	 return visit_stop;
2171591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2181591693c7b415e9869157c711fe11263c95d74eDavid Li
2191591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
2201591693c7b415e9869157c711fe11263c95d74eDavid Li}
2211591693c7b415e9869157c711fe11263c95d74eDavid Li
2221591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2231591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::visit_enter(ir_if *ir)
2241591693c7b415e9869157c711fe11263c95d74eDavid Li{
2251591693c7b415e9869157c711fe11263c95d74eDavid Li   if (do_graft(&ir->condition))
2261591693c7b415e9869157c711fe11263c95d74eDavid Li      return visit_stop;
2271591693c7b415e9869157c711fe11263c95d74eDavid Li
2281591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Do not traverse into the body of the if-statement since that is a
2291591693c7b415e9869157c711fe11263c95d74eDavid Li    * different basic block.
2301591693c7b415e9869157c711fe11263c95d74eDavid Li    */
2311591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue_with_parent;
2321591693c7b415e9869157c711fe11263c95d74eDavid Li}
2331591693c7b415e9869157c711fe11263c95d74eDavid Li
2341591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2351591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::visit_enter(ir_swizzle *ir)
2361591693c7b415e9869157c711fe11263c95d74eDavid Li{
2371591693c7b415e9869157c711fe11263c95d74eDavid Li   if (do_graft(&ir->val))
2381591693c7b415e9869157c711fe11263c95d74eDavid Li      return visit_stop;
2391591693c7b415e9869157c711fe11263c95d74eDavid Li
2401591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
2411591693c7b415e9869157c711fe11263c95d74eDavid Li}
2421591693c7b415e9869157c711fe11263c95d74eDavid Li
2431591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2441591693c7b415e9869157c711fe11263c95d74eDavid Liir_tree_grafting_visitor::visit_enter(ir_texture *ir)
2451591693c7b415e9869157c711fe11263c95d74eDavid Li{
2461591693c7b415e9869157c711fe11263c95d74eDavid Li   if (do_graft(&ir->coordinate) ||
2471591693c7b415e9869157c711fe11263c95d74eDavid Li       do_graft(&ir->projector) ||
2481591693c7b415e9869157c711fe11263c95d74eDavid Li       do_graft(&ir->shadow_comparitor))
2491591693c7b415e9869157c711fe11263c95d74eDavid Li	 return visit_stop;
2501591693c7b415e9869157c711fe11263c95d74eDavid Li
2511591693c7b415e9869157c711fe11263c95d74eDavid Li   switch (ir->op) {
2521591693c7b415e9869157c711fe11263c95d74eDavid Li   case ir_tex:
2531591693c7b415e9869157c711fe11263c95d74eDavid Li      break;
2541591693c7b415e9869157c711fe11263c95d74eDavid Li   case ir_txb:
2551591693c7b415e9869157c711fe11263c95d74eDavid Li      if (do_graft(&ir->lod_info.bias))
2561591693c7b415e9869157c711fe11263c95d74eDavid Li	 return visit_stop;
2571591693c7b415e9869157c711fe11263c95d74eDavid Li      break;
2581591693c7b415e9869157c711fe11263c95d74eDavid Li   case ir_txf:
2591591693c7b415e9869157c711fe11263c95d74eDavid Li   case ir_txl:
2601591693c7b415e9869157c711fe11263c95d74eDavid Li      if (do_graft(&ir->lod_info.lod))
2611591693c7b415e9869157c711fe11263c95d74eDavid Li	 return visit_stop;
2621591693c7b415e9869157c711fe11263c95d74eDavid Li      break;
2631591693c7b415e9869157c711fe11263c95d74eDavid Li   case ir_txd:
2641591693c7b415e9869157c711fe11263c95d74eDavid Li      if (do_graft(&ir->lod_info.grad.dPdx) ||
2651591693c7b415e9869157c711fe11263c95d74eDavid Li	  do_graft(&ir->lod_info.grad.dPdy))
2661591693c7b415e9869157c711fe11263c95d74eDavid Li	 return visit_stop;
2671591693c7b415e9869157c711fe11263c95d74eDavid Li      break;
2681591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2691591693c7b415e9869157c711fe11263c95d74eDavid Li
2701591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
2711591693c7b415e9869157c711fe11263c95d74eDavid Li}
2721591693c7b415e9869157c711fe11263c95d74eDavid Li
2731591693c7b415e9869157c711fe11263c95d74eDavid Listruct tree_grafting_info {
2741591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable_refcount_visitor *refs;
2751591693c7b415e9869157c711fe11263c95d74eDavid Li   bool progress;
2761591693c7b415e9869157c711fe11263c95d74eDavid Li};
2771591693c7b415e9869157c711fe11263c95d74eDavid Li
2781591693c7b415e9869157c711fe11263c95d74eDavid Listatic bool
2791591693c7b415e9869157c711fe11263c95d74eDavid Litry_tree_grafting(ir_assignment *start,
2801591693c7b415e9869157c711fe11263c95d74eDavid Li		  ir_variable *lhs_var,
2811591693c7b415e9869157c711fe11263c95d74eDavid Li		  ir_instruction *bb_last)
2821591693c7b415e9869157c711fe11263c95d74eDavid Li{
2831591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_tree_grafting_visitor v(start, lhs_var);
2841591693c7b415e9869157c711fe11263c95d74eDavid Li
2851591693c7b415e9869157c711fe11263c95d74eDavid Li   if (debug) {
2861591693c7b415e9869157c711fe11263c95d74eDavid Li      printf("trying to graft: ");
2871591693c7b415e9869157c711fe11263c95d74eDavid Li      lhs_var->print();
2881591693c7b415e9869157c711fe11263c95d74eDavid Li      printf("\n");
2891591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2901591693c7b415e9869157c711fe11263c95d74eDavid Li
2911591693c7b415e9869157c711fe11263c95d74eDavid Li   for (ir_instruction *ir = (ir_instruction *)start->next;
2921591693c7b415e9869157c711fe11263c95d74eDavid Li	ir != bb_last->next;
2931591693c7b415e9869157c711fe11263c95d74eDavid Li	ir = (ir_instruction *)ir->next) {
2941591693c7b415e9869157c711fe11263c95d74eDavid Li
2951591693c7b415e9869157c711fe11263c95d74eDavid Li      if (debug) {
2961591693c7b415e9869157c711fe11263c95d74eDavid Li	 printf("- ");
2971591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir->print();
2981591693c7b415e9869157c711fe11263c95d74eDavid Li	 printf("\n");
2991591693c7b415e9869157c711fe11263c95d74eDavid Li      }
3001591693c7b415e9869157c711fe11263c95d74eDavid Li
3011591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_visitor_status s = ir->accept(&v);
3021591693c7b415e9869157c711fe11263c95d74eDavid Li      if (s == visit_stop)
3031591693c7b415e9869157c711fe11263c95d74eDavid Li	 return v.progress;
3041591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3051591693c7b415e9869157c711fe11263c95d74eDavid Li
3061591693c7b415e9869157c711fe11263c95d74eDavid Li   return false;
3071591693c7b415e9869157c711fe11263c95d74eDavid Li}
3081591693c7b415e9869157c711fe11263c95d74eDavid Li
3091591693c7b415e9869157c711fe11263c95d74eDavid Listatic void
3101591693c7b415e9869157c711fe11263c95d74eDavid Litree_grafting_basic_block(ir_instruction *bb_first,
3111591693c7b415e9869157c711fe11263c95d74eDavid Li			  ir_instruction *bb_last,
3121591693c7b415e9869157c711fe11263c95d74eDavid Li			  void *data)
3131591693c7b415e9869157c711fe11263c95d74eDavid Li{
3141591693c7b415e9869157c711fe11263c95d74eDavid Li   struct tree_grafting_info *info = (struct tree_grafting_info *)data;
3151591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_instruction *ir, *next;
3161591693c7b415e9869157c711fe11263c95d74eDavid Li
3171591693c7b415e9869157c711fe11263c95d74eDavid Li   for (ir = bb_first, next = (ir_instruction *)ir->next;
3181591693c7b415e9869157c711fe11263c95d74eDavid Li	ir != bb_last->next;
3191591693c7b415e9869157c711fe11263c95d74eDavid Li	ir = next, next = (ir_instruction *)ir->next) {
3201591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_assignment *assign = ir->as_assignment();
3211591693c7b415e9869157c711fe11263c95d74eDavid Li
3221591693c7b415e9869157c711fe11263c95d74eDavid Li      if (!assign)
3231591693c7b415e9869157c711fe11263c95d74eDavid Li	 continue;
3241591693c7b415e9869157c711fe11263c95d74eDavid Li
3251591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_variable *lhs_var = assign->whole_variable_written();
3261591693c7b415e9869157c711fe11263c95d74eDavid Li      if (!lhs_var)
3271591693c7b415e9869157c711fe11263c95d74eDavid Li	 continue;
3281591693c7b415e9869157c711fe11263c95d74eDavid Li
3291591693c7b415e9869157c711fe11263c95d74eDavid Li      if (lhs_var->mode == ir_var_out ||
3301591693c7b415e9869157c711fe11263c95d74eDavid Li	  lhs_var->mode == ir_var_inout)
3311591693c7b415e9869157c711fe11263c95d74eDavid Li	 continue;
3321591693c7b415e9869157c711fe11263c95d74eDavid Li
3331591693c7b415e9869157c711fe11263c95d74eDavid Li      variable_entry *entry = info->refs->get_variable_entry(lhs_var);
3341591693c7b415e9869157c711fe11263c95d74eDavid Li
3351591693c7b415e9869157c711fe11263c95d74eDavid Li      if (!entry->declaration ||
3361591693c7b415e9869157c711fe11263c95d74eDavid Li	  entry->assigned_count != 1 ||
3371591693c7b415e9869157c711fe11263c95d74eDavid Li	  entry->referenced_count != 2)
3381591693c7b415e9869157c711fe11263c95d74eDavid Li	 continue;
3391591693c7b415e9869157c711fe11263c95d74eDavid Li
3401591693c7b415e9869157c711fe11263c95d74eDavid Li      assert(assign == entry->assign);
3411591693c7b415e9869157c711fe11263c95d74eDavid Li
3421591693c7b415e9869157c711fe11263c95d74eDavid Li      /* Found a possibly graftable assignment.  Now, walk through the
3431591693c7b415e9869157c711fe11263c95d74eDavid Li       * rest of the BB seeing if the deref is here, and if nothing interfered with
3441591693c7b415e9869157c711fe11263c95d74eDavid Li       * pasting its expression's values in between.
3451591693c7b415e9869157c711fe11263c95d74eDavid Li       */
3461591693c7b415e9869157c711fe11263c95d74eDavid Li      info->progress |= try_tree_grafting(assign, lhs_var, bb_last);
3471591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3481591693c7b415e9869157c711fe11263c95d74eDavid Li}
3491591693c7b415e9869157c711fe11263c95d74eDavid Li
3501591693c7b415e9869157c711fe11263c95d74eDavid Li/**
3511591693c7b415e9869157c711fe11263c95d74eDavid Li * Does a copy propagation pass on the code present in the instruction stream.
3521591693c7b415e9869157c711fe11263c95d74eDavid Li */
3531591693c7b415e9869157c711fe11263c95d74eDavid Libool
3541591693c7b415e9869157c711fe11263c95d74eDavid Lido_tree_grafting(exec_list *instructions)
3551591693c7b415e9869157c711fe11263c95d74eDavid Li{
3561591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable_refcount_visitor refs;
3571591693c7b415e9869157c711fe11263c95d74eDavid Li   struct tree_grafting_info info;
3581591693c7b415e9869157c711fe11263c95d74eDavid Li
3591591693c7b415e9869157c711fe11263c95d74eDavid Li   info.progress = false;
3601591693c7b415e9869157c711fe11263c95d74eDavid Li   info.refs = &refs;
3611591693c7b415e9869157c711fe11263c95d74eDavid Li
3621591693c7b415e9869157c711fe11263c95d74eDavid Li   visit_list_elements(info.refs, instructions);
3631591693c7b415e9869157c711fe11263c95d74eDavid Li
3641591693c7b415e9869157c711fe11263c95d74eDavid Li   call_for_basic_blocks(instructions, tree_grafting_basic_block, &info);
3651591693c7b415e9869157c711fe11263c95d74eDavid Li
3661591693c7b415e9869157c711fe11263c95d74eDavid Li   return info.progress;
3671591693c7b415e9869157c711fe11263c95d74eDavid Li}
368