Add files that I missed when importing NaCl changes earlier
[gcc/nacl-gcc.git] / gcc / ipa.c
blob681afd3312cbcdbbdfcee93cb85c310b4c6154bb
1 /* Basic IPA optimizations and utilities.
2 Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "cgraph.h"
26 /* Fill array order with all nodes with output flag set in the reverse
27 topological order. */
29 int
30 cgraph_postorder (struct cgraph_node **order)
32 struct cgraph_node *node, *node2;
33 int stack_size = 0;
34 int order_pos = 0;
35 struct cgraph_edge *edge, last;
37 struct cgraph_node **stack =
38 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
40 /* We have to deal with cycles nicely, so use a depth first traversal
41 output algorithm. Ignore the fact that some functions won't need
42 to be output and put them into order as well, so we get dependencies
43 right through intline functions. */
44 for (node = cgraph_nodes; node; node = node->next)
45 node->aux = NULL;
46 for (node = cgraph_nodes; node; node = node->next)
47 if (!node->aux)
49 node2 = node;
50 if (!node->callers)
51 node->aux = &last;
52 else
53 node->aux = node->callers;
54 while (node2)
56 while (node2->aux != &last)
58 edge = node2->aux;
59 if (edge->next_caller)
60 node2->aux = edge->next_caller;
61 else
62 node2->aux = &last;
63 if (!edge->caller->aux)
65 if (!edge->caller->callers)
66 edge->caller->aux = &last;
67 else
68 edge->caller->aux = edge->caller->callers;
69 stack[stack_size++] = node2;
70 node2 = edge->caller;
71 break;
74 if (node2->aux == &last)
76 order[order_pos++] = node2;
77 if (stack_size)
78 node2 = stack[--stack_size];
79 else
80 node2 = NULL;
84 free (stack);
85 for (node = cgraph_nodes; node; node = node->next)
86 node->aux = NULL;
87 return order_pos;
90 /* Perform reachability analysis and reclaim all unreachable nodes.
91 If BEFORE_INLINING_P is true this function is called before inlining
92 decisions has been made. If BEFORE_INLINING_P is false this function also
93 removes unneeded bodies of extern inline functions. */
95 bool
96 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
98 struct cgraph_node *first = (void *) 1;
99 struct cgraph_node *node, *next;
100 bool changed = false;
101 int insns = 0;
103 #ifdef ENABLE_CHECKING
104 verify_cgraph ();
105 #endif
106 if (file)
107 fprintf (file, "\nReclaiming functions:");
108 #ifdef ENABLE_CHECKING
109 for (node = cgraph_nodes; node; node = node->next)
110 gcc_assert (!node->aux);
111 #endif
112 for (node = cgraph_nodes; node; node = node->next)
113 if (node->needed && !node->global.inlined_to
114 && ((!DECL_EXTERNAL (node->decl))
115 || !node->analyzed
116 || before_inlining_p))
118 node->aux = first;
119 first = node;
121 else
122 gcc_assert (!node->aux);
124 /* Perform reachability analysis. As a special case do not consider
125 extern inline functions not inlined as live because we won't output
126 them at all. */
127 while (first != (void *) 1)
129 struct cgraph_edge *e;
130 node = first;
131 first = first->aux;
133 for (e = node->callees; e; e = e->next_callee)
134 if (!e->callee->aux
135 && node->analyzed
136 && (!e->inline_failed || !e->callee->analyzed
137 || (!DECL_EXTERNAL (e->callee->decl))
138 || before_inlining_p))
140 e->callee->aux = first;
141 first = e->callee;
145 /* Remove unreachable nodes. Extern inline functions need special care;
146 Unreachable extern inline functions shall be removed.
147 Reachable extern inline functions we never inlined shall get their bodies
148 eliminated.
149 Reachable extern inline functions we sometimes inlined will be turned into
150 unanalyzed nodes so they look like for true extern functions to the rest
151 of code. Body of such functions is released via remove_node once the
152 inline clones are eliminated. */
153 for (node = cgraph_nodes; node; node = next)
155 next = node->next;
156 if (!node->aux)
158 int local_insns;
159 tree decl = node->decl;
161 node->global.inlined_to = NULL;
162 if (DECL_STRUCT_FUNCTION (decl))
163 local_insns = node->local.self_insns;
164 else
165 local_insns = 0;
166 if (file)
167 fprintf (file, " %s", cgraph_node_name (node));
168 if (!node->analyzed || !DECL_EXTERNAL (node->decl)
169 || before_inlining_p)
170 cgraph_remove_node (node);
171 else
173 struct cgraph_edge *e;
175 for (e = node->callers; e; e = e->next_caller)
176 if (e->caller->aux)
177 break;
178 if (e || node->needed)
180 struct cgraph_node *clone;
182 for (clone = node->next_clone; clone;
183 clone = clone->next_clone)
184 if (clone->aux)
185 break;
186 if (!clone)
188 DECL_SAVED_TREE (node->decl) = NULL;
189 DECL_STRUCT_FUNCTION (node->decl) = NULL;
190 DECL_INITIAL (node->decl) = error_mark_node;
191 node->analyzed = false;
193 cgraph_node_remove_callees (node);
194 node->analyzed = false;
196 else
197 cgraph_remove_node (node);
199 if (!DECL_SAVED_TREE (decl))
200 insns += local_insns;
201 changed = true;
204 for (node = cgraph_nodes; node; node = node->next)
205 node->aux = NULL;
206 if (file)
207 fprintf (file, "\nReclaimed %i insns", insns);
208 return changed;