* testsuite/gcc.c-torture/execute/simd-3.c: New.
[official-gcc.git] / gcc / cgraph.c
blobfd638bc14fb572f79e336acaf0360e3064b7d123
1 /* Callgraph handling code.
2 Copyright (C) 2003 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "tree-inline.h"
28 #include "langhooks.h"
29 #include "hashtab.h"
30 #include "toplev.h"
31 #include "flags.h"
32 #include "ggc.h"
33 #include "debug.h"
34 #include "target.h"
35 #include "cgraph.h"
36 #include "varray.h"
38 /* The known declarations must not get garbage collected. Callgraph
39 datastructures should not get saved via PCH code since this would
40 make it difficult to extend into intra-module optimizer later. So
41 we store only the references into the array to prevent gabrage
42 collector from deleting live data. */
43 static GTY(()) varray_type known_fns;
45 /* Hash table used to convert declarations into nodes. */
46 static htab_t cgraph_hash = 0;
48 /* The linked list of cgraph nodes. */
49 struct cgraph_node *cgraph_nodes;
51 /* Number of nodes in existence. */
52 int cgraph_n_nodes;
54 /* Set when whole unit has been analyzed so we can access global info. */
55 bool cgraph_global_info_ready = false;
57 static struct cgraph_edge *create_edge PARAMS ((struct cgraph_node *,
58 struct cgraph_node *));
59 static void cgraph_remove_edge PARAMS ((struct cgraph_node *, struct cgraph_node *));
60 static hashval_t hash_node PARAMS ((const PTR));
61 static int eq_node PARAMS ((const PTR, const PTR));
63 /* Returns a hash code for P. */
65 static hashval_t
66 hash_node (p)
67 const PTR p;
69 return (hashval_t)
70 htab_hash_pointer (DECL_ASSEMBLER_NAME
71 (((struct cgraph_node *) p)->decl));
74 /* Returns non-zero if P1 and P2 are equal. */
76 static int
77 eq_node (p1, p2)
78 const PTR p1;
79 const PTR p2;
81 return ((DECL_ASSEMBLER_NAME (((struct cgraph_node *) p1)->decl)) ==
82 DECL_ASSEMBLER_NAME ((tree) p2));
85 /* Return cgraph node assigned to DECL. Create new one when needed. */
86 struct cgraph_node *
87 cgraph_node (decl)
88 tree decl;
90 struct cgraph_node *node;
91 struct cgraph_node **slot;
93 if (TREE_CODE (decl) != FUNCTION_DECL)
94 abort ();
96 if (!cgraph_hash)
98 cgraph_hash = htab_create (10, hash_node, eq_node, NULL);
99 VARRAY_TREE_INIT (known_fns, 32, "known_fns");
102 slot =
103 (struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash, decl,
104 htab_hash_pointer
105 (DECL_ASSEMBLER_NAME
106 (decl)), 1);
107 if (*slot)
108 return *slot;
109 node = xcalloc (sizeof (*node), 1);
110 node->decl = decl;
111 node->next = cgraph_nodes;
112 if (cgraph_nodes)
113 cgraph_nodes->previous = node;
114 node->previous = NULL;
115 cgraph_nodes = node;
116 cgraph_n_nodes++;
117 *slot = node;
118 if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
120 node->origin = cgraph_node (DECL_CONTEXT (decl));
121 node->next_nested = node->origin->nested;
122 node->origin->nested = node;
124 VARRAY_PUSH_TREE (known_fns, decl);
125 return node;
128 /* Create edge from CALLER to CALLEE in the cgraph. */
130 static struct cgraph_edge *
131 create_edge (caller, callee)
132 struct cgraph_node *caller, *callee;
134 struct cgraph_edge *edge = xmalloc (sizeof (struct cgraph_edge));
136 edge->caller = caller;
137 edge->callee = callee;
138 edge->next_caller = callee->callers;
139 edge->next_callee = caller->callees;
140 caller->callees = edge;
141 callee->callers = edge;
142 return edge;
145 /* Remove the edge from CALLER to CALLEE in the cgraph. */
147 static void
148 cgraph_remove_edge (caller, callee)
149 struct cgraph_node *caller, *callee;
151 struct cgraph_edge **edge, **edge2;
153 for (edge = &callee->callers; *edge && (*edge)->caller != caller;
154 edge = &((*edge)->next_caller))
155 continue;
156 if (!*edge)
157 abort ();
158 *edge = (*edge)->next_caller;
159 for (edge2 = &caller->callees; *edge2 && (*edge2)->callee != callee;
160 edge2 = &(*edge2)->next_callee)
161 continue;
162 if (!*edge2)
163 abort ();
164 *edge2 = (*edge2)->next_callee;
167 /* Remove the node from cgraph. */
169 void
170 cgraph_remove_node (node)
171 struct cgraph_node *node;
173 while (node->callers)
174 cgraph_remove_edge (node->callers->caller, node);
175 while (node->callees)
176 cgraph_remove_edge (node, node->callees->callee);
177 while (node->nested)
178 cgraph_remove_node (node->nested);
179 if (node->origin)
181 struct cgraph_node **node2 = &node->origin->nested;
183 while (*node2 != node)
184 node2 = &(*node2)->next_nested;
185 *node2 = node->next_nested;
187 if (node->previous)
188 node->previous->next = node->next;
189 else
190 cgraph_nodes = node;
191 if (node->next)
192 node->next->previous = node->previous;
193 DECL_SAVED_TREE (node->decl) = NULL;
194 /* Do not free the structure itself so the walk over chain can continue. */
198 /* Record call from CALLER to CALLEE */
200 struct cgraph_edge *
201 cgraph_record_call (caller, callee)
202 tree caller, callee;
204 return create_edge (cgraph_node (caller), cgraph_node (callee));
207 void
208 cgraph_remove_call (caller, callee)
209 tree caller, callee;
211 cgraph_remove_edge (cgraph_node (caller), cgraph_node (callee));
214 /* Return true when CALLER_DECL calls CALLEE_DECL. */
216 bool
217 cgraph_calls_p (caller_decl, callee_decl)
218 tree caller_decl, callee_decl;
220 struct cgraph_node *caller = cgraph_node (caller_decl);
221 struct cgraph_node *callee = cgraph_node (callee_decl);
222 struct cgraph_edge *edge;
224 for (edge = callee->callers; edge && (edge)->caller != caller;
225 edge = (edge->next_caller))
226 continue;
227 return edge != NULL;
230 /* Return local info for the compiled function. */
232 struct cgraph_local_info *
233 cgraph_local_info (decl)
234 tree decl;
236 struct cgraph_node *node;
237 if (TREE_CODE (decl) != FUNCTION_DECL)
238 abort ();
239 node = cgraph_node (decl);
240 return &node->local;
243 /* Return local info for the compiled function. */
245 struct cgraph_global_info *
246 cgraph_global_info (decl)
247 tree decl;
249 struct cgraph_node *node;
250 if (TREE_CODE (decl) != FUNCTION_DECL || !cgraph_global_info_ready)
251 abort ();
252 node = cgraph_node (decl);
253 return &node->global;
256 /* Return local info for the compiled function. */
258 struct cgraph_rtl_info *
259 cgraph_rtl_info (decl)
260 tree decl;
262 struct cgraph_node *node;
263 if (TREE_CODE (decl) != FUNCTION_DECL)
264 abort ();
265 node = cgraph_node (decl);
266 if (decl != current_function_decl
267 && !TREE_ASM_WRITTEN (node->decl))
268 return NULL;
269 return &node->rtl;
273 /* Dump the callgraph. */
275 void
276 dump_cgraph (f)
277 FILE *f;
279 struct cgraph_node *node;
281 fprintf (f, "\nCallgraph:\n\n");
282 for (node = cgraph_nodes; node; node = node->next)
284 struct cgraph_edge *edge;
285 fprintf (f, "%s", IDENTIFIER_POINTER (DECL_NAME (node->decl)));
286 if (node->origin)
287 fprintf (f, " nested in: %s",
288 IDENTIFIER_POINTER (DECL_NAME (node->origin->decl)));
289 if (node->needed)
290 fprintf (f, " needed");
291 else if (node->reachable)
292 fprintf (f, " reachable");
293 if (DECL_SAVED_TREE (node->decl))
294 fprintf (f, " tree");
296 fprintf (f, "\n called by :");
297 for (edge = node->callers; edge; edge = edge->next_caller)
298 fprintf (f, "%s ",
299 IDENTIFIER_POINTER (DECL_NAME (edge->caller->decl)));
301 fprintf (f, "\n calls: ");
302 for (edge = node->callees; edge; edge = edge->next_callee)
303 fprintf (f, "%s ",
304 IDENTIFIER_POINTER (DECL_NAME (edge->callee->decl)));
305 fprintf (f, "\n");
309 #include "gt-cgraph.h"