OSDN Git Service

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