1*e4b17023SJohn Marino /* Utilities for ipa analysis.
2*e4b17023SJohn Marino Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
3*e4b17023SJohn Marino Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
4*e4b17023SJohn Marino
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
8*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
9*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
10*e4b17023SJohn Marino version.
11*e4b17023SJohn Marino
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15*e4b17023SJohn Marino for more details.
16*e4b17023SJohn Marino
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
20*e4b17023SJohn Marino
21*e4b17023SJohn Marino #include "config.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "tree.h"
26*e4b17023SJohn Marino #include "tree-flow.h"
27*e4b17023SJohn Marino #include "tree-inline.h"
28*e4b17023SJohn Marino #include "tree-pass.h"
29*e4b17023SJohn Marino #include "langhooks.h"
30*e4b17023SJohn Marino #include "pointer-set.h"
31*e4b17023SJohn Marino #include "splay-tree.h"
32*e4b17023SJohn Marino #include "ggc.h"
33*e4b17023SJohn Marino #include "ipa-utils.h"
34*e4b17023SJohn Marino #include "ipa-reference.h"
35*e4b17023SJohn Marino #include "gimple.h"
36*e4b17023SJohn Marino #include "cgraph.h"
37*e4b17023SJohn Marino #include "output.h"
38*e4b17023SJohn Marino #include "flags.h"
39*e4b17023SJohn Marino #include "timevar.h"
40*e4b17023SJohn Marino #include "diagnostic.h"
41*e4b17023SJohn Marino #include "langhooks.h"
42*e4b17023SJohn Marino
43*e4b17023SJohn Marino /* Debugging function for postorder and inorder code. NOTE is a string
44*e4b17023SJohn Marino that is printed before the nodes are printed. ORDER is an array of
45*e4b17023SJohn Marino cgraph_nodes that has COUNT useful nodes in it. */
46*e4b17023SJohn Marino
47*e4b17023SJohn Marino void
ipa_print_order(FILE * out,const char * note,struct cgraph_node ** order,int count)48*e4b17023SJohn Marino ipa_print_order (FILE* out,
49*e4b17023SJohn Marino const char * note,
50*e4b17023SJohn Marino struct cgraph_node** order,
51*e4b17023SJohn Marino int count)
52*e4b17023SJohn Marino {
53*e4b17023SJohn Marino int i;
54*e4b17023SJohn Marino fprintf (out, "\n\n ordered call graph: %s\n", note);
55*e4b17023SJohn Marino
56*e4b17023SJohn Marino for (i = count - 1; i >= 0; i--)
57*e4b17023SJohn Marino dump_cgraph_node(dump_file, order[i]);
58*e4b17023SJohn Marino fprintf (out, "\n");
59*e4b17023SJohn Marino fflush(out);
60*e4b17023SJohn Marino }
61*e4b17023SJohn Marino
62*e4b17023SJohn Marino
63*e4b17023SJohn Marino struct searchc_env {
64*e4b17023SJohn Marino struct cgraph_node **stack;
65*e4b17023SJohn Marino int stack_size;
66*e4b17023SJohn Marino struct cgraph_node **result;
67*e4b17023SJohn Marino int order_pos;
68*e4b17023SJohn Marino splay_tree nodes_marked_new;
69*e4b17023SJohn Marino bool reduce;
70*e4b17023SJohn Marino bool allow_overwritable;
71*e4b17023SJohn Marino int count;
72*e4b17023SJohn Marino };
73*e4b17023SJohn Marino
74*e4b17023SJohn Marino /* This is an implementation of Tarjan's strongly connected region
75*e4b17023SJohn Marino finder as reprinted in Aho Hopcraft and Ullman's The Design and
76*e4b17023SJohn Marino Analysis of Computer Programs (1975) pages 192-193. This version
77*e4b17023SJohn Marino has been customized for cgraph_nodes. The env parameter is because
78*e4b17023SJohn Marino it is recursive and there are no nested functions here. This
79*e4b17023SJohn Marino function should only be called from itself or
80*e4b17023SJohn Marino ipa_reduced_postorder. ENV is a stack env and would be
81*e4b17023SJohn Marino unnecessary if C had nested functions. V is the node to start
82*e4b17023SJohn Marino searching from. */
83*e4b17023SJohn Marino
84*e4b17023SJohn Marino static void
searchc(struct searchc_env * env,struct cgraph_node * v,bool (* ignore_edge)(struct cgraph_edge *))85*e4b17023SJohn Marino searchc (struct searchc_env* env, struct cgraph_node *v,
86*e4b17023SJohn Marino bool (*ignore_edge) (struct cgraph_edge *))
87*e4b17023SJohn Marino {
88*e4b17023SJohn Marino struct cgraph_edge *edge;
89*e4b17023SJohn Marino struct ipa_dfs_info *v_info = (struct ipa_dfs_info *) v->aux;
90*e4b17023SJohn Marino
91*e4b17023SJohn Marino /* mark node as old */
92*e4b17023SJohn Marino v_info->new_node = false;
93*e4b17023SJohn Marino splay_tree_remove (env->nodes_marked_new, v->uid);
94*e4b17023SJohn Marino
95*e4b17023SJohn Marino v_info->dfn_number = env->count;
96*e4b17023SJohn Marino v_info->low_link = env->count;
97*e4b17023SJohn Marino env->count++;
98*e4b17023SJohn Marino env->stack[(env->stack_size)++] = v;
99*e4b17023SJohn Marino v_info->on_stack = true;
100*e4b17023SJohn Marino
101*e4b17023SJohn Marino for (edge = v->callees; edge; edge = edge->next_callee)
102*e4b17023SJohn Marino {
103*e4b17023SJohn Marino struct ipa_dfs_info * w_info;
104*e4b17023SJohn Marino enum availability avail;
105*e4b17023SJohn Marino struct cgraph_node *w = cgraph_function_or_thunk_node (edge->callee, &avail);
106*e4b17023SJohn Marino
107*e4b17023SJohn Marino if (!w || (ignore_edge && ignore_edge (edge)))
108*e4b17023SJohn Marino continue;
109*e4b17023SJohn Marino
110*e4b17023SJohn Marino if (w->aux
111*e4b17023SJohn Marino && (avail > AVAIL_OVERWRITABLE
112*e4b17023SJohn Marino || (env->allow_overwritable && avail == AVAIL_OVERWRITABLE)))
113*e4b17023SJohn Marino {
114*e4b17023SJohn Marino w_info = (struct ipa_dfs_info *) w->aux;
115*e4b17023SJohn Marino if (w_info->new_node)
116*e4b17023SJohn Marino {
117*e4b17023SJohn Marino searchc (env, w, ignore_edge);
118*e4b17023SJohn Marino v_info->low_link =
119*e4b17023SJohn Marino (v_info->low_link < w_info->low_link) ?
120*e4b17023SJohn Marino v_info->low_link : w_info->low_link;
121*e4b17023SJohn Marino }
122*e4b17023SJohn Marino else
123*e4b17023SJohn Marino if ((w_info->dfn_number < v_info->dfn_number)
124*e4b17023SJohn Marino && (w_info->on_stack))
125*e4b17023SJohn Marino v_info->low_link =
126*e4b17023SJohn Marino (w_info->dfn_number < v_info->low_link) ?
127*e4b17023SJohn Marino w_info->dfn_number : v_info->low_link;
128*e4b17023SJohn Marino }
129*e4b17023SJohn Marino }
130*e4b17023SJohn Marino
131*e4b17023SJohn Marino
132*e4b17023SJohn Marino if (v_info->low_link == v_info->dfn_number)
133*e4b17023SJohn Marino {
134*e4b17023SJohn Marino struct cgraph_node *last = NULL;
135*e4b17023SJohn Marino struct cgraph_node *x;
136*e4b17023SJohn Marino struct ipa_dfs_info *x_info;
137*e4b17023SJohn Marino do {
138*e4b17023SJohn Marino x = env->stack[--(env->stack_size)];
139*e4b17023SJohn Marino x_info = (struct ipa_dfs_info *) x->aux;
140*e4b17023SJohn Marino x_info->on_stack = false;
141*e4b17023SJohn Marino x_info->scc_no = v_info->dfn_number;
142*e4b17023SJohn Marino
143*e4b17023SJohn Marino if (env->reduce)
144*e4b17023SJohn Marino {
145*e4b17023SJohn Marino x_info->next_cycle = last;
146*e4b17023SJohn Marino last = x;
147*e4b17023SJohn Marino }
148*e4b17023SJohn Marino else
149*e4b17023SJohn Marino env->result[env->order_pos++] = x;
150*e4b17023SJohn Marino }
151*e4b17023SJohn Marino while (v != x);
152*e4b17023SJohn Marino if (env->reduce)
153*e4b17023SJohn Marino env->result[env->order_pos++] = v;
154*e4b17023SJohn Marino }
155*e4b17023SJohn Marino }
156*e4b17023SJohn Marino
157*e4b17023SJohn Marino /* Topsort the call graph by caller relation. Put the result in ORDER.
158*e4b17023SJohn Marino
159*e4b17023SJohn Marino The REDUCE flag is true if you want the cycles reduced to single nodes. Set
160*e4b17023SJohn Marino ALLOW_OVERWRITABLE if nodes with such availability should be included.
161*e4b17023SJohn Marino IGNORE_EDGE, if non-NULL is a hook that may make some edges insignificant
162*e4b17023SJohn Marino for the topological sort. */
163*e4b17023SJohn Marino
164*e4b17023SJohn Marino int
ipa_reduced_postorder(struct cgraph_node ** order,bool reduce,bool allow_overwritable,bool (* ignore_edge)(struct cgraph_edge *))165*e4b17023SJohn Marino ipa_reduced_postorder (struct cgraph_node **order,
166*e4b17023SJohn Marino bool reduce, bool allow_overwritable,
167*e4b17023SJohn Marino bool (*ignore_edge) (struct cgraph_edge *))
168*e4b17023SJohn Marino {
169*e4b17023SJohn Marino struct cgraph_node *node;
170*e4b17023SJohn Marino struct searchc_env env;
171*e4b17023SJohn Marino splay_tree_node result;
172*e4b17023SJohn Marino env.stack = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
173*e4b17023SJohn Marino env.stack_size = 0;
174*e4b17023SJohn Marino env.result = order;
175*e4b17023SJohn Marino env.order_pos = 0;
176*e4b17023SJohn Marino env.nodes_marked_new = splay_tree_new (splay_tree_compare_ints, 0, 0);
177*e4b17023SJohn Marino env.count = 1;
178*e4b17023SJohn Marino env.reduce = reduce;
179*e4b17023SJohn Marino env.allow_overwritable = allow_overwritable;
180*e4b17023SJohn Marino
181*e4b17023SJohn Marino for (node = cgraph_nodes; node; node = node->next)
182*e4b17023SJohn Marino {
183*e4b17023SJohn Marino enum availability avail = cgraph_function_body_availability (node);
184*e4b17023SJohn Marino
185*e4b17023SJohn Marino if (avail > AVAIL_OVERWRITABLE
186*e4b17023SJohn Marino || (allow_overwritable
187*e4b17023SJohn Marino && (avail == AVAIL_OVERWRITABLE)))
188*e4b17023SJohn Marino {
189*e4b17023SJohn Marino /* Reuse the info if it is already there. */
190*e4b17023SJohn Marino struct ipa_dfs_info *info = (struct ipa_dfs_info *) node->aux;
191*e4b17023SJohn Marino if (!info)
192*e4b17023SJohn Marino info = XCNEW (struct ipa_dfs_info);
193*e4b17023SJohn Marino info->new_node = true;
194*e4b17023SJohn Marino info->on_stack = false;
195*e4b17023SJohn Marino info->next_cycle = NULL;
196*e4b17023SJohn Marino node->aux = info;
197*e4b17023SJohn Marino
198*e4b17023SJohn Marino splay_tree_insert (env.nodes_marked_new,
199*e4b17023SJohn Marino (splay_tree_key)node->uid,
200*e4b17023SJohn Marino (splay_tree_value)node);
201*e4b17023SJohn Marino }
202*e4b17023SJohn Marino else
203*e4b17023SJohn Marino node->aux = NULL;
204*e4b17023SJohn Marino }
205*e4b17023SJohn Marino result = splay_tree_min (env.nodes_marked_new);
206*e4b17023SJohn Marino while (result)
207*e4b17023SJohn Marino {
208*e4b17023SJohn Marino node = (struct cgraph_node *)result->value;
209*e4b17023SJohn Marino searchc (&env, node, ignore_edge);
210*e4b17023SJohn Marino result = splay_tree_min (env.nodes_marked_new);
211*e4b17023SJohn Marino }
212*e4b17023SJohn Marino splay_tree_delete (env.nodes_marked_new);
213*e4b17023SJohn Marino free (env.stack);
214*e4b17023SJohn Marino
215*e4b17023SJohn Marino return env.order_pos;
216*e4b17023SJohn Marino }
217*e4b17023SJohn Marino
218*e4b17023SJohn Marino /* Deallocate all ipa_dfs_info structures pointed to by the aux pointer of call
219*e4b17023SJohn Marino graph nodes. */
220*e4b17023SJohn Marino
221*e4b17023SJohn Marino void
ipa_free_postorder_info(void)222*e4b17023SJohn Marino ipa_free_postorder_info (void)
223*e4b17023SJohn Marino {
224*e4b17023SJohn Marino struct cgraph_node *node;
225*e4b17023SJohn Marino for (node = cgraph_nodes; node; node = node->next)
226*e4b17023SJohn Marino {
227*e4b17023SJohn Marino /* Get rid of the aux information. */
228*e4b17023SJohn Marino if (node->aux)
229*e4b17023SJohn Marino {
230*e4b17023SJohn Marino free (node->aux);
231*e4b17023SJohn Marino node->aux = NULL;
232*e4b17023SJohn Marino }
233*e4b17023SJohn Marino }
234*e4b17023SJohn Marino }
235*e4b17023SJohn Marino
236*e4b17023SJohn Marino struct postorder_stack
237*e4b17023SJohn Marino {
238*e4b17023SJohn Marino struct cgraph_node *node;
239*e4b17023SJohn Marino struct cgraph_edge *edge;
240*e4b17023SJohn Marino int ref;
241*e4b17023SJohn Marino };
242*e4b17023SJohn Marino
243*e4b17023SJohn Marino /* Fill array order with all nodes with output flag set in the reverse
244*e4b17023SJohn Marino topological order. Return the number of elements in the array.
245*e4b17023SJohn Marino FIXME: While walking, consider aliases, too. */
246*e4b17023SJohn Marino
247*e4b17023SJohn Marino int
ipa_reverse_postorder(struct cgraph_node ** order)248*e4b17023SJohn Marino ipa_reverse_postorder (struct cgraph_node **order)
249*e4b17023SJohn Marino {
250*e4b17023SJohn Marino struct cgraph_node *node, *node2;
251*e4b17023SJohn Marino int stack_size = 0;
252*e4b17023SJohn Marino int order_pos = 0;
253*e4b17023SJohn Marino struct cgraph_edge *edge;
254*e4b17023SJohn Marino int pass;
255*e4b17023SJohn Marino struct ipa_ref *ref;
256*e4b17023SJohn Marino
257*e4b17023SJohn Marino struct postorder_stack *stack =
258*e4b17023SJohn Marino XCNEWVEC (struct postorder_stack, cgraph_n_nodes);
259*e4b17023SJohn Marino
260*e4b17023SJohn Marino /* We have to deal with cycles nicely, so use a depth first traversal
261*e4b17023SJohn Marino output algorithm. Ignore the fact that some functions won't need
262*e4b17023SJohn Marino to be output and put them into order as well, so we get dependencies
263*e4b17023SJohn Marino right through inline functions. */
264*e4b17023SJohn Marino for (node = cgraph_nodes; node; node = node->next)
265*e4b17023SJohn Marino node->aux = NULL;
266*e4b17023SJohn Marino for (pass = 0; pass < 2; pass++)
267*e4b17023SJohn Marino for (node = cgraph_nodes; node; node = node->next)
268*e4b17023SJohn Marino if (!node->aux
269*e4b17023SJohn Marino && (pass
270*e4b17023SJohn Marino || (!node->address_taken
271*e4b17023SJohn Marino && !node->global.inlined_to
272*e4b17023SJohn Marino && !node->alias && !node->thunk.thunk_p
273*e4b17023SJohn Marino && !cgraph_only_called_directly_p (node))))
274*e4b17023SJohn Marino {
275*e4b17023SJohn Marino stack_size = 0;
276*e4b17023SJohn Marino stack[stack_size].node = node;
277*e4b17023SJohn Marino stack[stack_size].edge = node->callers;
278*e4b17023SJohn Marino stack[stack_size].ref = 0;
279*e4b17023SJohn Marino node->aux = (void *)(size_t)1;
280*e4b17023SJohn Marino while (stack_size >= 0)
281*e4b17023SJohn Marino {
282*e4b17023SJohn Marino while (true)
283*e4b17023SJohn Marino {
284*e4b17023SJohn Marino node2 = NULL;
285*e4b17023SJohn Marino while (stack[stack_size].edge && !node2)
286*e4b17023SJohn Marino {
287*e4b17023SJohn Marino edge = stack[stack_size].edge;
288*e4b17023SJohn Marino node2 = edge->caller;
289*e4b17023SJohn Marino stack[stack_size].edge = edge->next_caller;
290*e4b17023SJohn Marino /* Break possible cycles involving always-inline
291*e4b17023SJohn Marino functions by ignoring edges from always-inline
292*e4b17023SJohn Marino functions to non-always-inline functions. */
293*e4b17023SJohn Marino if (DECL_DISREGARD_INLINE_LIMITS (edge->caller->decl)
294*e4b17023SJohn Marino && !DECL_DISREGARD_INLINE_LIMITS
295*e4b17023SJohn Marino (cgraph_function_node (edge->callee, NULL)->decl))
296*e4b17023SJohn Marino node2 = NULL;
297*e4b17023SJohn Marino }
298*e4b17023SJohn Marino for (;ipa_ref_list_refering_iterate (&stack[stack_size].node->ref_list,
299*e4b17023SJohn Marino stack[stack_size].ref,
300*e4b17023SJohn Marino ref) && !node2;
301*e4b17023SJohn Marino stack[stack_size].ref++)
302*e4b17023SJohn Marino {
303*e4b17023SJohn Marino if (ref->use == IPA_REF_ALIAS)
304*e4b17023SJohn Marino node2 = ipa_ref_refering_node (ref);
305*e4b17023SJohn Marino }
306*e4b17023SJohn Marino if (!node2)
307*e4b17023SJohn Marino break;
308*e4b17023SJohn Marino if (!node2->aux)
309*e4b17023SJohn Marino {
310*e4b17023SJohn Marino stack[++stack_size].node = node2;
311*e4b17023SJohn Marino stack[stack_size].edge = node2->callers;
312*e4b17023SJohn Marino stack[stack_size].ref = 0;
313*e4b17023SJohn Marino node2->aux = (void *)(size_t)1;
314*e4b17023SJohn Marino }
315*e4b17023SJohn Marino }
316*e4b17023SJohn Marino order[order_pos++] = stack[stack_size--].node;
317*e4b17023SJohn Marino }
318*e4b17023SJohn Marino }
319*e4b17023SJohn Marino free (stack);
320*e4b17023SJohn Marino for (node = cgraph_nodes; node; node = node->next)
321*e4b17023SJohn Marino node->aux = NULL;
322*e4b17023SJohn Marino return order_pos;
323*e4b17023SJohn Marino }
324*e4b17023SJohn Marino
325*e4b17023SJohn Marino
326*e4b17023SJohn Marino
327*e4b17023SJohn Marino /* Given a memory reference T, will return the variable at the bottom
328*e4b17023SJohn Marino of the access. Unlike get_base_address, this will recurse thru
329*e4b17023SJohn Marino INDIRECT_REFS. */
330*e4b17023SJohn Marino
331*e4b17023SJohn Marino tree
get_base_var(tree t)332*e4b17023SJohn Marino get_base_var (tree t)
333*e4b17023SJohn Marino {
334*e4b17023SJohn Marino while (!SSA_VAR_P (t)
335*e4b17023SJohn Marino && (!CONSTANT_CLASS_P (t))
336*e4b17023SJohn Marino && TREE_CODE (t) != LABEL_DECL
337*e4b17023SJohn Marino && TREE_CODE (t) != FUNCTION_DECL
338*e4b17023SJohn Marino && TREE_CODE (t) != CONST_DECL
339*e4b17023SJohn Marino && TREE_CODE (t) != CONSTRUCTOR)
340*e4b17023SJohn Marino {
341*e4b17023SJohn Marino t = TREE_OPERAND (t, 0);
342*e4b17023SJohn Marino }
343*e4b17023SJohn Marino return t;
344*e4b17023SJohn Marino }
345*e4b17023SJohn Marino
346*e4b17023SJohn Marino
347*e4b17023SJohn Marino /* Create a new cgraph node set. */
348*e4b17023SJohn Marino
349*e4b17023SJohn Marino cgraph_node_set
cgraph_node_set_new(void)350*e4b17023SJohn Marino cgraph_node_set_new (void)
351*e4b17023SJohn Marino {
352*e4b17023SJohn Marino cgraph_node_set new_node_set;
353*e4b17023SJohn Marino
354*e4b17023SJohn Marino new_node_set = XCNEW (struct cgraph_node_set_def);
355*e4b17023SJohn Marino new_node_set->map = pointer_map_create ();
356*e4b17023SJohn Marino new_node_set->nodes = NULL;
357*e4b17023SJohn Marino return new_node_set;
358*e4b17023SJohn Marino }
359*e4b17023SJohn Marino
360*e4b17023SJohn Marino
361*e4b17023SJohn Marino /* Add cgraph_node NODE to cgraph_node_set SET. */
362*e4b17023SJohn Marino
363*e4b17023SJohn Marino void
cgraph_node_set_add(cgraph_node_set set,struct cgraph_node * node)364*e4b17023SJohn Marino cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
365*e4b17023SJohn Marino {
366*e4b17023SJohn Marino void **slot;
367*e4b17023SJohn Marino
368*e4b17023SJohn Marino slot = pointer_map_insert (set->map, node);
369*e4b17023SJohn Marino
370*e4b17023SJohn Marino if (*slot)
371*e4b17023SJohn Marino {
372*e4b17023SJohn Marino int index = (size_t) *slot - 1;
373*e4b17023SJohn Marino gcc_checking_assert ((VEC_index (cgraph_node_ptr, set->nodes, index)
374*e4b17023SJohn Marino == node));
375*e4b17023SJohn Marino return;
376*e4b17023SJohn Marino }
377*e4b17023SJohn Marino
378*e4b17023SJohn Marino *slot = (void *)(size_t) (VEC_length (cgraph_node_ptr, set->nodes) + 1);
379*e4b17023SJohn Marino
380*e4b17023SJohn Marino /* Insert into node vector. */
381*e4b17023SJohn Marino VEC_safe_push (cgraph_node_ptr, heap, set->nodes, node);
382*e4b17023SJohn Marino }
383*e4b17023SJohn Marino
384*e4b17023SJohn Marino
385*e4b17023SJohn Marino /* Remove cgraph_node NODE from cgraph_node_set SET. */
386*e4b17023SJohn Marino
387*e4b17023SJohn Marino void
cgraph_node_set_remove(cgraph_node_set set,struct cgraph_node * node)388*e4b17023SJohn Marino cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
389*e4b17023SJohn Marino {
390*e4b17023SJohn Marino void **slot, **last_slot;
391*e4b17023SJohn Marino int index;
392*e4b17023SJohn Marino struct cgraph_node *last_node;
393*e4b17023SJohn Marino
394*e4b17023SJohn Marino slot = pointer_map_contains (set->map, node);
395*e4b17023SJohn Marino if (slot == NULL || !*slot)
396*e4b17023SJohn Marino return;
397*e4b17023SJohn Marino
398*e4b17023SJohn Marino index = (size_t) *slot - 1;
399*e4b17023SJohn Marino gcc_checking_assert (VEC_index (cgraph_node_ptr, set->nodes, index)
400*e4b17023SJohn Marino == node);
401*e4b17023SJohn Marino
402*e4b17023SJohn Marino /* Remove from vector. We do this by swapping node with the last element
403*e4b17023SJohn Marino of the vector. */
404*e4b17023SJohn Marino last_node = VEC_pop (cgraph_node_ptr, set->nodes);
405*e4b17023SJohn Marino if (last_node != node)
406*e4b17023SJohn Marino {
407*e4b17023SJohn Marino last_slot = pointer_map_contains (set->map, last_node);
408*e4b17023SJohn Marino gcc_checking_assert (last_slot && *last_slot);
409*e4b17023SJohn Marino *last_slot = (void *)(size_t) (index + 1);
410*e4b17023SJohn Marino
411*e4b17023SJohn Marino /* Move the last element to the original spot of NODE. */
412*e4b17023SJohn Marino VEC_replace (cgraph_node_ptr, set->nodes, index, last_node);
413*e4b17023SJohn Marino }
414*e4b17023SJohn Marino
415*e4b17023SJohn Marino /* Remove element from hash table. */
416*e4b17023SJohn Marino *slot = NULL;
417*e4b17023SJohn Marino }
418*e4b17023SJohn Marino
419*e4b17023SJohn Marino
420*e4b17023SJohn Marino /* Find NODE in SET and return an iterator to it if found. A null iterator
421*e4b17023SJohn Marino is returned if NODE is not in SET. */
422*e4b17023SJohn Marino
423*e4b17023SJohn Marino cgraph_node_set_iterator
cgraph_node_set_find(cgraph_node_set set,struct cgraph_node * node)424*e4b17023SJohn Marino cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
425*e4b17023SJohn Marino {
426*e4b17023SJohn Marino void **slot;
427*e4b17023SJohn Marino cgraph_node_set_iterator csi;
428*e4b17023SJohn Marino
429*e4b17023SJohn Marino slot = pointer_map_contains (set->map, node);
430*e4b17023SJohn Marino if (slot == NULL || !*slot)
431*e4b17023SJohn Marino csi.index = (unsigned) ~0;
432*e4b17023SJohn Marino else
433*e4b17023SJohn Marino csi.index = (size_t)*slot - 1;
434*e4b17023SJohn Marino csi.set = set;
435*e4b17023SJohn Marino
436*e4b17023SJohn Marino return csi;
437*e4b17023SJohn Marino }
438*e4b17023SJohn Marino
439*e4b17023SJohn Marino
440*e4b17023SJohn Marino /* Dump content of SET to file F. */
441*e4b17023SJohn Marino
442*e4b17023SJohn Marino void
dump_cgraph_node_set(FILE * f,cgraph_node_set set)443*e4b17023SJohn Marino dump_cgraph_node_set (FILE *f, cgraph_node_set set)
444*e4b17023SJohn Marino {
445*e4b17023SJohn Marino cgraph_node_set_iterator iter;
446*e4b17023SJohn Marino
447*e4b17023SJohn Marino for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
448*e4b17023SJohn Marino {
449*e4b17023SJohn Marino struct cgraph_node *node = csi_node (iter);
450*e4b17023SJohn Marino fprintf (f, " %s/%i", cgraph_node_name (node), node->uid);
451*e4b17023SJohn Marino }
452*e4b17023SJohn Marino fprintf (f, "\n");
453*e4b17023SJohn Marino }
454*e4b17023SJohn Marino
455*e4b17023SJohn Marino
456*e4b17023SJohn Marino /* Dump content of SET to stderr. */
457*e4b17023SJohn Marino
458*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_cgraph_node_set(cgraph_node_set set)459*e4b17023SJohn Marino debug_cgraph_node_set (cgraph_node_set set)
460*e4b17023SJohn Marino {
461*e4b17023SJohn Marino dump_cgraph_node_set (stderr, set);
462*e4b17023SJohn Marino }
463*e4b17023SJohn Marino
464*e4b17023SJohn Marino
465*e4b17023SJohn Marino /* Free varpool node set. */
466*e4b17023SJohn Marino
467*e4b17023SJohn Marino void
free_cgraph_node_set(cgraph_node_set set)468*e4b17023SJohn Marino free_cgraph_node_set (cgraph_node_set set)
469*e4b17023SJohn Marino {
470*e4b17023SJohn Marino VEC_free (cgraph_node_ptr, heap, set->nodes);
471*e4b17023SJohn Marino pointer_map_destroy (set->map);
472*e4b17023SJohn Marino free (set);
473*e4b17023SJohn Marino }
474*e4b17023SJohn Marino
475*e4b17023SJohn Marino
476*e4b17023SJohn Marino /* Create a new varpool node set. */
477*e4b17023SJohn Marino
478*e4b17023SJohn Marino varpool_node_set
varpool_node_set_new(void)479*e4b17023SJohn Marino varpool_node_set_new (void)
480*e4b17023SJohn Marino {
481*e4b17023SJohn Marino varpool_node_set new_node_set;
482*e4b17023SJohn Marino
483*e4b17023SJohn Marino new_node_set = XCNEW (struct varpool_node_set_def);
484*e4b17023SJohn Marino new_node_set->map = pointer_map_create ();
485*e4b17023SJohn Marino new_node_set->nodes = NULL;
486*e4b17023SJohn Marino return new_node_set;
487*e4b17023SJohn Marino }
488*e4b17023SJohn Marino
489*e4b17023SJohn Marino
490*e4b17023SJohn Marino /* Add varpool_node NODE to varpool_node_set SET. */
491*e4b17023SJohn Marino
492*e4b17023SJohn Marino void
varpool_node_set_add(varpool_node_set set,struct varpool_node * node)493*e4b17023SJohn Marino varpool_node_set_add (varpool_node_set set, struct varpool_node *node)
494*e4b17023SJohn Marino {
495*e4b17023SJohn Marino void **slot;
496*e4b17023SJohn Marino
497*e4b17023SJohn Marino slot = pointer_map_insert (set->map, node);
498*e4b17023SJohn Marino
499*e4b17023SJohn Marino if (*slot)
500*e4b17023SJohn Marino {
501*e4b17023SJohn Marino int index = (size_t) *slot - 1;
502*e4b17023SJohn Marino gcc_checking_assert ((VEC_index (varpool_node_ptr, set->nodes, index)
503*e4b17023SJohn Marino == node));
504*e4b17023SJohn Marino return;
505*e4b17023SJohn Marino }
506*e4b17023SJohn Marino
507*e4b17023SJohn Marino *slot = (void *)(size_t) (VEC_length (varpool_node_ptr, set->nodes) + 1);
508*e4b17023SJohn Marino
509*e4b17023SJohn Marino /* Insert into node vector. */
510*e4b17023SJohn Marino VEC_safe_push (varpool_node_ptr, heap, set->nodes, node);
511*e4b17023SJohn Marino }
512*e4b17023SJohn Marino
513*e4b17023SJohn Marino
514*e4b17023SJohn Marino /* Remove varpool_node NODE from varpool_node_set SET. */
515*e4b17023SJohn Marino
516*e4b17023SJohn Marino void
varpool_node_set_remove(varpool_node_set set,struct varpool_node * node)517*e4b17023SJohn Marino varpool_node_set_remove (varpool_node_set set, struct varpool_node *node)
518*e4b17023SJohn Marino {
519*e4b17023SJohn Marino void **slot, **last_slot;
520*e4b17023SJohn Marino int index;
521*e4b17023SJohn Marino struct varpool_node *last_node;
522*e4b17023SJohn Marino
523*e4b17023SJohn Marino slot = pointer_map_contains (set->map, node);
524*e4b17023SJohn Marino if (slot == NULL || !*slot)
525*e4b17023SJohn Marino return;
526*e4b17023SJohn Marino
527*e4b17023SJohn Marino index = (size_t) *slot - 1;
528*e4b17023SJohn Marino gcc_checking_assert (VEC_index (varpool_node_ptr, set->nodes, index)
529*e4b17023SJohn Marino == node);
530*e4b17023SJohn Marino
531*e4b17023SJohn Marino /* Remove from vector. We do this by swapping node with the last element
532*e4b17023SJohn Marino of the vector. */
533*e4b17023SJohn Marino last_node = VEC_pop (varpool_node_ptr, set->nodes);
534*e4b17023SJohn Marino if (last_node != node)
535*e4b17023SJohn Marino {
536*e4b17023SJohn Marino last_slot = pointer_map_contains (set->map, last_node);
537*e4b17023SJohn Marino gcc_checking_assert (last_slot && *last_slot);
538*e4b17023SJohn Marino *last_slot = (void *)(size_t) (index + 1);
539*e4b17023SJohn Marino
540*e4b17023SJohn Marino /* Move the last element to the original spot of NODE. */
541*e4b17023SJohn Marino VEC_replace (varpool_node_ptr, set->nodes, index, last_node);
542*e4b17023SJohn Marino }
543*e4b17023SJohn Marino
544*e4b17023SJohn Marino /* Remove element from hash table. */
545*e4b17023SJohn Marino *slot = NULL;
546*e4b17023SJohn Marino }
547*e4b17023SJohn Marino
548*e4b17023SJohn Marino
549*e4b17023SJohn Marino /* Find NODE in SET and return an iterator to it if found. A null iterator
550*e4b17023SJohn Marino is returned if NODE is not in SET. */
551*e4b17023SJohn Marino
552*e4b17023SJohn Marino varpool_node_set_iterator
varpool_node_set_find(varpool_node_set set,struct varpool_node * node)553*e4b17023SJohn Marino varpool_node_set_find (varpool_node_set set, struct varpool_node *node)
554*e4b17023SJohn Marino {
555*e4b17023SJohn Marino void **slot;
556*e4b17023SJohn Marino varpool_node_set_iterator vsi;
557*e4b17023SJohn Marino
558*e4b17023SJohn Marino slot = pointer_map_contains (set->map, node);
559*e4b17023SJohn Marino if (slot == NULL || !*slot)
560*e4b17023SJohn Marino vsi.index = (unsigned) ~0;
561*e4b17023SJohn Marino else
562*e4b17023SJohn Marino vsi.index = (size_t)*slot - 1;
563*e4b17023SJohn Marino vsi.set = set;
564*e4b17023SJohn Marino
565*e4b17023SJohn Marino return vsi;
566*e4b17023SJohn Marino }
567*e4b17023SJohn Marino
568*e4b17023SJohn Marino
569*e4b17023SJohn Marino /* Dump content of SET to file F. */
570*e4b17023SJohn Marino
571*e4b17023SJohn Marino void
dump_varpool_node_set(FILE * f,varpool_node_set set)572*e4b17023SJohn Marino dump_varpool_node_set (FILE *f, varpool_node_set set)
573*e4b17023SJohn Marino {
574*e4b17023SJohn Marino varpool_node_set_iterator iter;
575*e4b17023SJohn Marino
576*e4b17023SJohn Marino for (iter = vsi_start (set); !vsi_end_p (iter); vsi_next (&iter))
577*e4b17023SJohn Marino {
578*e4b17023SJohn Marino struct varpool_node *node = vsi_node (iter);
579*e4b17023SJohn Marino fprintf (f, " %s", varpool_node_name (node));
580*e4b17023SJohn Marino }
581*e4b17023SJohn Marino fprintf (f, "\n");
582*e4b17023SJohn Marino }
583*e4b17023SJohn Marino
584*e4b17023SJohn Marino
585*e4b17023SJohn Marino /* Free varpool node set. */
586*e4b17023SJohn Marino
587*e4b17023SJohn Marino void
free_varpool_node_set(varpool_node_set set)588*e4b17023SJohn Marino free_varpool_node_set (varpool_node_set set)
589*e4b17023SJohn Marino {
590*e4b17023SJohn Marino VEC_free (varpool_node_ptr, heap, set->nodes);
591*e4b17023SJohn Marino pointer_map_destroy (set->map);
592*e4b17023SJohn Marino free (set);
593*e4b17023SJohn Marino }
594*e4b17023SJohn Marino
595*e4b17023SJohn Marino
596*e4b17023SJohn Marino /* Dump content of SET to stderr. */
597*e4b17023SJohn Marino
598*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_varpool_node_set(varpool_node_set set)599*e4b17023SJohn Marino debug_varpool_node_set (varpool_node_set set)
600*e4b17023SJohn Marino {
601*e4b17023SJohn Marino dump_varpool_node_set (stderr, set);
602*e4b17023SJohn Marino }
603