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