OSDN Git Service

2009-12-15 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 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       gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
374                   || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
375       if (cgraph_externally_visible_p (node, whole_program))
376         {
377           gcc_assert (!node->global.inlined_to);
378           node->local.externally_visible = true;
379         }
380       else
381         node->local.externally_visible = false;
382       if (!node->local.externally_visible && node->analyzed
383           && !DECL_EXTERNAL (node->decl))
384         {
385           gcc_assert (whole_program || !TREE_PUBLIC (node->decl));
386           TREE_PUBLIC (node->decl) = 0;
387           DECL_COMDAT (node->decl) = 0;
388           DECL_WEAK (node->decl) = 0;
389         }
390       node->local.local = (cgraph_only_called_directly_p (node)
391                            && node->analyzed
392                            && !DECL_EXTERNAL (node->decl)
393                            && !node->local.externally_visible);
394     }
395   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
396     {
397       if (!vnode->finalized)
398         continue;
399       gcc_assert ((!DECL_WEAK (vnode->decl) && !DECL_COMMON (vnode->decl))
400                   || TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl));
401       if (vnode->needed
402           && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))
403           && (!whole_program
404               /* We can privatize comdat readonly variables whose address is not taken,
405                  but doing so is not going to bring us optimization oppurtunities until
406                  we start reordering datastructures.  */
407               || DECL_COMDAT (vnode->decl)
408               || DECL_WEAK (vnode->decl)
409               || lookup_attribute ("externally_visible",
410                                    DECL_ATTRIBUTES (vnode->decl))))
411         vnode->externally_visible = true;
412       else
413         vnode->externally_visible = false;
414       if (!vnode->externally_visible)
415         {
416           gcc_assert (whole_program || !TREE_PUBLIC (vnode->decl));
417           TREE_PUBLIC (vnode->decl) = 0;
418           DECL_COMMON (vnode->decl) = 0;
419         }
420      gcc_assert (TREE_STATIC (vnode->decl));
421     }
422
423   if (dump_file)
424     {
425       fprintf (dump_file, "\nMarking local functions:");
426       for (node = cgraph_nodes; node; node = node->next)
427         if (node->local.local)
428           fprintf (dump_file, " %s", cgraph_node_name (node));
429       fprintf (dump_file, "\n\n");
430       fprintf (dump_file, "\nMarking externally visible functions:");
431       for (node = cgraph_nodes; node; node = node->next)
432         if (node->local.externally_visible)
433           fprintf (dump_file, " %s", cgraph_node_name (node));
434       fprintf (dump_file, "\n\n");
435       fprintf (dump_file, "\nMarking externally visible variables:");
436       for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
437         if (vnode->externally_visible)
438           fprintf (dump_file, " %s", varpool_node_name (vnode));
439       fprintf (dump_file, "\n\n");
440     }
441   cgraph_function_flags_ready = true;
442   return 0;
443 }
444
445 /* Local function pass handling visibilities.  This happens before LTO streaming
446    so in particular -fwhole-program should be ignored at this level.  */
447
448 static unsigned int
449 local_function_and_variable_visibility (void)
450 {
451   return function_and_variable_visibility (flag_whole_program && !flag_lto && !flag_whopr);
452 }
453
454 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
455 {
456  {
457   SIMPLE_IPA_PASS,
458   "visibility",                         /* name */
459   NULL,                                 /* gate */
460   local_function_and_variable_visibility,/* execute */
461   NULL,                                 /* sub */
462   NULL,                                 /* next */
463   0,                                    /* static_pass_number */
464   TV_CGRAPHOPT,                         /* tv_id */
465   0,                                    /* properties_required */
466   0,                                    /* properties_provided */
467   0,                                    /* properties_destroyed */
468   0,                                    /* todo_flags_start */
469   TODO_remove_functions | TODO_dump_cgraph/* todo_flags_finish */
470  }
471 };
472
473 /* Do not re-run on ltrans stage.  */
474
475 static bool
476 gate_whole_program_function_and_variable_visibility (void)
477 {
478   return !flag_ltrans;
479 }
480
481 /* Bring functionss local at LTO time whith -fwhole-program.  */
482
483 static unsigned int
484 whole_program_function_and_variable_visibility (void)
485 {
486   struct cgraph_node *node;
487   struct varpool_node *vnode;
488
489   function_and_variable_visibility (flag_whole_program);
490
491   for (node = cgraph_nodes; node; node = node->next)
492     if ((node->local.externally_visible && !DECL_COMDAT (node->decl))
493         && node->local.finalized)
494       cgraph_mark_needed_node (node);
495   for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
496     if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
497       varpool_mark_needed_node (vnode);
498   if (dump_file)
499     {
500       fprintf (dump_file, "\nNeeded variables:");
501       for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
502         if (vnode->needed)
503           fprintf (dump_file, " %s", varpool_node_name (vnode));
504       fprintf (dump_file, "\n\n");
505     }
506   return 0;
507 }
508
509 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
510 {
511  {
512   IPA_PASS,
513   "whole-program",                      /* name */
514   gate_whole_program_function_and_variable_visibility,/* gate */
515   whole_program_function_and_variable_visibility,/* execute */
516   NULL,                                 /* sub */
517   NULL,                                 /* next */
518   0,                                    /* static_pass_number */
519   TV_CGRAPHOPT,                         /* tv_id */
520   0,                                    /* properties_required */
521   0,                                    /* properties_provided */
522   0,                                    /* properties_destroyed */
523   0,                                    /* todo_flags_start */
524   TODO_dump_cgraph | TODO_remove_functions/* todo_flags_finish */
525  },
526  NULL,                                  /* generate_summary */
527  NULL,                                  /* write_summary */
528  NULL,                                  /* read_summary */
529  NULL,                                  /* function_read_summary */
530  NULL,                                  /* stmt_fixup */
531  0,                                     /* TODOs */
532  NULL,                                  /* function_transform */
533  NULL,                                  /* variable_transform */
534 };
535
536 /* Hash a cgraph node set element.  */
537
538 static hashval_t
539 hash_cgraph_node_set_element (const void *p)
540 {
541   const_cgraph_node_set_element element = (const_cgraph_node_set_element) p;
542   return htab_hash_pointer (element->node);
543 }
544
545 /* Compare two cgraph node set elements.  */
546
547 static int
548 eq_cgraph_node_set_element (const void *p1, const void *p2)
549 {
550   const_cgraph_node_set_element e1 = (const_cgraph_node_set_element) p1;
551   const_cgraph_node_set_element e2 = (const_cgraph_node_set_element) p2;
552
553   return e1->node == e2->node;
554 }
555
556 /* Create a new cgraph node set.  */
557
558 cgraph_node_set
559 cgraph_node_set_new (void)
560 {
561   cgraph_node_set new_node_set;
562
563   new_node_set = GGC_NEW (struct cgraph_node_set_def);
564   new_node_set->hashtab = htab_create_ggc (10,
565                                            hash_cgraph_node_set_element,
566                                            eq_cgraph_node_set_element,
567                                            NULL);
568   new_node_set->nodes = NULL;
569   return new_node_set;
570 }
571
572 /* Add cgraph_node NODE to cgraph_node_set SET.  */
573
574 void
575 cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
576 {
577   void **slot;
578   cgraph_node_set_element element;
579   struct cgraph_node_set_element_def dummy;
580
581   dummy.node = node;
582   slot = htab_find_slot (set->hashtab, &dummy, INSERT);
583
584   if (*slot != HTAB_EMPTY_ENTRY)
585     {
586       element = (cgraph_node_set_element) *slot;
587       gcc_assert (node == element->node
588                   && (VEC_index (cgraph_node_ptr, set->nodes, element->index)
589                       == node));
590       return;
591     }
592
593   /* Insert node into hash table.  */
594   element =
595     (cgraph_node_set_element) GGC_NEW (struct cgraph_node_set_element_def);
596   element->node = node;
597   element->index = VEC_length (cgraph_node_ptr, set->nodes);
598   *slot = element;
599
600   /* Insert into node vector.  */
601   VEC_safe_push (cgraph_node_ptr, gc, set->nodes, node);
602 }
603
604 /* Remove cgraph_node NODE from cgraph_node_set SET.  */
605
606 void
607 cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
608 {
609   void **slot, **last_slot;
610   cgraph_node_set_element element, last_element;
611   struct cgraph_node *last_node;
612   struct cgraph_node_set_element_def dummy;
613
614   dummy.node = node;
615   slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
616   if (slot == NULL)
617     return;
618
619   element = (cgraph_node_set_element) *slot;
620   gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
621               == node);
622
623   /* Remove from vector. We do this by swapping node with the last element
624      of the vector.  */
625   last_node = VEC_pop (cgraph_node_ptr, set->nodes);
626   if (last_node != node)
627     {
628       dummy.node = last_node;
629       last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
630       last_element = (cgraph_node_set_element) *last_slot;
631       gcc_assert (last_element);
632
633       /* Move the last element to the original spot of NODE.  */
634       last_element->index = element->index;
635       VEC_replace (cgraph_node_ptr, set->nodes, last_element->index,
636                    last_node);
637     }
638
639   /* Remove element from hash table.  */
640   htab_clear_slot (set->hashtab, slot);
641   ggc_free (element);
642 }
643
644 /* Find NODE in SET and return an iterator to it if found.  A null iterator
645    is returned if NODE is not in SET.  */
646
647 cgraph_node_set_iterator
648 cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
649 {
650   void **slot;
651   struct cgraph_node_set_element_def dummy;
652   cgraph_node_set_element element;
653   cgraph_node_set_iterator csi;
654
655   dummy.node = node;
656   slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
657   if (slot == NULL)
658     csi.index = (unsigned) ~0;
659   else
660     {
661       element = (cgraph_node_set_element) *slot;
662       gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
663                   == node);
664       csi.index = element->index;
665     }
666   csi.set = set;
667
668   return csi;
669 }
670
671 /* Dump content of SET to file F.  */
672
673 void
674 dump_cgraph_node_set (FILE *f, cgraph_node_set set)
675 {
676   cgraph_node_set_iterator iter;
677
678   for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
679     {
680       struct cgraph_node *node = csi_node (iter);
681       dump_cgraph_node (f, node);
682     }
683 }
684
685 /* Dump content of SET to stderr.  */
686
687 void
688 debug_cgraph_node_set (cgraph_node_set set)
689 {
690   dump_cgraph_node_set (stderr, set);
691 }
692