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_dead_code.cpp 261591693c7b415e9869157c711fe11263c95d74eDavid Li * 271591693c7b415e9869157c711fe11263c95d74eDavid Li * Eliminates dead assignments and variable declarations from the code. 281591693c7b415e9869157c711fe11263c95d74eDavid Li */ 291591693c7b415e9869157c711fe11263c95d74eDavid Li 301591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir.h" 311591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_visitor.h" 321591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_variable_refcount.h" 331591693c7b415e9869157c711fe11263c95d74eDavid Li#include "glsl_types.h" 341591693c7b415e9869157c711fe11263c95d74eDavid Li 351591693c7b415e9869157c711fe11263c95d74eDavid Listatic bool debug = false; 361591693c7b415e9869157c711fe11263c95d74eDavid Li 371591693c7b415e9869157c711fe11263c95d74eDavid Li/** 381591693c7b415e9869157c711fe11263c95d74eDavid Li * Do a dead code pass over instructions and everything that instructions 391591693c7b415e9869157c711fe11263c95d74eDavid Li * references. 401591693c7b415e9869157c711fe11263c95d74eDavid Li * 411591693c7b415e9869157c711fe11263c95d74eDavid Li * Note that this will remove assignments to globals, so it is not suitable 421591693c7b415e9869157c711fe11263c95d74eDavid Li * for usage on an unlinked instruction stream. 431591693c7b415e9869157c711fe11263c95d74eDavid Li */ 441591693c7b415e9869157c711fe11263c95d74eDavid Libool 451591693c7b415e9869157c711fe11263c95d74eDavid Lido_dead_code(exec_list *instructions) 461591693c7b415e9869157c711fe11263c95d74eDavid Li{ 471591693c7b415e9869157c711fe11263c95d74eDavid Li ir_variable_refcount_visitor v; 481591693c7b415e9869157c711fe11263c95d74eDavid Li bool progress = false; 491591693c7b415e9869157c711fe11263c95d74eDavid Li 501591693c7b415e9869157c711fe11263c95d74eDavid Li v.run(instructions); 511591693c7b415e9869157c711fe11263c95d74eDavid Li 521591693c7b415e9869157c711fe11263c95d74eDavid Li foreach_iter(exec_list_iterator, iter, v.variable_list) { 531591693c7b415e9869157c711fe11263c95d74eDavid Li variable_entry *entry = (variable_entry *)iter.get(); 541591693c7b415e9869157c711fe11263c95d74eDavid Li 551591693c7b415e9869157c711fe11263c95d74eDavid Li /* Since each assignment is a reference, the refereneced count must be 561591693c7b415e9869157c711fe11263c95d74eDavid Li * greater than or equal to the assignment count. If they are equal, 571591693c7b415e9869157c711fe11263c95d74eDavid Li * then all of the references are assignments, and the variable is 581591693c7b415e9869157c711fe11263c95d74eDavid Li * dead. 591591693c7b415e9869157c711fe11263c95d74eDavid Li * 601591693c7b415e9869157c711fe11263c95d74eDavid Li * Note that if the variable is neither assigned nor referenced, both 611591693c7b415e9869157c711fe11263c95d74eDavid Li * counts will be zero and will be caught by the equality test. 621591693c7b415e9869157c711fe11263c95d74eDavid Li */ 631591693c7b415e9869157c711fe11263c95d74eDavid Li assert(entry->referenced_count >= entry->assigned_count); 641591693c7b415e9869157c711fe11263c95d74eDavid Li 651591693c7b415e9869157c711fe11263c95d74eDavid Li if (debug) { 661591693c7b415e9869157c711fe11263c95d74eDavid Li printf("%s@%p: %d refs, %d assigns, %sdeclared in our scope\n", 671591693c7b415e9869157c711fe11263c95d74eDavid Li entry->var->name, (void *) entry->var, 681591693c7b415e9869157c711fe11263c95d74eDavid Li entry->referenced_count, entry->assigned_count, 691591693c7b415e9869157c711fe11263c95d74eDavid Li entry->declaration ? "" : "not "); 701591693c7b415e9869157c711fe11263c95d74eDavid Li } 711591693c7b415e9869157c711fe11263c95d74eDavid Li 721591693c7b415e9869157c711fe11263c95d74eDavid Li if ((entry->referenced_count > entry->assigned_count) 731591693c7b415e9869157c711fe11263c95d74eDavid Li || !entry->declaration) 741591693c7b415e9869157c711fe11263c95d74eDavid Li continue; 751591693c7b415e9869157c711fe11263c95d74eDavid Li 761591693c7b415e9869157c711fe11263c95d74eDavid Li if (entry->assign) { 771591693c7b415e9869157c711fe11263c95d74eDavid Li /* Remove a single dead assignment to the variable we found. 781591693c7b415e9869157c711fe11263c95d74eDavid Li * Don't do so if it's a shader output, though. 791591693c7b415e9869157c711fe11263c95d74eDavid Li */ 801591693c7b415e9869157c711fe11263c95d74eDavid Li if (entry->var->mode != ir_var_out && 811591693c7b415e9869157c711fe11263c95d74eDavid Li entry->var->mode != ir_var_inout && 821591693c7b415e9869157c711fe11263c95d74eDavid Li !ir_has_call(entry->assign)) { 831591693c7b415e9869157c711fe11263c95d74eDavid Li entry->assign->remove(); 841591693c7b415e9869157c711fe11263c95d74eDavid Li progress = true; 851591693c7b415e9869157c711fe11263c95d74eDavid Li 861591693c7b415e9869157c711fe11263c95d74eDavid Li if (debug) { 871591693c7b415e9869157c711fe11263c95d74eDavid Li printf("Removed assignment to %s@%p\n", 881591693c7b415e9869157c711fe11263c95d74eDavid Li entry->var->name, (void *) entry->var); 891591693c7b415e9869157c711fe11263c95d74eDavid Li } 901591693c7b415e9869157c711fe11263c95d74eDavid Li } 911591693c7b415e9869157c711fe11263c95d74eDavid Li } else { 921591693c7b415e9869157c711fe11263c95d74eDavid Li /* If there are no assignments or references to the variable left, 931591693c7b415e9869157c711fe11263c95d74eDavid Li * then we can remove its declaration. 941591693c7b415e9869157c711fe11263c95d74eDavid Li */ 951591693c7b415e9869157c711fe11263c95d74eDavid Li 961591693c7b415e9869157c711fe11263c95d74eDavid Li /* uniform initializers are precious, and could get used by another 971591693c7b415e9869157c711fe11263c95d74eDavid Li * stage. 981591693c7b415e9869157c711fe11263c95d74eDavid Li */ 991591693c7b415e9869157c711fe11263c95d74eDavid Li if (entry->var->mode == ir_var_uniform && 1001591693c7b415e9869157c711fe11263c95d74eDavid Li entry->var->constant_value) 1011591693c7b415e9869157c711fe11263c95d74eDavid Li continue; 1021591693c7b415e9869157c711fe11263c95d74eDavid Li 1031591693c7b415e9869157c711fe11263c95d74eDavid Li entry->var->remove(); 1041591693c7b415e9869157c711fe11263c95d74eDavid Li progress = true; 1051591693c7b415e9869157c711fe11263c95d74eDavid Li 1061591693c7b415e9869157c711fe11263c95d74eDavid Li if (debug) { 1071591693c7b415e9869157c711fe11263c95d74eDavid Li printf("Removed declaration of %s@%p\n", 1081591693c7b415e9869157c711fe11263c95d74eDavid Li entry->var->name, (void *) entry->var); 1091591693c7b415e9869157c711fe11263c95d74eDavid Li } 1101591693c7b415e9869157c711fe11263c95d74eDavid Li } 1111591693c7b415e9869157c711fe11263c95d74eDavid Li } 1121591693c7b415e9869157c711fe11263c95d74eDavid Li 1131591693c7b415e9869157c711fe11263c95d74eDavid Li return progress; 1141591693c7b415e9869157c711fe11263c95d74eDavid Li} 1151591693c7b415e9869157c711fe11263c95d74eDavid Li 1161591693c7b415e9869157c711fe11263c95d74eDavid Li/** 1171591693c7b415e9869157c711fe11263c95d74eDavid Li * Does a dead code pass on the functions present in the instruction stream. 1181591693c7b415e9869157c711fe11263c95d74eDavid Li * 1191591693c7b415e9869157c711fe11263c95d74eDavid Li * This is suitable for use while the program is not linked, as it will 1201591693c7b415e9869157c711fe11263c95d74eDavid Li * ignore variable declarations (and the assignments to them) for variables 1211591693c7b415e9869157c711fe11263c95d74eDavid Li * with global scope. 1221591693c7b415e9869157c711fe11263c95d74eDavid Li */ 1231591693c7b415e9869157c711fe11263c95d74eDavid Libool 1241591693c7b415e9869157c711fe11263c95d74eDavid Lido_dead_code_unlinked(exec_list *instructions) 1251591693c7b415e9869157c711fe11263c95d74eDavid Li{ 1261591693c7b415e9869157c711fe11263c95d74eDavid Li bool progress = false; 1271591693c7b415e9869157c711fe11263c95d74eDavid Li 1281591693c7b415e9869157c711fe11263c95d74eDavid Li foreach_iter(exec_list_iterator, iter, *instructions) { 1291591693c7b415e9869157c711fe11263c95d74eDavid Li ir_instruction *ir = (ir_instruction *)iter.get(); 1301591693c7b415e9869157c711fe11263c95d74eDavid Li ir_function *f = ir->as_function(); 1311591693c7b415e9869157c711fe11263c95d74eDavid Li if (f) { 1321591693c7b415e9869157c711fe11263c95d74eDavid Li foreach_iter(exec_list_iterator, sigiter, *f) { 1331591693c7b415e9869157c711fe11263c95d74eDavid Li ir_function_signature *sig = 1341591693c7b415e9869157c711fe11263c95d74eDavid Li (ir_function_signature *) sigiter.get(); 1351591693c7b415e9869157c711fe11263c95d74eDavid Li if (do_dead_code(&sig->body)) 1361591693c7b415e9869157c711fe11263c95d74eDavid Li progress = true; 1371591693c7b415e9869157c711fe11263c95d74eDavid Li } 1381591693c7b415e9869157c711fe11263c95d74eDavid Li } 1391591693c7b415e9869157c711fe11263c95d74eDavid Li } 1401591693c7b415e9869157c711fe11263c95d74eDavid Li 1411591693c7b415e9869157c711fe11263c95d74eDavid Li return progress; 1421591693c7b415e9869157c711fe11263c95d74eDavid Li} 143