OSDN Git Service

* cgraph.c (cgraph_create_edge, cgraph_set_call_stmt): Set proper cfun.
[pf3gnuchains/gcc-fork.git] / gcc / ipa-pure-const.c
1 /* Callgraph based analysis of static variables.
2    Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
3    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
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 /* This file marks functions as being either const (TREE_READONLY) or
22    pure (DECL_PURE_P).  It can also set a variant of these that
23    are allowed to loop indefinitely (DECL_LOOPING_CONST_PURE_P).
24
25    This must be run after inlining decisions have been made since
26    otherwise, the local sets will not contain information that is
27    consistent with post inlined state.  The global sets are not prone
28    to this problem since they are by definition transitive.  */
29
30 /* The code in this module is called by the ipa pass manager. It
31    should be one of the later passes since it's information is used by
32    the rest of the compilation. */
33
34 #include "config.h"
35 #include "system.h"
36 #include "coretypes.h"
37 #include "tm.h"
38 #include "tree.h"
39 #include "tree-flow.h"
40 #include "tree-inline.h"
41 #include "tree-pass.h"
42 #include "langhooks.h"
43 #include "pointer-set.h"
44 #include "ggc.h"
45 #include "ipa-utils.h"
46 #include "c-common.h"
47 #include "gimple.h"
48 #include "cgraph.h"
49 #include "output.h"
50 #include "flags.h"
51 #include "timevar.h"
52 #include "diagnostic.h"
53 #include "langhooks.h"
54 #include "target.h"
55
56 static struct pointer_set_t *visited_nodes;
57
58 /* Lattice values for const and pure functions.  Everything starts out
59    being const, then may drop to pure and then neither depending on
60    what is found.  */
61 enum pure_const_state_e
62 {
63   IPA_CONST,
64   IPA_PURE,
65   IPA_NEITHER
66 };
67
68 /* Holder for the const_state.  There is one of these per function
69    decl.  */
70 struct funct_state_d 
71 {
72   /* See above.  */
73   enum pure_const_state_e pure_const_state;
74   /* What user set here; we can be always sure about this.  */
75   enum pure_const_state_e state_set_in_source; 
76
77   /* True if the function could possibly infinite loop.  There are a
78      lot of ways that this could be determined.  We are pretty
79      conservative here.  While it is possible to cse pure and const
80      calls, it is not legal to have dce get rid of the call if there
81      is a possibility that the call could infinite loop since this is
82      a behavioral change.  */
83   bool looping;
84
85   bool can_throw;
86 };
87
88 typedef struct funct_state_d * funct_state;
89
90 /* The storage of the funct_state is abstracted because there is the
91    possibility that it may be desirable to move this to the cgraph
92    local info.  */ 
93
94 /* Array, indexed by cgraph node uid, of function states.  */
95
96 DEF_VEC_P (funct_state);
97 DEF_VEC_ALLOC_P (funct_state, heap);
98 static VEC (funct_state, heap) *funct_state_vec;
99
100 /* Holders of ipa cgraph hooks: */
101 static struct cgraph_node_hook_list *function_insertion_hook_holder;
102 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
103 static struct cgraph_node_hook_list *node_removal_hook_holder;
104
105 /* Init the function state.  */
106
107 static void
108 finish_state (void)
109 {
110   free (funct_state_vec);
111 }
112
113
114 /* Return the function state from NODE.  */ 
115
116 static inline funct_state
117 get_function_state (struct cgraph_node *node)
118 {
119   if (!funct_state_vec
120       || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid)
121     return NULL;
122   return VEC_index (funct_state, funct_state_vec, node->uid);
123 }
124
125 /* Set the function state S for NODE.  */
126
127 static inline void
128 set_function_state (struct cgraph_node *node, funct_state s)
129 {
130   if (!funct_state_vec
131       || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid)
132      VEC_safe_grow_cleared (funct_state, heap, funct_state_vec, node->uid + 1);
133   VEC_replace (funct_state, funct_state_vec, node->uid, s);
134 }
135
136 /* Check to see if the use (or definition when CHECKING_WRITE is true)
137    variable T is legal in a function that is either pure or const.  */
138
139 static inline void 
140 check_decl (funct_state local, 
141             tree t, bool checking_write)
142 {
143   /* Do not want to do anything with volatile except mark any
144      function that uses one to be not const or pure.  */
145   if (TREE_THIS_VOLATILE (t)) 
146     { 
147       local->pure_const_state = IPA_NEITHER;
148       if (dump_file)
149         fprintf (dump_file, "    Volatile operand is not const/pure");
150       return;
151     }
152
153   /* Do not care about a local automatic that is not static.  */
154   if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
155     return;
156
157   /* If the variable has the "used" attribute, treat it as if it had a
158      been touched by the devil.  */
159   if (lookup_attribute ("used", DECL_ATTRIBUTES (t)))
160     {
161       local->pure_const_state = IPA_NEITHER;
162       if (dump_file)
163         fprintf (dump_file, "    Used static/global variable is not const/pure\n");
164       return;
165     }
166
167   /* Since we have dealt with the locals and params cases above, if we
168      are CHECKING_WRITE, this cannot be a pure or constant
169      function.  */
170   if (checking_write) 
171     {
172       local->pure_const_state = IPA_NEITHER;
173       if (dump_file)
174         fprintf (dump_file, "    static/global memory write is not const/pure\n");
175       return;
176     }
177
178   if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
179     {
180       /* Readonly reads are safe.  */
181       if (TREE_READONLY (t) && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t)))
182         return; /* Read of a constant, do not change the function state.  */
183       else 
184         {
185           if (dump_file)
186             fprintf (dump_file, "    global memory read is not const\n");
187           /* Just a regular read.  */
188           if (local->pure_const_state == IPA_CONST)
189             local->pure_const_state = IPA_PURE;
190         }
191     }
192   else
193     {
194       /* Compilation level statics can be read if they are readonly
195          variables.  */
196       if (TREE_READONLY (t))
197         return;
198
199       if (dump_file)
200         fprintf (dump_file, "    static memory read is not const\n");
201       /* Just a regular read.  */
202       if (local->pure_const_state == IPA_CONST)
203         local->pure_const_state = IPA_PURE;
204     }
205 }
206
207
208 /* Check to see if the use (or definition when CHECKING_WRITE is true)
209    variable T is legal in a function that is either pure or const.  */
210
211 static inline void 
212 check_op (funct_state local, tree t, bool checking_write)
213 {
214   if (TREE_THIS_VOLATILE (t))
215     {
216       local->pure_const_state = IPA_NEITHER;
217       if (dump_file)
218         fprintf (dump_file, "    Volatile indirect ref is not const/pure\n");
219       return;
220     }
221   else if (checking_write)
222     {
223       local->pure_const_state = IPA_NEITHER;
224       if (dump_file)
225         fprintf (dump_file, "    Indirect ref write is not const/pure\n");
226       return;
227     }
228   else
229     {
230       if (dump_file)
231         fprintf (dump_file, "    Indirect ref read is not const\n");
232       if (local->pure_const_state == IPA_CONST)
233         local->pure_const_state = IPA_PURE;
234     }
235 }
236
237 /* Check the parameters of a function call to CALL_EXPR to see if
238    there are any references in the parameters that are not allowed for
239    pure or const functions.  Also check to see if this is either an
240    indirect call, a call outside the compilation unit, or has special
241    attributes that may also effect the purity.  The CALL_EXPR node for
242    the entire call expression.  */
243
244 static void
245 check_call (funct_state local, gimple call, bool ipa)
246 {
247   int flags = gimple_call_flags (call);
248   tree callee_t = gimple_call_fndecl (call);
249   struct cgraph_node* callee;
250   enum availability avail = AVAIL_NOT_AVAILABLE;
251   bool possibly_throws = stmt_could_throw_p (call);
252   bool possibly_throws_externally = (possibly_throws
253                                      && stmt_can_throw_external (call));
254
255   if (possibly_throws)
256     {
257       unsigned int i;
258       for (i = 0; i < gimple_num_ops (call); i++)
259         if (gimple_op (call, i)
260             && tree_could_throw_p (gimple_op (call, i)))
261           {
262             if (possibly_throws && flag_non_call_exceptions)
263               {
264                 if (dump_file)
265                   fprintf (dump_file, "    operand can throw; looping\n");
266                 local->looping = true;
267               }
268             if (possibly_throws_externally)
269               {
270                 if (dump_file)
271                   fprintf (dump_file, "    operand can throw externally\n");
272                 local->can_throw = true;
273               }
274           }
275     }
276   
277   /* The const and pure flags are set by a variety of places in the
278      compiler (including here).  If someone has already set the flags
279      for the callee, (such as for some of the builtins) we will use
280      them, otherwise we will compute our own information. 
281   
282      Const and pure functions have less clobber effects than other
283      functions so we process these first.  Otherwise if it is a call
284      outside the compilation unit or an indirect call we punt.  This
285      leaves local calls which will be processed by following the call
286      graph.  */  
287   if (callee_t)
288     {
289       callee = cgraph_node(callee_t);
290       avail = cgraph_function_body_availability (callee);
291
292       /* When bad things happen to bad functions, they cannot be const
293          or pure.  */
294       if (setjmp_call_p (callee_t))
295         {
296           if (dump_file)
297             fprintf (dump_file, "    setjmp is not const/pure\n");
298           local->looping = true;
299           local->pure_const_state = IPA_NEITHER;
300         }
301
302       if (DECL_BUILT_IN_CLASS (callee_t) == BUILT_IN_NORMAL)
303         switch (DECL_FUNCTION_CODE (callee_t))
304           {
305           case BUILT_IN_LONGJMP:
306           case BUILT_IN_NONLOCAL_GOTO:
307             if (dump_file)
308               fprintf (dump_file, "    longjmp and nonlocal goto is not const/pure\n");
309             local->pure_const_state = IPA_NEITHER;
310             local->looping = true;
311             break;
312           default:
313             break;
314           }
315     }
316
317   /* When not in IPA mode, we can still handle self recursion.  */
318   if (!ipa && callee_t == current_function_decl)
319     local->looping = true;
320   /* The callee is either unknown (indirect call) or there is just no
321      scannable code for it (external call) .  We look to see if there
322      are any bits available for the callee (such as by declaration or
323      because it is builtin) and process solely on the basis of those
324      bits. */
325   else if (avail <= AVAIL_OVERWRITABLE || !ipa)
326     {
327       if (possibly_throws && flag_non_call_exceptions)
328         {
329           if (dump_file)
330             fprintf (dump_file, "    can throw; looping\n");
331           local->looping = true;
332         }
333       if (possibly_throws_externally)
334         {
335           if (dump_file)
336             {
337               fprintf (dump_file, "    can throw externally in region %i\n",
338                        lookup_stmt_eh_region (call));
339               if (callee_t)
340                 fprintf (dump_file, "     callee:%s\n",
341                          IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (callee_t)));
342             }
343           local->can_throw = true;
344         }
345       if (flags & ECF_CONST) 
346         {
347           if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
348             local->looping = true;
349          }
350       else if (flags & ECF_PURE) 
351         {
352           if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
353             local->looping = true;
354           if (dump_file)
355             fprintf (dump_file, "    pure function call in not const\n");
356           if (local->pure_const_state == IPA_CONST)
357             local->pure_const_state = IPA_PURE;
358         }
359       else 
360         {
361           if (dump_file)
362             fprintf (dump_file, "    uknown function call is not const/pure\n");
363           local->pure_const_state = IPA_NEITHER;
364           local->looping = true;
365         }
366     }
367   /* Direct functions calls are handled by IPA propagation.  */
368 }
369
370 /* Wrapper around check_decl for loads.  */
371
372 static bool
373 check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
374 {
375   if (DECL_P (op))
376     check_decl ((funct_state)data, op, false);
377   else
378     check_op ((funct_state)data, op, false);
379   return false;
380 }
381
382 /* Wrapper around check_decl for stores.  */
383
384 static bool
385 check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
386 {
387   if (DECL_P (op))
388     check_decl ((funct_state)data, op, true);
389   else
390     check_op ((funct_state)data, op, true);
391   return false;
392 }
393
394 /* Look into pointer pointed to by GSIP and figure out what interesting side
395    effects it has.  */
396 static void
397 check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
398 {
399   gimple stmt = gsi_stmt (*gsip);
400   unsigned int i = 0;
401
402   if (dump_file)
403     {
404       fprintf (dump_file, "  scanning: ");
405       print_gimple_stmt (dump_file, stmt, 0, 0);
406     }
407
408   /* Look for loads and stores.  */
409   walk_stmt_load_store_ops (stmt, local, check_load, check_store);
410
411   if (gimple_code (stmt) != GIMPLE_CALL
412       && stmt_could_throw_p (stmt))
413     {
414       if (flag_non_call_exceptions)
415         {
416           if (dump_file)
417             fprintf (dump_file, "    can throw; looping");
418           local->looping = true;
419         }
420       if (stmt_can_throw_external (stmt))
421         {
422           if (dump_file)
423             fprintf (dump_file, "    can throw externally");
424           local->can_throw = true;
425         }
426     }
427   switch (gimple_code (stmt))
428     {
429     case GIMPLE_CALL:
430       check_call (local, stmt, ipa);
431       break;
432     case GIMPLE_LABEL:
433       if (DECL_NONLOCAL (gimple_label_label (stmt)))
434         /* Target of long jump. */
435         {
436           if (dump_file)
437             fprintf (dump_file, "    nonlocal label is not const/pure");
438           local->pure_const_state = IPA_NEITHER;
439         }
440       break;
441     case GIMPLE_ASM:
442       for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
443         {
444           tree op = gimple_asm_clobber_op (stmt, i);
445           if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1) 
446             {
447               if (dump_file)
448                 fprintf (dump_file, "    memory asm clobber is not const/pure");
449               /* Abandon all hope, ye who enter here. */
450               local->pure_const_state = IPA_NEITHER;
451             }
452         }
453       if (gimple_asm_volatile_p (stmt))
454         {
455           if (dump_file)
456             fprintf (dump_file, "    volatile is not const/pure");
457           /* Abandon all hope, ye who enter here. */
458           local->pure_const_state = IPA_NEITHER;
459           local->looping = true;
460         }
461       return;
462     default:
463       break;
464     }
465 }
466
467
468 /* This is the main routine for finding the reference patterns for
469    global variables within a function FN.  */
470
471 static funct_state
472 analyze_function (struct cgraph_node *fn, bool ipa)
473 {
474   tree decl = fn->decl;
475   tree old_decl = current_function_decl;
476   funct_state l;
477   basic_block this_block;
478
479   if (cgraph_function_body_availability (fn) <= AVAIL_OVERWRITABLE)
480     {
481       if (dump_file)
482         fprintf (dump_file, "Function is not available or overwrittable; not analyzing.\n");
483       return NULL;
484     }
485
486   l = XCNEW (struct funct_state_d);
487   l->pure_const_state = IPA_CONST;
488   l->state_set_in_source = IPA_NEITHER;
489   l->looping = false;
490   l->can_throw = false;
491
492   if (dump_file)
493     {
494       fprintf (dump_file, "\n\n local analysis of %s\n ", 
495                cgraph_node_name (fn));
496     }
497   
498   push_cfun (DECL_STRUCT_FUNCTION (decl));
499   current_function_decl = decl;
500   
501   FOR_EACH_BB (this_block)
502     {
503       gimple_stmt_iterator gsi;
504       struct walk_stmt_info wi;
505
506       memset (&wi, 0, sizeof(wi));
507       for (gsi = gsi_start_bb (this_block);
508            !gsi_end_p (gsi);
509            gsi_next (&gsi))
510         {
511           check_stmt (&gsi, l, ipa);
512           if (l->pure_const_state == IPA_NEITHER && l->looping && l->can_throw)
513             goto end;
514         }
515     }
516
517 end:
518   if (l->pure_const_state != IPA_NEITHER)
519     {
520       /* Const functions cannot have back edges (an
521          indication of possible infinite loop side
522          effect.  */
523       if (mark_dfs_back_edges ())
524         l->looping = true;
525       
526     }
527
528   if (TREE_READONLY (decl))
529     {
530       l->pure_const_state = IPA_CONST;
531       l->state_set_in_source = IPA_CONST;
532       if (!DECL_LOOPING_CONST_OR_PURE_P (decl))
533         l->looping = false;
534     }
535   if (DECL_PURE_P (decl))
536     {
537       if (l->pure_const_state != IPA_CONST)
538         l->pure_const_state = IPA_PURE;
539       l->state_set_in_source = IPA_PURE;
540       if (!DECL_LOOPING_CONST_OR_PURE_P (decl))
541         l->looping = false;
542     }
543   if (TREE_NOTHROW (decl))
544     l->can_throw = false;
545
546   pop_cfun ();
547   current_function_decl = old_decl;
548   if (dump_file)
549     {
550       if (l->looping)
551         fprintf (dump_file, "Function is locally looping.\n");
552       if (l->can_throw)
553         fprintf (dump_file, "Function is locally throwing.\n");
554       if (l->pure_const_state == IPA_CONST)
555         fprintf (dump_file, "Function is locally const.\n");
556       if (l->pure_const_state == IPA_PURE)
557         fprintf (dump_file, "Function is locally pure.\n");
558     }
559   return l;
560 }
561
562 /* Called when new function is inserted to callgraph late.  */
563 static void
564 add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
565 {
566  if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
567    return;
568   /* There are some shared nodes, in particular the initializers on
569      static declarations.  We do not need to scan them more than once
570      since all we would be interested in are the addressof
571      operations.  */
572   visited_nodes = pointer_set_create ();
573   set_function_state (node, analyze_function (node, true));
574   pointer_set_destroy (visited_nodes);
575   visited_nodes = NULL;
576 }
577
578 /* Called when new clone is inserted to callgraph late.  */
579
580 static void
581 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
582                      void *data ATTRIBUTE_UNUSED)
583 {
584   if (get_function_state (src))
585     {
586       funct_state l = XNEW (struct funct_state_d);
587       gcc_assert (!get_function_state (dst));
588       memcpy (l, get_function_state (src), sizeof (*l));
589       set_function_state (dst, l);
590     }
591 }
592
593 /* Called when new clone is inserted to callgraph late.  */
594
595 static void
596 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
597 {
598   if (get_function_state (node))
599     {
600       free (get_function_state (node));
601       set_function_state (node, NULL);
602     }
603 }
604
605 \f
606 /* Analyze each function in the cgraph to see if it is locally PURE or
607    CONST.  */
608
609 static void 
610 generate_summary (void)
611 {
612   struct cgraph_node *node;
613
614   node_removal_hook_holder =
615       cgraph_add_node_removal_hook (&remove_node_data, NULL);
616   node_duplication_hook_holder =
617       cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
618   function_insertion_hook_holder =
619       cgraph_add_function_insertion_hook (&add_new_function, NULL);
620   /* There are some shared nodes, in particular the initializers on
621      static declarations.  We do not need to scan them more than once
622      since all we would be interested in are the addressof
623      operations.  */
624   visited_nodes = pointer_set_create ();
625
626   /* Process all of the functions. 
627
628      We do NOT process any AVAIL_OVERWRITABLE functions, we cannot
629      guarantee that what we learn about the one we see will be true
630      for the one that overrides it.
631   */
632   for (node = cgraph_nodes; node; node = node->next)
633     if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
634       set_function_state (node, analyze_function (node, true));
635
636   pointer_set_destroy (visited_nodes);
637   visited_nodes = NULL;
638 }
639
640 static bool
641 ignore_edge (struct cgraph_edge *e)
642 {
643   return (!e->can_throw_external);
644 }
645
646 /* Produce the global information by preforming a transitive closure
647    on the local information that was produced by generate_summary.
648    Note that there is no function_transform pass since this only
649    updates the function_decl.  */
650
651 static unsigned int
652 propagate (void)
653 {
654   struct cgraph_node *node;
655   struct cgraph_node *w;
656   struct cgraph_node **order =
657     XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
658   int order_pos;
659   int i;
660   struct ipa_dfs_info * w_info;
661
662   cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
663   cgraph_remove_node_duplication_hook (node_duplication_hook_holder);
664   cgraph_remove_node_removal_hook (node_removal_hook_holder);
665   order_pos = ipa_utils_reduced_inorder (order, true, false, NULL);
666   if (dump_file)
667     {
668       dump_cgraph (dump_file);
669       ipa_utils_print_order(dump_file, "reduced", order, order_pos);
670     }
671
672   /* Propagate the local information thru the call graph to produce
673      the global information.  All the nodes within a cycle will have
674      the same info so we collapse cycles first.  Then we can do the
675      propagation in one pass from the leaves to the roots.  */
676   for (i = 0; i < order_pos; i++ )
677     {
678       enum pure_const_state_e pure_const_state = IPA_CONST;
679       bool looping = false;
680       int count = 0;
681       node = order[i];
682
683       /* Find the worst state for any node in the cycle.  */
684       w = node;
685       while (w)
686         {
687           struct cgraph_edge *e;
688           funct_state w_l = get_function_state (w);
689           if (pure_const_state < w_l->pure_const_state)
690             pure_const_state = w_l->pure_const_state;
691
692           if (w_l->looping)
693             looping = true;
694
695           if (pure_const_state == IPA_NEITHER)
696             break;
697
698           count++;
699
700           if (count > 1)
701             looping = true;
702                 
703           for (e = w->callees; e; e = e->next_callee) 
704             {
705               struct cgraph_node *y = e->callee;
706
707               if (cgraph_function_body_availability (y) > AVAIL_OVERWRITABLE)
708                 {
709                   funct_state y_l = get_function_state (y);
710                   if (pure_const_state < y_l->pure_const_state)
711                     pure_const_state = y_l->pure_const_state;
712                   if (pure_const_state == IPA_NEITHER)
713                     break;
714                   if (y_l->looping)
715                     looping = true;
716                 }
717             }
718           w_info = (struct ipa_dfs_info *) w->aux;
719           w = w_info->next_cycle;
720         }
721
722       /* Copy back the region's pure_const_state which is shared by
723          all nodes in the region.  */
724       w = node;
725       while (w)
726         {
727           funct_state w_l = get_function_state (w);
728           enum pure_const_state_e this_state = pure_const_state;
729           bool this_looping = looping;
730
731           if (w_l->state_set_in_source != IPA_NEITHER)
732             {
733               if (this_state > w_l->state_set_in_source)
734                 this_state = w_l->state_set_in_source;
735               this_looping = false;
736             }
737
738           /* All nodes within a cycle share the same info.  */
739           w_l->pure_const_state = this_state;
740           w_l->looping = this_looping;
741
742           switch (this_state)
743             {
744             case IPA_CONST:
745               if (!TREE_READONLY (w->decl) && dump_file)
746                 fprintf (dump_file, "Function found to be %sconst: %s\n",  
747                          this_looping ? "looping " : "",
748                          cgraph_node_name (w)); 
749               TREE_READONLY (w->decl) = 1;
750               DECL_LOOPING_CONST_OR_PURE_P (w->decl) = this_looping;
751               break;
752               
753             case IPA_PURE:
754               if (!DECL_PURE_P (w->decl) && dump_file)
755                 fprintf (dump_file, "Function found to be %spure: %s\n",  
756                          this_looping ? "looping " : "",
757                          cgraph_node_name (w)); 
758               DECL_PURE_P (w->decl) = 1;
759               DECL_LOOPING_CONST_OR_PURE_P (w->decl) = this_looping;
760               break;
761               
762             default:
763               break;
764             }
765           w_info = (struct ipa_dfs_info *) w->aux;
766           w = w_info->next_cycle;
767         }
768     }
769
770   /* Cleanup. */
771   for (node = cgraph_nodes; node; node = node->next)
772     {
773       /* Get rid of the aux information.  */
774       if (node->aux)
775         {
776           w_info = (struct ipa_dfs_info *) node->aux;
777           free (node->aux);
778           node->aux = NULL;
779         }
780     }
781   order_pos = ipa_utils_reduced_inorder (order, true, false, ignore_edge);
782   if (dump_file)
783     {
784       dump_cgraph (dump_file);
785       ipa_utils_print_order(dump_file, "reduced for nothrow", order, order_pos);
786     }
787   /* Propagate the local information thru the call graph to produce
788      the global information.  All the nodes within a cycle will have
789      the same info so we collapse cycles first.  Then we can do the
790      propagation in one pass from the leaves to the roots.  */
791   for (i = 0; i < order_pos; i++ )
792     {
793       bool can_throw = false;
794       node = order[i];
795
796       /* Find the worst state for any node in the cycle.  */
797       w = node;
798       while (w)
799         {
800           struct cgraph_edge *e;
801           funct_state w_l = get_function_state (w);
802
803           if (w_l->can_throw)
804             can_throw = true;
805
806           if (can_throw)
807             break;
808                 
809           for (e = w->callees; e; e = e->next_callee) 
810             {
811               struct cgraph_node *y = e->callee;
812
813               if (cgraph_function_body_availability (y) > AVAIL_OVERWRITABLE)
814                 {
815                   funct_state y_l = get_function_state (y);
816
817                   if (can_throw) 
818                     break;
819                   if (y_l->can_throw && !TREE_NOTHROW (w->decl)
820                       && e->can_throw_external)
821                     can_throw = true;
822                 }
823             }
824           w_info = (struct ipa_dfs_info *) w->aux;
825           w = w_info->next_cycle;
826         }
827
828       /* Copy back the region's pure_const_state which is shared by
829          all nodes in the region.  */
830       w = node;
831       while (w)
832         {
833           funct_state w_l = get_function_state (w);
834           if (!can_throw && !TREE_NOTHROW (w->decl))
835             {
836               struct cgraph_edge *e;
837               TREE_NOTHROW (w->decl) = true;
838               for (e = w->callers; e; e = e->next_caller)
839                 e->can_throw_external = false;
840               if (dump_file)
841                 fprintf (dump_file, "Function found to be nothrow: %s\n",  
842                          cgraph_node_name (w));
843             }
844           else if (can_throw && !TREE_NOTHROW (w->decl))
845             w_l->can_throw = true;
846           w_info = (struct ipa_dfs_info *) w->aux;
847           w = w_info->next_cycle;
848         }
849     }
850
851   /* Cleanup. */
852   for (node = cgraph_nodes; node; node = node->next)
853     {
854       /* Get rid of the aux information.  */
855       if (node->aux)
856         {
857           w_info = (struct ipa_dfs_info *) node->aux;
858           free (node->aux);
859           node->aux = NULL;
860         }
861       if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
862         free (get_function_state (node));
863     }
864   
865   free (order);
866   VEC_free (funct_state, heap, funct_state_vec);
867   finish_state ();
868   return 0;
869 }
870
871 static bool
872 gate_pure_const (void)
873 {
874   return (flag_ipa_pure_const
875           /* Don't bother doing anything if the program has errors.  */
876           && !(errorcount || sorrycount));
877 }
878
879 struct ipa_opt_pass pass_ipa_pure_const =
880 {
881  {
882   IPA_PASS,
883   "pure-const",                         /* name */
884   gate_pure_const,                      /* gate */
885   propagate,                            /* execute */
886   NULL,                                 /* sub */
887   NULL,                                 /* next */
888   0,                                    /* static_pass_number */
889   TV_IPA_PURE_CONST,                    /* tv_id */
890   0,                                    /* properties_required */
891   0,                                    /* properties_provided */
892   0,                                    /* properties_destroyed */
893   0,                                    /* todo_flags_start */
894   0                                     /* todo_flags_finish */
895  },
896  generate_summary,                      /* generate_summary */
897  NULL,                                  /* write_summary */
898  NULL,                                  /* read_summary */
899  NULL,                                  /* function_read_summary */
900  0,                                     /* TODOs */
901  NULL,                                  /* function_transform */
902  NULL                                   /* variable_transform */
903 };
904
905 /* Simple local pass for pure const discovery reusing the analysis from
906    ipa_pure_const.   This pass is effective when executed together with
907    other optimization passes in early optimization pass queue.  */
908
909 static unsigned int
910 local_pure_const (void)
911 {
912   bool changed = false;
913   funct_state l;
914
915   /* Because we do not schedule pass_fixup_cfg over whole program after early optimizations
916      we must not promote functions that are called by already processed functions.  */
917
918   if (function_called_by_processed_nodes_p ())
919     {
920       if (dump_file)
921         fprintf (dump_file, "Function called in recursive cycle; ignoring\n");
922       return 0;
923     }
924
925   l = analyze_function (cgraph_node (current_function_decl), false);
926   if (!l)
927     {
928       if (dump_file)
929         fprintf (dump_file, "Function has wrong visibility; ignoring\n");
930       return 0;
931     }
932
933   switch (l->pure_const_state)
934     {
935     case IPA_CONST:
936       if (!TREE_READONLY (current_function_decl))
937         {
938           TREE_READONLY (current_function_decl) = 1;
939           DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = l->looping;
940           changed = true;
941           if (dump_file)
942             fprintf (dump_file, "Function found to be %sconst: %s\n",
943                      l->looping ? "looping " : "",
944                      lang_hooks.decl_printable_name (current_function_decl,
945                                                      2));
946         }
947       else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
948                && !l->looping)
949         {
950           DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = false;
951           changed = true;
952           if (dump_file)
953             fprintf (dump_file, "Function found to be non-looping: %s\n",
954                      lang_hooks.decl_printable_name (current_function_decl,
955                                                      2));
956         }
957       break;
958
959     case IPA_PURE:
960       if (!TREE_READONLY (current_function_decl))
961         {
962           DECL_PURE_P (current_function_decl) = 1;
963           DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = l->looping;
964           changed = true;
965           if (dump_file)
966             fprintf (dump_file, "Function found to be %spure: %s\n",
967                      l->looping ? "looping " : "",
968                      lang_hooks.decl_printable_name (current_function_decl,
969                                                      2));
970         }
971       else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
972                && !l->looping)
973         {
974           DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = false;
975           changed = true;
976           if (dump_file)
977             fprintf (dump_file, "Function found to be non-looping: %s\n",
978                      lang_hooks.decl_printable_name (current_function_decl,
979                                                      2));
980         }
981       break;
982
983     default:
984       break;
985     }
986   if (!l->can_throw && !TREE_NOTHROW (current_function_decl))
987     {
988       struct cgraph_edge *e;
989
990       TREE_NOTHROW (current_function_decl) = true;
991       for (e = cgraph_node (current_function_decl)->callers;
992            e; e = e->next_caller)
993         e->can_throw_external = false;
994       changed = true;
995       if (dump_file)
996         fprintf (dump_file, "Function found to be nothrow: %s\n",
997                  lang_hooks.decl_printable_name (current_function_decl,
998                                                  2));
999     }
1000   if (l)
1001     free (l);
1002   if (changed)
1003     return execute_fixup_cfg ();
1004   else
1005     return 0;
1006 }
1007
1008 struct gimple_opt_pass pass_local_pure_const =
1009 {
1010  {
1011   GIMPLE_PASS,
1012   "local-pure-const",                   /* name */
1013   gate_pure_const,                      /* gate */
1014   local_pure_const,                     /* execute */
1015   NULL,                                 /* sub */
1016   NULL,                                 /* next */
1017   0,                                    /* static_pass_number */
1018   TV_IPA_PURE_CONST,                    /* tv_id */
1019   0,                                    /* properties_required */
1020   0,                                    /* properties_provided */
1021   0,                                    /* properties_destroyed */
1022   0,                                    /* todo_flags_start */
1023   0                                     /* todo_flags_finish */
1024  }
1025 };