OSDN Git Service

2008-05-07 Kenneth Zadeck <zadeck@naturalbridge.com>
[pf3gnuchains/gcc-fork.git] / gcc / ipa-pure-const.c
1 /* Callgraph based analysis of static variables.
2    Copyright (C) 2004, 2005, 2007 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 mark functions as being either const (TREE_READONLY) or
22    pure (DECL_PURE_P).  It can also set the a variant of these that
23    are allowed to infinite loop (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 "tree-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 inserted into the ipa_dfs_info aux field to hold the
69    const_state.  */
70 struct funct_state_d 
71 {
72   enum pure_const_state_e pure_const_state;
73   bool looping;
74   bool state_set_in_source;
75 };
76
77 typedef struct funct_state_d * funct_state;
78
79 /* Return the function state from NODE.  */ 
80
81 static inline funct_state
82 get_function_state (struct cgraph_node *node)
83 {
84   struct ipa_dfs_info * info = (struct ipa_dfs_info *) node->aux;
85   return (funct_state) info->aux;
86 }
87
88 /* Check to see if the use (or definition when CHECHING_WRITE is true) 
89    variable T is legal in a function that is either pure or const.  */
90
91 static inline void 
92 check_decl (funct_state local, 
93             tree t, bool checking_write)
94 {
95   /* If the variable has the "used" attribute, treat it as if it had a
96      been touched by the devil.  */
97   if (lookup_attribute ("used", DECL_ATTRIBUTES (t)))
98     {
99       local->pure_const_state = IPA_NEITHER;
100       local->looping = false;
101       return;
102     }
103
104   /* Do not want to do anything with volatile except mark any
105      function that uses one to be not const or pure.  */
106   if (TREE_THIS_VOLATILE (t)) 
107     { 
108       local->pure_const_state = IPA_NEITHER;
109       local->looping = false;
110       return;
111     }
112
113   /* Do not care about a local automatic that is not static.  */
114   if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
115     return;
116
117   /* Since we have dealt with the locals and params cases above, if we
118      are CHECKING_WRITE, this cannot be a pure or constant
119      function.  */
120   if (checking_write) 
121     {
122       local->pure_const_state = IPA_NEITHER;
123       local->looping = false;
124       return;
125     }
126
127   if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
128     {
129       /* If the front end set the variable to be READONLY and
130          constant, we can allow this variable in pure or const
131          functions but the scope is too large for our analysis to set
132          these bits ourselves.  */
133       
134       if (TREE_READONLY (t)
135           && DECL_INITIAL (t)
136           && is_gimple_min_invariant (DECL_INITIAL (t)))
137         ; /* Read of a constant, do not change the function state.  */
138       else 
139         {
140           /* Just a regular read.  */
141           if (local->pure_const_state == IPA_CONST)
142             local->pure_const_state = IPA_PURE;
143         }
144     }
145   
146   /* Compilation level statics can be read if they are readonly
147      variables.  */
148   if (TREE_READONLY (t))
149     return;
150
151   /* Just a regular read.  */
152   if (local->pure_const_state == IPA_CONST)
153     local->pure_const_state = IPA_PURE;
154 }
155
156 /* If T is a VAR_DECL check to see if it is an allowed reference.  */
157
158 static void
159 check_operand (funct_state local, 
160                tree t, bool checking_write)
161 {
162   if (!t) return;
163
164   if (TREE_CODE (t) == VAR_DECL)
165     check_decl (local, t, checking_write); 
166 }
167
168 /* Examine tree T for references.  */
169
170 static void
171 check_tree (funct_state local, tree t, bool checking_write)
172 {
173   if ((TREE_CODE (t) == EXC_PTR_EXPR) || (TREE_CODE (t) == FILTER_EXPR)
174       || TREE_CODE (t) == SSA_NAME)
175     return;
176
177   /* Any tree which is volatile disqualifies thie function from being
178      const or pure. */
179   if (TREE_THIS_VOLATILE (t))
180     {
181       local->pure_const_state = IPA_NEITHER;
182       local->looping = false;
183       return;
184     }
185
186   while (TREE_CODE (t) == REALPART_EXPR 
187          || TREE_CODE (t) == IMAGPART_EXPR
188          || handled_component_p (t))
189     {
190       if (TREE_CODE (t) == ARRAY_REF)
191         check_operand (local, TREE_OPERAND (t, 1), false);
192       t = TREE_OPERAND (t, 0);
193     }
194
195   /* The bottom of an indirect reference can only be read, not
196      written.  */
197   if (INDIRECT_REF_P (t))
198     {
199       check_tree (local, TREE_OPERAND (t, 0), false);
200       
201       /* Any indirect reference that occurs on the lhs
202          disqualifies the function from being pure or const. Any
203          indirect reference that occurs on the rhs disqualifies the
204          function from being const.  */
205       if (checking_write) 
206         {
207           local->pure_const_state = IPA_NEITHER;
208           local->looping = false;
209           return;
210         }
211       else if (local->pure_const_state == IPA_CONST)
212         local->pure_const_state = IPA_PURE;
213     }
214
215   if (SSA_VAR_P (t))
216     check_operand (local, t, checking_write);
217 }
218
219 /* Scan tree T to see if there are any addresses taken in within T.  */
220
221 static void 
222 look_for_address_of (funct_state local, tree t)
223 {
224   if (TREE_CODE (t) == ADDR_EXPR)
225     {
226       tree x = get_base_var (t);
227       if (TREE_CODE (x) == VAR_DECL) 
228         {
229           check_decl (local, x, false);
230           
231           /* Taking the address of something appears to be reasonable
232              in PURE code.  Not allowed in const.  */
233           if (local->pure_const_state == IPA_CONST)
234             local->pure_const_state = IPA_PURE;
235         }
236     }
237 }
238
239 /* Check to see if T is a read or address of operation on a var we are
240    interested in analyzing.  LOCAL is passed in to get access to its
241    bit vectors.  */
242
243 static void
244 check_rhs_var (funct_state local, tree t)
245 {
246   look_for_address_of (local, t);
247
248   /* Memcmp and strlen can both trap and they are declared pure.  */
249   if (tree_could_trap_p (t)
250       && local->pure_const_state == IPA_CONST)
251     local->pure_const_state = IPA_PURE;
252
253   check_tree(local, t, false);
254 }
255
256 /* Check to see if T is an assignment to a var we are interested in
257    analyzing.  LOCAL is passed in to get access to its bit vectors. */
258
259 static void
260 check_lhs_var (funct_state local, tree t)
261 {
262   /* Memcmp and strlen can both trap and they are declared pure.
263      Which seems to imply that we can apply the same rule here.  */
264   if (tree_could_trap_p (t)
265       && local->pure_const_state == IPA_CONST)
266     local->pure_const_state = IPA_PURE;
267     
268   check_tree(local, t, true);
269 }
270
271 /* This is a scaled down version of get_asm_expr_operands from
272    tree_ssa_operands.c.  The version there runs much later and assumes
273    that aliasing information is already available. Here we are just
274    trying to find if the set of inputs and outputs contain references
275    or address of operations to local static variables.  STMT is the
276    actual asm statement.  */
277
278 static void
279 get_asm_expr_operands (funct_state local, tree stmt)
280 {
281   int noutputs = list_length (ASM_OUTPUTS (stmt));
282   const char **oconstraints
283     = (const char **) alloca ((noutputs) * sizeof (const char *));
284   int i;
285   tree link;
286   const char *constraint;
287   bool allows_mem, allows_reg, is_inout;
288   
289   for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
290     {
291       oconstraints[i] = constraint
292         = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
293       parse_output_constraint (&constraint, i, 0, 0,
294                                &allows_mem, &allows_reg, &is_inout);
295       
296       check_lhs_var (local, TREE_VALUE (link));
297     }
298
299   for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
300     {
301       constraint
302         = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
303       parse_input_constraint (&constraint, 0, 0, noutputs, 0,
304                               oconstraints, &allows_mem, &allows_reg);
305       
306       check_rhs_var (local, TREE_VALUE (link));
307     }
308   
309   for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
310     if (simple_cst_equal(TREE_VALUE (link), memory_identifier_string) == 1) 
311       /* Abandon all hope, ye who enter here. */
312       local->pure_const_state = IPA_NEITHER;
313
314   if (ASM_VOLATILE_P (stmt))
315     local->pure_const_state = IPA_NEITHER;
316 }
317
318 /* Check the parameters of a function call to CALL_EXPR to see if
319    there are any references in the parameters that are not allowed for
320    pure or const functions.  Also check to see if this is either an
321    indirect call, a call outside the compilation unit, or has special
322    attributes that may also effect the purity.  The CALL_EXPR node for
323    the entire call expression.  */
324
325 static void
326 check_call (funct_state local, tree call_expr) 
327 {
328   int flags = call_expr_flags (call_expr);
329   tree operand;
330   call_expr_arg_iterator iter;
331   tree callee_t = get_callee_fndecl (call_expr);
332   struct cgraph_node* callee;
333   enum availability avail = AVAIL_NOT_AVAILABLE;
334
335   FOR_EACH_CALL_EXPR_ARG (operand, iter, call_expr)
336     check_rhs_var (local, operand);
337   
338   /* The const and pure flags are set by a variety of places in the
339      compiler (including here).  If someone has already set the flags
340      for the callee, (such as for some of the builtins) we will use
341      them, otherwise we will compute our own information. 
342   
343      Const and pure functions have less clobber effects than other
344      functions so we process these first.  Otherwise if it is a call
345      outside the compilation unit or an indirect call we punt.  This
346      leaves local calls which will be processed by following the call
347      graph.  */  
348   if (callee_t)
349     {
350       callee = cgraph_node(callee_t);
351       avail = cgraph_function_body_availability (callee);
352
353       /* When bad things happen to bad functions, they cannot be const
354          or pure.  */
355       if (setjmp_call_p (callee_t))
356         {
357           local->pure_const_state = IPA_NEITHER;
358           local->looping = false;
359         }
360
361       if (DECL_BUILT_IN_CLASS (callee_t) == BUILT_IN_NORMAL)
362         switch (DECL_FUNCTION_CODE (callee_t))
363           {
364           case BUILT_IN_LONGJMP:
365           case BUILT_IN_NONLOCAL_GOTO:
366             local->pure_const_state = IPA_NEITHER;
367             local->looping = false;
368             break;
369           default:
370             break;
371           }
372     }
373
374   /* The callee is either unknown (indirect call) or there is just no
375      scannable code for it (external call) .  We look to see if there
376      are any bits available for the callee (such as by declaration or
377      because it is builtin) and process solely on the basis of those
378      bits. */
379   if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE)
380     {
381       if (flags & ECF_PURE) 
382         {
383           if (local->pure_const_state == IPA_CONST)
384             local->pure_const_state = IPA_PURE;
385         }
386       else 
387         local->pure_const_state = IPA_NEITHER;
388     }
389   else
390     {
391       /* We have the code and we will scan it for the effects. */
392       if (flags & ECF_PURE) 
393         {
394           if (local->pure_const_state == IPA_CONST)
395             local->pure_const_state = IPA_PURE;
396         }
397     }
398 }
399
400 /* TP is the part of the tree currently under the microscope.
401    WALK_SUBTREES is part of the walk_tree api but is unused here.
402    DATA is cgraph_node of the function being walked.  */
403
404 /* FIXME: When this is converted to run over SSA form, this code
405    should be converted to use the operand scanner.  */
406
407 static tree
408 scan_function (tree *tp, 
409                       int *walk_subtrees, 
410                       void *data)
411 {
412   struct cgraph_node *fn = (struct cgraph_node *) data;
413   tree t = *tp;
414   funct_state local = get_function_state (fn);
415
416   switch (TREE_CODE (t))  
417     {
418     case VAR_DECL:
419       if (DECL_INITIAL (t))
420         walk_tree (&DECL_INITIAL (t), scan_function, fn, visited_nodes);
421       *walk_subtrees = 0;
422       break;
423
424     case GIMPLE_MODIFY_STMT:
425       {
426         /* First look on the lhs and see what variable is stored to */
427         tree lhs = GIMPLE_STMT_OPERAND (t, 0);
428         tree rhs = GIMPLE_STMT_OPERAND (t, 1);
429         check_lhs_var (local, lhs);
430
431         /* For the purposes of figuring out what the cast affects */
432
433         /* Next check the operands on the rhs to see if they are ok. */
434         switch (TREE_CODE_CLASS (TREE_CODE (rhs))) 
435           {
436           case tcc_binary:          
437             {
438               tree op0 = TREE_OPERAND (rhs, 0);
439               tree op1 = TREE_OPERAND (rhs, 1);
440               check_rhs_var (local, op0);
441               check_rhs_var (local, op1);
442             }
443             break;
444           case tcc_unary:
445             {
446               tree op0 = TREE_OPERAND (rhs, 0);
447               check_rhs_var (local, op0);
448             }
449
450             break;
451           case tcc_reference:
452             check_rhs_var (local, rhs);
453             break;
454           case tcc_declaration:
455             check_rhs_var (local, rhs);
456             break;
457           case tcc_expression:
458             switch (TREE_CODE (rhs)) 
459               {
460               case ADDR_EXPR:
461                 check_rhs_var (local, rhs);
462                 break;
463               default:
464                 break;
465               }
466             break;
467           case tcc_vl_exp:
468             switch (TREE_CODE (rhs)) 
469               {
470               case CALL_EXPR:
471                 check_call (local, rhs);
472                 break;
473               default:
474                 break;
475               }
476             break;
477           default:
478             break;
479           }
480         *walk_subtrees = 0;
481       }
482       break;
483
484     case ADDR_EXPR:
485       /* This case is here to find addresses on rhs of constructors in
486          decl_initial of static variables. */
487       check_rhs_var (local, t);
488       *walk_subtrees = 0;
489       break;
490
491     case LABEL_EXPR:
492       if (DECL_NONLOCAL (TREE_OPERAND (t, 0)))
493         /* Target of long jump. */
494         {
495           local->pure_const_state = IPA_NEITHER;
496           local->looping = false;
497         }
498       break;
499
500     case CALL_EXPR: 
501       check_call (local, t);
502       *walk_subtrees = 0;
503       break;
504       
505     case ASM_EXPR:
506       get_asm_expr_operands (local, t);
507       *walk_subtrees = 0;
508       break;
509       
510     default:
511       break;
512     }
513   return NULL;
514 }
515
516 /* This is the main routine for finding the reference patterns for
517    global variables within a function FN.  */
518
519 static void
520 analyze_function (struct cgraph_node *fn)
521 {
522   funct_state l = XCNEW (struct funct_state_d);
523   tree decl = fn->decl;
524   struct ipa_dfs_info * w_info = (struct ipa_dfs_info *) fn->aux;
525
526   w_info->aux = l;
527
528   l->pure_const_state = IPA_CONST;
529   l->state_set_in_source = false;
530   if (DECL_LOOPING_CONST_OR_PURE_P (decl))
531     l->looping = true;
532   else
533     l->looping = false;
534
535   /* If this function does not return normally or does not bind local,
536      do not touch this unless it has been marked as const or pure by the
537      front end.  */
538   if (TREE_THIS_VOLATILE (decl)
539       || !targetm.binds_local_p (decl))
540     {
541       l->pure_const_state = IPA_NEITHER;
542       return;
543     }
544
545   if (TREE_READONLY (decl))
546     {
547       l->pure_const_state = IPA_CONST;
548       l->state_set_in_source = true;
549     }
550   if (DECL_PURE_P (decl))
551     {
552       l->pure_const_state = IPA_PURE;
553       l->state_set_in_source = true;
554     }
555
556   if (dump_file)
557     {
558       fprintf (dump_file, "\n local analysis of %s with initial value = %d\n ", 
559                cgraph_node_name (fn),
560                l->pure_const_state);
561     }
562   
563   if (!l->state_set_in_source)
564     {
565       struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
566       basic_block this_block;
567       
568       FOR_EACH_BB_FN (this_block, this_cfun)
569         {
570           block_stmt_iterator bsi;
571           for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
572             {
573               walk_tree (bsi_stmt_ptr (bsi), scan_function, 
574                          fn, visited_nodes);
575               if (l->pure_const_state == IPA_NEITHER) 
576                 goto end;
577             }
578         }
579
580       if (l->pure_const_state != IPA_NEITHER)
581         {
582           tree old_decl = current_function_decl;
583           /* Const functions cannot have back edges (an
584              indication of possible infinite loop side
585              effect.  */
586             
587           current_function_decl = fn->decl;
588
589           /* The C++ front end, has a tendency to some times jerk away
590              a function after it has created it.  This should have
591              been fixed.  */
592           gcc_assert (DECL_STRUCT_FUNCTION (fn->decl));
593           
594           push_cfun (DECL_STRUCT_FUNCTION (fn->decl));
595           
596           if (mark_dfs_back_edges ())
597             l->pure_const_state = IPA_NEITHER;
598           
599           current_function_decl = old_decl;
600           pop_cfun ();
601         }
602     }
603
604 end:
605   if (dump_file)
606     {
607       fprintf (dump_file, "after local analysis of %s with initial value = %d\n ", 
608                cgraph_node_name (fn),
609                l->pure_const_state);
610     }
611 }
612
613 \f
614 /* Produce the global information by preforming a transitive closure
615    on the local information that was produced by ipa_analyze_function
616    and ipa_analyze_variable.  */
617
618 static unsigned int
619 static_execute (void)
620 {
621   struct cgraph_node *node;
622   struct cgraph_node *w;
623   struct cgraph_node **order =
624     XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
625   int order_pos = ipa_utils_reduced_inorder (order, true, false);
626   int i;
627   struct ipa_dfs_info * w_info;
628
629   if (!memory_identifier_string)
630     memory_identifier_string = build_string(7, "memory");
631
632   /* There are some shared nodes, in particular the initializers on
633      static declarations.  We do not need to scan them more than once
634      since all we would be interested in are the addressof
635      operations.  */
636   visited_nodes = pointer_set_create ();
637
638   /* Process all of the functions. 
639
640      We do not want to process any of the clones so we check that this
641      is a master clone.  However, we do NOT process any
642      AVAIL_OVERWRITABLE functions (these are never clones) we cannot
643      guarantee that what we learn about the one we see will be true
644      for the one that overriders it.
645   */
646   for (node = cgraph_nodes; node; node = node->next)
647     if (node->analyzed && cgraph_is_master_clone (node))
648       analyze_function (node);
649
650   pointer_set_destroy (visited_nodes);
651   visited_nodes = NULL;
652   if (dump_file)
653     {
654       dump_cgraph (dump_file);
655       ipa_utils_print_order(dump_file, "reduced", order, order_pos);
656     }
657
658   /* Propagate the local information thru the call graph to produce
659      the global information.  All the nodes within a cycle will have
660      the same info so we collapse cycles first.  Then we can do the
661      propagation in one pass from the leaves to the roots.  */
662   for (i = 0; i < order_pos; i++ )
663     {
664       enum pure_const_state_e pure_const_state = IPA_CONST;
665       bool looping = false;
666       int count = 0;
667       node = order[i];
668
669       /* Find the worst state for any node in the cycle.  */
670       w = node;
671       while (w)
672         {
673           funct_state w_l = get_function_state (w);
674           if (pure_const_state < w_l->pure_const_state)
675             pure_const_state = w_l->pure_const_state;
676
677           if (w_l->looping)
678             looping = true;
679
680           if (pure_const_state == IPA_NEITHER) 
681             break;
682
683           if (!w_l->state_set_in_source)
684             {
685               struct cgraph_edge *e;
686               count++;
687
688               if (count > 1)
689                 looping = true;
690                     
691               for (e = w->callees; e; e = e->next_callee) 
692                 {
693                   struct cgraph_node *y = e->callee;
694                   /* Only look at the master nodes and skip external nodes.  */
695                   y = cgraph_master_clone (y);
696
697                   if (w == y)
698                     looping = true;
699                   if (y)
700                     {
701                       funct_state y_l = get_function_state (y);
702                       if (pure_const_state < y_l->pure_const_state)
703                         pure_const_state = y_l->pure_const_state;
704                       if (pure_const_state == IPA_NEITHER) 
705                         break;
706                       if (y_l->looping)
707                         looping = true;
708                     }
709                 }
710             }
711           w_info = (struct ipa_dfs_info *) w->aux;
712           w = w_info->next_cycle;
713         }
714
715       /* Copy back the region's pure_const_state which is shared by
716          all nodes in the region.  */
717       w = node;
718       while (w)
719         {
720           funct_state w_l = get_function_state (w);
721
722           /* All nodes within a cycle share the same info.  */
723           if (!w_l->state_set_in_source)
724             {
725               w_l->pure_const_state = pure_const_state;
726               switch (pure_const_state)
727                 {
728                 case IPA_CONST:
729                   TREE_READONLY (w->decl) = 1;
730                   DECL_LOOPING_CONST_OR_PURE_P (w->decl) = looping;
731                   if (dump_file)
732                     fprintf (dump_file, "Function found to be %sconst: %s\n",  
733                              looping ? "looping " : "",
734                              lang_hooks.decl_printable_name(w->decl, 2)); 
735                   break;
736                   
737                 case IPA_PURE:
738                   DECL_PURE_P (w->decl) = 1;
739                   DECL_LOOPING_CONST_OR_PURE_P (w->decl) = looping;
740                   if (dump_file)
741                     fprintf (dump_file, "Function found to be %spure: %s\n",  
742                              looping ? "looping " : "",
743                              lang_hooks.decl_printable_name(w->decl, 2)); 
744                   break;
745                   
746                 default:
747                   break;
748                 }
749             }
750           w_info = (struct ipa_dfs_info *) w->aux;
751           w = w_info->next_cycle;
752         }
753     }
754
755   /* Cleanup. */
756   for (node = cgraph_nodes; node; node = node->next)
757     /* Get rid of the aux information.  */
758     if (node->aux)
759       {
760         w_info = (struct ipa_dfs_info *) node->aux;
761         if (w_info->aux)
762           free (w_info->aux);
763         free (node->aux);
764         node->aux = NULL;
765       }
766
767   free (order);
768   return 0;
769 }
770
771 static bool
772 gate_pure_const (void)
773 {
774   return (flag_unit_at_a_time != 0 && flag_ipa_pure_const 
775           /* Don't bother doing anything if the program has errors.  */
776           && !(errorcount || sorrycount));
777 }
778
779 struct simple_ipa_opt_pass pass_ipa_pure_const =
780 {
781  {
782   SIMPLE_IPA_PASS,
783   "pure-const",                         /* name */
784   gate_pure_const,                      /* gate */
785   static_execute,                       /* execute */
786   NULL,                                 /* sub */
787   NULL,                                 /* next */
788   0,                                    /* static_pass_number */
789   TV_IPA_PURE_CONST,                    /* tv_id */
790   0,                                    /* properties_required */
791   0,                                    /* properties_provided */
792   0,                                    /* properties_destroyed */
793   0,                                    /* todo_flags_start */
794   0                                     /* todo_flags_finish */
795  }
796 };
797
798