• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright © 2010 Intel Corporation
3   *
4   * Permission is hereby granted, free of charge, to any person obtaining a
5   * copy of this software and associated documentation files (the "Software"),
6   * to deal in the Software without restriction, including without limitation
7   * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8   * and/or sell copies of the Software, and to permit persons to whom the
9   * Software is furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice (including the next
12   * paragraph) shall be included in all copies or substantial portions of the
13   * Software.
14   *
15   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18   * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21   * DEALINGS IN THE SOFTWARE.
22   */
23 
24  /**
25   * \file opt_dead_functions.cpp
26   *
27   * Eliminates unused functions from the linked program.
28   */
29 
30  #include "ir.h"
31  #include "ir_visitor.h"
32  #include "ir_expression_flattening.h"
33  #include "glsl_types.h"
34 
35  class signature_entry : public exec_node
36  {
37  public:
signature_entry(ir_function_signature * sig)38     signature_entry(ir_function_signature *sig)
39     {
40        this->signature = sig;
41        this->used = false;
42     }
43 
44     ir_function_signature *signature;
45     bool used;
46  };
47 
48  class ir_dead_functions_visitor : public ir_hierarchical_visitor {
49  public:
ir_dead_functions_visitor()50     ir_dead_functions_visitor()
51     {
52        this->mem_ctx = hieralloc_new(NULL);
53     }
54 
~ir_dead_functions_visitor()55     ~ir_dead_functions_visitor()
56     {
57        hieralloc_free(this->mem_ctx);
58     }
59 
60     virtual ir_visitor_status visit_enter(ir_function_signature *);
61     virtual ir_visitor_status visit_enter(ir_call *);
62 
63     signature_entry *get_signature_entry(ir_function_signature *var);
64 
65     bool (*predicate)(ir_instruction *ir);
66 
67     /* List of signature_entry */
68     exec_list signature_list;
69     void *mem_ctx;
70  };
71 
72 
73  signature_entry *
get_signature_entry(ir_function_signature * sig)74  ir_dead_functions_visitor::get_signature_entry(ir_function_signature *sig)
75  {
76     foreach_iter(exec_list_iterator, iter, this->signature_list) {
77        signature_entry *entry = (signature_entry *)iter.get();
78        if (entry->signature == sig)
79 	  return entry;
80     }
81 
82     signature_entry *entry = new(mem_ctx) signature_entry(sig);
83     this->signature_list.push_tail(entry);
84     return entry;
85  }
86 
87 
88  ir_visitor_status
visit_enter(ir_function_signature * ir)89  ir_dead_functions_visitor::visit_enter(ir_function_signature *ir)
90  {
91     signature_entry *entry = this->get_signature_entry(ir);
92 
93     if (strcmp(ir->function_name(), "main") == 0) {
94        entry->used = true;
95     }
96 
97     return visit_continue;
98  }
99 
100 
101  ir_visitor_status
visit_enter(ir_call * ir)102  ir_dead_functions_visitor::visit_enter(ir_call *ir)
103  {
104     signature_entry *entry = this->get_signature_entry(ir->get_callee());
105 
106     entry->used = true;
107 
108    return visit_continue;
109 }
110 
111 bool
do_dead_functions(exec_list * instructions)112 do_dead_functions(exec_list *instructions)
113 {
114    ir_dead_functions_visitor v;
115    bool progress = false;
116 
117    visit_list_elements(&v, instructions);
118 
119    /* Now that we've figured out which function signatures are used, remove
120     * the unused ones, and remove function definitions that have no more
121     * signatures.
122     */
123     foreach_iter(exec_list_iterator, iter, v.signature_list) {
124       signature_entry *entry = (signature_entry *)iter.get();
125 
126       if (!entry->used) {
127 	 entry->signature->remove();
128 	 delete entry->signature;
129 	 progress = true;
130       }
131       delete(entry);
132    }
133 
134    /* We don't just do this above when we nuked a signature because of
135     * const pointers.
136     */
137    foreach_iter(exec_list_iterator, iter, *instructions) {
138       ir_instruction *ir = (ir_instruction *)iter.get();
139       ir_function *func = ir->as_function();
140 
141       if (func && func->signatures.is_empty()) {
142 	 /* At this point (post-linking), the symbol table is no
143 	  * longer in use, so not removing the function from the
144 	  * symbol table should be OK.
145 	  */
146 	 func->remove();
147 	 delete func;
148 	 progress = true;
149       }
150    }
151 
152    return progress;
153 }
154