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>
5 This file is part of GCC.
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
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
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/>. */
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).
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. */
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. */
36 #include "coretypes.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"
45 #include "ipa-utils.h"
52 #include "diagnostic.h"
53 #include "langhooks.h"
56 static struct pointer_set_t
*visited_nodes
;
58 /* Lattice values for const and pure functions. Everything starts out
59 being const, then may drop to pure and then neither depending on
61 enum pure_const_state_e
68 /* Holder for the const_state. There is one of these per function
73 enum pure_const_state_e pure_const_state
;
75 /* True if the function could possibly infinite loop. There are a
76 lot of ways that this could be determined. We are pretty
77 conservative here. While it is possible to cse pure and const
78 calls, it is not legal to have dce get rid of the call if there
79 is a possibility that the call could infinite loop since this is
80 a behavioral change. */
83 /* If the state of the function was set in the source, then assume
84 that it was done properly even if the analysis we do would be
86 bool state_set_in_source
;
89 typedef struct funct_state_d
* funct_state
;
91 /* The storage of the funct_state is abstracted because there is the
92 possibility that it may be desirable to move this to the cgraph
95 /* Array, indexed by cgraph node uid, of function states. */
97 DEF_VEC_P (funct_state
);
98 DEF_VEC_ALLOC_P (funct_state
, heap
);
99 static VEC (funct_state
, heap
) *funct_state_vec
;
101 /* Holders of ipa cgraph hooks: */
102 static struct cgraph_node_hook_list
*function_insertion_hook_holder
;
103 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
104 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
106 /* Init the function state. */
111 free (funct_state_vec
);
115 /* Return the function state from NODE. */
117 static inline funct_state
118 get_function_state (struct cgraph_node
*node
)
121 || VEC_length (funct_state
, funct_state_vec
) <= (unsigned int)node
->uid
)
123 return VEC_index (funct_state
, funct_state_vec
, node
->uid
);
126 /* Set the function state S for NODE. */
129 set_function_state (struct cgraph_node
*node
, funct_state s
)
132 || VEC_length (funct_state
, funct_state_vec
) <= (unsigned int)node
->uid
)
133 VEC_safe_grow_cleared (funct_state
, heap
, funct_state_vec
, node
->uid
+ 1);
134 VEC_replace (funct_state
, funct_state_vec
, node
->uid
, s
);
137 /* Check to see if the use (or definition when CHECKING_WRITE is true)
138 variable T is legal in a function that is either pure or const. */
141 check_decl (funct_state local
,
142 tree t
, bool checking_write
)
144 /* If the variable has the "used" attribute, treat it as if it had a
145 been touched by the devil. */
146 if (lookup_attribute ("used", DECL_ATTRIBUTES (t
)))
148 local
->pure_const_state
= IPA_NEITHER
;
149 local
->looping
= false;
153 /* Do not want to do anything with volatile except mark any
154 function that uses one to be not const or pure. */
155 if (TREE_THIS_VOLATILE (t
))
157 local
->pure_const_state
= IPA_NEITHER
;
158 local
->looping
= false;
162 /* Do not care about a local automatic that is not static. */
163 if (!TREE_STATIC (t
) && !DECL_EXTERNAL (t
))
166 /* Since we have dealt with the locals and params cases above, if we
167 are CHECKING_WRITE, this cannot be a pure or constant
171 local
->pure_const_state
= IPA_NEITHER
;
172 local
->looping
= false;
176 if (DECL_EXTERNAL (t
) || TREE_PUBLIC (t
))
178 /* If the front end set the variable to be READONLY and
179 constant, we can allow this variable in pure or const
180 functions but the scope is too large for our analysis to set
181 these bits ourselves. */
183 if (TREE_READONLY (t
)
185 && is_gimple_min_invariant (DECL_INITIAL (t
)))
186 ; /* Read of a constant, do not change the function state. */
189 /* Just a regular read. */
190 if (local
->pure_const_state
== IPA_CONST
)
191 local
->pure_const_state
= IPA_PURE
;
195 /* Compilation level statics can be read if they are readonly
197 if (TREE_READONLY (t
))
200 /* Just a regular read. */
201 if (local
->pure_const_state
== IPA_CONST
)
202 local
->pure_const_state
= IPA_PURE
;
205 /* If T is a VAR_DECL check to see if it is an allowed reference. */
208 check_operand (funct_state local
,
209 tree t
, bool checking_write
)
213 if (TREE_CODE (t
) == VAR_DECL
)
214 check_decl (local
, t
, checking_write
);
217 /* Examine tree T for references. */
220 check_tree (funct_state local
, tree t
, bool checking_write
)
222 if ((TREE_CODE (t
) == EXC_PTR_EXPR
) || (TREE_CODE (t
) == FILTER_EXPR
)
223 || TREE_CODE (t
) == SSA_NAME
)
226 /* Any tree which is volatile disqualifies this function from being
228 if (TREE_THIS_VOLATILE (t
))
230 local
->pure_const_state
= IPA_NEITHER
;
231 local
->looping
= false;
235 while (TREE_CODE (t
) == REALPART_EXPR
236 || TREE_CODE (t
) == IMAGPART_EXPR
237 || handled_component_p (t
))
239 if (TREE_CODE (t
) == ARRAY_REF
)
240 check_operand (local
, TREE_OPERAND (t
, 1), false);
241 t
= TREE_OPERAND (t
, 0);
244 /* The bottom of an indirect reference can only be read, not
246 if (INDIRECT_REF_P (t
))
248 check_tree (local
, TREE_OPERAND (t
, 0), false);
250 /* Any indirect reference that occurs on the lhs
251 disqualifies the function from being pure or const. Any
252 indirect reference that occurs on the rhs disqualifies the
253 function from being const. */
256 local
->pure_const_state
= IPA_NEITHER
;
257 local
->looping
= false;
260 else if (local
->pure_const_state
== IPA_CONST
)
261 local
->pure_const_state
= IPA_PURE
;
265 check_operand (local
, t
, checking_write
);
268 /* Scan tree T to see if there are any addresses taken in within T. */
271 look_for_address_of (funct_state local
, tree t
)
273 if (TREE_CODE (t
) == ADDR_EXPR
)
275 tree x
= get_base_var (t
);
276 if (TREE_CODE (x
) == VAR_DECL
)
278 check_decl (local
, x
, false);
280 /* Taking the address of something appears to be reasonable
281 in PURE code. Not allowed in const. */
282 if (local
->pure_const_state
== IPA_CONST
)
283 local
->pure_const_state
= IPA_PURE
;
288 /* Check to see if T is a read or address of operation on a var we are
289 interested in analyzing. LOCAL is passed in to get access to its
293 check_rhs_var (funct_state local
, tree t
)
295 look_for_address_of (local
, t
);
297 /* Memcmp and strlen can both trap and they are declared pure. */
298 if (tree_could_trap_p (t
)
299 && local
->pure_const_state
== IPA_CONST
)
300 local
->pure_const_state
= IPA_PURE
;
302 check_tree(local
, t
, false);
305 /* Check to see if T is an assignment to a var we are interested in
306 analyzing. LOCAL is passed in to get access to its bit vectors. */
309 check_lhs_var (funct_state local
, tree t
)
311 /* Memcmp and strlen can both trap and they are declared pure.
312 Which seems to imply that we can apply the same rule here. */
313 if (tree_could_trap_p (t
)
314 && local
->pure_const_state
== IPA_CONST
)
315 local
->pure_const_state
= IPA_PURE
;
317 check_tree(local
, t
, true);
320 /* This is a scaled down version of get_asm_expr_operands from
321 tree_ssa_operands.c. The version there runs much later and assumes
322 that aliasing information is already available. Here we are just
323 trying to find if the set of inputs and outputs contain references
324 or address of operations to local static variables. STMT is the
325 actual asm statement. */
328 get_asm_expr_operands (funct_state local
, gimple stmt
)
330 size_t noutputs
= gimple_asm_noutputs (stmt
);
331 const char **oconstraints
332 = (const char **) alloca ((noutputs
) * sizeof (const char *));
335 const char *constraint
;
336 bool allows_mem
, allows_reg
, is_inout
;
338 for (i
= 0; i
< noutputs
; i
++)
340 op
= gimple_asm_output_op (stmt
, i
);
341 oconstraints
[i
] = constraint
342 = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op
)));
343 parse_output_constraint (&constraint
, i
, 0, 0,
344 &allows_mem
, &allows_reg
, &is_inout
);
346 check_lhs_var (local
, TREE_VALUE (op
));
349 for (i
= 0; i
< gimple_asm_ninputs (stmt
); i
++)
351 op
= gimple_asm_input_op (stmt
, i
);
353 = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op
)));
354 parse_input_constraint (&constraint
, 0, 0, noutputs
, 0,
355 oconstraints
, &allows_mem
, &allows_reg
);
357 check_rhs_var (local
, TREE_VALUE (op
));
360 for (i
= 0; i
< gimple_asm_nclobbers (stmt
); i
++)
362 op
= gimple_asm_clobber_op (stmt
, i
);
363 if (simple_cst_equal(TREE_VALUE (op
), memory_identifier_string
) == 1)
364 /* Abandon all hope, ye who enter here. */
365 local
->pure_const_state
= IPA_NEITHER
;
368 if (gimple_asm_volatile_p (stmt
))
369 local
->pure_const_state
= IPA_NEITHER
;
372 /* Check the parameters of a function call to CALL_EXPR to see if
373 there are any references in the parameters that are not allowed for
374 pure or const functions. Also check to see if this is either an
375 indirect call, a call outside the compilation unit, or has special
376 attributes that may also effect the purity. The CALL_EXPR node for
377 the entire call expression. */
380 check_call (funct_state local
, gimple call
)
382 int flags
= gimple_call_flags (call
);
383 tree lhs
, callee_t
= gimple_call_fndecl (call
);
384 struct cgraph_node
* callee
;
385 enum availability avail
= AVAIL_NOT_AVAILABLE
;
388 lhs
= gimple_call_lhs (call
);
390 check_lhs_var (local
, lhs
);
392 for (i
= 0; i
< gimple_call_num_args (call
); i
++)
393 check_rhs_var (local
, gimple_call_arg (call
, i
));
395 /* The const and pure flags are set by a variety of places in the
396 compiler (including here). If someone has already set the flags
397 for the callee, (such as for some of the builtins) we will use
398 them, otherwise we will compute our own information.
400 Const and pure functions have less clobber effects than other
401 functions so we process these first. Otherwise if it is a call
402 outside the compilation unit or an indirect call we punt. This
403 leaves local calls which will be processed by following the call
407 callee
= cgraph_node(callee_t
);
408 avail
= cgraph_function_body_availability (callee
);
410 /* When bad things happen to bad functions, they cannot be const
412 if (setjmp_call_p (callee_t
))
414 local
->pure_const_state
= IPA_NEITHER
;
415 local
->looping
= false;
418 if (DECL_BUILT_IN_CLASS (callee_t
) == BUILT_IN_NORMAL
)
419 switch (DECL_FUNCTION_CODE (callee_t
))
421 case BUILT_IN_LONGJMP
:
422 case BUILT_IN_NONLOCAL_GOTO
:
423 local
->pure_const_state
= IPA_NEITHER
;
424 local
->looping
= false;
431 /* The callee is either unknown (indirect call) or there is just no
432 scannable code for it (external call) . We look to see if there
433 are any bits available for the callee (such as by declaration or
434 because it is builtin) and process solely on the basis of those
436 if (avail
== AVAIL_NOT_AVAILABLE
|| avail
== AVAIL_OVERWRITABLE
)
438 if (flags
& ECF_PURE
)
440 if (local
->pure_const_state
== IPA_CONST
)
441 local
->pure_const_state
= IPA_PURE
;
444 local
->pure_const_state
= IPA_NEITHER
;
448 /* We have the code and we will scan it for the effects. */
449 if (flags
& ECF_PURE
)
451 if (local
->pure_const_state
== IPA_CONST
)
452 local
->pure_const_state
= IPA_PURE
;
457 /* TP is the part of the tree currently under the microscope.
458 WALK_SUBTREES is part of the walk_tree api but is unused here.
459 DATA is cgraph_node of the function being walked. */
461 /* FIXME: When this is converted to run over SSA form, this code
462 should be converted to use the operand scanner. */
465 scan_function_op (tree
*tp
, int *walk_subtrees
, void *data
)
467 struct walk_stmt_info
*wi
= (struct walk_stmt_info
*) data
;
468 struct cgraph_node
*fn
= (struct cgraph_node
*) wi
->info
;
470 funct_state local
= get_function_state (fn
);
472 switch (TREE_CODE (t
))
475 if (DECL_INITIAL (t
))
476 walk_tree (&DECL_INITIAL (t
), scan_function_op
, data
, visited_nodes
);
481 /* This case is here to find addresses on rhs of constructors in
482 decl_initial of static variables. */
483 check_rhs_var (local
, t
);
494 scan_function_stmt (gimple_stmt_iterator
*gsi_p
,
496 struct walk_stmt_info
*wi
)
498 struct cgraph_node
*fn
= (struct cgraph_node
*) wi
->info
;
499 gimple stmt
= gsi_stmt (*gsi_p
);
500 funct_state local
= get_function_state (fn
);
502 switch (gimple_code (stmt
))
506 /* First look on the lhs and see what variable is stored to */
507 tree lhs
= gimple_assign_lhs (stmt
);
508 tree rhs1
= gimple_assign_rhs1 (stmt
);
509 tree rhs2
= gimple_assign_rhs2 (stmt
);
510 enum tree_code code
= gimple_assign_rhs_code (stmt
);
512 check_lhs_var (local
, lhs
);
514 /* For the purposes of figuring out what the cast affects */
516 /* Next check the operands on the rhs to see if they are ok. */
517 switch (TREE_CODE_CLASS (code
))
521 check_rhs_var (local
, rhs1
);
522 check_rhs_var (local
, rhs2
);
527 check_rhs_var (local
, rhs1
);
532 check_rhs_var (local
, rhs1
);
534 case tcc_declaration
:
535 check_rhs_var (local
, rhs1
);
541 check_rhs_var (local
, rhs1
);
550 *handled_ops_p
= true;
555 if (DECL_NONLOCAL (gimple_label_label (stmt
)))
556 /* Target of long jump. */
558 local
->pure_const_state
= IPA_NEITHER
;
559 local
->looping
= false;
564 check_call (local
, stmt
);
565 *handled_ops_p
= true;
569 get_asm_expr_operands (local
, stmt
);
570 *handled_ops_p
= true;
580 /* This is the main routine for finding the reference patterns for
581 global variables within a function FN. */
584 analyze_function (struct cgraph_node
*fn
)
586 tree decl
= fn
->decl
;
587 funct_state l
= XCNEW (struct funct_state_d
);
589 if (cgraph_function_body_availability (fn
) <= AVAIL_OVERWRITABLE
)
592 set_function_state (fn
, l
);
594 l
->pure_const_state
= IPA_CONST
;
595 l
->state_set_in_source
= false;
596 if (DECL_LOOPING_CONST_OR_PURE_P (decl
))
601 /* If this function does not return normally or does not bind local,
602 do not touch this unless it has been marked as const or pure by the
604 if (TREE_THIS_VOLATILE (decl
)
605 || !targetm
.binds_local_p (decl
))
607 l
->pure_const_state
= IPA_NEITHER
;
611 if (TREE_READONLY (decl
))
613 l
->pure_const_state
= IPA_CONST
;
614 l
->state_set_in_source
= true;
616 if (DECL_PURE_P (decl
))
618 l
->pure_const_state
= IPA_PURE
;
619 l
->state_set_in_source
= true;
624 fprintf (dump_file
, "\n local analysis of %s with initial value = %d\n ",
625 cgraph_node_name (fn
),
626 l
->pure_const_state
);
629 if (!l
->state_set_in_source
)
631 struct function
*this_cfun
= DECL_STRUCT_FUNCTION (decl
);
632 basic_block this_block
;
634 FOR_EACH_BB_FN (this_block
, this_cfun
)
636 gimple_stmt_iterator gsi
;
637 struct walk_stmt_info wi
;
639 memset (&wi
, 0, sizeof(wi
));
640 for (gsi
= gsi_start_bb (this_block
);
645 wi
.pset
= visited_nodes
;
646 walk_gimple_stmt (&gsi
, scan_function_stmt
, scan_function_op
,
648 if (l
->pure_const_state
== IPA_NEITHER
)
653 if (l
->pure_const_state
!= IPA_NEITHER
)
655 tree old_decl
= current_function_decl
;
656 /* Const functions cannot have back edges (an
657 indication of possible infinite loop side
660 current_function_decl
= fn
->decl
;
662 /* The C++ front end, has a tendency to some times jerk away
663 a function after it has created it. This should have
665 gcc_assert (DECL_STRUCT_FUNCTION (fn
->decl
));
667 push_cfun (DECL_STRUCT_FUNCTION (fn
->decl
));
669 if (mark_dfs_back_edges ())
670 l
->pure_const_state
= IPA_NEITHER
;
672 current_function_decl
= old_decl
;
680 fprintf (dump_file
, "after local analysis of %s with initial value = %d\n ",
681 cgraph_node_name (fn
),
682 l
->pure_const_state
);
686 /* Called when new function is inserted to callgraph late. */
688 add_new_function (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
690 if (cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
692 /* There are some shared nodes, in particular the initializers on
693 static declarations. We do not need to scan them more than once
694 since all we would be interested in are the addressof
696 visited_nodes
= pointer_set_create ();
697 analyze_function (node
);
698 pointer_set_destroy (visited_nodes
);
699 visited_nodes
= NULL
;
702 /* Called when new clone is inserted to callgraph late. */
705 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
706 void *data ATTRIBUTE_UNUSED
)
708 if (get_function_state (src
))
710 funct_state l
= XNEW (struct funct_state_d
);
711 gcc_assert (!get_function_state (dst
));
712 memcpy (l
, get_function_state (src
), sizeof (*l
));
713 set_function_state (dst
, l
);
717 /* Called when new clone is inserted to callgraph late. */
720 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
722 if (get_function_state (node
))
724 free (get_function_state (node
));
725 set_function_state (node
, NULL
);
730 /* Analyze each function in the cgraph to see if it is locally PURE or
734 generate_summary (void)
736 struct cgraph_node
*node
;
738 node_removal_hook_holder
=
739 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
740 node_duplication_hook_holder
=
741 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
742 function_insertion_hook_holder
=
743 cgraph_add_function_insertion_hook (&add_new_function
, NULL
);
744 /* There are some shared nodes, in particular the initializers on
745 static declarations. We do not need to scan them more than once
746 since all we would be interested in are the addressof
748 visited_nodes
= pointer_set_create ();
750 /* Process all of the functions.
752 We do NOT process any AVAIL_OVERWRITABLE functions, we cannot
753 guarantee that what we learn about the one we see will be true
754 for the one that overrides it.
756 for (node
= cgraph_nodes
; node
; node
= node
->next
)
757 if (cgraph_function_body_availability (node
) > AVAIL_OVERWRITABLE
)
758 analyze_function (node
);
760 pointer_set_destroy (visited_nodes
);
761 visited_nodes
= NULL
;
764 /* Produce the global information by preforming a transitive closure
765 on the local information that was produced by generate_summary.
766 Note that there is no function_transform pass since this only
767 updates the function_decl. */
772 struct cgraph_node
*node
;
773 struct cgraph_node
*w
;
774 struct cgraph_node
**order
=
775 XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
778 struct ipa_dfs_info
* w_info
;
780 cgraph_remove_function_insertion_hook (function_insertion_hook_holder
);
781 cgraph_remove_node_duplication_hook (node_duplication_hook_holder
);
782 cgraph_remove_node_removal_hook (node_removal_hook_holder
);
783 order_pos
= ipa_utils_reduced_inorder (order
, true, false);
786 dump_cgraph (dump_file
);
787 ipa_utils_print_order(dump_file
, "reduced", order
, order_pos
);
790 /* Propagate the local information thru the call graph to produce
791 the global information. All the nodes within a cycle will have
792 the same info so we collapse cycles first. Then we can do the
793 propagation in one pass from the leaves to the roots. */
794 for (i
= 0; i
< order_pos
; i
++ )
796 enum pure_const_state_e pure_const_state
= IPA_CONST
;
797 bool looping
= false;
801 /* Find the worst state for any node in the cycle. */
805 funct_state w_l
= get_function_state (w
);
806 if (pure_const_state
< w_l
->pure_const_state
)
807 pure_const_state
= w_l
->pure_const_state
;
812 if (pure_const_state
== IPA_NEITHER
)
815 if (!w_l
->state_set_in_source
)
817 struct cgraph_edge
*e
;
823 for (e
= w
->callees
; e
; e
= e
->next_callee
)
825 struct cgraph_node
*y
= e
->callee
;
827 if (cgraph_function_body_availability (y
) > AVAIL_OVERWRITABLE
)
829 funct_state y_l
= get_function_state (y
);
830 if (pure_const_state
< y_l
->pure_const_state
)
831 pure_const_state
= y_l
->pure_const_state
;
832 if (pure_const_state
== IPA_NEITHER
)
839 w_info
= (struct ipa_dfs_info
*) w
->aux
;
840 w
= w_info
->next_cycle
;
843 /* Copy back the region's pure_const_state which is shared by
844 all nodes in the region. */
848 funct_state w_l
= get_function_state (w
);
850 /* All nodes within a cycle share the same info. */
851 if (!w_l
->state_set_in_source
)
853 w_l
->pure_const_state
= pure_const_state
;
854 w_l
->looping
= looping
;
856 switch (pure_const_state
)
859 TREE_READONLY (w
->decl
) = 1;
860 DECL_LOOPING_CONST_OR_PURE_P (w
->decl
) = looping
;
862 fprintf (dump_file
, "Function found to be %sconst: %s\n",
863 looping
? "looping " : "",
864 lang_hooks
.decl_printable_name(w
->decl
, 2));
868 DECL_PURE_P (w
->decl
) = 1;
869 DECL_LOOPING_CONST_OR_PURE_P (w
->decl
) = looping
;
871 fprintf (dump_file
, "Function found to be %spure: %s\n",
872 looping
? "looping " : "",
873 lang_hooks
.decl_printable_name(w
->decl
, 2));
880 w_info
= (struct ipa_dfs_info
*) w
->aux
;
881 w
= w_info
->next_cycle
;
886 for (node
= cgraph_nodes
; node
; node
= node
->next
)
888 /* Get rid of the aux information. */
891 w_info
= (struct ipa_dfs_info
*) node
->aux
;
895 if (cgraph_function_body_availability (node
) > AVAIL_OVERWRITABLE
)
896 free (get_function_state (node
));
900 VEC_free (funct_state
, heap
, funct_state_vec
);
906 gate_pure_const (void)
908 return (flag_ipa_pure_const
909 /* Don't bother doing anything if the program has errors. */
910 && !(errorcount
|| sorrycount
));
913 struct ipa_opt_pass pass_ipa_pure_const
=
917 "pure-const", /* name */
918 gate_pure_const
, /* gate */
919 propagate
, /* execute */
922 0, /* static_pass_number */
923 TV_IPA_PURE_CONST
, /* tv_id */
924 0, /* properties_required */
925 0, /* properties_provided */
926 0, /* properties_destroyed */
927 0, /* todo_flags_start */
928 0 /* todo_flags_finish */
930 generate_summary
, /* generate_summary */
931 NULL
, /* write_summary */
932 NULL
, /* read_summary */
933 NULL
, /* function_read_summary */
935 NULL
, /* function_transform */
936 NULL
/* variable_transform */