xref: /dflybsd-src/contrib/gcc-4.7/gcc/ipa-utils.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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