diff options
| -rw-r--r-- | src/glsl/Makefile | 1 | ||||
| -rw-r--r-- | src/glsl/glsl_symbol_table.h | 6 | ||||
| -rw-r--r-- | src/glsl/ir.h | 1 | ||||
| -rw-r--r-- | src/glsl/ir_dead_functions.cpp | 151 | ||||
| -rw-r--r-- | src/glsl/ir_optimization.h | 1 | ||||
| -rw-r--r-- | src/glsl/linker.cpp | 1 | 
6 files changed, 160 insertions, 1 deletions
diff --git a/src/glsl/Makefile b/src/glsl/Makefile index 3102947494..844385792a 100644 --- a/src/glsl/Makefile +++ b/src/glsl/Makefile @@ -39,6 +39,7 @@ CXX_SOURCES = \  	ir.cpp \  	ir_dead_code.cpp \  	ir_dead_code_local.cpp \ +	ir_dead_functions.cpp \  	ir_div_to_mul_rcp.cpp \  	ir_expression_flattening.cpp \  	ir_function_can_inline.cpp \ diff --git a/src/glsl/glsl_symbol_table.h b/src/glsl/glsl_symbol_table.h index 27e825597c..02e4542cf3 100644 --- a/src/glsl/glsl_symbol_table.h +++ b/src/glsl/glsl_symbol_table.h @@ -133,6 +133,12 @@ public:        return _mesa_symbol_table_add_symbol(table, glsl_function_name_space,  					   name, f) == 0;     } + +   bool remove_function(const char *name, ir_function *f) +   { +      return _mesa_symbol_table_add_symbol(table, glsl_function_name_space, +					   name, f) == 0; +   }     /*@}*/     /** diff --git a/src/glsl/ir.h b/src/glsl/ir.h index e61485813d..f58602515e 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -410,7 +410,6 @@ public:      */     const char *name; -private:     /**      * List of ir_function_signature for each overloaded function with this name.      */ diff --git a/src/glsl/ir_dead_functions.cpp b/src/glsl/ir_dead_functions.cpp new file mode 100644 index 0000000000..26554441d3 --- /dev/null +++ b/src/glsl/ir_dead_functions.cpp @@ -0,0 +1,151 @@ + /* +  * Copyright © 2010 Intel Corporation +  * +  * Permission is hereby granted, free of charge, to any person obtaining a +  * copy of this software and associated documentation files (the "Software"), +  * to deal in the Software without restriction, including without limitation +  * the rights to use, copy, modify, merge, publish, distribute, sublicense, +  * and/or sell copies of the Software, and to permit persons to whom the +  * Software is furnished to do so, subject to the following conditions: +  * +  * The above copyright notice and this permission notice (including the next +  * paragraph) shall be included in all copies or substantial portions of the +  * Software. +  * +  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL +  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +  * DEALINGS IN THE SOFTWARE. +  */ + + /** +  * \file ir_dead_functions.cpp +  * +  * Eliminates unused functions from the linked program. +  */ + + #include "ir.h" + #include "ir_visitor.h" + #include "ir_expression_flattening.h" + #include "glsl_types.h" + + class signature_entry : public exec_node + { + public: +    signature_entry(ir_function_signature *sig) +    { +       this->signature = sig; +       this->used = false; +    } + +    ir_function_signature *signature; +    bool used; + }; + + class ir_dead_functions_visitor : public ir_hierarchical_visitor { + public: +    ir_dead_functions_visitor() +    { +       this->mem_ctx = talloc_new(NULL); +    } + +    ~ir_dead_functions_visitor() +    { +       talloc_free(this->mem_ctx); +    } + +    virtual ir_visitor_status visit_enter(ir_function_signature *); +    virtual ir_visitor_status visit_enter(ir_call *); + +    signature_entry *get_signature_entry(ir_function_signature *var); + +    bool (*predicate)(ir_instruction *ir); + +    /* List of signature_entry */ +    exec_list signature_list; +    void *mem_ctx; + }; + + + signature_entry * + ir_dead_functions_visitor::get_signature_entry(ir_function_signature *sig) + { +    foreach_iter(exec_list_iterator, iter, this->signature_list) { +       signature_entry *entry = (signature_entry *)iter.get(); +       if (entry->signature == sig) +	  return entry; +    } + +    signature_entry *entry = new(mem_ctx) signature_entry(sig); +    this->signature_list.push_tail(entry); +    return entry; + } + + + ir_visitor_status + ir_dead_functions_visitor::visit_enter(ir_function_signature *ir) + { +    signature_entry *entry = this->get_signature_entry(ir); + +    if (strcmp(ir->function_name(), "main") == 0) { +       entry->used = true; +    } + +    return visit_continue; + } + + + ir_visitor_status + ir_dead_functions_visitor::visit_enter(ir_call *ir) + { +    signature_entry *entry = this->get_signature_entry(ir->get_callee()); + +    entry->used = true; + +   return visit_continue; +} + +bool +do_dead_functions(exec_list *instructions) +{ +   ir_dead_functions_visitor v; +   bool progress = false; + +   visit_list_elements(&v, instructions); + +   /* Now that we've figured out which function signatures are used, remove +    * the unused ones, and remove function definitions that have no more +    * signatures. +    */ +    foreach_iter(exec_list_iterator, iter, v.signature_list) { +      signature_entry *entry = (signature_entry *)iter.get(); + +      if (!entry->used) { +	 entry->signature->remove(); +	 progress = true; +      } +      delete(entry); +   } + +   /* We don't just do this above when we nuked a signature because of +    * const pointers. +    */ +   foreach_iter(exec_list_iterator, iter, *instructions) { +      ir_instruction *ir = (ir_instruction *)iter.get(); +      ir_function *func = ir->as_function(); + +      if (func && func->signatures.is_empty()) { +	 /* At this point (post-linking), the symbol table is no +	  * longer in use, so not removing the function from the +	  * symbol table should be OK. +	  */ +	 func->remove(); +	 progress = true; +      } +   } + +   return progress; +} diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h index 55ec327193..e0c0715cf5 100644 --- a/src/glsl/ir_optimization.h +++ b/src/glsl/ir_optimization.h @@ -36,6 +36,7 @@ bool do_copy_propagation(exec_list *instructions);  bool do_dead_code(exec_list *instructions);  bool do_dead_code_local(exec_list *instructions);  bool do_dead_code_unlinked(exec_list *instructions); +bool do_dead_functions(exec_list *instructions);  bool do_div_to_mul_rcp(exec_list *instructions);  bool do_function_inlining(exec_list *instructions);  bool do_if_return(exec_list *instructions); diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 94db57d6a5..f9e24ca0f1 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1286,6 +1286,7 @@ link_shaders(struct gl_shader_program *prog)  	 progress = false;  	 progress = do_function_inlining(ir) || progress; +	 progress = do_dead_functions(ir) || progress;  	 progress = do_if_simplification(ir) || progress;  	 progress = do_copy_propagation(ir) || progress;  	 progress = do_dead_code_local(ir) || progress;  | 
