2005-04-29 Jim Tison <jtison@us.ibm.com>
[official-gcc.git] / gcc / ipa.c
blobfe1055dc12bcb9a9402482a6680237ba884cc952
1 /* Basic IPA optimizations and utilities.
2 Copyright (C) 2003, 2004, 2005 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 2, 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 COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "cgraph.h"
27 /* Fill array order with all nodes with output flag set in the reverse
28 topological order. */
30 int
31 cgraph_postorder (struct cgraph_node **order)
33 struct cgraph_node *node, *node2;
34 int stack_size = 0;
35 int order_pos = 0;
36 struct cgraph_edge *edge, last;
38 struct cgraph_node **stack =
39 xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
41 /* We have to deal with cycles nicely, so use a depth first traversal
42 output algorithm. Ignore the fact that some functions won't need
43 to be output and put them into order as well, so we get dependencies
44 right through intline functions. */
45 for (node = cgraph_nodes; node; node = node->next)
46 node->aux = NULL;
47 for (node = cgraph_nodes; node; node = node->next)
48 if (!node->aux)
50 node2 = node;
51 if (!node->callers)
52 node->aux = &last;
53 else
54 node->aux = node->callers;
55 while (node2)
57 while (node2->aux != &last)
59 edge = node2->aux;
60 if (edge->next_caller)
61 node2->aux = edge->next_caller;
62 else
63 node2->aux = &last;
64 if (!edge->caller->aux)
66 if (!edge->caller->callers)
67 edge->caller->aux = &last;
68 else
69 edge->caller->aux = edge->caller->callers;
70 stack[stack_size++] = node2;
71 node2 = edge->caller;
72 break;
75 if (node2->aux == &last)
77 order[order_pos++] = node2;
78 if (stack_size)
79 node2 = stack[--stack_size];
80 else
81 node2 = NULL;
85 free (stack);
86 return order_pos;
89 /* Perform reachability analysis and reclaim all unreachable nodes.
90 If BEFORE_INLINING_P is true this function is called before inlining
91 decisions has been made. If BEFORE_INLINING_P is false this function also
92 removes unneeded bodies of extern inline functions. */
94 bool
95 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *dump_file)
97 struct cgraph_node *first = (void *) 1;
98 struct cgraph_node *node;
99 bool changed = false;
100 int insns = 0;
102 #ifdef ENABLE_CHECKING
103 verify_cgraph ();
104 #endif
105 if (dump_file)
106 fprintf (dump_file, "\nReclaiming functions:");
107 #ifdef ENABLE_CHECKING
108 for (node = cgraph_nodes; node; node = node->next)
109 gcc_assert (!node->aux);
110 #endif
111 for (node = cgraph_nodes; node; node = node->next)
112 if (node->needed && !node->global.inlined_to
113 && ((!DECL_EXTERNAL (node->decl))
114 || !node->analyzed
115 || before_inlining_p))
117 node->aux = first;
118 first = node;
120 else
121 gcc_assert (!node->aux);
123 /* Perform reachability analysis. As a special case do not consider
124 extern inline functions not inlined as live because we won't output
125 them at all. */
126 while (first != (void *) 1)
128 struct cgraph_edge *e;
129 node = first;
130 first = first->aux;
132 for (e = node->callees; e; e = e->next_callee)
133 if (!e->callee->aux
134 && node->analyzed
135 && (!e->inline_failed || !e->callee->analyzed
136 || (!DECL_EXTERNAL (e->callee->decl))
137 || before_inlining_p))
139 e->callee->aux = first;
140 first = e->callee;
144 /* Remove unreachable nodes. Extern inline functions need special care;
145 Unreachable extern inline functions shall be removed.
146 Reachable extern inline functions we never inlined shall get their bodies
147 eliminated.
148 Reachable extern inline functions we sometimes inlined will be turned into
149 unanalyzed nodes so they look like for true extern functions to the rest
150 of code. Body of such functions is released via remove_node once the
151 inline clones are eliminated. */
152 for (node = cgraph_nodes; node; node = node->next)
154 if (!node->aux)
156 int local_insns;
157 tree decl = node->decl;
159 node->global.inlined_to = NULL;
160 if (DECL_STRUCT_FUNCTION (decl))
161 local_insns = node->local.self_insns;
162 else
163 local_insns = 0;
164 if (dump_file)
165 fprintf (dump_file, " %s", cgraph_node_name (node));
166 if (!node->analyzed || !DECL_EXTERNAL (node->decl)
167 || before_inlining_p)
168 cgraph_remove_node (node);
169 else
171 struct cgraph_edge *e;
173 for (e = node->callers; e; e = e->next_caller)
174 if (e->caller->aux)
175 break;
176 if (e || node->needed)
178 struct cgraph_node *clone;
180 for (clone = node->next_clone; clone;
181 clone = clone->next_clone)
182 if (clone->aux)
183 break;
184 if (!clone)
186 DECL_SAVED_TREE (node->decl) = NULL;
187 DECL_STRUCT_FUNCTION (node->decl) = NULL;
188 DECL_INITIAL (node->decl) = error_mark_node;
189 node->analyzed = false;
191 cgraph_node_remove_callees (node);
192 node->analyzed = false;
194 else
195 cgraph_remove_node (node);
197 if (!DECL_SAVED_TREE (decl))
198 insns += local_insns;
199 changed = true;
202 for (node = cgraph_nodes; node; node = node->next)
203 node->aux = NULL;
204 if (dump_file)
205 fprintf (dump_file, "\nReclaimed %i insns", insns);
206 return changed;