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