OSDN Git Service

PR middle-end/42068
[pf3gnuchains/gcc-fork.git] / gcc / ipa.c
1 /* Basic IPA optimizations and utilities.
2    Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
3    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
31 /* Fill array order with all nodes with output flag set in the reverse
32    topological order.  */
33
34 int
35 cgraph_postorder (struct cgraph_node **order)
36 {
37   struct cgraph_node *node, *node2;
38   int stack_size = 0;
39   int order_pos = 0;
40   struct cgraph_edge *edge, last;
41   int pass;
42
43   struct cgraph_node **stack =
44     XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
45
46   /* We have to deal with cycles nicely, so use a depth first traversal
47      output algorithm.  Ignore the fact that some functions won't need
48      to be output and put them into order as well, so we get dependencies
49      right through inline functions.  */
50   for (node = cgraph_nodes; node; node = node->next)
51     node->aux = NULL;
52   for (pass = 0; pass < 2; pass++)
53     for (node = cgraph_nodes; node; node = node->next)
54       if (!node->aux
55           && (pass
56               || (!cgraph_only_called_directly_p (node)
57                   && !node->address_taken)))
58         {
59           node2 = node;
60           if (!node->callers)
61             node->aux = &last;
62           else
63             node->aux = node->callers;
64           while (node2)
65             {
66               while (node2->aux != &last)
67                 {
68                   edge = (struct cgraph_edge *) node2->aux;
69                   if (edge->next_caller)
70                     node2->aux = edge->next_caller;
71                   else
72                     node2->aux = &last;
73                   if (!edge->caller->aux)
74                     {
75                       if (!edge->caller->callers)
76                         edge->caller->aux = &last;
77                       else
78                         edge->caller->aux = edge->caller->callers;
79                       stack[stack_size++] = node2;
80                       node2 = edge->caller;
81                       break;
82                     }
83                 }
84               if (node2->aux == &last)
85                 {
86                   order[order_pos++] = node2;
87                   if (stack_size)
88                     node2 = stack[--stack_size];
89                   else
90                     node2 = NULL;
91                 }
92             }
93         }
94   free (stack);
95   for (node = cgraph_nodes; node; node = node->next)
96     node->aux = NULL;
97   return order_pos;
98 }
99
100 /* Look for all functions inlined to NODE and update their inlined_to pointers
101    to INLINED_TO.  */
102
103 static void
104 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
105 {
106   struct cgraph_edge *e;
107   for (e = node->callees; e; e = e->next_callee)
108     if (e->callee->global.inlined_to)
109       {
110         e->callee->global.inlined_to = inlined_to;
111         update_inlined_to_pointer (e->callee, inlined_to);
112       }
113 }
114
115 /* Perform reachability analysis and reclaim all unreachable nodes.
116    If BEFORE_INLINING_P is true this function is called before inlining
117    decisions has been made.  If BEFORE_INLINING_P is false this function also
118    removes unneeded bodies of extern inline functions.  */
119
120 bool
121 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
122 {
123   struct cgraph_node *first = (struct cgraph_node *) (void *) 1;
124   struct cgraph_node *processed = (struct cgraph_node *) (void *) 2;
125   struct cgraph_node *node, *next;
126   bool changed = false;
127
128 #ifdef ENABLE_CHECKING
129   verify_cgraph ();
130 #endif
131   if (file)
132     fprintf (file, "\nReclaiming functions:");
133 #ifdef ENABLE_CHECKING
134   for (node = cgraph_nodes; node; node = node->next)
135     gcc_assert (!node->aux);
136 #endif
137   for (node = cgraph_nodes; node; node = node->next)
138     if (!cgraph_can_remove_if_no_direct_calls_p (node)
139         && ((!DECL_EXTERNAL (node->decl))
140             || !node->analyzed
141             || before_inlining_p))
142       {
143         gcc_assert (!node->global.inlined_to);
144         node->aux = first;
145         first = node;
146         node->reachable = true;
147       }
148     else
149       {
150         gcc_assert (!node->aux);
151         node->reachable = false;
152       }
153
154   /* Perform reachability analysis.  As a special case do not consider
155      extern inline functions not inlined as live because we won't output
156      them at all.  */
157   while (first != (void *) 1)
158     {
159       struct cgraph_edge *e;
160       node = first;
161       first = (struct cgraph_node *) first->aux;
162       node->aux = processed;
163
164       if (node->reachable)
165         for (e = node->callees; e; e = e->next_callee)
166           if (!e->callee->reachable
167               && node->analyzed
168               && (!e->inline_failed || !e->callee->analyzed
169                   || (!DECL_EXTERNAL (e->callee->decl))
170                   || before_inlining_p))
171             {
172               bool prev_reachable = e->callee->reachable;
173               e->callee->reachable |= node->reachable;
174               if (!e->callee->aux
175                   || (e->callee->aux == processed
176                       && prev_reachable != e->callee->reachable))
177                 {
178                   e->callee->aux = first;
179                   first = e->callee;
180                 }
181             }
182
183       /* If any function in a comdat group is reachable, force
184          all other functions in the same comdat group to be
185          also reachable.  */
186       if (node->same_comdat_group
187           && node->reachable
188           && !node->global.inlined_to)
189         {
190           for (next = node->same_comdat_group;
191                next != node;
192                next = next->same_comdat_group)
193             if (!next->reachable)
194               {
195                 next->aux = first;
196                 first = next;
197                 next->reachable = true;
198               }
199         }
200
201       /* We can freely remove inline clones even if they are cloned, however if
202          function is clone of real clone, we must keep it around in order to
203          make materialize_clones produce function body with the changes
204          applied.  */
205       while (node->clone_of && !node->clone_of->aux && !gimple_has_body_p (node->decl))
206         {
207           bool noninline = node->clone_of->decl != node->decl;
208           node = node->clone_of;
209           if (noninline)
210             {
211               node->aux = first;
212               first = node;
213               break;
214             }
215         }
216     }
217
218   /* Remove unreachable nodes.  Extern inline functions need special care;
219      Unreachable extern inline functions shall be removed.
220      Reachable extern inline functions we never inlined shall get their bodies
221      eliminated.
222      Reachable extern inline functions we sometimes inlined will be turned into
223      unanalyzed nodes so they look like for true extern functions to the rest
224      of code.  Body of such functions is released via remove_node once the
225      inline clones are eliminated.  */
226   for (node = cgraph_nodes; node; node = next)
227     {
228       next = node->next;
229       if (node->aux && !node->reachable)
230         {
231           cgraph_node_remove_callees (node);
232           node->analyzed = false;
233           node->local.inlinable = false;
234         }
235       if (!node->aux)
236         {
237           node->global.inlined_to = NULL;
238           if (file)
239             fprintf (file, " %s", cgraph_node_name (node));
240           if (!node->analyzed || !DECL_EXTERNAL (node->decl) || before_inlining_p)
241             cgraph_remove_node (node);
242           else
243             {
244               struct cgraph_edge *e;
245
246               /* See if there is reachable caller.  */
247               for (e = node->callers; e; e = e->next_caller)
248                 if (e->caller->aux)
249                   break;
250
251               /* If so, we need to keep node in the callgraph.  */
252               if (e || node->needed)
253                 {
254                   struct cgraph_node *clone;
255
256                   /* If there are still clones, we must keep body around.
257                      Otherwise we can just remove the body but keep the clone.  */
258                   for (clone = node->clones; clone;
259                        clone = clone->next_sibling_clone)
260                     if (clone->aux)
261                       break;
262                   if (!clone)
263                     {
264                       cgraph_release_function_body (node);
265                       cgraph_node_remove_callees (node);
266                       node->analyzed = false;
267                       node->local.inlinable = false;
268                     }
269                   if (node->prev_sibling_clone)
270                     node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
271                   else if (node->clone_of)
272                     node->clone_of->clones = node->next_sibling_clone;
273                   if (node->next_sibling_clone)
274                     node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
275                   node->clone_of = NULL;
276                   node->next_sibling_clone = NULL;
277                   node->prev_sibling_clone = NULL;
278                 }
279               else
280                 cgraph_remove_node (node);
281             }
282           changed = true;
283         }
284     }
285   for (node = cgraph_nodes; node; node = node->next)
286     {
287       /* Inline clones might be kept around so their materializing allows further
288          cloning.  If the function the clone is inlined into is removed, we need
289          to turn it into normal cone.  */
290       if (node->global.inlined_to
291           && !node->callers)
292         {
293           gcc_assert (node->clones);
294           node->global.inlined_to = NULL;
295           update_inlined_to_pointer (node, node);
296         }
297       node->aux = NULL;
298     }
299 #ifdef ENABLE_CHECKING
300   verify_cgraph ();
301 #endif
302
303   /* Reclaim alias pairs for functions that have disappeared from the
304      call graph.  */
305   remove_unreachable_alias_pairs ();
306
307   return changed;
308 }
309
310 static bool
311 cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program)
312 {
313   if (!node->local.finalized)
314     return false;
315   if (!DECL_COMDAT (node->decl)
316       && (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)))
317     return false;
318   if (!whole_program)
319     return true;
320   /* COMDAT functions must be shared only if they have address taken,
321      otherwise we can produce our own private implementation with
322      -fwhole-program.  */
323   if (DECL_COMDAT (node->decl))
324     {
325       if (node->address_taken || !node->analyzed)
326         return true;
327       if (node->same_comdat_group)
328         {
329           struct cgraph_node *next;
330
331           /* If more than one function is in the same COMDAT group, it must
332              be shared even if just one function in the comdat group has
333              address taken.  */
334           for (next = node->same_comdat_group;
335                next != node;
336                next = next->same_comdat_group)
337             if (next->address_taken || !next->analyzed)
338               return true;
339         }
340     }
341   if (MAIN_NAME_P (DECL_NAME (node->decl)))
342     return true;
343   if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
344     return true;
345   return false;
346 }
347
348 /* Mark visibility of all functions.
349
350    A local function is one whose calls can occur only in the current
351    compilation unit and all its calls are explicit, so we can change
352    its calling convention.  We simply mark all static functions whose
353    address is not taken as local.
354
355    We also change the TREE_PUBLIC flag of all declarations that are public
356    in language point of view but we want to overwrite this default
357    via visibilities for the backend point of view.  */
358
359 static unsigned int
360 function_and_variable_visibility (bool whole_program)
361 {
362   struct cgraph_node *node;
363   struct varpool_node *vnode;
364
365   for (node = cgraph_nodes; node; node = node->next)
366     {
367       /* C++ FE on lack of COMDAT support create local COMDAT functions
368          (that ought to be shared but can not due to object format
369          limitations).  It is neccesary to keep the flag to make rest of C++ FE
370          happy.  Clear the flag here to avoid confusion in middle-end.  */
371       if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
372         DECL_COMDAT (node->decl) = 0;
373       /* For external decls stop tracking same_comdat_group, it doesn't matter
374          what comdat group they are in when they won't be emitted in this TU,
375          and simplifies later passes.  */
376       if (node->same_comdat_group && DECL_EXTERNAL (node->decl))
377         {
378           struct cgraph_node *n = node, *next;
379           do
380             {
381               /* If at least one of same comdat group functions is external,
382                  all of them have to be, otherwise it is a front-end bug.  */
383               gcc_assert (DECL_EXTERNAL (n->decl));
384               next = n->same_comdat_group;
385               n->same_comdat_group = NULL;
386               n = next;
387             }
388           while (n != node);
389         }
390       gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
391                   || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
392       if (cgraph_externally_visible_p (node, whole_program))
393         {
394           gcc_assert (!node->global.inlined_to);
395           node->local.externally_visible = true;
396         }
397       else
398         node->local.externally_visible = false;
399       if (!node->local.externally_visible && node->analyzed
400           && !DECL_EXTERNAL (node->decl))
401         {
402           gcc_assert (whole_program || !TREE_PUBLIC (node->decl));
403           TREE_PUBLIC (node->decl) = 0;
404           DECL_COMDAT (node->decl) = 0;
405           DECL_WEAK (node->decl) = 0;
406         }
407       node->local.local = (cgraph_only_called_directly_p (node)
408                            && node->analyzed
409                            && !DECL_EXTERNAL (node->decl)
410                            && !node->local.externally_visible);
411     }
412   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
413     {
414       if (!vnode->finalized)
415         continue;
416       gcc_assert ((!DECL_WEAK (vnode->decl) && !DECL_COMMON (vnode->decl))
417                   || TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl));
418       if (vnode->needed
419           && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))
420           && (!whole_program
421               /* We can privatize comdat readonly variables whose address is not taken,
422                  but doing so is not going to bring us optimization oppurtunities until
423                  we start reordering datastructures.  */
424               || DECL_COMDAT (vnode->decl)
425               || DECL_WEAK (vnode->decl)
426               || lookup_attribute ("externally_visible",
427                                    DECL_ATTRIBUTES (vnode->decl))))
428         vnode->externally_visible = true;
429       else
430         vnode->externally_visible = false;
431       if (!vnode->externally_visible)
432         {
433           gcc_assert (whole_program || !TREE_PUBLIC (vnode->decl));
434           TREE_PUBLIC (vnode->decl) = 0;
435           DECL_COMMON (vnode->decl) = 0;
436         }
437      gcc_assert (TREE_STATIC (vnode->decl));
438     }
439
440   if (dump_file)
441     {
442       fprintf (dump_file, "\nMarking local functions:");
443       for (node = cgraph_nodes; node; node = node->next)
444         if (node->local.local)
445           fprintf (dump_file, " %s", cgraph_node_name (node));
446       fprintf (dump_file, "\n\n");
447       fprintf (dump_file, "\nMarking externally visible functions:");
448       for (node = cgraph_nodes; node; node = node->next)
449         if (node->local.externally_visible)
450           fprintf (dump_file, " %s", cgraph_node_name (node));
451       fprintf (dump_file, "\n\n");
452       fprintf (dump_file, "\nMarking externally visible variables:");
453       for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
454         if (vnode->externally_visible)
455           fprintf (dump_file, " %s", varpool_node_name (vnode));
456       fprintf (dump_file, "\n\n");
457     }
458   cgraph_function_flags_ready = true;
459   return 0;
460 }
461
462 /* Local function pass handling visibilities.  This happens before LTO streaming
463    so in particular -fwhole-program should be ignored at this level.  */
464
465 static unsigned int
466 local_function_and_variable_visibility (void)
467 {
468   return function_and_variable_visibility (flag_whole_program && !flag_lto && !flag_whopr);
469 }
470
471 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
472 {
473  {
474   SIMPLE_IPA_PASS,
475   "visibility",                         /* name */
476   NULL,                                 /* gate */
477   local_function_and_variable_visibility,/* execute */
478   NULL,                                 /* sub */
479   NULL,                                 /* next */
480   0,                                    /* static_pass_number */
481   TV_CGRAPHOPT,                         /* tv_id */
482   0,                                    /* properties_required */
483   0,                                    /* properties_provided */
484   0,                                    /* properties_destroyed */
485   0,                                    /* todo_flags_start */
486   TODO_remove_functions | TODO_dump_cgraph/* todo_flags_finish */
487  }
488 };
489
490 /* Do not re-run on ltrans stage.  */
491
492 static bool
493 gate_whole_program_function_and_variable_visibility (void)
494 {
495   return !flag_ltrans;
496 }
497
498 /* Bring functionss local at LTO time whith -fwhole-program.  */
499
500 static unsigned int
501 whole_program_function_and_variable_visibility (void)
502 {
503   struct cgraph_node *node;
504   struct varpool_node *vnode;
505
506   function_and_variable_visibility (flag_whole_program);
507
508   for (node = cgraph_nodes; node; node = node->next)
509     if ((node->local.externally_visible && !DECL_COMDAT (node->decl))
510         && node->local.finalized)
511       cgraph_mark_needed_node (node);
512   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
513     if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
514       varpool_mark_needed_node (vnode);
515   if (dump_file)
516     {
517       fprintf (dump_file, "\nNeeded variables:");
518       for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
519         if (vnode->needed)
520           fprintf (dump_file, " %s", varpool_node_name (vnode));
521       fprintf (dump_file, "\n\n");
522     }
523   return 0;
524 }
525
526 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
527 {
528  {
529   IPA_PASS,
530   "whole-program",                      /* name */
531   gate_whole_program_function_and_variable_visibility,/* gate */
532   whole_program_function_and_variable_visibility,/* execute */
533   NULL,                                 /* sub */
534   NULL,                                 /* next */
535   0,                                    /* static_pass_number */
536   TV_CGRAPHOPT,                         /* tv_id */
537   0,                                    /* properties_required */
538   0,                                    /* properties_provided */
539   0,                                    /* properties_destroyed */
540   0,                                    /* todo_flags_start */
541   TODO_dump_cgraph | TODO_remove_functions/* todo_flags_finish */
542  },
543  NULL,                                  /* generate_summary */
544  NULL,                                  /* write_summary */
545  NULL,                                  /* read_summary */
546  NULL,                                  /* function_read_summary */
547  NULL,                                  /* stmt_fixup */
548  0,                                     /* TODOs */
549  NULL,                                  /* function_transform */
550  NULL,                                  /* variable_transform */
551 };
552
553 /* Hash a cgraph node set element.  */
554
555 static hashval_t
556 hash_cgraph_node_set_element (const void *p)
557 {
558   const_cgraph_node_set_element element = (const_cgraph_node_set_element) p;
559   return htab_hash_pointer (element->node);
560 }
561
562 /* Compare two cgraph node set elements.  */
563
564 static int
565 eq_cgraph_node_set_element (const void *p1, const void *p2)
566 {
567   const_cgraph_node_set_element e1 = (const_cgraph_node_set_element) p1;
568   const_cgraph_node_set_element e2 = (const_cgraph_node_set_element) p2;
569
570   return e1->node == e2->node;
571 }
572
573 /* Create a new cgraph node set.  */
574
575 cgraph_node_set
576 cgraph_node_set_new (void)
577 {
578   cgraph_node_set new_node_set;
579
580   new_node_set = GGC_NEW (struct cgraph_node_set_def);
581   new_node_set->hashtab = htab_create_ggc (10,
582                                            hash_cgraph_node_set_element,
583                                            eq_cgraph_node_set_element,
584                                            NULL);
585   new_node_set->nodes = NULL;
586   return new_node_set;
587 }
588
589 /* Add cgraph_node NODE to cgraph_node_set SET.  */
590
591 void
592 cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
593 {
594   void **slot;
595   cgraph_node_set_element element;
596   struct cgraph_node_set_element_def dummy;
597
598   dummy.node = node;
599   slot = htab_find_slot (set->hashtab, &dummy, INSERT);
600
601   if (*slot != HTAB_EMPTY_ENTRY)
602     {
603       element = (cgraph_node_set_element) *slot;
604       gcc_assert (node == element->node
605                   && (VEC_index (cgraph_node_ptr, set->nodes, element->index)
606                       == node));
607       return;
608     }
609
610   /* Insert node into hash table.  */
611   element =
612     (cgraph_node_set_element) GGC_NEW (struct cgraph_node_set_element_def);
613   element->node = node;
614   element->index = VEC_length (cgraph_node_ptr, set->nodes);
615   *slot = element;
616
617   /* Insert into node vector.  */
618   VEC_safe_push (cgraph_node_ptr, gc, set->nodes, node);
619 }
620
621 /* Remove cgraph_node NODE from cgraph_node_set SET.  */
622
623 void
624 cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
625 {
626   void **slot, **last_slot;
627   cgraph_node_set_element element, last_element;
628   struct cgraph_node *last_node;
629   struct cgraph_node_set_element_def dummy;
630
631   dummy.node = node;
632   slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
633   if (slot == NULL)
634     return;
635
636   element = (cgraph_node_set_element) *slot;
637   gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
638               == node);
639
640   /* Remove from vector. We do this by swapping node with the last element
641      of the vector.  */
642   last_node = VEC_pop (cgraph_node_ptr, set->nodes);
643   if (last_node != node)
644     {
645       dummy.node = last_node;
646       last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
647       last_element = (cgraph_node_set_element) *last_slot;
648       gcc_assert (last_element);
649
650       /* Move the last element to the original spot of NODE.  */
651       last_element->index = element->index;
652       VEC_replace (cgraph_node_ptr, set->nodes, last_element->index,
653                    last_node);
654     }
655
656   /* Remove element from hash table.  */
657   htab_clear_slot (set->hashtab, slot);
658   ggc_free (element);
659 }
660
661 /* Find NODE in SET and return an iterator to it if found.  A null iterator
662    is returned if NODE is not in SET.  */
663
664 cgraph_node_set_iterator
665 cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
666 {
667   void **slot;
668   struct cgraph_node_set_element_def dummy;
669   cgraph_node_set_element element;
670   cgraph_node_set_iterator csi;
671
672   dummy.node = node;
673   slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
674   if (slot == NULL)
675     csi.index = (unsigned) ~0;
676   else
677     {
678       element = (cgraph_node_set_element) *slot;
679       gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
680                   == node);
681       csi.index = element->index;
682     }
683   csi.set = set;
684
685   return csi;
686 }
687
688 /* Dump content of SET to file F.  */
689
690 void
691 dump_cgraph_node_set (FILE *f, cgraph_node_set set)
692 {
693   cgraph_node_set_iterator iter;
694
695   for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
696     {
697       struct cgraph_node *node = csi_node (iter);
698       dump_cgraph_node (f, node);
699     }
700 }
701
702 /* Dump content of SET to stderr.  */
703
704 void
705 debug_cgraph_node_set (cgraph_node_set set)
706 {
707   dump_cgraph_node_set (stderr, set);
708 }
709