xref: /dragonfly/contrib/gcc-4.7/gcc/ipa.c (revision 51871435)
1 /* Basic IPA optimizations and utilities.
2    Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
3    Free Software Foundation, Inc.
4 
5 This file is part of GCC.
6 
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 3, or (at your option) any later
10 version.
11 
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.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "cgraph.h"
26 #include "tree-pass.h"
27 #include "timevar.h"
28 #include "gimple.h"
29 #include "ggc.h"
30 #include "flags.h"
31 #include "pointer-set.h"
32 #include "target.h"
33 #include "tree-iterator.h"
34 #include "ipa-utils.h"
35 
36 /* Look for all functions inlined to NODE and update their inlined_to pointers
37    to INLINED_TO.  */
38 
39 static void
40 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
41 {
42   struct cgraph_edge *e;
43   for (e = node->callees; e; e = e->next_callee)
44     if (e->callee->global.inlined_to)
45       {
46         e->callee->global.inlined_to = inlined_to;
47 	update_inlined_to_pointer (e->callee, inlined_to);
48       }
49 }
50 
51 /* Add cgraph NODE to queue starting at FIRST.
52 
53    The queue is linked via AUX pointers and terminated by pointer to 1.
54    We enqueue nodes at two occasions: when we find them reachable or when we find
55    their bodies needed for further clonning.  In the second case we mark them
56    by pointer to 2 after processing so they are re-queue when they become
57    reachable.  */
58 
59 static void
60 enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first)
61 {
62   /* Node is still in queue; do nothing.  */
63   if (node->aux && node->aux != (void *) 2)
64     return;
65   /* Node was already processed as unreachable, re-enqueue
66      only if it became reachable now.  */
67   if (node->aux == (void *)2 && !node->reachable)
68     return;
69   node->aux = *first;
70   *first = node;
71 }
72 
73 /* Add varpool NODE to queue starting at FIRST.  */
74 
75 static void
76 enqueue_varpool_node (struct varpool_node *node, struct varpool_node **first)
77 {
78   node->aux = *first;
79   *first = node;
80 }
81 
82 /* Process references.  */
83 
84 static void
85 process_references (struct ipa_ref_list *list,
86 		    struct cgraph_node **first,
87 		    struct varpool_node **first_varpool,
88 		    bool before_inlining_p)
89 {
90   int i;
91   struct ipa_ref *ref;
92   for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
93     {
94       if (ref->refered_type == IPA_REF_CGRAPH)
95 	{
96 	  struct cgraph_node *node = ipa_ref_node (ref);
97 	  if (!node->reachable
98 	      && node->analyzed
99 	      && (!DECL_EXTERNAL (node->decl)
100 	          || before_inlining_p))
101 	    node->reachable = true;
102 	  enqueue_cgraph_node (node, first);
103 	}
104       else
105 	{
106 	  struct varpool_node *node = ipa_ref_varpool_node (ref);
107 	  if (!node->needed)
108 	    {
109 	      varpool_mark_needed_node (node);
110 	      enqueue_varpool_node (node, first_varpool);
111 	    }
112 	}
113     }
114 }
115 
116 
117 /* Return true when NODE can not be local. Worker for cgraph_local_node_p.  */
118 
119 static bool
120 cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
121 {
122    /* FIXME: Aliases can be local, but i386 gets thunks wrong then.  */
123    return !(cgraph_only_called_directly_or_aliased_p (node)
124 	    && !ipa_ref_has_aliases_p (&node->ref_list)
125 	    && node->analyzed
126 	    && !DECL_EXTERNAL (node->decl)
127 	    && !node->local.externally_visible
128 	    && !node->reachable_from_other_partition
129 	    && !node->in_other_partition);
130 }
131 
132 /* Return true when function can be marked local.  */
133 
134 static bool
135 cgraph_local_node_p (struct cgraph_node *node)
136 {
137    struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
138 
139    /* FIXME: thunks can be considered local, but we need prevent i386
140       from attempting to change calling convention of them.  */
141    if (n->thunk.thunk_p)
142      return false;
143    return !cgraph_for_node_and_aliases (n,
144 					cgraph_non_local_node_p_1, NULL, true);
145 
146 }
147 
148 /* Return true when NODE has ADDR reference.  */
149 
150 static bool
151 has_addr_references_p (struct cgraph_node *node,
152 		       void *data ATTRIBUTE_UNUSED)
153 {
154   int i;
155   struct ipa_ref *ref;
156 
157   for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
158     if (ref->use == IPA_REF_ADDR)
159       return true;
160   return false;
161 }
162 
163 /* Perform reachability analysis and reclaim all unreachable nodes.
164    If BEFORE_INLINING_P is true this function is called before inlining
165    decisions has been made.  If BEFORE_INLINING_P is false this function also
166    removes unneeded bodies of extern inline functions.  */
167 
168 bool
169 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
170 {
171   struct cgraph_node *first = (struct cgraph_node *) (void *) 1;
172   struct varpool_node *first_varpool = (struct varpool_node *) (void *) 1;
173   struct cgraph_node *node, *next;
174   struct varpool_node *vnode, *vnext;
175   bool changed = false;
176 
177 #ifdef ENABLE_CHECKING
178   verify_cgraph ();
179 #endif
180   if (file)
181     fprintf (file, "\nReclaiming functions:");
182 #ifdef ENABLE_CHECKING
183   for (node = cgraph_nodes; node; node = node->next)
184     gcc_assert (!node->aux);
185   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
186     gcc_assert (!vnode->aux);
187 #endif
188   varpool_reset_queue ();
189   /* Mark functions whose bodies are obviously needed.
190      This is mostly when they can be referenced externally.  Inline clones
191      are special since their declarations are shared with master clone and thus
192      cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them.  */
193   for (node = cgraph_nodes; node; node = node->next)
194     if (node->analyzed && !node->global.inlined_to
195 	&& (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
196 	    /* Keep around virtual functions for possible devirtualization.  */
197 	    || (before_inlining_p
198 		&& DECL_VIRTUAL_P (node->decl)
199 		&& (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)))))
200       {
201         gcc_assert (!node->global.inlined_to);
202 	enqueue_cgraph_node (node, &first);
203 	node->reachable = true;
204       }
205     else
206       {
207         gcc_assert (!node->aux);
208 	node->reachable = false;
209       }
210 
211   /* Mark variables that are obviously needed.  */
212   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
213     {
214       vnode->next_needed = NULL;
215       vnode->prev_needed = NULL;
216       if ((vnode->analyzed || vnode->force_output)
217 	  && !varpool_can_remove_if_no_refs (vnode))
218 	{
219 	  vnode->needed = false;
220 	  varpool_mark_needed_node (vnode);
221 	  enqueue_varpool_node (vnode, &first_varpool);
222 	}
223       else
224 	vnode->needed = false;
225     }
226 
227   /* Perform reachability analysis.  As a special case do not consider
228      extern inline functions not inlined as live because we won't output
229      them at all.
230 
231      We maintain two worklist, one for cgraph nodes other for varpools and
232      are finished once both are empty.  */
233 
234   while (first != (struct cgraph_node *) (void *) 1
235   	 || first_varpool != (struct varpool_node *) (void *) 1)
236     {
237       if (first != (struct cgraph_node *) (void *) 1)
238 	{
239 	  struct cgraph_edge *e;
240 	  node = first;
241 	  first = (struct cgraph_node *) first->aux;
242 	  if (!node->reachable)
243 	    node->aux = (void *)2;
244 
245 	  /* If we found this node reachable, first mark on the callees
246 	     reachable too, unless they are direct calls to extern inline functions
247 	     we decided to not inline.  */
248 	  if (node->reachable)
249 	    {
250 	      for (e = node->callees; e; e = e->next_callee)
251 		{
252 		  if (!e->callee->reachable
253 		      && node->analyzed
254 		      && (!e->inline_failed
255 			  || !DECL_EXTERNAL (e->callee->decl)
256 			  || before_inlining_p))
257 		    e->callee->reachable = true;
258 		  enqueue_cgraph_node (e->callee, &first);
259 		}
260 	      process_references (&node->ref_list, &first, &first_varpool, before_inlining_p);
261 	    }
262 
263 	  /* If any function in a comdat group is reachable, force
264 	     all other functions in the same comdat group to be
265 	     also reachable.  */
266 	  if (node->same_comdat_group
267 	      && node->reachable
268 	      && !node->global.inlined_to)
269 	    {
270 	      for (next = node->same_comdat_group;
271 		   next != node;
272 		   next = next->same_comdat_group)
273 		if (!next->reachable)
274 		  {
275 		    next->reachable = true;
276 		    enqueue_cgraph_node (next, &first);
277 		  }
278 	    }
279 
280 	  /* We can freely remove inline clones even if they are cloned, however if
281 	     function is clone of real clone, we must keep it around in order to
282 	     make materialize_clones produce function body with the changes
283 	     applied.  */
284 	  while (node->clone_of && !node->clone_of->aux
285 	         && !gimple_has_body_p (node->decl))
286 	    {
287 	      bool noninline = node->clone_of->decl != node->decl;
288 	      node = node->clone_of;
289 	      if (noninline && !node->reachable && !node->aux)
290 	      	{
291 		  enqueue_cgraph_node (node, &first);
292 		  break;
293 		}
294 	    }
295 	}
296       if (first_varpool != (struct varpool_node *) (void *) 1)
297 	{
298 	  vnode = first_varpool;
299 	  first_varpool = (struct varpool_node *)first_varpool->aux;
300 	  vnode->aux = NULL;
301 	  process_references (&vnode->ref_list, &first, &first_varpool, before_inlining_p);
302 	  /* If any function in a comdat group is reachable, force
303 	     all other functions in the same comdat group to be
304 	     also reachable.  */
305 	  if (vnode->same_comdat_group)
306 	    {
307 	      struct varpool_node *next;
308 	      for (next = vnode->same_comdat_group;
309 		   next != vnode;
310 		   next = next->same_comdat_group)
311 		if (!next->needed)
312 		  {
313 		    varpool_mark_needed_node (next);
314 		    enqueue_varpool_node (next, &first_varpool);
315 		  }
316 	    }
317 	}
318     }
319 
320   /* Remove unreachable nodes.
321 
322      Completely unreachable functions can be fully removed from the callgraph.
323      Extern inline functions that we decided to not inline need to become unanalyzed nodes of
324      callgraph (so we still have edges to them).  We remove function body then.
325 
326      Also we need to care functions that are unreachable but we need to keep them around
327      for later clonning.  In this case we also turn them to unanalyzed nodes, but
328      keep the body around.  */
329   for (node = cgraph_nodes; node; node = next)
330     {
331       next = node->next;
332       if (node->aux && !node->reachable)
333         {
334 	  cgraph_node_remove_callees (node);
335 	  ipa_remove_all_references (&node->ref_list);
336 	  node->analyzed = false;
337 	}
338       if (!node->aux)
339 	{
340 	  struct cgraph_edge *e;
341 	  bool found = false;
342 	  int i;
343 	  struct ipa_ref *ref;
344 
345           node->global.inlined_to = NULL;
346 	  if (file)
347 	    fprintf (file, " %s", cgraph_node_name (node));
348 	  /* See if there is reachable caller.  */
349 	  for (e = node->callers; e && !found; e = e->next_caller)
350 	    if (e->caller->reachable)
351 	      found = true;
352 	  for (i = 0; (ipa_ref_list_refering_iterate (&node->ref_list, i, ref)
353 		       && !found); i++)
354 	    if (ref->refering_type == IPA_REF_CGRAPH
355 		&& ipa_ref_refering_node (ref)->reachable)
356 	      found = true;
357 	    else if (ref->refering_type == IPA_REF_VARPOOL
358 		     && ipa_ref_refering_varpool_node (ref)->needed)
359 	      found = true;
360 
361 	  /* If so, we need to keep node in the callgraph.  */
362 	  if (found)
363 	    {
364 	      if (node->analyzed)
365 		{
366 		  struct cgraph_node *clone;
367 
368 		  /* If there are still clones, we must keep body around.
369 		     Otherwise we can just remove the body but keep the clone.  */
370 		  for (clone = node->clones; clone;
371 		       clone = clone->next_sibling_clone)
372 		    if (clone->aux)
373 		      break;
374 		  if (!clone)
375 		    {
376 		      cgraph_release_function_body (node);
377 		      if (node->prev_sibling_clone)
378 			node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
379 		      else if (node->clone_of)
380 			node->clone_of->clones = node->next_sibling_clone;
381 		      if (node->next_sibling_clone)
382 			node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
383 		      if (node->clone_of)
384 			node->former_clone_of = node->clone_of->decl;
385 		      node->clone_of = NULL;
386 		      node->next_sibling_clone = NULL;
387 		      node->prev_sibling_clone = NULL;
388 		    }
389 		  else
390 		    gcc_assert (!clone->in_other_partition);
391 		  node->analyzed = false;
392 		  changed = true;
393 		  cgraph_node_remove_callees (node);
394 		  ipa_remove_all_references (&node->ref_list);
395 		}
396 	    }
397 	  else
398 	    {
399 	      cgraph_remove_node (node);
400 	      changed = true;
401 	    }
402 	}
403     }
404   for (node = cgraph_nodes; node; node = node->next)
405     {
406       /* Inline clones might be kept around so their materializing allows further
407          cloning.  If the function the clone is inlined into is removed, we need
408          to turn it into normal cone.  */
409       if (node->global.inlined_to
410 	  && !node->callers)
411 	{
412 	  gcc_assert (node->clones);
413 	  node->global.inlined_to = NULL;
414 	  update_inlined_to_pointer (node, node);
415 	}
416       node->aux = NULL;
417     }
418 
419   if (file)
420     fprintf (file, "\n");
421 
422   /* We must release unused extern inlines or sanity checking will fail.  Rest of transformations
423      are undesirable at -O0 since we do not want to remove anything.  */
424   if (!optimize)
425     return changed;
426 
427   if (file)
428     fprintf (file, "Reclaiming variables:");
429   for (vnode = varpool_nodes; vnode; vnode = vnext)
430     {
431       vnext = vnode->next;
432       if (!vnode->needed)
433         {
434 	  if (file)
435 	    fprintf (file, " %s", varpool_node_name (vnode));
436 	  varpool_remove_node (vnode);
437 	  changed = true;
438 	}
439     }
440 
441   /* Now update address_taken flags and try to promote functions to be local.  */
442 
443   if (file)
444     fprintf (file, "\nClearing address taken flags:");
445   for (node = cgraph_nodes; node; node = node->next)
446     if (node->address_taken
447 	&& !node->reachable_from_other_partition)
448       {
449 	if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true))
450 	  {
451 	    if (file)
452 	      fprintf (file, " %s", cgraph_node_name (node));
453 	    node->address_taken = false;
454 	    changed = true;
455 	    if (cgraph_local_node_p (node))
456 	      {
457 		node->local.local = true;
458 		if (file)
459 		  fprintf (file, " (local)");
460 	      }
461 	  }
462       }
463   if (file)
464     fprintf (file, "\n");
465 
466 #ifdef ENABLE_CHECKING
467   verify_cgraph ();
468 #endif
469 
470   /* Reclaim alias pairs for functions that have disappeared from the
471      call graph.  */
472   remove_unreachable_alias_pairs ();
473 
474   return changed;
475 }
476 
477 /* Discover variables that have no longer address taken or that are read only
478    and update their flags.
479 
480    FIXME: This can not be done in between gimplify and omp_expand since
481    readonly flag plays role on what is shared and what is not.  Currently we do
482    this transformation as part of whole program visibility and re-do at
483    ipa-reference pass (to take into account clonning), but it would
484    make sense to do it before early optimizations.  */
485 
486 void
487 ipa_discover_readonly_nonaddressable_vars (void)
488 {
489   struct varpool_node *vnode;
490   if (dump_file)
491     fprintf (dump_file, "Clearing variable flags:");
492   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
493     if (vnode->finalized && varpool_all_refs_explicit_p (vnode)
494 	&& (TREE_ADDRESSABLE (vnode->decl) || !TREE_READONLY (vnode->decl)))
495       {
496 	bool written = false;
497 	bool address_taken = false;
498 	int i;
499         struct ipa_ref *ref;
500         for (i = 0; ipa_ref_list_refering_iterate (&vnode->ref_list, i, ref)
501 		    && (!written || !address_taken); i++)
502 	  switch (ref->use)
503 	    {
504 	    case IPA_REF_ADDR:
505 	      address_taken = true;
506 	      break;
507 	    case IPA_REF_LOAD:
508 	      break;
509 	    case IPA_REF_STORE:
510 	      written = true;
511 	      break;
512 	    }
513 	if (TREE_ADDRESSABLE (vnode->decl) && !address_taken)
514 	  {
515 	    if (dump_file)
516 	      fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
517 	    TREE_ADDRESSABLE (vnode->decl) = 0;
518 	  }
519 	if (!TREE_READONLY (vnode->decl) && !address_taken && !written
520 	    /* Making variable in explicit section readonly can cause section
521 	       type conflict.
522 	       See e.g. gcc.c-torture/compile/pr23237.c */
523 	    && DECL_SECTION_NAME (vnode->decl) == NULL)
524 	  {
525 	    if (dump_file)
526 	      fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
527 	    TREE_READONLY (vnode->decl) = 1;
528 	  }
529       }
530   if (dump_file)
531     fprintf (dump_file, "\n");
532 }
533 
534 /* Return true when there is a reference to node and it is not vtable.  */
535 static bool
536 cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
537 {
538   int i;
539   struct ipa_ref *ref;
540   for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++)
541     if (ref->use == IPA_REF_ADDR)
542       {
543 	struct varpool_node *node;
544 	if (ref->refering_type == IPA_REF_CGRAPH)
545 	  return true;
546 	node = ipa_ref_refering_varpool_node (ref);
547 	if (!DECL_VIRTUAL_P (node->decl))
548 	  return true;
549       }
550   return false;
551 }
552 
553 /* COMDAT functions must be shared only if they have address taken,
554    otherwise we can produce our own private implementation with
555    -fwhole-program.
556    Return true when turning COMDAT functoin static can not lead to wrong
557    code when the resulting object links with a library defining same COMDAT.
558 
559    Virtual functions do have their addresses taken from the vtables,
560    but in C++ there is no way to compare their addresses for equality.  */
561 
562 bool
563 cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
564 {
565   if ((cgraph_address_taken_from_non_vtable_p (node)
566        && !DECL_VIRTUAL_P (node->decl))
567       || !node->analyzed)
568     return false;
569   if (node->same_comdat_group)
570     {
571       struct cgraph_node *next;
572 
573       /* If more than one function is in the same COMDAT group, it must
574          be shared even if just one function in the comdat group has
575          address taken.  */
576       for (next = node->same_comdat_group;
577 	   next != node; next = next->same_comdat_group)
578 	if (cgraph_address_taken_from_non_vtable_p (next)
579 	    && !DECL_VIRTUAL_P (next->decl))
580 	  return false;
581     }
582   return true;
583 }
584 
585 /* Return true when function NODE should be considered externally visible.  */
586 
587 static bool
588 cgraph_externally_visible_p (struct cgraph_node *node,
589 			     bool whole_program, bool aliased)
590 {
591   if (!node->local.finalized)
592     return false;
593   if (!DECL_COMDAT (node->decl)
594       && (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)))
595     return false;
596 
597   /* Do not even try to be smart about aliased nodes.  Until we properly
598      represent everything by same body alias, these are just evil.  */
599   if (aliased)
600     return true;
601 
602   /* Do not try to localize built-in functions yet.  One of problems is that we
603      end up mangling their asm for WHOPR that makes it impossible to call them
604      using the implicit built-in declarations anymore.  Similarly this enables
605      us to remove them as unreachable before actual calls may appear during
606      expansion or folding.  */
607   if (DECL_BUILT_IN (node->decl))
608     return true;
609 
610   /* If linker counts on us, we must preserve the function.  */
611   if (cgraph_used_from_object_file_p (node))
612     return true;
613   if (DECL_PRESERVE_P (node->decl))
614     return true;
615   if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
616     return true;
617   if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
618       && lookup_attribute ("dllexport", DECL_ATTRIBUTES (node->decl)))
619     return true;
620   if (node->resolution == LDPR_PREVAILING_DEF_IRONLY)
621     return false;
622   /* When doing LTO or whole program, we can bring COMDAT functoins static.
623      This improves code quality and we know we will duplicate them at most twice
624      (in the case that we are not using plugin and link with object file
625       implementing same COMDAT)  */
626   if ((in_lto_p || whole_program)
627       && DECL_COMDAT (node->decl)
628       && cgraph_comdat_can_be_unshared_p (node))
629     return false;
630 
631   /* When doing link time optimizations, hidden symbols become local.  */
632   if (in_lto_p
633       && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
634 	  || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
635       /* Be sure that node is defined in IR file, not in other object
636 	 file.  In that case we don't set used_from_other_object_file.  */
637       && node->analyzed)
638     ;
639   else if (!whole_program)
640     return true;
641 
642   if (MAIN_NAME_P (DECL_NAME (node->decl)))
643     return true;
644 
645   return false;
646 }
647 
648 /* Return true when variable VNODE should be considered externally visible.  */
649 
650 bool
651 varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
652 {
653   if (!DECL_COMDAT (vnode->decl) && !TREE_PUBLIC (vnode->decl))
654     return false;
655 
656   /* Do not even try to be smart about aliased nodes.  Until we properly
657      represent everything by same body alias, these are just evil.  */
658   if (aliased)
659     return true;
660 
661   /* If linker counts on us, we must preserve the function.  */
662   if (varpool_used_from_object_file_p (vnode))
663     return true;
664 
665   if (DECL_HARD_REGISTER (vnode->decl))
666     return true;
667   if (DECL_PRESERVE_P (vnode->decl))
668     return true;
669   if (lookup_attribute ("externally_visible",
670 			DECL_ATTRIBUTES (vnode->decl)))
671     return true;
672   if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
673       && lookup_attribute ("dllexport",
674 			   DECL_ATTRIBUTES (vnode->decl)))
675     return true;
676 
677   /* See if we have linker information about symbol not being used or
678      if we need to make guess based on the declaration.
679 
680      Even if the linker clams the symbol is unused, never bring internal
681      symbols that are declared by user as used or externally visible.
682      This is needed for i.e. references from asm statements.   */
683   if (varpool_used_from_object_file_p (vnode))
684     return true;
685   if (vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
686     return false;
687 
688   /* As a special case, the COMDAT virutal tables can be unshared.
689      In LTO mode turn vtables into static variables.  The variable is readonly,
690      so this does not enable more optimization, but referring static var
691      is faster for dynamic linking.  Also this match logic hidding vtables
692      from LTO symbol tables.  */
693   if ((in_lto_p || flag_whole_program)
694       && !vnode->force_output
695       && DECL_COMDAT (vnode->decl) && DECL_VIRTUAL_P (vnode->decl))
696     return false;
697 
698   /* When doing link time optimizations, hidden symbols become local.  */
699   if (in_lto_p
700       && (DECL_VISIBILITY (vnode->decl) == VISIBILITY_HIDDEN
701 	  || DECL_VISIBILITY (vnode->decl) == VISIBILITY_INTERNAL)
702       /* Be sure that node is defined in IR file, not in other object
703 	 file.  In that case we don't set used_from_other_object_file.  */
704       && vnode->finalized)
705     ;
706   else if (!flag_whole_program)
707     return true;
708 
709   /* Do not attempt to privatize COMDATS by default.
710      This would break linking with C++ libraries sharing
711      inline definitions.
712 
713      FIXME: We can do so for readonly vars with no address taken and
714      possibly also for vtables since no direct pointer comparsion is done.
715      It might be interesting to do so to reduce linking overhead.  */
716   if (DECL_COMDAT (vnode->decl) || DECL_WEAK (vnode->decl))
717     return true;
718   return false;
719 }
720 
721 /* Dissolve the same_comdat_group list in which NODE resides.  */
722 
723 static void
724 dissolve_same_comdat_group_list (struct cgraph_node *node)
725 {
726   struct cgraph_node *n = node, *next;
727   do
728     {
729       next = n->same_comdat_group;
730       n->same_comdat_group = NULL;
731       n = next;
732     }
733   while (n != node);
734 }
735 
736 /* Mark visibility of all functions.
737 
738    A local function is one whose calls can occur only in the current
739    compilation unit and all its calls are explicit, so we can change
740    its calling convention.  We simply mark all static functions whose
741    address is not taken as local.
742 
743    We also change the TREE_PUBLIC flag of all declarations that are public
744    in language point of view but we want to overwrite this default
745    via visibilities for the backend point of view.  */
746 
747 static unsigned int
748 function_and_variable_visibility (bool whole_program)
749 {
750   struct cgraph_node *node;
751   struct varpool_node *vnode;
752   struct pointer_set_t *aliased_nodes = pointer_set_create ();
753   struct pointer_set_t *aliased_vnodes = pointer_set_create ();
754   unsigned i;
755   alias_pair *p;
756 
757   /* Discover aliased nodes.  */
758   FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
759     {
760       if (dump_file)
761        fprintf (dump_file, "Alias %s->%s",
762 		IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
763 		IDENTIFIER_POINTER (p->target));
764 
765       if ((node = cgraph_node_for_asm (p->target)) != NULL
766 	  && !DECL_EXTERNAL (node->decl))
767         {
768 	  if (!node->analyzed)
769 	    continue;
770 	  cgraph_mark_needed_node (node);
771 	  gcc_assert (node->needed);
772 	  pointer_set_insert (aliased_nodes, node);
773 	  if (dump_file)
774 	    fprintf (dump_file, "  node %s/%i",
775 		     cgraph_node_name (node), node->uid);
776         }
777       else if ((vnode = varpool_node_for_asm (p->target)) != NULL
778 	       && !DECL_EXTERNAL (vnode->decl))
779         {
780 	  varpool_mark_needed_node (vnode);
781 	  gcc_assert (vnode->needed);
782 	  pointer_set_insert (aliased_vnodes, vnode);
783 	  if (dump_file)
784 	    fprintf (dump_file, "  varpool node %s",
785 		     varpool_node_name (vnode));
786         }
787       if (dump_file)
788        fprintf (dump_file, "\n");
789     }
790 
791   for (node = cgraph_nodes; node; node = node->next)
792     {
793       int flags = flags_from_decl_or_type (node->decl);
794 
795       /* Optimize away PURE and CONST constructors and destructors.  */
796       if (optimize
797 	  && (flags & (ECF_CONST | ECF_PURE))
798 	  && !(flags & ECF_LOOPING_CONST_OR_PURE))
799 	{
800 	  DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
801 	  DECL_STATIC_DESTRUCTOR (node->decl) = 0;
802 	}
803 
804       /* Frontends and alias code marks nodes as needed before parsing is finished.
805 	 We may end up marking as node external nodes where this flag is meaningless
806 	 strip it.  */
807       if (node->needed
808 	  && (DECL_EXTERNAL (node->decl) || !node->analyzed))
809 	node->needed = 0;
810 
811       /* C++ FE on lack of COMDAT support create local COMDAT functions
812 	 (that ought to be shared but can not due to object format
813 	 limitations).  It is neccesary to keep the flag to make rest of C++ FE
814 	 happy.  Clear the flag here to avoid confusion in middle-end.  */
815       if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
816         DECL_COMDAT (node->decl) = 0;
817       /* For external decls stop tracking same_comdat_group, it doesn't matter
818 	 what comdat group they are in when they won't be emitted in this TU,
819 	 and simplifies later passes.  */
820       if (node->same_comdat_group && DECL_EXTERNAL (node->decl))
821 	{
822 #ifdef ENABLE_CHECKING
823 	  struct cgraph_node *n;
824 
825 	  for (n = node->same_comdat_group;
826 	       n != node;
827 	       n = n->same_comdat_group)
828 	      /* If at least one of same comdat group functions is external,
829 		 all of them have to be, otherwise it is a front-end bug.  */
830 	      gcc_assert (DECL_EXTERNAL (n->decl));
831 #endif
832 	  dissolve_same_comdat_group_list (node);
833 	}
834       gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
835       	          || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
836       if (cgraph_externally_visible_p (node, whole_program,
837 				       pointer_set_contains (aliased_nodes,
838 							     node)))
839         {
840 	  gcc_assert (!node->global.inlined_to);
841 	  node->local.externally_visible = true;
842 	}
843       else
844 	node->local.externally_visible = false;
845       if (!node->local.externally_visible && node->analyzed
846 	  && !DECL_EXTERNAL (node->decl))
847 	{
848 	  gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
849 	  cgraph_make_decl_local (node->decl);
850 	  node->resolution = LDPR_PREVAILING_DEF_IRONLY;
851 	  if (node->same_comdat_group)
852 	    /* cgraph_externally_visible_p has already checked all other nodes
853 	       in the group and they will all be made local.  We need to
854 	       dissolve the group at once so that the predicate does not
855 	       segfault though. */
856 	    dissolve_same_comdat_group_list (node);
857 	}
858 
859       if (node->thunk.thunk_p
860 	  && TREE_PUBLIC (node->decl))
861 	{
862 	  struct cgraph_node *decl_node = node;
863 
864 	  decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
865 
866 	  /* Thunks have the same visibility as function they are attached to.
867 	     Make sure the C++ front end set this up properly.  */
868 	  if (DECL_ONE_ONLY (decl_node->decl))
869 	    {
870 	      gcc_checking_assert (DECL_COMDAT (node->decl)
871 				   == DECL_COMDAT (decl_node->decl));
872 	      gcc_checking_assert (DECL_COMDAT_GROUP (node->decl)
873 				   == DECL_COMDAT_GROUP (decl_node->decl));
874 	      gcc_checking_assert (node->same_comdat_group);
875 	    }
876 	  if (DECL_EXTERNAL (decl_node->decl))
877 	    DECL_EXTERNAL (node->decl) = 1;
878 	}
879     }
880   for (node = cgraph_nodes; node; node = node->next)
881     node->local.local = cgraph_local_node_p (node);
882   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
883     {
884       /* weak flag makes no sense on local variables.  */
885       gcc_assert (!DECL_WEAK (vnode->decl)
886       		  || TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl));
887       /* In several cases declarations can not be common:
888 
889 	 - when declaration has initializer
890 	 - when it is in weak
891 	 - when it has specific section
892 	 - when it resides in non-generic address space.
893 	 - if declaration is local, it will get into .local common section
894 	   so common flag is not needed.  Frontends still produce these in
895 	   certain cases, such as for:
896 
897 	     static int a __attribute__ ((common))
898 
899 	 Canonicalize things here and clear the redundant flag.  */
900       if (DECL_COMMON (vnode->decl)
901 	  && (!(TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl))
902 	      || (DECL_INITIAL (vnode->decl)
903 		  && DECL_INITIAL (vnode->decl) != error_mark_node)
904 	      || DECL_WEAK (vnode->decl)
905 	      || DECL_SECTION_NAME (vnode->decl) != NULL
906 	      || ! (ADDR_SPACE_GENERIC_P
907 		    (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
908 	DECL_COMMON (vnode->decl) = 0;
909     }
910   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
911     {
912       if (!vnode->finalized)
913         continue;
914       if (vnode->needed
915 	  && varpool_externally_visible_p
916 	      (vnode,
917 	       pointer_set_contains (aliased_vnodes, vnode)))
918 	vnode->externally_visible = true;
919       else
920         vnode->externally_visible = false;
921       if (!vnode->externally_visible)
922 	{
923 	  gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
924 	  cgraph_make_decl_local (vnode->decl);
925 	  vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
926 	}
927      gcc_assert (TREE_STATIC (vnode->decl));
928     }
929   pointer_set_destroy (aliased_nodes);
930   pointer_set_destroy (aliased_vnodes);
931 
932   if (dump_file)
933     {
934       fprintf (dump_file, "\nMarking local functions:");
935       for (node = cgraph_nodes; node; node = node->next)
936 	if (node->local.local)
937 	  fprintf (dump_file, " %s", cgraph_node_name (node));
938       fprintf (dump_file, "\n\n");
939       fprintf (dump_file, "\nMarking externally visible functions:");
940       for (node = cgraph_nodes; node; node = node->next)
941 	if (node->local.externally_visible)
942 	  fprintf (dump_file, " %s", cgraph_node_name (node));
943       fprintf (dump_file, "\n\n");
944       fprintf (dump_file, "\nMarking externally visible variables:");
945       for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
946 	if (vnode->externally_visible)
947 	  fprintf (dump_file, " %s", varpool_node_name (vnode));
948       fprintf (dump_file, "\n\n");
949     }
950   cgraph_function_flags_ready = true;
951   return 0;
952 }
953 
954 /* Local function pass handling visibilities.  This happens before LTO streaming
955    so in particular -fwhole-program should be ignored at this level.  */
956 
957 static unsigned int
958 local_function_and_variable_visibility (void)
959 {
960   return function_and_variable_visibility (flag_whole_program && !flag_lto);
961 }
962 
963 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
964 {
965  {
966   SIMPLE_IPA_PASS,
967   "visibility",				/* name */
968   NULL,					/* gate */
969   local_function_and_variable_visibility,/* execute */
970   NULL,					/* sub */
971   NULL,					/* next */
972   0,					/* static_pass_number */
973   TV_CGRAPHOPT,				/* tv_id */
974   0,	                                /* properties_required */
975   0,					/* properties_provided */
976   0,					/* properties_destroyed */
977   0,					/* todo_flags_start */
978   TODO_remove_functions | TODO_dump_cgraph
979   | TODO_ggc_collect			/* todo_flags_finish */
980  }
981 };
982 
983 /* Do not re-run on ltrans stage.  */
984 
985 static bool
986 gate_whole_program_function_and_variable_visibility (void)
987 {
988   return !flag_ltrans;
989 }
990 
991 /* Bring functionss local at LTO time whith -fwhole-program.  */
992 
993 static unsigned int
994 whole_program_function_and_variable_visibility (void)
995 {
996   struct cgraph_node *node;
997   struct varpool_node *vnode;
998 
999   function_and_variable_visibility (flag_whole_program);
1000 
1001   for (node = cgraph_nodes; node; node = node->next)
1002     if ((node->local.externally_visible && !DECL_COMDAT (node->decl))
1003         && node->local.finalized)
1004       cgraph_mark_needed_node (node);
1005   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
1006     if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
1007       varpool_mark_needed_node (vnode);
1008   if (dump_file)
1009     {
1010       fprintf (dump_file, "\nNeeded variables:");
1011       for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
1012 	if (vnode->needed)
1013 	  fprintf (dump_file, " %s", varpool_node_name (vnode));
1014       fprintf (dump_file, "\n\n");
1015     }
1016   if (optimize)
1017     ipa_discover_readonly_nonaddressable_vars ();
1018   return 0;
1019 }
1020 
1021 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
1022 {
1023  {
1024   IPA_PASS,
1025   "whole-program",			/* name */
1026   gate_whole_program_function_and_variable_visibility,/* gate */
1027   whole_program_function_and_variable_visibility,/* execute */
1028   NULL,					/* sub */
1029   NULL,					/* next */
1030   0,					/* static_pass_number */
1031   TV_CGRAPHOPT,				/* tv_id */
1032   0,	                                /* properties_required */
1033   0,					/* properties_provided */
1034   0,					/* properties_destroyed */
1035   0,					/* todo_flags_start */
1036   TODO_remove_functions | TODO_dump_cgraph
1037   | TODO_ggc_collect			/* todo_flags_finish */
1038  },
1039  NULL,					/* generate_summary */
1040  NULL,					/* write_summary */
1041  NULL,					/* read_summary */
1042  NULL,					/* write_optimization_summary */
1043  NULL,					/* read_optimization_summary */
1044  NULL,					/* stmt_fixup */
1045  0,					/* TODOs */
1046  NULL,					/* function_transform */
1047  NULL,					/* variable_transform */
1048 };
1049 
1050 
1051 /* Simple ipa profile pass propagating frequencies across the callgraph.  */
1052 
1053 static unsigned int
1054 ipa_profile (void)
1055 {
1056   struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1057   struct cgraph_edge *e;
1058   int order_pos;
1059   bool something_changed = false;
1060   int i;
1061 
1062   order_pos = ipa_reverse_postorder (order);
1063   for (i = order_pos - 1; i >= 0; i--)
1064     {
1065       if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
1066 	{
1067 	  for (e = order[i]->callees; e; e = e->next_callee)
1068 	    if (e->callee->local.local && !e->callee->aux)
1069 	      {
1070 	        something_changed = true;
1071 	        e->callee->aux = (void *)1;
1072 	      }
1073 	}
1074       order[i]->aux = NULL;
1075     }
1076 
1077   while (something_changed)
1078     {
1079       something_changed = false;
1080       for (i = order_pos - 1; i >= 0; i--)
1081 	{
1082 	  if (order[i]->aux && cgraph_propagate_frequency (order[i]))
1083 	    {
1084 	      for (e = order[i]->callees; e; e = e->next_callee)
1085 		if (e->callee->local.local && !e->callee->aux)
1086 		  {
1087 		    something_changed = true;
1088 		    e->callee->aux = (void *)1;
1089 		  }
1090 	    }
1091 	  order[i]->aux = NULL;
1092 	}
1093     }
1094   free (order);
1095   return 0;
1096 }
1097 
1098 static bool
1099 gate_ipa_profile (void)
1100 {
1101   return flag_ipa_profile;
1102 }
1103 
1104 struct ipa_opt_pass_d pass_ipa_profile =
1105 {
1106  {
1107   IPA_PASS,
1108   "profile_estimate",			/* name */
1109   gate_ipa_profile,			/* gate */
1110   ipa_profile,			        /* execute */
1111   NULL,					/* sub */
1112   NULL,					/* next */
1113   0,					/* static_pass_number */
1114   TV_IPA_PROFILE,		        /* tv_id */
1115   0,	                                /* properties_required */
1116   0,					/* properties_provided */
1117   0,					/* properties_destroyed */
1118   0,					/* todo_flags_start */
1119   0                                     /* todo_flags_finish */
1120  },
1121  NULL,				        /* generate_summary */
1122  NULL,					/* write_summary */
1123  NULL,					/* read_summary */
1124  NULL,					/* write_optimization_summary */
1125  NULL,					/* read_optimization_summary */
1126  NULL,					/* stmt_fixup */
1127  0,					/* TODOs */
1128  NULL,			                /* function_transform */
1129  NULL					/* variable_transform */
1130 };
1131 
1132 /* Generate and emit a static constructor or destructor.  WHICH must
1133    be one of 'I' (for a constructor) or 'D' (for a destructor).  BODY
1134    is a STATEMENT_LIST containing GENERIC statements.  PRIORITY is the
1135    initialization priority for this constructor or destructor.
1136 
1137    FINAL specify whether the externally visible name for collect2 should
1138    be produced. */
1139 
1140 static void
1141 cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
1142 {
1143   static int counter = 0;
1144   char which_buf[16];
1145   tree decl, name, resdecl;
1146 
1147   /* The priority is encoded in the constructor or destructor name.
1148      collect2 will sort the names and arrange that they are called at
1149      program startup.  */
1150   if (final)
1151     sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
1152   else
1153   /* Proudce sane name but one not recognizable by collect2, just for the
1154      case we fail to inline the function.  */
1155     sprintf (which_buf, "sub_%c_%.5d_%d", which, priority, counter++);
1156   name = get_file_function_name (which_buf);
1157 
1158   decl = build_decl (input_location, FUNCTION_DECL, name,
1159 		     build_function_type_list (void_type_node, NULL_TREE));
1160   current_function_decl = decl;
1161 
1162   resdecl = build_decl (input_location,
1163 			RESULT_DECL, NULL_TREE, void_type_node);
1164   DECL_ARTIFICIAL (resdecl) = 1;
1165   DECL_RESULT (decl) = resdecl;
1166   DECL_CONTEXT (resdecl) = decl;
1167 
1168   allocate_struct_function (decl, false);
1169 
1170   TREE_STATIC (decl) = 1;
1171   TREE_USED (decl) = 1;
1172   DECL_ARTIFICIAL (decl) = 1;
1173   DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1174   DECL_SAVED_TREE (decl) = body;
1175   if (!targetm.have_ctors_dtors && final)
1176     {
1177       TREE_PUBLIC (decl) = 1;
1178       DECL_PRESERVE_P (decl) = 1;
1179     }
1180   DECL_UNINLINABLE (decl) = 1;
1181 
1182   DECL_INITIAL (decl) = make_node (BLOCK);
1183   TREE_USED (DECL_INITIAL (decl)) = 1;
1184 
1185   DECL_SOURCE_LOCATION (decl) = input_location;
1186   cfun->function_end_locus = input_location;
1187 
1188   switch (which)
1189     {
1190     case 'I':
1191       DECL_STATIC_CONSTRUCTOR (decl) = 1;
1192       decl_init_priority_insert (decl, priority);
1193       break;
1194     case 'D':
1195       DECL_STATIC_DESTRUCTOR (decl) = 1;
1196       decl_fini_priority_insert (decl, priority);
1197       break;
1198     default:
1199       gcc_unreachable ();
1200     }
1201 
1202   gimplify_function_tree (decl);
1203 
1204   cgraph_add_new_function (decl, false);
1205 
1206   set_cfun (NULL);
1207   current_function_decl = NULL;
1208 }
1209 
1210 /* Generate and emit a static constructor or destructor.  WHICH must
1211    be one of 'I' (for a constructor) or 'D' (for a destructor).  BODY
1212    is a STATEMENT_LIST containing GENERIC statements.  PRIORITY is the
1213    initialization priority for this constructor or destructor.  */
1214 
1215 void
1216 cgraph_build_static_cdtor (char which, tree body, int priority)
1217 {
1218   cgraph_build_static_cdtor_1 (which, body, priority, false);
1219 }
1220 
1221 /* A vector of FUNCTION_DECLs declared as static constructors.  */
1222 static VEC(tree, heap) *static_ctors;
1223 /* A vector of FUNCTION_DECLs declared as static destructors.  */
1224 static VEC(tree, heap) *static_dtors;
1225 
1226 /* When target does not have ctors and dtors, we call all constructor
1227    and destructor by special initialization/destruction function
1228    recognized by collect2.
1229 
1230    When we are going to build this function, collect all constructors and
1231    destructors and turn them into normal functions.  */
1232 
1233 static void
1234 record_cdtor_fn (struct cgraph_node *node)
1235 {
1236   if (DECL_STATIC_CONSTRUCTOR (node->decl))
1237     VEC_safe_push (tree, heap, static_ctors, node->decl);
1238   if (DECL_STATIC_DESTRUCTOR (node->decl))
1239     VEC_safe_push (tree, heap, static_dtors, node->decl);
1240   node = cgraph_get_node (node->decl);
1241   DECL_DISREGARD_INLINE_LIMITS (node->decl) = 1;
1242 }
1243 
1244 /* Define global constructors/destructor functions for the CDTORS, of
1245    which they are LEN.  The CDTORS are sorted by initialization
1246    priority.  If CTOR_P is true, these are constructors; otherwise,
1247    they are destructors.  */
1248 
1249 static void
1250 build_cdtor (bool ctor_p, VEC (tree, heap) *cdtors)
1251 {
1252   size_t i,j;
1253   size_t len = VEC_length (tree, cdtors);
1254 
1255   i = 0;
1256   while (i < len)
1257     {
1258       tree body;
1259       tree fn;
1260       priority_type priority;
1261 
1262       priority = 0;
1263       body = NULL_TREE;
1264       j = i;
1265       do
1266 	{
1267 	  priority_type p;
1268 	  fn = VEC_index (tree, cdtors, j);
1269 	  p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
1270 	  if (j == i)
1271 	    priority = p;
1272 	  else if (p != priority)
1273 	    break;
1274 	  j++;
1275 	}
1276       while (j < len);
1277 
1278       /* When there is only one cdtor and target supports them, do nothing.  */
1279       if (j == i + 1
1280 	  && targetm.have_ctors_dtors)
1281 	{
1282 	  i++;
1283 	  continue;
1284 	}
1285       /* Find the next batch of constructors/destructors with the same
1286 	 initialization priority.  */
1287       for (;i < j; i++)
1288 	{
1289 	  tree call;
1290 	  fn = VEC_index (tree, cdtors, i);
1291 	  call = build_call_expr (fn, 0);
1292 	  if (ctor_p)
1293 	    DECL_STATIC_CONSTRUCTOR (fn) = 0;
1294 	  else
1295 	    DECL_STATIC_DESTRUCTOR (fn) = 0;
1296 	  /* We do not want to optimize away pure/const calls here.
1297 	     When optimizing, these should be already removed, when not
1298 	     optimizing, we want user to be able to breakpoint in them.  */
1299 	  TREE_SIDE_EFFECTS (call) = 1;
1300 	  append_to_statement_list (call, &body);
1301 	}
1302       gcc_assert (body != NULL_TREE);
1303       /* Generate a function to call all the function of like
1304 	 priority.  */
1305       cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true);
1306     }
1307 }
1308 
1309 /* Comparison function for qsort.  P1 and P2 are actually of type
1310    "tree *" and point to static constructors.  DECL_INIT_PRIORITY is
1311    used to determine the sort order.  */
1312 
1313 static int
1314 compare_ctor (const void *p1, const void *p2)
1315 {
1316   tree f1;
1317   tree f2;
1318   int priority1;
1319   int priority2;
1320 
1321   f1 = *(const tree *)p1;
1322   f2 = *(const tree *)p2;
1323   priority1 = DECL_INIT_PRIORITY (f1);
1324   priority2 = DECL_INIT_PRIORITY (f2);
1325 
1326   if (priority1 < priority2)
1327     return -1;
1328   else if (priority1 > priority2)
1329     return 1;
1330   else
1331     /* Ensure a stable sort.  Constructors are executed in backwarding
1332        order to make LTO initialize braries first.  */
1333     return DECL_UID (f2) - DECL_UID (f1);
1334 }
1335 
1336 /* Comparison function for qsort.  P1 and P2 are actually of type
1337    "tree *" and point to static destructors.  DECL_FINI_PRIORITY is
1338    used to determine the sort order.  */
1339 
1340 static int
1341 compare_dtor (const void *p1, const void *p2)
1342 {
1343   tree f1;
1344   tree f2;
1345   int priority1;
1346   int priority2;
1347 
1348   f1 = *(const tree *)p1;
1349   f2 = *(const tree *)p2;
1350   priority1 = DECL_FINI_PRIORITY (f1);
1351   priority2 = DECL_FINI_PRIORITY (f2);
1352 
1353   if (priority1 < priority2)
1354     return -1;
1355   else if (priority1 > priority2)
1356     return 1;
1357   else
1358     /* Ensure a stable sort.  */
1359     return DECL_UID (f1) - DECL_UID (f2);
1360 }
1361 
1362 /* Generate functions to call static constructors and destructors
1363    for targets that do not support .ctors/.dtors sections.  These
1364    functions have magic names which are detected by collect2.  */
1365 
1366 static void
1367 build_cdtor_fns (void)
1368 {
1369   if (!VEC_empty (tree, static_ctors))
1370     {
1371       gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1372       VEC_qsort (tree, static_ctors, compare_ctor);
1373       build_cdtor (/*ctor_p=*/true, static_ctors);
1374     }
1375 
1376   if (!VEC_empty (tree, static_dtors))
1377     {
1378       gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1379       VEC_qsort (tree, static_dtors, compare_dtor);
1380       build_cdtor (/*ctor_p=*/false, static_dtors);
1381     }
1382 }
1383 
1384 /* Look for constructors and destructors and produce function calling them.
1385    This is needed for targets not supporting ctors or dtors, but we perform the
1386    transformation also at linktime to merge possibly numberous
1387    constructors/destructors into single function to improve code locality and
1388    reduce size.  */
1389 
1390 static unsigned int
1391 ipa_cdtor_merge (void)
1392 {
1393   struct cgraph_node *node;
1394   for (node = cgraph_nodes; node; node = node->next)
1395     if (node->analyzed
1396 	&& (DECL_STATIC_CONSTRUCTOR (node->decl)
1397 	    || DECL_STATIC_DESTRUCTOR (node->decl)))
1398        record_cdtor_fn (node);
1399   build_cdtor_fns ();
1400   VEC_free (tree, heap, static_ctors);
1401   VEC_free (tree, heap, static_dtors);
1402   return 0;
1403 }
1404 
1405 /* Perform the pass when we have no ctors/dtors support
1406    or at LTO time to merge multiple constructors into single
1407    function.  */
1408 
1409 static bool
1410 gate_ipa_cdtor_merge (void)
1411 {
1412   return !targetm.have_ctors_dtors || (optimize && in_lto_p);
1413 }
1414 
1415 struct ipa_opt_pass_d pass_ipa_cdtor_merge =
1416 {
1417  {
1418   IPA_PASS,
1419   "cdtor",				/* name */
1420   gate_ipa_cdtor_merge,			/* gate */
1421   ipa_cdtor_merge,		        /* execute */
1422   NULL,					/* sub */
1423   NULL,					/* next */
1424   0,					/* static_pass_number */
1425   TV_CGRAPHOPT,			        /* tv_id */
1426   0,	                                /* properties_required */
1427   0,					/* properties_provided */
1428   0,					/* properties_destroyed */
1429   0,					/* todo_flags_start */
1430   0                                     /* todo_flags_finish */
1431  },
1432  NULL,				        /* generate_summary */
1433  NULL,					/* write_summary */
1434  NULL,					/* read_summary */
1435  NULL,					/* write_optimization_summary */
1436  NULL,					/* read_optimization_summary */
1437  NULL,					/* stmt_fixup */
1438  0,					/* TODOs */
1439  NULL,			                /* function_transform */
1440  NULL					/* variable_transform */
1441 };
1442