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_constant_folding.cpp 261591693c7b415e9869157c711fe11263c95d74eDavid Li * Replace constant-valued expressions with references to constant values. 271591693c7b415e9869157c711fe11263c95d74eDavid Li */ 281591693c7b415e9869157c711fe11263c95d74eDavid Li 291591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir.h" 301591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_visitor.h" 311591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_rvalue_visitor.h" 321591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_optimization.h" 331591693c7b415e9869157c711fe11263c95d74eDavid Li#include "glsl_types.h" 341591693c7b415e9869157c711fe11263c95d74eDavid Li 351591693c7b415e9869157c711fe11263c95d74eDavid Li/** 361591693c7b415e9869157c711fe11263c95d74eDavid Li * Visitor class for replacing expressions with ir_constant values. 371591693c7b415e9869157c711fe11263c95d74eDavid Li */ 381591693c7b415e9869157c711fe11263c95d74eDavid Li 391591693c7b415e9869157c711fe11263c95d74eDavid Liclass ir_constant_folding_visitor : public ir_rvalue_visitor { 401591693c7b415e9869157c711fe11263c95d74eDavid Lipublic: 411591693c7b415e9869157c711fe11263c95d74eDavid Li ir_constant_folding_visitor() 421591693c7b415e9869157c711fe11263c95d74eDavid Li { 431591693c7b415e9869157c711fe11263c95d74eDavid Li this->progress = false; 441591693c7b415e9869157c711fe11263c95d74eDavid Li } 451591693c7b415e9869157c711fe11263c95d74eDavid Li 461591693c7b415e9869157c711fe11263c95d74eDavid Li virtual ~ir_constant_folding_visitor() 471591693c7b415e9869157c711fe11263c95d74eDavid Li { 481591693c7b415e9869157c711fe11263c95d74eDavid Li /* empty */ 491591693c7b415e9869157c711fe11263c95d74eDavid Li } 501591693c7b415e9869157c711fe11263c95d74eDavid Li 511591693c7b415e9869157c711fe11263c95d74eDavid Li virtual ir_visitor_status visit_enter(ir_assignment *ir); 521591693c7b415e9869157c711fe11263c95d74eDavid Li virtual ir_visitor_status visit_enter(ir_call *ir); 531591693c7b415e9869157c711fe11263c95d74eDavid Li 541591693c7b415e9869157c711fe11263c95d74eDavid Li virtual void handle_rvalue(ir_rvalue **rvalue); 551591693c7b415e9869157c711fe11263c95d74eDavid Li 561591693c7b415e9869157c711fe11263c95d74eDavid Li bool progress; 571591693c7b415e9869157c711fe11263c95d74eDavid Li}; 581591693c7b415e9869157c711fe11263c95d74eDavid Li 591591693c7b415e9869157c711fe11263c95d74eDavid Livoid 601591693c7b415e9869157c711fe11263c95d74eDavid Liir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue) 611591693c7b415e9869157c711fe11263c95d74eDavid Li{ 621591693c7b415e9869157c711fe11263c95d74eDavid Li if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant) 631591693c7b415e9869157c711fe11263c95d74eDavid Li return; 641591693c7b415e9869157c711fe11263c95d74eDavid Li 651591693c7b415e9869157c711fe11263c95d74eDavid Li /* Note that we do rvalue visitoring on leaving. So if an 661591693c7b415e9869157c711fe11263c95d74eDavid Li * expression has a non-constant operand, no need to go looking 671591693c7b415e9869157c711fe11263c95d74eDavid Li * down it to find if it's constant. This cuts the time of this 681591693c7b415e9869157c711fe11263c95d74eDavid Li * pass down drastically. 691591693c7b415e9869157c711fe11263c95d74eDavid Li */ 701591693c7b415e9869157c711fe11263c95d74eDavid Li ir_expression *expr = (*rvalue)->as_expression(); 711591693c7b415e9869157c711fe11263c95d74eDavid Li if (expr) { 721591693c7b415e9869157c711fe11263c95d74eDavid Li for (unsigned int i = 0; i < expr->get_num_operands(); i++) { 731591693c7b415e9869157c711fe11263c95d74eDavid Li if (!expr->operands[i]->as_constant()) 741591693c7b415e9869157c711fe11263c95d74eDavid Li return; 751591693c7b415e9869157c711fe11263c95d74eDavid Li } 761591693c7b415e9869157c711fe11263c95d74eDavid Li } 771591693c7b415e9869157c711fe11263c95d74eDavid Li 781591693c7b415e9869157c711fe11263c95d74eDavid Li ir_constant *constant = (*rvalue)->constant_expression_value(); 791591693c7b415e9869157c711fe11263c95d74eDavid Li if (constant) { 801591693c7b415e9869157c711fe11263c95d74eDavid Li *rvalue = constant; 811591693c7b415e9869157c711fe11263c95d74eDavid Li this->progress = true; 821591693c7b415e9869157c711fe11263c95d74eDavid Li } else { 831591693c7b415e9869157c711fe11263c95d74eDavid Li (*rvalue)->accept(this); 841591693c7b415e9869157c711fe11263c95d74eDavid Li } 851591693c7b415e9869157c711fe11263c95d74eDavid Li} 861591693c7b415e9869157c711fe11263c95d74eDavid Li 871591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status 881591693c7b415e9869157c711fe11263c95d74eDavid Liir_constant_folding_visitor::visit_enter(ir_assignment *ir) 891591693c7b415e9869157c711fe11263c95d74eDavid Li{ 901591693c7b415e9869157c711fe11263c95d74eDavid Li ir->rhs->accept(this); 911591693c7b415e9869157c711fe11263c95d74eDavid Li handle_rvalue(&ir->rhs); 921591693c7b415e9869157c711fe11263c95d74eDavid Li 931591693c7b415e9869157c711fe11263c95d74eDavid Li if (ir->condition) { 941591693c7b415e9869157c711fe11263c95d74eDavid Li ir->condition->accept(this); 951591693c7b415e9869157c711fe11263c95d74eDavid Li handle_rvalue(&ir->condition); 961591693c7b415e9869157c711fe11263c95d74eDavid Li 971591693c7b415e9869157c711fe11263c95d74eDavid Li ir_constant *const_val = ir->condition->as_constant(); 981591693c7b415e9869157c711fe11263c95d74eDavid Li /* If the condition is constant, either remove the condition or 991591693c7b415e9869157c711fe11263c95d74eDavid Li * remove the never-executed assignment. 1001591693c7b415e9869157c711fe11263c95d74eDavid Li */ 1011591693c7b415e9869157c711fe11263c95d74eDavid Li if (const_val) { 1021591693c7b415e9869157c711fe11263c95d74eDavid Li if (const_val->value.b[0]) 1031591693c7b415e9869157c711fe11263c95d74eDavid Li ir->condition = NULL; 1041591693c7b415e9869157c711fe11263c95d74eDavid Li else 1051591693c7b415e9869157c711fe11263c95d74eDavid Li ir->remove(); 1061591693c7b415e9869157c711fe11263c95d74eDavid Li this->progress = true; 1071591693c7b415e9869157c711fe11263c95d74eDavid Li } 1081591693c7b415e9869157c711fe11263c95d74eDavid Li } 1091591693c7b415e9869157c711fe11263c95d74eDavid Li 1101591693c7b415e9869157c711fe11263c95d74eDavid Li /* Don't descend into the LHS because we want it to stay as a 1111591693c7b415e9869157c711fe11263c95d74eDavid Li * variable dereference. FINISHME: We probably should to get array 1121591693c7b415e9869157c711fe11263c95d74eDavid Li * indices though. 1131591693c7b415e9869157c711fe11263c95d74eDavid Li */ 1141591693c7b415e9869157c711fe11263c95d74eDavid Li return visit_continue_with_parent; 1151591693c7b415e9869157c711fe11263c95d74eDavid Li} 1161591693c7b415e9869157c711fe11263c95d74eDavid Li 1171591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status 1181591693c7b415e9869157c711fe11263c95d74eDavid Liir_constant_folding_visitor::visit_enter(ir_call *ir) 1191591693c7b415e9869157c711fe11263c95d74eDavid Li{ 1201591693c7b415e9869157c711fe11263c95d74eDavid Li exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator(); 1211591693c7b415e9869157c711fe11263c95d74eDavid Li foreach_iter(exec_list_iterator, iter, *ir) { 1221591693c7b415e9869157c711fe11263c95d74eDavid Li ir_rvalue *param_rval = (ir_rvalue *)iter.get(); 1231591693c7b415e9869157c711fe11263c95d74eDavid Li ir_variable *sig_param = (ir_variable *)sig_iter.get(); 1241591693c7b415e9869157c711fe11263c95d74eDavid Li 1251591693c7b415e9869157c711fe11263c95d74eDavid Li if (sig_param->mode == ir_var_in) { 1261591693c7b415e9869157c711fe11263c95d74eDavid Li ir_rvalue *new_param = param_rval; 1271591693c7b415e9869157c711fe11263c95d74eDavid Li 1281591693c7b415e9869157c711fe11263c95d74eDavid Li handle_rvalue(&new_param); 1291591693c7b415e9869157c711fe11263c95d74eDavid Li if (new_param != param_rval) { 1301591693c7b415e9869157c711fe11263c95d74eDavid Li param_rval->replace_with(new_param); 1311591693c7b415e9869157c711fe11263c95d74eDavid Li } 1321591693c7b415e9869157c711fe11263c95d74eDavid Li } 1331591693c7b415e9869157c711fe11263c95d74eDavid Li sig_iter.next(); 1341591693c7b415e9869157c711fe11263c95d74eDavid Li } 1351591693c7b415e9869157c711fe11263c95d74eDavid Li 1361591693c7b415e9869157c711fe11263c95d74eDavid Li return visit_continue_with_parent; 1371591693c7b415e9869157c711fe11263c95d74eDavid Li} 1381591693c7b415e9869157c711fe11263c95d74eDavid Li 1391591693c7b415e9869157c711fe11263c95d74eDavid Libool 1401591693c7b415e9869157c711fe11263c95d74eDavid Lido_constant_folding(exec_list *instructions) 1411591693c7b415e9869157c711fe11263c95d74eDavid Li{ 1421591693c7b415e9869157c711fe11263c95d74eDavid Li ir_constant_folding_visitor constant_folding; 1431591693c7b415e9869157c711fe11263c95d74eDavid Li 1441591693c7b415e9869157c711fe11263c95d74eDavid Li visit_list_elements(&constant_folding, instructions); 1451591693c7b415e9869157c711fe11263c95d74eDavid Li 1461591693c7b415e9869157c711fe11263c95d74eDavid Li return constant_folding.progress; 1471591693c7b415e9869157c711fe11263c95d74eDavid Li} 148