17d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt/* 27d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * Copyright © 2010 Intel Corporation 37d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * 47d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * Permission is hereby granted, free of charge, to any person obtaining a 57d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * copy of this software and associated documentation files (the "Software"), 67d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * to deal in the Software without restriction, including without limitation 77d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * and/or sell copies of the Software, and to permit persons to whom the 97d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * Software is furnished to do so, subject to the following conditions: 107d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * 117d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * The above copyright notice and this permission notice (including the next 127d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * paragraph) shall be included in all copies or substantial portions of the 137d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * Software. 147d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * 157d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 217d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * DEALINGS IN THE SOFTWARE. 227d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt */ 237d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 247d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt/** 25df883eb1575a740bf91e01cbe2eaa4dbc1f9f154Chad Versace * \file opt_dead_code.cpp 267d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * 277d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * Eliminates dead assignments and variable declarations from the code. 287d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt */ 297d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 307d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt#include "ir.h" 317d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt#include "ir_visitor.h" 32d72edc4dddb6dd7908ef0d3f2cec353b028bf6c5Eric Anholt#include "ir_variable_refcount.h" 337d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt#include "glsl_types.h" 347d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 353bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholtstatic bool debug = false; 363bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt 377d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt/** 387d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * Do a dead code pass over instructions and everything that instructions 397d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * references. 407d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * 417d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * Note that this will remove assignments to globals, so it is not suitable 427d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * for usage on an unlinked instruction stream. 437d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt */ 447d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholtbool 451d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanickdo_dead_code(exec_list *instructions, bool uniform_locations_assigned) 467d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt{ 47d72edc4dddb6dd7908ef0d3f2cec353b028bf6c5Eric Anholt ir_variable_refcount_visitor v; 487d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt bool progress = false; 497d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 50b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick v.run(instructions); 517d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 527d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt foreach_iter(exec_list_iterator, iter, v.variable_list) { 53e3b520049675f78065eccbc25c001ea77861c129Kenneth Graunke ir_variable_refcount_entry *entry = (ir_variable_refcount_entry *)iter.get(); 547d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 55b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick /* Since each assignment is a reference, the refereneced count must be 56b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick * greater than or equal to the assignment count. If they are equal, 57b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick * then all of the references are assignments, and the variable is 58b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick * dead. 59b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick * 60b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick * Note that if the variable is neither assigned nor referenced, both 61b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick * counts will be zero and will be caught by the equality test. 62b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick */ 63b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick assert(entry->referenced_count >= entry->assigned_count); 64b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick 653bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt if (debug) { 663bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt printf("%s@%p: %d refs, %d assigns, %sdeclared in our scope\n", 679f9386d22aca8d14d1b1e6d4de9b24dcb183ca10Brian Paul entry->var->name, (void *) entry->var, 683bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt entry->referenced_count, entry->assigned_count, 693bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt entry->declaration ? "" : "not "); 703bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt } 713bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt 72b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick if ((entry->referenced_count > entry->assigned_count) 73b5a7cf93442c2def485dcfd05df46abcd78b5d21Ian Romanick || !entry->declaration) 747d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt continue; 757d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 767d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt if (entry->assign) { 777d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt /* Remove a single dead assignment to the variable we found. 787d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * Don't do so if it's a shader output, though. 797d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt */ 80046bef235744e891e4a48076e1a3ff9a61a63092Eric Anholt if (entry->var->mode != ir_var_out && 81d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke entry->var->mode != ir_var_inout) { 827d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt entry->assign->remove(); 837d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt progress = true; 843bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt 853bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt if (debug) { 863bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt printf("Removed assignment to %s@%p\n", 879f9386d22aca8d14d1b1e6d4de9b24dcb183ca10Brian Paul entry->var->name, (void *) entry->var); 883bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt } 897d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt } 907d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt } else { 917d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt /* If there are no assignments or references to the variable left, 927d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * then we can remove its declaration. 937d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt */ 947de4d8fe11c53e59265b8a4252ab9940ffcc9929Eric Anholt 957de4d8fe11c53e59265b8a4252ab9940ffcc9929Eric Anholt /* uniform initializers are precious, and could get used by another 961d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanick * stage. Also, once uniform locations have been assigned, the 971d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanick * declaration cannot be deleted. 980cea8a56b627cea297e4213266b57b7a1085dccaEric Anholt * 990cea8a56b627cea297e4213266b57b7a1085dccaEric Anholt * Also, GL_ARB_uniform_buffer_object says that std140 1000cea8a56b627cea297e4213266b57b7a1085dccaEric Anholt * uniforms will not be eliminated. Since we always do 1010cea8a56b627cea297e4213266b57b7a1085dccaEric Anholt * std140, just don't eliminate uniforms in UBOs. 1027de4d8fe11c53e59265b8a4252ab9940ffcc9929Eric Anholt */ 1037de4d8fe11c53e59265b8a4252ab9940ffcc9929Eric Anholt if (entry->var->mode == ir_var_uniform && 1040cea8a56b627cea297e4213266b57b7a1085dccaEric Anholt (uniform_locations_assigned || 1050cea8a56b627cea297e4213266b57b7a1085dccaEric Anholt entry->var->constant_value || 1060cea8a56b627cea297e4213266b57b7a1085dccaEric Anholt entry->var->uniform_block != -1)) 1077de4d8fe11c53e59265b8a4252ab9940ffcc9929Eric Anholt continue; 1087de4d8fe11c53e59265b8a4252ab9940ffcc9929Eric Anholt 1097d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt entry->var->remove(); 1107d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt progress = true; 1113bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt 1123bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt if (debug) { 1133bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt printf("Removed declaration of %s@%p\n", 1149f9386d22aca8d14d1b1e6d4de9b24dcb183ca10Brian Paul entry->var->name, (void *) entry->var); 1153bd7e70bf7c4a9a52b425284c9f23689f00de93cEric Anholt } 1167d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt } 1177d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt } 11866d4c65ee2c311ea0c71c39a28456d0c11798d6bEric Anholt 1197d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt return progress; 1207d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt} 1217d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 1227d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt/** 1237d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * Does a dead code pass on the functions present in the instruction stream. 1247d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * 1257d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * This is suitable for use while the program is not linked, as it will 1267d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * ignore variable declarations (and the assignments to them) for variables 1277d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt * with global scope. 1287d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt */ 1297d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholtbool 13066d4c65ee2c311ea0c71c39a28456d0c11798d6bEric Anholtdo_dead_code_unlinked(exec_list *instructions) 1317d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt{ 1327d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt bool progress = false; 1337d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 1347d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt foreach_iter(exec_list_iterator, iter, *instructions) { 1357d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt ir_instruction *ir = (ir_instruction *)iter.get(); 1366202cbfe3614141e330501959a7322522b35f4e4Kenneth Graunke ir_function *f = ir->as_function(); 1376202cbfe3614141e330501959a7322522b35f4e4Kenneth Graunke if (f) { 1386202cbfe3614141e330501959a7322522b35f4e4Kenneth Graunke foreach_iter(exec_list_iterator, sigiter, *f) { 1396202cbfe3614141e330501959a7322522b35f4e4Kenneth Graunke ir_function_signature *sig = 1406202cbfe3614141e330501959a7322522b35f4e4Kenneth Graunke (ir_function_signature *) sigiter.get(); 1411d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanick /* The setting of the uniform_locations_assigned flag here is 1421d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanick * irrelevent. If there is a uniform declaration encountered 1431d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanick * inside the body of the function, something has already gone 1441d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanick * terribly, terribly wrong. 1451d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanick */ 1461d5d67f8adac9f94715de9804adb536d9a7ec5eeIan Romanick if (do_dead_code(&sig->body, false)) 1476202cbfe3614141e330501959a7322522b35f4e4Kenneth Graunke progress = true; 1486202cbfe3614141e330501959a7322522b35f4e4Kenneth Graunke } 1497d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt } 1507d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt } 1517d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt 1527d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt return progress; 1537d21104a8b92c139051e9a224c5d863802a8ade6Eric Anholt} 154