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;
74 /* What user set here; we can be always sure about this. */
75 enum pure_const_state_e state_set_in_source;
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. */
88 typedef struct funct_state_d * funct_state;
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
94 /* Array, indexed by cgraph node uid, of function states. */
96 DEF_VEC_P (funct_state);
97 DEF_VEC_ALLOC_P (funct_state, heap);
98 static VEC (funct_state, heap) *funct_state_vec;
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;
105 /* Init the function state. */
110 free (funct_state_vec);
114 /* Return the function state from NODE. */
116 static inline funct_state
117 get_function_state (struct cgraph_node *node)
120 || VEC_length (funct_state, funct_state_vec) <= (unsigned int)node->uid)
122 return VEC_index (funct_state, funct_state_vec, node->uid);
125 /* Set the function state S for NODE. */
128 set_function_state (struct cgraph_node *node, funct_state s)
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);
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. */
140 check_decl (funct_state local,
141 tree t, bool checking_write)
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))
147 local->pure_const_state = IPA_NEITHER;
149 fprintf (dump_file, " Volatile operand is not const/pure");
153 /* Do not care about a local automatic that is not static. */
154 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
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)))
161 local->pure_const_state = IPA_NEITHER;
163 fprintf (dump_file, " Used static/global variable is not const/pure\n");
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
172 local->pure_const_state = IPA_NEITHER;
174 fprintf (dump_file, " static/global memory write is not const/pure\n");
178 if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
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. */
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;
194 /* Compilation level statics can be read if they are readonly
196 if (TREE_READONLY (t))
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;
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. */
212 check_op (funct_state local,
213 tree t, bool checking_write)
215 while (t && handled_component_p (t))
216 t = TREE_OPERAND (t, 0);
219 if (INDIRECT_REF_P (t) || TREE_CODE (t) == TARGET_MEM_REF)
221 if (TREE_THIS_VOLATILE (t))
223 local->pure_const_state = IPA_NEITHER;
225 fprintf (dump_file, " Volatile indirect ref is not const/pure\n");
228 else if (checking_write)
230 local->pure_const_state = IPA_NEITHER;
232 fprintf (dump_file, " Indirect ref write is not const/pure\n");
238 fprintf (dump_file, " Indirect ref read is not const\n");
239 if (local->pure_const_state == IPA_CONST)
240 local->pure_const_state = IPA_PURE;
245 /* Check the parameters of a function call to CALL_EXPR to see if
246 there are any references in the parameters that are not allowed for
247 pure or const functions. Also check to see if this is either an
248 indirect call, a call outside the compilation unit, or has special
249 attributes that may also effect the purity. The CALL_EXPR node for
250 the entire call expression. */
253 check_call (funct_state local, gimple call, bool ipa)
255 int flags = gimple_call_flags (call);
256 tree callee_t = gimple_call_fndecl (call);
257 struct cgraph_node* callee;
258 enum availability avail = AVAIL_NOT_AVAILABLE;
259 bool possibly_throws = stmt_could_throw_p (call);
260 bool possibly_throws_externally = (possibly_throws
261 && stmt_can_throw_external (call));
266 for (i = 0; i < gimple_num_ops (call); i++)
267 if (gimple_op (call, i)
268 && tree_could_throw_p (gimple_op (call, i)))
270 if (possibly_throws && flag_non_call_exceptions)
273 fprintf (dump_file, " operand can throw; looping\n");
274 local->looping = true;
276 if (possibly_throws_externally)
279 fprintf (dump_file, " operand can throw externally\n");
280 local->can_throw = true;
285 /* The const and pure flags are set by a variety of places in the
286 compiler (including here). If someone has already set the flags
287 for the callee, (such as for some of the builtins) we will use
288 them, otherwise we will compute our own information.
290 Const and pure functions have less clobber effects than other
291 functions so we process these first. Otherwise if it is a call
292 outside the compilation unit or an indirect call we punt. This
293 leaves local calls which will be processed by following the call
297 callee = cgraph_node(callee_t);
298 avail = cgraph_function_body_availability (callee);
300 /* When bad things happen to bad functions, they cannot be const
302 if (setjmp_call_p (callee_t))
305 fprintf (dump_file, " setjmp is not const/pure\n");
306 local->looping = true;
307 local->pure_const_state = IPA_NEITHER;
310 if (DECL_BUILT_IN_CLASS (callee_t) == BUILT_IN_NORMAL)
311 switch (DECL_FUNCTION_CODE (callee_t))
313 case BUILT_IN_LONGJMP:
314 case BUILT_IN_NONLOCAL_GOTO:
316 fprintf (dump_file, " longjmp and nonlocal goto is not const/pure\n");
317 local->pure_const_state = IPA_NEITHER;
318 local->looping = true;
325 /* When not in IPA mode, we can still handle self recursion. */
326 if (!ipa && callee_t == current_function_decl)
327 local->looping = true;
328 /* The callee is either unknown (indirect call) or there is just no
329 scannable code for it (external call) . We look to see if there
330 are any bits available for the callee (such as by declaration or
331 because it is builtin) and process solely on the basis of those
333 else if (avail <= AVAIL_OVERWRITABLE || !ipa)
335 if (possibly_throws && flag_non_call_exceptions)
338 fprintf (dump_file, " can throw; looping\n");
339 local->looping = true;
341 if (possibly_throws_externally)
345 fprintf (dump_file, " can throw externally in region %i\n",
346 lookup_stmt_eh_region (call));
348 fprintf (dump_file, " callee:%s\n",
349 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (callee_t)));
351 local->can_throw = true;
353 if (flags & ECF_CONST)
355 if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
356 local->looping = true;
358 else if (flags & ECF_PURE)
360 if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
361 local->looping = true;
363 fprintf (dump_file, " pure function call in not const\n");
364 if (local->pure_const_state == IPA_CONST)
365 local->pure_const_state = IPA_PURE;
370 fprintf (dump_file, " uknown function call is not const/pure\n");
371 local->pure_const_state = IPA_NEITHER;
372 local->looping = true;
375 /* Direct functions calls are handled by IPA propagation. */
378 /* Look into pointer pointed to by GSIP and figure out what interesting side
381 check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
383 gimple stmt = gsi_stmt (*gsip);
388 fprintf (dump_file, " scanning: ");
389 print_gimple_stmt (dump_file, stmt, 0, 0);
392 /* Look for direct loads and stores. */
393 if (gimple_has_lhs (stmt))
395 tree lhs = get_base_address (gimple_get_lhs (stmt));
396 if (lhs && DECL_P (lhs))
397 check_decl (local, lhs, true);
399 if (gimple_assign_single_p (stmt))
401 tree rhs = get_base_address (gimple_assign_rhs1 (stmt));
402 if (rhs && DECL_P (rhs))
403 check_decl (local, rhs, false);
405 else if (is_gimple_call (stmt))
407 for (i = 0; i < gimple_call_num_args (stmt); ++i)
409 tree rhs = get_base_address (gimple_call_arg (stmt, i));
410 if (rhs && DECL_P (rhs))
411 check_decl (local, rhs, false);
414 else if (gimple_code (stmt) == GIMPLE_ASM)
416 for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
418 tree op = TREE_VALUE (gimple_asm_input_op (stmt, i));
419 op = get_base_address (op);
420 if (op && DECL_P (op))
421 check_decl (local, op, false);
423 for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
425 tree op = TREE_VALUE (gimple_asm_output_op (stmt, i));
426 op = get_base_address (op);
427 if (op && DECL_P (op))
428 check_decl (local, op, true);
432 if (gimple_code (stmt) != GIMPLE_CALL
433 && stmt_could_throw_p (stmt))
435 if (flag_non_call_exceptions)
438 fprintf (dump_file, " can throw; looping");
439 local->looping = true;
441 if (stmt_can_throw_external (stmt))
444 fprintf (dump_file, " can throw externally");
445 local->can_throw = true;
448 switch (gimple_code (stmt))
451 check_op (local, gimple_assign_lhs (stmt), true);
455 check_op (local, gimple_call_lhs (stmt), true);
457 check_call (local, stmt, ipa);
460 if (DECL_NONLOCAL (gimple_label_label (stmt)))
461 /* Target of long jump. */
464 fprintf (dump_file, " nonlocal label is not const/pure");
465 local->pure_const_state = IPA_NEITHER;
469 for (i = 0; i < gimple_asm_noutputs (stmt); i++)
470 check_op (local, TREE_VALUE (gimple_asm_output_op (stmt, i)), true);
471 for (i = 0; i < gimple_asm_ninputs (stmt); i++)
472 check_op (local, TREE_VALUE (gimple_asm_input_op (stmt, i)), false);
473 for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
475 tree op = gimple_asm_clobber_op (stmt, i);
476 if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1)
479 fprintf (dump_file, " memory asm clobber is not const/pure");
480 /* Abandon all hope, ye who enter here. */
481 local->pure_const_state = IPA_NEITHER;
484 if (gimple_asm_volatile_p (stmt))
487 fprintf (dump_file, " volatile is not const/pure");
488 /* Abandon all hope, ye who enter here. */
489 local->pure_const_state = IPA_NEITHER;
490 local->looping = true;
497 for (; i < gimple_num_ops (stmt); i++)
498 check_op (local, gimple_op (stmt, i), false);
502 /* This is the main routine for finding the reference patterns for
503 global variables within a function FN. */
506 analyze_function (struct cgraph_node *fn, bool ipa)
508 tree decl = fn->decl;
509 tree old_decl = current_function_decl;
511 basic_block this_block;
513 if (cgraph_function_body_availability (fn) <= AVAIL_OVERWRITABLE)
516 fprintf (dump_file, "Function is not available or overwrittable; not analyzing.\n");
520 l = XCNEW (struct funct_state_d);
521 l->pure_const_state = IPA_CONST;
522 l->state_set_in_source = IPA_NEITHER;
524 l->can_throw = false;
528 fprintf (dump_file, "\n\n local analysis of %s\n ",
529 cgraph_node_name (fn));
532 push_cfun (DECL_STRUCT_FUNCTION (decl));
533 current_function_decl = decl;
535 FOR_EACH_BB (this_block)
537 gimple_stmt_iterator gsi;
538 struct walk_stmt_info wi;
540 memset (&wi, 0, sizeof(wi));
541 for (gsi = gsi_start_bb (this_block);
545 check_stmt (&gsi, l, ipa);
546 if (l->pure_const_state == IPA_NEITHER && l->looping && l->can_throw)
552 if (l->pure_const_state != IPA_NEITHER)
554 /* Const functions cannot have back edges (an
555 indication of possible infinite loop side
557 if (mark_dfs_back_edges ())
562 if (TREE_READONLY (decl))
564 l->pure_const_state = IPA_CONST;
565 l->state_set_in_source = IPA_CONST;
566 if (!DECL_LOOPING_CONST_OR_PURE_P (decl))
569 if (DECL_PURE_P (decl))
571 if (l->pure_const_state != IPA_CONST)
572 l->pure_const_state = IPA_PURE;
573 l->state_set_in_source = IPA_PURE;
574 if (!DECL_LOOPING_CONST_OR_PURE_P (decl))
577 if (TREE_NOTHROW (decl))
578 l->can_throw = false;
581 current_function_decl = old_decl;
585 fprintf (dump_file, "Function is locally looping.\n");
587 fprintf (dump_file, "Function is locally throwing.\n");
588 if (l->pure_const_state == IPA_CONST)
589 fprintf (dump_file, "Function is locally const.\n");
590 if (l->pure_const_state == IPA_PURE)
591 fprintf (dump_file, "Function is locally pure.\n");
596 /* Called when new function is inserted to callgraph late. */
598 add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
600 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
602 /* There are some shared nodes, in particular the initializers on
603 static declarations. We do not need to scan them more than once
604 since all we would be interested in are the addressof
606 visited_nodes = pointer_set_create ();
607 set_function_state (node, analyze_function (node, true));
608 pointer_set_destroy (visited_nodes);
609 visited_nodes = NULL;
612 /* Called when new clone is inserted to callgraph late. */
615 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
616 void *data ATTRIBUTE_UNUSED)
618 if (get_function_state (src))
620 funct_state l = XNEW (struct funct_state_d);
621 gcc_assert (!get_function_state (dst));
622 memcpy (l, get_function_state (src), sizeof (*l));
623 set_function_state (dst, l);
627 /* Called when new clone is inserted to callgraph late. */
630 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
632 if (get_function_state (node))
634 free (get_function_state (node));
635 set_function_state (node, NULL);
640 /* Analyze each function in the cgraph to see if it is locally PURE or
644 generate_summary (void)
646 struct cgraph_node *node;
648 node_removal_hook_holder =
649 cgraph_add_node_removal_hook (&remove_node_data, NULL);
650 node_duplication_hook_holder =
651 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
652 function_insertion_hook_holder =
653 cgraph_add_function_insertion_hook (&add_new_function, NULL);
654 /* There are some shared nodes, in particular the initializers on
655 static declarations. We do not need to scan them more than once
656 since all we would be interested in are the addressof
658 visited_nodes = pointer_set_create ();
660 /* Process all of the functions.
662 We do NOT process any AVAIL_OVERWRITABLE functions, we cannot
663 guarantee that what we learn about the one we see will be true
664 for the one that overrides it.
666 for (node = cgraph_nodes; node; node = node->next)
667 if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
668 set_function_state (node, analyze_function (node, true));
670 pointer_set_destroy (visited_nodes);
671 visited_nodes = NULL;
674 /* Produce the global information by preforming a transitive closure
675 on the local information that was produced by generate_summary.
676 Note that there is no function_transform pass since this only
677 updates the function_decl. */
682 struct cgraph_node *node;
683 struct cgraph_node *w;
684 struct cgraph_node **order =
685 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
688 struct ipa_dfs_info * w_info;
690 cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
691 cgraph_remove_node_duplication_hook (node_duplication_hook_holder);
692 cgraph_remove_node_removal_hook (node_removal_hook_holder);
693 order_pos = ipa_utils_reduced_inorder (order, true, false);
696 dump_cgraph (dump_file);
697 ipa_utils_print_order(dump_file, "reduced", order, order_pos);
700 /* Propagate the local information thru the call graph to produce
701 the global information. All the nodes within a cycle will have
702 the same info so we collapse cycles first. Then we can do the
703 propagation in one pass from the leaves to the roots. */
704 for (i = 0; i < order_pos; i++ )
706 enum pure_const_state_e pure_const_state = IPA_CONST;
707 bool looping = false;
708 bool can_throw = false;
712 /* Find the worst state for any node in the cycle. */
716 struct cgraph_edge *e;
717 funct_state w_l = get_function_state (w);
718 if (pure_const_state < w_l->pure_const_state)
719 pure_const_state = w_l->pure_const_state;
726 if (pure_const_state == IPA_NEITHER
735 for (e = w->callees; e; e = e->next_callee)
737 struct cgraph_node *y = e->callee;
739 if (cgraph_function_body_availability (y) > AVAIL_OVERWRITABLE)
741 funct_state y_l = get_function_state (y);
742 if (pure_const_state < y_l->pure_const_state)
743 pure_const_state = y_l->pure_const_state;
744 if (pure_const_state == IPA_NEITHER
749 if (y_l->can_throw && !TREE_NOTHROW (w->decl)
750 /* FIXME: We should check that the throw can get external.
751 We also should handle only loops formed by can throw external
756 w_info = (struct ipa_dfs_info *) w->aux;
757 w = w_info->next_cycle;
760 /* Copy back the region's pure_const_state which is shared by
761 all nodes in the region. */
765 funct_state w_l = get_function_state (w);
766 enum pure_const_state_e this_state = pure_const_state;
767 bool this_looping = looping;
769 if (w_l->state_set_in_source != IPA_NEITHER)
771 if (this_state > w_l->state_set_in_source)
772 this_state = w_l->state_set_in_source;
773 this_looping = false;
776 /* All nodes within a cycle share the same info. */
777 w_l->pure_const_state = this_state;
778 w_l->looping = this_looping;
783 if (!TREE_READONLY (w->decl) && dump_file)
784 fprintf (dump_file, "Function found to be %sconst: %s\n",
785 this_looping ? "looping " : "",
786 cgraph_node_name (w));
787 TREE_READONLY (w->decl) = 1;
788 DECL_LOOPING_CONST_OR_PURE_P (w->decl) = this_looping;
792 if (!DECL_PURE_P (w->decl) && dump_file)
793 fprintf (dump_file, "Function found to be %spure: %s\n",
794 this_looping ? "looping " : "",
795 cgraph_node_name (w));
796 DECL_PURE_P (w->decl) = 1;
797 DECL_LOOPING_CONST_OR_PURE_P (w->decl) = this_looping;
803 if (!can_throw && !TREE_NOTHROW (w->decl))
805 /* FIXME: TREE_NOTHROW is not set because passmanager will execute
806 verify_ssa and verify_cfg on every function. Before fixup_cfg is done,
807 those functions are going to have NOTHROW calls in EH regions reulting
810 fprintf (dump_file, "Function found to be nothrow: %s\n",
811 cgraph_node_name (w));
813 w_info = (struct ipa_dfs_info *) w->aux;
814 w = w_info->next_cycle;
819 for (node = cgraph_nodes; node; node = node->next)
821 /* Get rid of the aux information. */
824 w_info = (struct ipa_dfs_info *) node->aux;
828 if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
829 free (get_function_state (node));
833 VEC_free (funct_state, heap, funct_state_vec);
839 gate_pure_const (void)
841 return (flag_ipa_pure_const
842 /* Don't bother doing anything if the program has errors. */
843 && !(errorcount || sorrycount));
846 struct ipa_opt_pass pass_ipa_pure_const =
850 "pure-const", /* name */
851 gate_pure_const, /* gate */
852 propagate, /* execute */
855 0, /* static_pass_number */
856 TV_IPA_PURE_CONST, /* tv_id */
857 0, /* properties_required */
858 0, /* properties_provided */
859 0, /* properties_destroyed */
860 0, /* todo_flags_start */
861 0 /* todo_flags_finish */
863 generate_summary, /* generate_summary */
864 NULL, /* write_summary */
865 NULL, /* read_summary */
866 NULL, /* function_read_summary */
868 NULL, /* function_transform */
869 NULL /* variable_transform */
872 /* Simple local pass for pure const discovery reusing the analysis from
873 ipa_pure_const. This pass is effective when executed together with
874 other optimization passes in early optimization pass queue. */
877 local_pure_const (void)
879 bool changed = false;
882 /* Because we do not schedule pass_fixup_cfg over whole program after early optimizations
883 we must not promote functions that are called by already processed functions. */
885 if (function_called_by_processed_nodes_p ())
888 fprintf (dump_file, "Function called in recursive cycle; ignoring\n");
892 l = analyze_function (cgraph_node (current_function_decl), false);
896 fprintf (dump_file, "Function has wrong visibility; ignoring\n");
900 switch (l->pure_const_state)
903 if (!TREE_READONLY (current_function_decl))
905 TREE_READONLY (current_function_decl) = 1;
906 DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = l->looping;
909 fprintf (dump_file, "Function found to be %sconst: %s\n",
910 l->looping ? "looping " : "",
911 lang_hooks.decl_printable_name (current_function_decl,
914 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
917 DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = false;
920 fprintf (dump_file, "Function found to be non-looping: %s\n",
921 lang_hooks.decl_printable_name (current_function_decl,
927 if (!TREE_READONLY (current_function_decl))
929 DECL_PURE_P (current_function_decl) = 1;
930 DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = l->looping;
933 fprintf (dump_file, "Function found to be %spure: %s\n",
934 l->looping ? "looping " : "",
935 lang_hooks.decl_printable_name (current_function_decl,
938 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
941 DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = false;
944 fprintf (dump_file, "Function found to be non-looping: %s\n",
945 lang_hooks.decl_printable_name (current_function_decl,
953 if (!l->can_throw && !TREE_NOTHROW (current_function_decl))
955 TREE_NOTHROW (current_function_decl) = 1;
958 fprintf (dump_file, "Function found to be nothrow: %s\n",
959 lang_hooks.decl_printable_name (current_function_decl,
965 return execute_fixup_cfg ();
970 struct gimple_opt_pass pass_local_pure_const =
974 "local-pure-const", /* name */
975 gate_pure_const, /* gate */
976 local_pure_const, /* execute */
979 0, /* static_pass_number */
980 TV_IPA_PURE_CONST, /* tv_id */
981 0, /* properties_required */
982 0, /* properties_provided */
983 0, /* properties_destroyed */
984 0, /* todo_flags_start */
985 0 /* todo_flags_finish */