OSDN Git Service

2010-11-13 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / ipa.c
1 /* Basic IPA optimizations and utilities.
2    Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
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
35 /* Fill array order with all nodes with output flag set in the reverse
36    topological order.  */
37
38 int
39 cgraph_postorder (struct cgraph_node **order)
40 {
41   struct cgraph_node *node, *node2;
42   int stack_size = 0;
43   int order_pos = 0;
44   struct cgraph_edge *edge, last;
45   int pass;
46
47   struct cgraph_node **stack =
48     XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
49
50   /* We have to deal with cycles nicely, so use a depth first traversal
51      output algorithm.  Ignore the fact that some functions won't need
52      to be output and put them into order as well, so we get dependencies
53      right through inline functions.  */
54   for (node = cgraph_nodes; node; node = node->next)
55     node->aux = NULL;
56   for (pass = 0; pass < 2; pass++)
57     for (node = cgraph_nodes; node; node = node->next)
58       if (!node->aux
59           && (pass
60               || (!node->address_taken
61                   && !node->global.inlined_to
62                   && !cgraph_only_called_directly_p (node))))
63         {
64           node2 = node;
65           if (!node->callers)
66             node->aux = &last;
67           else
68             node->aux = node->callers;
69           while (node2)
70             {
71               while (node2->aux != &last)
72                 {
73                   edge = (struct cgraph_edge *) node2->aux;
74                   if (edge->next_caller)
75                     node2->aux = edge->next_caller;
76                   else
77                     node2->aux = &last;
78                   /* Break possible cycles involving always-inline
79                      functions by ignoring edges from always-inline
80                      functions to non-always-inline functions.  */
81                   if (edge->caller->local.disregard_inline_limits
82                       && !edge->callee->local.disregard_inline_limits)
83                     continue;
84                   if (!edge->caller->aux)
85                     {
86                       if (!edge->caller->callers)
87                         edge->caller->aux = &last;
88                       else
89                         edge->caller->aux = edge->caller->callers;
90                       stack[stack_size++] = node2;
91                       node2 = edge->caller;
92                       break;
93                     }
94                 }
95               if (node2->aux == &last)
96                 {
97                   order[order_pos++] = node2;
98                   if (stack_size)
99                     node2 = stack[--stack_size];
100                   else
101                     node2 = NULL;
102                 }
103             }
104         }
105   free (stack);
106   for (node = cgraph_nodes; node; node = node->next)
107     node->aux = NULL;
108   return order_pos;
109 }
110
111 /* Look for all functions inlined to NODE and update their inlined_to pointers
112    to INLINED_TO.  */
113
114 static void
115 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
116 {
117   struct cgraph_edge *e;
118   for (e = node->callees; e; e = e->next_callee)
119     if (e->callee->global.inlined_to)
120       {
121         e->callee->global.inlined_to = inlined_to;
122         update_inlined_to_pointer (e->callee, inlined_to);
123       }
124 }
125
126 /* Add cgraph NODE to queue starting at FIRST.
127
128    The queue is linked via AUX pointers and terminated by pointer to 1.
129    We enqueue nodes at two occasions: when we find them reachable or when we find
130    their bodies needed for further clonning.  In the second case we mark them
131    by pointer to 2 after processing so they are re-queue when they become
132    reachable.  */
133
134 static void
135 enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first)
136 {
137   /* Node is still in queue; do nothing.  */
138   if (node->aux && node->aux != (void *) 2)
139     return;
140   /* Node was already processed as unreachable, re-enqueue
141      only if it became reachable now.  */
142   if (node->aux == (void *)2 && !node->reachable)
143     return;
144   node->aux = *first;
145   *first = node;
146 }
147
148 /* Add varpool NODE to queue starting at FIRST.  */
149
150 static void
151 enqueue_varpool_node (struct varpool_node *node, struct varpool_node **first)
152 {
153   node->aux = *first;
154   *first = node;
155 }
156
157 /* Process references.  */
158
159 static void
160 process_references (struct ipa_ref_list *list,
161                     struct cgraph_node **first,
162                     struct varpool_node **first_varpool,
163                     bool before_inlining_p)
164 {
165   int i;
166   struct ipa_ref *ref;
167   for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
168     {
169       if (ref->refered_type == IPA_REF_CGRAPH)
170         {
171           struct cgraph_node *node = ipa_ref_node (ref);
172           if (!node->reachable
173               && node->analyzed
174               && (!DECL_EXTERNAL (node->decl)
175                   || before_inlining_p))
176             node->reachable = true;
177           enqueue_cgraph_node (node, first);
178         }
179       else
180         {
181           struct varpool_node *node = ipa_ref_varpool_node (ref);
182           if (!node->needed)
183             {
184               varpool_mark_needed_node (node);
185               enqueue_varpool_node (node, first_varpool);
186             }
187         }
188     }
189 }
190
191 /* Return true when function NODE can be removed from callgraph
192    if all direct calls are eliminated.  */
193
194 static inline bool
195 varpool_can_remove_if_no_refs (struct varpool_node *node)
196 {
197   return (!node->force_output && !node->used_from_other_partition
198           && (DECL_COMDAT (node->decl) || !node->externally_visible));
199 }
200
201 /* Return true when function can be marked local.  */
202
203 static bool
204 cgraph_local_node_p (struct cgraph_node *node)
205 {
206    return (cgraph_only_called_directly_p (node)
207            && node->analyzed
208            && !DECL_EXTERNAL (node->decl)
209            && !node->local.externally_visible
210            && !node->reachable_from_other_partition
211            && !node->in_other_partition);
212 }
213
214 /* Perform reachability analysis and reclaim all unreachable nodes.
215    If BEFORE_INLINING_P is true this function is called before inlining
216    decisions has been made.  If BEFORE_INLINING_P is false this function also
217    removes unneeded bodies of extern inline functions.  */
218
219 bool
220 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
221 {
222   struct cgraph_node *first = (struct cgraph_node *) (void *) 1;
223   struct varpool_node *first_varpool = (struct varpool_node *) (void *) 1;
224   struct cgraph_node *node, *next;
225   struct varpool_node *vnode, *vnext;
226   bool changed = false;
227
228 #ifdef ENABLE_CHECKING
229   verify_cgraph ();
230 #endif
231   if (file)
232     fprintf (file, "\nReclaiming functions:");
233 #ifdef ENABLE_CHECKING
234   for (node = cgraph_nodes; node; node = node->next)
235     gcc_assert (!node->aux);
236   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
237     gcc_assert (!vnode->aux);
238 #endif
239   varpool_reset_queue ();
240   /* Mark functions whose bodies are obviously needed.
241      This is mostly when they can be referenced externally.  Inline clones
242      are special since their declarations are shared with master clone and thus
243      cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them.  */
244   for (node = cgraph_nodes; node; node = node->next)
245     if (node->analyzed && !node->global.inlined_to
246         && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
247             /* Keep around virtual functions for possible devirtualization.  */
248             || (before_inlining_p
249                 && DECL_VIRTUAL_P (node->decl)
250                 && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)))
251             /* Also external functions with address taken are better to stay
252                for indirect inlining.  */
253             || (before_inlining_p
254                 && DECL_EXTERNAL (node->decl)
255                 && node->address_taken)))
256       {
257         gcc_assert (!node->global.inlined_to);
258         enqueue_cgraph_node (node, &first);
259         node->reachable = true;
260       }
261     else
262       {
263         gcc_assert (!node->aux);
264         node->reachable = false;
265       }
266
267   /* Mark variables that are obviously needed.  */
268   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
269     {
270       vnode->next_needed = NULL;
271       vnode->prev_needed = NULL;
272       if (!varpool_can_remove_if_no_refs (vnode))
273         {
274           vnode->needed = false;
275           varpool_mark_needed_node (vnode);
276           enqueue_varpool_node (vnode, &first_varpool);
277         }
278       else
279         vnode->needed = false;
280     }
281
282   /* Perform reachability analysis.  As a special case do not consider
283      extern inline functions not inlined as live because we won't output
284      them at all. 
285
286      We maintain two worklist, one for cgraph nodes other for varpools and
287      are finished once both are empty.  */
288
289   while (first != (struct cgraph_node *) (void *) 1
290          || first_varpool != (struct varpool_node *) (void *) 1)
291     {
292       if (first != (struct cgraph_node *) (void *) 1)
293         {
294           struct cgraph_edge *e;
295           node = first;
296           first = (struct cgraph_node *) first->aux;
297           if (!node->reachable)
298             node->aux = (void *)2;
299
300           /* If we found this node reachable, first mark on the callees
301              reachable too, unless they are direct calls to extern inline functions
302              we decided to not inline.  */
303           if (node->reachable)
304             {
305               for (e = node->callees; e; e = e->next_callee)
306                 {
307                   if (!e->callee->reachable
308                       && node->analyzed
309                       && (!e->inline_failed
310                           || !DECL_EXTERNAL (e->callee->decl)
311                           || before_inlining_p))
312                     e->callee->reachable = true;
313                   enqueue_cgraph_node (e->callee, &first);
314                 }
315               process_references (&node->ref_list, &first, &first_varpool, before_inlining_p);
316             }
317
318           /* If any function in a comdat group is reachable, force
319              all other functions in the same comdat group to be
320              also reachable.  */
321           if (node->same_comdat_group
322               && node->reachable
323               && !node->global.inlined_to)
324             {
325               for (next = node->same_comdat_group;
326                    next != node;
327                    next = next->same_comdat_group)
328                 if (!next->reachable)
329                   {
330                     next->reachable = true;
331                     enqueue_cgraph_node (next, &first);
332                   }
333             }
334
335           /* We can freely remove inline clones even if they are cloned, however if
336              function is clone of real clone, we must keep it around in order to
337              make materialize_clones produce function body with the changes
338              applied.  */
339           while (node->clone_of && !node->clone_of->aux
340                  && !gimple_has_body_p (node->decl))
341             {
342               bool noninline = node->clone_of->decl != node->decl;
343               node = node->clone_of;
344               if (noninline && !node->reachable && !node->aux)
345                 {
346                   enqueue_cgraph_node (node, &first);
347                   break;
348                 }
349             }
350         }
351       if (first_varpool != (struct varpool_node *) (void *) 1)
352         {
353           vnode = first_varpool;
354           first_varpool = (struct varpool_node *)first_varpool->aux;
355           vnode->aux = NULL;
356           process_references (&vnode->ref_list, &first, &first_varpool, before_inlining_p);
357           /* If any function in a comdat group is reachable, force
358              all other functions in the same comdat group to be
359              also reachable.  */
360           if (vnode->same_comdat_group)
361             {
362               struct varpool_node *next;
363               for (next = vnode->same_comdat_group;
364                    next != vnode;
365                    next = next->same_comdat_group)
366                 if (!next->needed)
367                   {
368                     varpool_mark_needed_node (next);
369                     enqueue_varpool_node (next, &first_varpool);
370                   }
371             }
372         }
373     }
374
375   /* Remove unreachable nodes. 
376
377      Completely unreachable functions can be fully removed from the callgraph.
378      Extern inline functions that we decided to not inline need to become unanalyzed nodes of
379      callgraph (so we still have edges to them).  We remove function body then.
380
381      Also we need to care functions that are unreachable but we need to keep them around
382      for later clonning.  In this case we also turn them to unanalyzed nodes, but
383      keep the body around.  */
384   for (node = cgraph_nodes; node; node = next)
385     {
386       next = node->next;
387       if (node->aux && !node->reachable)
388         {
389           cgraph_node_remove_callees (node);
390           ipa_remove_all_references (&node->ref_list);
391           node->analyzed = false;
392           node->local.inlinable = false;
393         }
394       if (!node->aux)
395         {
396           struct cgraph_edge *e;
397           bool found = false;
398           int i;
399           struct ipa_ref *ref;
400
401           node->global.inlined_to = NULL;
402           if (file)
403             fprintf (file, " %s", cgraph_node_name (node));
404           /* See if there is reachable caller.  */
405           for (e = node->callers; e && !found; e = e->next_caller)
406             if (e->caller->reachable)
407               found = true;
408           for (i = 0; (ipa_ref_list_refering_iterate (&node->ref_list, i, ref)
409                        && !found); i++)
410             if (ref->refering_type == IPA_REF_CGRAPH
411                 && ipa_ref_refering_node (ref)->reachable)
412               found = true;
413             else if (ref->refering_type == IPA_REF_VARPOOL
414                      && ipa_ref_refering_varpool_node (ref)->needed)
415               found = true;
416
417           /* If so, we need to keep node in the callgraph.  */
418           if (found)
419             {
420               if (node->analyzed)
421                 {
422                   struct cgraph_node *clone;
423
424                   /* If there are still clones, we must keep body around.
425                      Otherwise we can just remove the body but keep the clone.  */
426                   for (clone = node->clones; clone;
427                        clone = clone->next_sibling_clone)
428                     if (clone->aux)
429                       break;
430                   if (!clone)
431                     {
432                       cgraph_release_function_body (node);
433                       node->local.inlinable = false;
434                       if (node->prev_sibling_clone)
435                         node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
436                       else if (node->clone_of)
437                         node->clone_of->clones = node->next_sibling_clone;
438                       if (node->next_sibling_clone)
439                         node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
440 #ifdef ENABLE_CHECKING
441                       if (node->clone_of)
442                         node->former_clone_of = node->clone_of->decl;
443 #endif
444                       node->clone_of = NULL;
445                       node->next_sibling_clone = NULL;
446                       node->prev_sibling_clone = NULL;
447                     }
448                   else
449                     gcc_assert (!clone->in_other_partition);
450                   node->analyzed = false;
451                   changed = true;
452                   cgraph_node_remove_callees (node);
453                   ipa_remove_all_references (&node->ref_list);
454                 }
455             }
456           else
457             {
458               cgraph_remove_node (node);
459               changed = true;
460             }
461         }
462     }
463   for (node = cgraph_nodes; node; node = node->next)
464     {
465       /* Inline clones might be kept around so their materializing allows further
466          cloning.  If the function the clone is inlined into is removed, we need
467          to turn it into normal cone.  */
468       if (node->global.inlined_to
469           && !node->callers)
470         {
471           gcc_assert (node->clones);
472           node->global.inlined_to = NULL;
473           update_inlined_to_pointer (node, node);
474         }
475       node->aux = NULL;
476     }
477
478   if (file)
479     fprintf (file, "\n");
480
481   /* We must release unused extern inlines or sanity checking will fail.  Rest of transformations
482      are undesirable at -O0 since we do not want to remove anything.  */
483   if (!optimize)
484     return changed;
485
486   if (file)
487     fprintf (file, "Reclaiming variables:");
488   for (vnode = varpool_nodes; vnode; vnode = vnext)
489     {
490       vnext = vnode->next;
491       if (!vnode->needed)
492         {
493           if (file)
494             fprintf (file, " %s", varpool_node_name (vnode));
495           varpool_remove_node (vnode);
496           changed = true;
497         }
498     }
499
500   /* Now update address_taken flags and try to promote functions to be local.  */
501
502   if (file)
503     fprintf (file, "\nClearing address taken flags:");
504   for (node = cgraph_nodes; node; node = node->next)
505     if (node->address_taken
506         && !node->reachable_from_other_partition)
507       {
508         int i;
509         struct ipa_ref *ref;
510         bool found = false;
511         for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref)
512                     && !found; i++)
513           {
514             gcc_assert (ref->use == IPA_REF_ADDR);
515             found = true;
516           }
517         if (!found)
518           {
519             if (file)
520               fprintf (file, " %s", cgraph_node_name (node));
521             node->address_taken = false;
522             changed = true;
523             if (cgraph_local_node_p (node))
524               {
525                 node->local.local = true;
526                 if (file)
527                   fprintf (file, " (local)");
528               }
529           }
530       }
531
532 #ifdef ENABLE_CHECKING
533   verify_cgraph ();
534 #endif
535
536   /* Reclaim alias pairs for functions that have disappeared from the
537      call graph.  */
538   remove_unreachable_alias_pairs ();
539
540   return changed;
541 }
542
543 /* Discover variables that have no longer address taken or that are read only
544    and update their flags.
545
546    FIXME: This can not be done in between gimplify and omp_expand since
547    readonly flag plays role on what is shared and what is not.  Currently we do
548    this transformation as part of whole program visibility and re-do at
549    ipa-reference pass (to take into account clonning), but it would
550    make sense to do it before early optimizations.  */
551
552 void
553 ipa_discover_readonly_nonaddressable_vars (void)
554 {
555   struct varpool_node *vnode;
556   if (dump_file)
557     fprintf (dump_file, "Clearing variable flags:");
558   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
559     if (vnode->finalized && varpool_all_refs_explicit_p (vnode)
560         && (TREE_ADDRESSABLE (vnode->decl) || !TREE_READONLY (vnode->decl)))
561       {
562         bool written = false;
563         bool address_taken = false;
564         int i;
565         struct ipa_ref *ref;
566         for (i = 0; ipa_ref_list_refering_iterate (&vnode->ref_list, i, ref)
567                     && (!written || !address_taken); i++)
568           switch (ref->use)
569             {
570             case IPA_REF_ADDR:
571               address_taken = true;
572               break;
573             case IPA_REF_LOAD:
574               break;
575             case IPA_REF_STORE:
576               written = true;
577               break;
578             }
579         if (TREE_ADDRESSABLE (vnode->decl) && !address_taken)
580           {
581             if (dump_file)
582               fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
583             TREE_ADDRESSABLE (vnode->decl) = 0;
584           }
585         if (!TREE_READONLY (vnode->decl) && !address_taken && !written
586             /* Making variable in explicit section readonly can cause section
587                type conflict. 
588                See e.g. gcc.c-torture/compile/pr23237.c */
589             && DECL_SECTION_NAME (vnode->decl) == NULL)
590           {
591             if (dump_file)
592               fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
593             TREE_READONLY (vnode->decl) = 1;
594           }
595       }
596   if (dump_file)
597     fprintf (dump_file, "\n");
598 }
599
600 /* Return true when function NODE should be considered externally visible.  */
601
602 static bool
603 cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool aliased)
604 {
605   struct cgraph_node *alias;
606   if (!node->local.finalized)
607     return false;
608   if (!DECL_COMDAT (node->decl)
609       && (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)))
610     return false;
611
612   /* Do not even try to be smart about aliased nodes.  Until we properly
613      represent everything by same body alias, these are just evil.  */
614   if (aliased)
615     return true;
616
617   /* If linker counts on us, we must preserve the function.  */
618   if (cgraph_used_from_object_file_p (node))
619     return true;
620   if (DECL_PRESERVE_P (node->decl))
621     return true;
622   if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
623     return true;
624
625   /* See if we have linker information about symbol not being used or
626      if we need to make guess based on the declaration.
627
628      Even if the linker clams the symbol is unused, never bring internal
629      symbols that are declared by user as used or externally visible.
630      This is needed for i.e. references from asm statements.   */
631   for (alias = node->same_body; alias; alias = alias->next)
632     if (alias->resolution != LDPR_PREVAILING_DEF_IRONLY)
633       break;
634   if (!alias && node->resolution == LDPR_PREVAILING_DEF_IRONLY)
635     return false;
636
637   /* When doing link time optimizations, hidden symbols become local.  */
638   if (in_lto_p
639       && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
640           || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
641       /* Be sure that node is defined in IR file, not in other object
642          file.  In that case we don't set used_from_other_object_file.  */
643       && node->analyzed)
644     ;
645   else if (!whole_program)
646     return true;
647   /* COMDAT functions must be shared only if they have address taken,
648      otherwise we can produce our own private implementation with
649      -fwhole-program.  */
650   else if (DECL_COMDAT (node->decl))
651     {
652       if (node->address_taken || !node->analyzed)
653         return true;
654       if (node->same_comdat_group)
655         {
656           struct cgraph_node *next;
657
658           /* If more than one function is in the same COMDAT group, it must
659              be shared even if just one function in the comdat group has
660              address taken.  */
661           for (next = node->same_comdat_group;
662                next != node;
663                next = next->same_comdat_group)
664             if (next->address_taken || !next->analyzed)
665               return true;
666         }
667     }
668
669   if (MAIN_NAME_P (DECL_NAME (node->decl)))
670     return true;
671
672   return false;
673 }
674
675 /* Return true when variable VNODE should be considered externally visible.  */
676
677 static bool
678 varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
679 {
680   struct varpool_node *alias;
681   if (!DECL_COMDAT (vnode->decl) && !TREE_PUBLIC (vnode->decl))
682     return false;
683
684   /* Do not even try to be smart about aliased nodes.  Until we properly
685      represent everything by same body alias, these are just evil.  */
686   if (aliased)
687     return true;
688
689   /* If linker counts on us, we must preserve the function.  */
690   if (varpool_used_from_object_file_p (vnode))
691     return true;
692
693   if (DECL_PRESERVE_P (vnode->decl))
694     return true;
695   if (lookup_attribute ("externally_visible",
696                         DECL_ATTRIBUTES (vnode->decl)))
697     return true;
698
699   /* See if we have linker information about symbol not being used or
700      if we need to make guess based on the declaration.
701
702      Even if the linker clams the symbol is unused, never bring internal
703      symbols that are declared by user as used or externally visible.
704      This is needed for i.e. references from asm statements.   */
705   if (varpool_used_from_object_file_p (vnode))
706     return true;
707   for (alias = vnode->extra_name; alias; alias = alias->next)
708     if (alias->resolution != LDPR_PREVAILING_DEF_IRONLY)
709       break;
710   if (!alias && vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
711     return false;
712
713   /* When doing link time optimizations, hidden symbols become local.  */
714   if (in_lto_p
715       && (DECL_VISIBILITY (vnode->decl) == VISIBILITY_HIDDEN
716           || DECL_VISIBILITY (vnode->decl) == VISIBILITY_INTERNAL)
717       /* Be sure that node is defined in IR file, not in other object
718          file.  In that case we don't set used_from_other_object_file.  */
719       && vnode->finalized)
720     ;
721   else if (!flag_whole_program)
722     return true;
723
724   /* Do not attempt to privatize COMDATS by default.
725      This would break linking with C++ libraries sharing
726      inline definitions.
727
728      FIXME: We can do so for readonly vars with no address taken and
729      possibly also for vtables since no direct pointer comparsion is done.
730      It might be interesting to do so to reduce linking overhead.  */
731   if (DECL_COMDAT (vnode->decl) || DECL_WEAK (vnode->decl))
732     return true;
733   return false;
734 }
735
736 /* Dissolve the same_comdat_group list in which NODE resides.  */
737
738 static void
739 dissolve_same_comdat_group_list (struct cgraph_node *node)
740 {
741   struct cgraph_node *n = node, *next;
742   do
743     {
744       next = n->same_comdat_group;
745       n->same_comdat_group = NULL;
746       n = next;
747     }
748   while (n != node);
749 }
750
751 /* Mark visibility of all functions.
752
753    A local function is one whose calls can occur only in the current
754    compilation unit and all its calls are explicit, so we can change
755    its calling convention.  We simply mark all static functions whose
756    address is not taken as local.
757
758    We also change the TREE_PUBLIC flag of all declarations that are public
759    in language point of view but we want to overwrite this default
760    via visibilities for the backend point of view.  */
761
762 static unsigned int
763 function_and_variable_visibility (bool whole_program)
764 {
765   struct cgraph_node *node;
766   struct varpool_node *vnode;
767   struct pointer_set_t *aliased_nodes = pointer_set_create ();
768   struct pointer_set_t *aliased_vnodes = pointer_set_create ();
769   unsigned i;
770   alias_pair *p;
771
772   /* Discover aliased nodes.  */
773   FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
774     {
775       if (dump_file)
776        fprintf (dump_file, "Alias %s->%s",
777                 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
778                 IDENTIFIER_POINTER (p->target));
779                 
780       if ((node = cgraph_node_for_asm (p->target)) != NULL)
781         {
782           gcc_assert (node->needed);
783           pointer_set_insert (aliased_nodes, node);
784           if (dump_file)
785             fprintf (dump_file, "  node %s/%i",
786                      cgraph_node_name (node), node->uid);
787         }
788       else if ((vnode = varpool_node_for_asm (p->target)) != NULL)
789         {
790           gcc_assert (vnode->needed);
791           pointer_set_insert (aliased_vnodes, vnode);
792           if (dump_file)
793             fprintf (dump_file, "  varpool node %s",
794                      varpool_node_name (vnode));
795         }
796       if (dump_file)
797        fprintf (dump_file, "\n");
798     }
799
800   for (node = cgraph_nodes; node; node = node->next)
801     {
802       int flags = flags_from_decl_or_type (node->decl);
803       if (optimize
804           && (flags & (ECF_CONST | ECF_PURE))
805           && !(flags & ECF_LOOPING_CONST_OR_PURE))
806         {
807           DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
808           DECL_STATIC_DESTRUCTOR (node->decl) = 0;
809         }
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           struct cgraph_node *alias;
849           gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
850           cgraph_make_decl_local (node->decl);
851           node->resolution = LDPR_PREVAILING_DEF_IRONLY;
852           for (alias = node->same_body; alias; alias = alias->next)
853             cgraph_make_decl_local (alias->decl);
854           if (node->same_comdat_group)
855             /* cgraph_externally_visible_p has already checked all other nodes
856                in the group and they will all be made local.  We need to
857                dissolve the group at once so that the predicate does not
858                segfault though. */
859             dissolve_same_comdat_group_list (node);
860         }
861       node->local.local = cgraph_local_node_p (node);
862     }
863   for (vnode = varpool_nodes; vnode; vnode = vnode->next)
864     {
865       /* weak flag makes no sense on local variables.  */
866       gcc_assert (!DECL_WEAK (vnode->decl)
867                   || TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl));
868       /* In several cases declarations can not be common:
869
870          - when declaration has initializer
871          - when it is in weak
872          - when it has specific section
873          - when it resides in non-generic address space.
874          - if declaration is local, it will get into .local common section
875            so common flag is not needed.  Frontends still produce these in
876            certain cases, such as for:
877
878              static int a __attribute__ ((common))
879
880          Canonicalize things here and clear the redundant flag.  */
881       if (DECL_COMMON (vnode->decl)
882           && (!(TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl))
883               || (DECL_INITIAL (vnode->decl)
884                   && DECL_INITIAL (vnode->decl) != error_mark_node)
885               || DECL_WEAK (vnode->decl)
886               || DECL_SECTION_NAME (vnode->decl) != NULL
887               || ! (ADDR_SPACE_GENERIC_P
888                     (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
889         DECL_COMMON (vnode->decl) = 0;
890     }
891   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
892     {
893       if (!vnode->finalized)
894         continue;
895       if (vnode->needed
896           && varpool_externally_visible_p
897               (vnode, 
898                pointer_set_contains (aliased_vnodes, vnode)))
899         vnode->externally_visible = true;
900       else
901         vnode->externally_visible = false;
902       if (!vnode->externally_visible)
903         {
904           gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
905           cgraph_make_decl_local (vnode->decl);
906           vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
907         }
908      gcc_assert (TREE_STATIC (vnode->decl));
909     }
910   pointer_set_destroy (aliased_nodes);
911   pointer_set_destroy (aliased_vnodes);
912
913   if (dump_file)
914     {
915       fprintf (dump_file, "\nMarking local functions:");
916       for (node = cgraph_nodes; node; node = node->next)
917         if (node->local.local)
918           fprintf (dump_file, " %s", cgraph_node_name (node));
919       fprintf (dump_file, "\n\n");
920       fprintf (dump_file, "\nMarking externally visible functions:");
921       for (node = cgraph_nodes; node; node = node->next)
922         if (node->local.externally_visible)
923           fprintf (dump_file, " %s", cgraph_node_name (node));
924       fprintf (dump_file, "\n\n");
925       fprintf (dump_file, "\nMarking externally visible variables:");
926       for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
927         if (vnode->externally_visible)
928           fprintf (dump_file, " %s", varpool_node_name (vnode));
929       fprintf (dump_file, "\n\n");
930     }
931   cgraph_function_flags_ready = true;
932   return 0;
933 }
934
935 /* Local function pass handling visibilities.  This happens before LTO streaming
936    so in particular -fwhole-program should be ignored at this level.  */
937
938 static unsigned int
939 local_function_and_variable_visibility (void)
940 {
941   return function_and_variable_visibility (flag_whole_program && !flag_lto);
942 }
943
944 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
945 {
946  {
947   SIMPLE_IPA_PASS,
948   "visibility",                         /* name */
949   NULL,                                 /* gate */
950   local_function_and_variable_visibility,/* execute */
951   NULL,                                 /* sub */
952   NULL,                                 /* next */
953   0,                                    /* static_pass_number */
954   TV_CGRAPHOPT,                         /* tv_id */
955   0,                                    /* properties_required */
956   0,                                    /* properties_provided */
957   0,                                    /* properties_destroyed */
958   0,                                    /* todo_flags_start */
959   TODO_remove_functions | TODO_dump_cgraph
960   | TODO_ggc_collect                    /* todo_flags_finish */
961  }
962 };
963
964 /* Do not re-run on ltrans stage.  */
965
966 static bool
967 gate_whole_program_function_and_variable_visibility (void)
968 {
969   return !flag_ltrans;
970 }
971
972 /* Bring functionss local at LTO time whith -fwhole-program.  */
973
974 static unsigned int
975 whole_program_function_and_variable_visibility (void)
976 {
977   struct cgraph_node *node;
978   struct varpool_node *vnode;
979
980   function_and_variable_visibility (flag_whole_program);
981
982   for (node = cgraph_nodes; node; node = node->next)
983     if ((node->local.externally_visible && !DECL_COMDAT (node->decl))
984         && node->local.finalized)
985       cgraph_mark_needed_node (node);
986   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
987     if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
988       varpool_mark_needed_node (vnode);
989   if (dump_file)
990     {
991       fprintf (dump_file, "\nNeeded variables:");
992       for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
993         if (vnode->needed)
994           fprintf (dump_file, " %s", varpool_node_name (vnode));
995       fprintf (dump_file, "\n\n");
996     }
997   if (optimize)
998     ipa_discover_readonly_nonaddressable_vars ();
999   return 0;
1000 }
1001
1002 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
1003 {
1004  {
1005   IPA_PASS,
1006   "whole-program",                      /* name */
1007   gate_whole_program_function_and_variable_visibility,/* gate */
1008   whole_program_function_and_variable_visibility,/* execute */
1009   NULL,                                 /* sub */
1010   NULL,                                 /* next */
1011   0,                                    /* static_pass_number */
1012   TV_CGRAPHOPT,                         /* tv_id */
1013   0,                                    /* properties_required */
1014   0,                                    /* properties_provided */
1015   0,                                    /* properties_destroyed */
1016   0,                                    /* todo_flags_start */
1017   TODO_remove_functions | TODO_dump_cgraph
1018   | TODO_ggc_collect                    /* todo_flags_finish */
1019  },
1020  NULL,                                  /* generate_summary */
1021  NULL,                                  /* write_summary */
1022  NULL,                                  /* read_summary */
1023  NULL,                                  /* write_optimization_summary */
1024  NULL,                                  /* read_optimization_summary */
1025  NULL,                                  /* stmt_fixup */
1026  0,                                     /* TODOs */
1027  NULL,                                  /* function_transform */
1028  NULL,                                  /* variable_transform */
1029 };
1030
1031 /* Hash a cgraph node set element.  */
1032
1033 static hashval_t
1034 hash_cgraph_node_set_element (const void *p)
1035 {
1036   const_cgraph_node_set_element element = (const_cgraph_node_set_element) p;
1037   return htab_hash_pointer (element->node);
1038 }
1039
1040 /* Compare two cgraph node set elements.  */
1041
1042 static int
1043 eq_cgraph_node_set_element (const void *p1, const void *p2)
1044 {
1045   const_cgraph_node_set_element e1 = (const_cgraph_node_set_element) p1;
1046   const_cgraph_node_set_element e2 = (const_cgraph_node_set_element) p2;
1047
1048   return e1->node == e2->node;
1049 }
1050
1051 /* Create a new cgraph node set.  */
1052
1053 cgraph_node_set
1054 cgraph_node_set_new (void)
1055 {
1056   cgraph_node_set new_node_set;
1057
1058   new_node_set = ggc_alloc_cgraph_node_set_def ();
1059   new_node_set->hashtab = htab_create_ggc (10,
1060                                            hash_cgraph_node_set_element,
1061                                            eq_cgraph_node_set_element,
1062                                            NULL);
1063   new_node_set->nodes = NULL;
1064   return new_node_set;
1065 }
1066
1067 /* Add cgraph_node NODE to cgraph_node_set SET.  */
1068
1069 void
1070 cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
1071 {
1072   void **slot;
1073   cgraph_node_set_element element;
1074   struct cgraph_node_set_element_def dummy;
1075
1076   dummy.node = node;
1077   slot = htab_find_slot (set->hashtab, &dummy, INSERT);
1078
1079   if (*slot != HTAB_EMPTY_ENTRY)
1080     {
1081       element = (cgraph_node_set_element) *slot;
1082       gcc_assert (node == element->node
1083                   && (VEC_index (cgraph_node_ptr, set->nodes, element->index)
1084                       == node));
1085       return;
1086     }
1087
1088   /* Insert node into hash table.  */
1089   element = ggc_alloc_cgraph_node_set_element_def ();
1090   element->node = node;
1091   element->index = VEC_length (cgraph_node_ptr, set->nodes);
1092   *slot = element;
1093
1094   /* Insert into node vector.  */
1095   VEC_safe_push (cgraph_node_ptr, gc, set->nodes, node);
1096 }
1097
1098 /* Remove cgraph_node NODE from cgraph_node_set SET.  */
1099
1100 void
1101 cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
1102 {
1103   void **slot, **last_slot;
1104   cgraph_node_set_element element, last_element;
1105   struct cgraph_node *last_node;
1106   struct cgraph_node_set_element_def dummy;
1107
1108   dummy.node = node;
1109   slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1110   if (slot == NULL)
1111     return;
1112
1113   element = (cgraph_node_set_element) *slot;
1114   gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
1115               == node);
1116
1117   /* Remove from vector. We do this by swapping node with the last element
1118      of the vector.  */
1119   last_node = VEC_pop (cgraph_node_ptr, set->nodes);
1120   if (last_node != node)
1121     {
1122       dummy.node = last_node;
1123       last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1124       last_element = (cgraph_node_set_element) *last_slot;
1125       gcc_assert (last_element);
1126
1127       /* Move the last element to the original spot of NODE.  */
1128       last_element->index = element->index;
1129       VEC_replace (cgraph_node_ptr, set->nodes, last_element->index,
1130                    last_node);
1131     }
1132
1133   /* Remove element from hash table.  */
1134   htab_clear_slot (set->hashtab, slot);
1135   ggc_free (element);
1136 }
1137
1138 /* Find NODE in SET and return an iterator to it if found.  A null iterator
1139    is returned if NODE is not in SET.  */
1140
1141 cgraph_node_set_iterator
1142 cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
1143 {
1144   void **slot;
1145   struct cgraph_node_set_element_def dummy;
1146   cgraph_node_set_element element;
1147   cgraph_node_set_iterator csi;
1148
1149   dummy.node = node;
1150   slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1151   if (slot == NULL)
1152     csi.index = (unsigned) ~0;
1153   else
1154     {
1155       element = (cgraph_node_set_element) *slot;
1156       gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
1157                   == node);
1158       csi.index = element->index;
1159     }
1160   csi.set = set;
1161
1162   return csi;
1163 }
1164
1165 /* Dump content of SET to file F.  */
1166
1167 void
1168 dump_cgraph_node_set (FILE *f, cgraph_node_set set)
1169 {
1170   cgraph_node_set_iterator iter;
1171
1172   for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
1173     {
1174       struct cgraph_node *node = csi_node (iter);
1175       fprintf (f, " %s/%i", cgraph_node_name (node), node->uid);
1176     }
1177   fprintf (f, "\n");
1178 }
1179
1180 /* Dump content of SET to stderr.  */
1181
1182 DEBUG_FUNCTION void
1183 debug_cgraph_node_set (cgraph_node_set set)
1184 {
1185   dump_cgraph_node_set (stderr, set);
1186 }
1187
1188 /* Hash a varpool node set element.  */
1189
1190 static hashval_t
1191 hash_varpool_node_set_element (const void *p)
1192 {
1193   const_varpool_node_set_element element = (const_varpool_node_set_element) p;
1194   return htab_hash_pointer (element->node);
1195 }
1196
1197 /* Compare two varpool node set elements.  */
1198
1199 static int
1200 eq_varpool_node_set_element (const void *p1, const void *p2)
1201 {
1202   const_varpool_node_set_element e1 = (const_varpool_node_set_element) p1;
1203   const_varpool_node_set_element e2 = (const_varpool_node_set_element) p2;
1204
1205   return e1->node == e2->node;
1206 }
1207
1208 /* Create a new varpool node set.  */
1209
1210 varpool_node_set
1211 varpool_node_set_new (void)
1212 {
1213   varpool_node_set new_node_set;
1214
1215   new_node_set = ggc_alloc_varpool_node_set_def ();
1216   new_node_set->hashtab = htab_create_ggc (10,
1217                                            hash_varpool_node_set_element,
1218                                            eq_varpool_node_set_element,
1219                                            NULL);
1220   new_node_set->nodes = NULL;
1221   return new_node_set;
1222 }
1223
1224 /* Add varpool_node NODE to varpool_node_set SET.  */
1225
1226 void
1227 varpool_node_set_add (varpool_node_set set, struct varpool_node *node)
1228 {
1229   void **slot;
1230   varpool_node_set_element element;
1231   struct varpool_node_set_element_def dummy;
1232
1233   dummy.node = node;
1234   slot = htab_find_slot (set->hashtab, &dummy, INSERT);
1235
1236   if (*slot != HTAB_EMPTY_ENTRY)
1237     {
1238       element = (varpool_node_set_element) *slot;
1239       gcc_assert (node == element->node
1240                   && (VEC_index (varpool_node_ptr, set->nodes, element->index)
1241                       == node));
1242       return;
1243     }
1244
1245   /* Insert node into hash table.  */
1246   element = ggc_alloc_varpool_node_set_element_def ();
1247   element->node = node;
1248   element->index = VEC_length (varpool_node_ptr, set->nodes);
1249   *slot = element;
1250
1251   /* Insert into node vector.  */
1252   VEC_safe_push (varpool_node_ptr, gc, set->nodes, node);
1253 }
1254
1255 /* Remove varpool_node NODE from varpool_node_set SET.  */
1256
1257 void
1258 varpool_node_set_remove (varpool_node_set set, struct varpool_node *node)
1259 {
1260   void **slot, **last_slot;
1261   varpool_node_set_element element, last_element;
1262   struct varpool_node *last_node;
1263   struct varpool_node_set_element_def dummy;
1264
1265   dummy.node = node;
1266   slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1267   if (slot == NULL)
1268     return;
1269
1270   element = (varpool_node_set_element) *slot;
1271   gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
1272               == node);
1273
1274   /* Remove from vector. We do this by swapping node with the last element
1275      of the vector.  */
1276   last_node = VEC_pop (varpool_node_ptr, set->nodes);
1277   if (last_node != node)
1278     {
1279       dummy.node = last_node;
1280       last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1281       last_element = (varpool_node_set_element) *last_slot;
1282       gcc_assert (last_element);
1283
1284       /* Move the last element to the original spot of NODE.  */
1285       last_element->index = element->index;
1286       VEC_replace (varpool_node_ptr, set->nodes, last_element->index,
1287                    last_node);
1288     }
1289
1290   /* Remove element from hash table.  */
1291   htab_clear_slot (set->hashtab, slot);
1292   ggc_free (element);
1293 }
1294
1295 /* Find NODE in SET and return an iterator to it if found.  A null iterator
1296    is returned if NODE is not in SET.  */
1297
1298 varpool_node_set_iterator
1299 varpool_node_set_find (varpool_node_set set, struct varpool_node *node)
1300 {
1301   void **slot;
1302   struct varpool_node_set_element_def dummy;
1303   varpool_node_set_element element;
1304   varpool_node_set_iterator vsi;
1305
1306   dummy.node = node;
1307   slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1308   if (slot == NULL)
1309     vsi.index = (unsigned) ~0;
1310   else
1311     {
1312       element = (varpool_node_set_element) *slot;
1313       gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
1314                   == node);
1315       vsi.index = element->index;
1316     }
1317   vsi.set = set;
1318
1319   return vsi;
1320 }
1321
1322 /* Dump content of SET to file F.  */
1323
1324 void
1325 dump_varpool_node_set (FILE *f, varpool_node_set set)
1326 {
1327   varpool_node_set_iterator iter;
1328
1329   for (iter = vsi_start (set); !vsi_end_p (iter); vsi_next (&iter))
1330     {
1331       struct varpool_node *node = vsi_node (iter);
1332       fprintf (f, " %s", varpool_node_name (node));
1333     }
1334   fprintf (f, "\n");
1335 }
1336
1337 /* Dump content of SET to stderr.  */
1338
1339 DEBUG_FUNCTION void
1340 debug_varpool_node_set (varpool_node_set set)
1341 {
1342   dump_varpool_node_set (stderr, set);
1343 }
1344
1345
1346 /* Simple ipa profile pass propagating frequencies across the callgraph.  */
1347
1348 static unsigned int
1349 ipa_profile (void)
1350 {
1351   struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1352   struct cgraph_edge *e;
1353   int order_pos;
1354   bool something_changed = false;
1355   int i;
1356
1357   order_pos = cgraph_postorder (order);
1358   for (i = order_pos - 1; i >= 0; i--)
1359     {
1360       if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
1361         {
1362           for (e = order[i]->callees; e; e = e->next_callee)
1363             if (e->callee->local.local && !e->callee->aux)
1364               {
1365                 something_changed = true;
1366                 e->callee->aux = (void *)1;
1367               }
1368         }
1369       order[i]->aux = NULL;
1370     }
1371
1372   while (something_changed)
1373     {
1374       something_changed = false;
1375       for (i = order_pos - 1; i >= 0; i--)
1376         {
1377           if (order[i]->aux && cgraph_propagate_frequency (order[i]))
1378             {
1379               for (e = order[i]->callees; e; e = e->next_callee)
1380                 if (e->callee->local.local && !e->callee->aux)
1381                   {
1382                     something_changed = true;
1383                     e->callee->aux = (void *)1;
1384                   }
1385             }
1386           order[i]->aux = NULL;
1387         }
1388     }
1389   free (order);
1390   return 0;
1391 }
1392
1393 static bool
1394 gate_ipa_profile (void)
1395 {
1396   return flag_ipa_profile;
1397 }
1398
1399 struct ipa_opt_pass_d pass_ipa_profile =
1400 {
1401  {
1402   IPA_PASS,
1403   "ipa-profile",                        /* name */
1404   gate_ipa_profile,                     /* gate */
1405   ipa_profile,                          /* execute */
1406   NULL,                                 /* sub */
1407   NULL,                                 /* next */
1408   0,                                    /* static_pass_number */
1409   TV_IPA_PROFILE,                       /* tv_id */
1410   0,                                    /* properties_required */
1411   0,                                    /* properties_provided */
1412   0,                                    /* properties_destroyed */
1413   0,                                    /* todo_flags_start */
1414   0                                     /* todo_flags_finish */
1415  },
1416  NULL,                                  /* generate_summary */
1417  NULL,                                  /* write_summary */
1418  NULL,                                  /* read_summary */
1419  NULL,                                  /* write_optimization_summary */
1420  NULL,                                  /* read_optimization_summary */
1421  NULL,                                  /* stmt_fixup */
1422  0,                                     /* TODOs */
1423  NULL,                                  /* function_transform */
1424  NULL                                   /* variable_transform */
1425 };
1426
1427 /* Generate and emit a static constructor or destructor.  WHICH must
1428    be one of 'I' (for a constructor) or 'D' (for a destructor).  BODY
1429    is a STATEMENT_LIST containing GENERIC statements.  PRIORITY is the
1430    initialization priority for this constructor or destructor.  */
1431
1432 void
1433 cgraph_build_static_cdtor (char which, tree body, int priority)
1434 {
1435   static int counter = 0;
1436   char which_buf[16];
1437   tree decl, name, resdecl;
1438
1439   /* The priority is encoded in the constructor or destructor name.
1440      collect2 will sort the names and arrange that they are called at
1441      program startup.  */
1442   sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
1443   name = get_file_function_name (which_buf);
1444
1445   decl = build_decl (input_location, FUNCTION_DECL, name,
1446                      build_function_type_list (void_type_node, NULL_TREE));
1447   current_function_decl = decl;
1448
1449   resdecl = build_decl (input_location,
1450                         RESULT_DECL, NULL_TREE, void_type_node);
1451   DECL_ARTIFICIAL (resdecl) = 1;
1452   DECL_RESULT (decl) = resdecl;
1453   DECL_CONTEXT (resdecl) = decl;
1454
1455   allocate_struct_function (decl, false);
1456
1457   TREE_STATIC (decl) = 1;
1458   TREE_USED (decl) = 1;
1459   DECL_ARTIFICIAL (decl) = 1;
1460   DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1461   DECL_SAVED_TREE (decl) = body;
1462   if (!targetm.have_ctors_dtors)
1463     {
1464       TREE_PUBLIC (decl) = 1;
1465       DECL_PRESERVE_P (decl) = 1;
1466     }
1467   DECL_UNINLINABLE (decl) = 1;
1468
1469   DECL_INITIAL (decl) = make_node (BLOCK);
1470   TREE_USED (DECL_INITIAL (decl)) = 1;
1471
1472   DECL_SOURCE_LOCATION (decl) = input_location;
1473   cfun->function_end_locus = input_location;
1474
1475   switch (which)
1476     {
1477     case 'I':
1478       DECL_STATIC_CONSTRUCTOR (decl) = 1;
1479       decl_init_priority_insert (decl, priority);
1480       break;
1481     case 'D':
1482       DECL_STATIC_DESTRUCTOR (decl) = 1;
1483       decl_fini_priority_insert (decl, priority);
1484       break;
1485     default:
1486       gcc_unreachable ();
1487     }
1488
1489   gimplify_function_tree (decl);
1490
1491   cgraph_add_new_function (decl, false);
1492
1493   set_cfun (NULL);
1494   current_function_decl = NULL;
1495 }
1496
1497
1498 /* A vector of FUNCTION_DECLs declared as static constructors.  */
1499 static VEC(tree, heap) *static_ctors;
1500 /* A vector of FUNCTION_DECLs declared as static destructors.  */
1501 static VEC(tree, heap) *static_dtors;
1502
1503 /* When target does not have ctors and dtors, we call all constructor
1504    and destructor by special initialization/destruction function
1505    recognized by collect2.
1506
1507    When we are going to build this function, collect all constructors and
1508    destructors and turn them into normal functions.  */
1509
1510 static void
1511 record_cdtor_fn (struct cgraph_node *node)
1512 {
1513   if (DECL_STATIC_CONSTRUCTOR (node->decl))
1514     VEC_safe_push (tree, heap, static_ctors, node->decl);
1515   if (DECL_STATIC_DESTRUCTOR (node->decl))
1516     VEC_safe_push (tree, heap, static_dtors, node->decl);
1517   node = cgraph_node (node->decl);
1518   node->local.disregard_inline_limits = 1;
1519 }
1520
1521 /* Define global constructors/destructor functions for the CDTORS, of
1522    which they are LEN.  The CDTORS are sorted by initialization
1523    priority.  If CTOR_P is true, these are constructors; otherwise,
1524    they are destructors.  */
1525
1526 static void
1527 build_cdtor (bool ctor_p, VEC (tree, heap) *cdtors)
1528 {
1529   size_t i,j;
1530   size_t len = VEC_length (tree, cdtors);
1531
1532   i = 0;
1533   while (i < len)
1534     {
1535       tree body;
1536       tree fn;
1537       priority_type priority;
1538
1539       priority = 0;
1540       body = NULL_TREE;
1541       j = i;
1542       do
1543         {
1544           priority_type p;
1545           fn = VEC_index (tree, cdtors, j);
1546           p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
1547           if (j == i)
1548             priority = p;
1549           else if (p != priority)
1550             break;
1551           j++;
1552         }
1553       while (j < len);
1554
1555       /* When there is only one cdtor and target supports them, do nothing.  */
1556       if (j == i + 1
1557           && targetm.have_ctors_dtors)
1558         {
1559           i++;
1560           continue;
1561         }
1562       /* Find the next batch of constructors/destructors with the same
1563          initialization priority.  */
1564       for (;i < j; i++)
1565         {
1566           tree call;
1567           fn = VEC_index (tree, cdtors, i);
1568           call = build_call_expr (fn, 0);
1569           if (ctor_p)
1570             DECL_STATIC_CONSTRUCTOR (fn) = 0;
1571           else
1572             DECL_STATIC_DESTRUCTOR (fn) = 0;
1573           /* We do not want to optimize away pure/const calls here.
1574              When optimizing, these should be already removed, when not
1575              optimizing, we want user to be able to breakpoint in them.  */
1576           TREE_SIDE_EFFECTS (call) = 1;
1577           append_to_statement_list (call, &body);
1578         }
1579       gcc_assert (body != NULL_TREE);
1580       /* Generate a function to call all the function of like
1581          priority.  */
1582       cgraph_build_static_cdtor (ctor_p ? 'I' : 'D', body, priority);
1583     }
1584 }
1585
1586 /* Comparison function for qsort.  P1 and P2 are actually of type
1587    "tree *" and point to static constructors.  DECL_INIT_PRIORITY is
1588    used to determine the sort order.  */
1589
1590 static int
1591 compare_ctor (const void *p1, const void *p2)
1592 {
1593   tree f1;
1594   tree f2;
1595   int priority1;
1596   int priority2;
1597
1598   f1 = *(const tree *)p1;
1599   f2 = *(const tree *)p2;
1600   priority1 = DECL_INIT_PRIORITY (f1);
1601   priority2 = DECL_INIT_PRIORITY (f2);
1602
1603   if (priority1 < priority2)
1604     return -1;
1605   else if (priority1 > priority2)
1606     return 1;
1607   else
1608     /* Ensure a stable sort.  Constructors are executed in backwarding
1609        order to make LTO initialize braries first.  */
1610     return DECL_UID (f2) - DECL_UID (f1);
1611 }
1612
1613 /* Comparison function for qsort.  P1 and P2 are actually of type
1614    "tree *" and point to static destructors.  DECL_FINI_PRIORITY is
1615    used to determine the sort order.  */
1616
1617 static int
1618 compare_dtor (const void *p1, const void *p2)
1619 {
1620   tree f1;
1621   tree f2;
1622   int priority1;
1623   int priority2;
1624
1625   f1 = *(const tree *)p1;
1626   f2 = *(const tree *)p2;
1627   priority1 = DECL_FINI_PRIORITY (f1);
1628   priority2 = DECL_FINI_PRIORITY (f2);
1629
1630   if (priority1 < priority2)
1631     return -1;
1632   else if (priority1 > priority2)
1633     return 1;
1634   else
1635     /* Ensure a stable sort.  */
1636     return DECL_UID (f1) - DECL_UID (f2);
1637 }
1638
1639 /* Generate functions to call static constructors and destructors
1640    for targets that do not support .ctors/.dtors sections.  These
1641    functions have magic names which are detected by collect2.  */
1642
1643 static void
1644 build_cdtor_fns (void)
1645 {
1646   if (!VEC_empty (tree, static_ctors))
1647     {
1648       gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1649       VEC_qsort (tree, static_ctors, compare_ctor);
1650       build_cdtor (/*ctor_p=*/true, static_ctors);
1651     }
1652
1653   if (!VEC_empty (tree, static_dtors))
1654     {
1655       gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1656       VEC_qsort (tree, static_dtors, compare_dtor);
1657       build_cdtor (/*ctor_p=*/false, static_dtors);
1658     }
1659 }
1660
1661 /* Look for constructors and destructors and produce function calling them.
1662    This is needed for targets not supporting ctors or dtors, but we perform the
1663    transformation also at linktime to merge possibly numberous
1664    constructors/destructors into single function to improve code locality and
1665    reduce size.  */
1666
1667 static unsigned int
1668 ipa_cdtor_merge (void)
1669 {
1670   struct cgraph_node *node;
1671   for (node = cgraph_nodes; node; node = node->next)
1672     if (node->analyzed
1673         && (DECL_STATIC_CONSTRUCTOR (node->decl)
1674             || DECL_STATIC_DESTRUCTOR (node->decl)))
1675        record_cdtor_fn (node);
1676   build_cdtor_fns ();
1677   VEC_free (tree, heap, static_ctors);
1678   VEC_free (tree, heap, static_dtors);
1679   return 0;
1680 }
1681
1682 /* Perform the pass when we have no ctors/dtors support
1683    or at LTO time to merge multiple constructors into single
1684    function.  */
1685
1686 static bool
1687 gate_ipa_cdtor_merge (void)
1688 {
1689   return !targetm.have_ctors_dtors || (optimize && in_lto_p);
1690 }
1691
1692 struct ipa_opt_pass_d pass_ipa_cdtor_merge =
1693 {
1694  {
1695   IPA_PASS,
1696   "cdtor",                              /* name */
1697   gate_ipa_cdtor_merge,                 /* gate */
1698   ipa_cdtor_merge,                      /* execute */
1699   NULL,                                 /* sub */
1700   NULL,                                 /* next */
1701   0,                                    /* static_pass_number */
1702   TV_CGRAPHOPT,                         /* tv_id */
1703   0,                                    /* properties_required */
1704   0,                                    /* properties_provided */
1705   0,                                    /* properties_destroyed */
1706   0,                                    /* todo_flags_start */
1707   0                                     /* todo_flags_finish */
1708  },
1709  NULL,                                  /* generate_summary */
1710  NULL,                                  /* write_summary */
1711  NULL,                                  /* read_summary */
1712  NULL,                                  /* write_optimization_summary */
1713  NULL,                                  /* read_optimization_summary */
1714  NULL,                                  /* stmt_fixup */
1715  0,                                     /* TODOs */
1716  NULL,                                  /* function_transform */
1717  NULL                                   /* variable_transform */
1718 };