1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2014 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 "print-tree.h"
41 #include "basic-block.h"
42 #include "tree-ssa-alias.h"
43 #include "internal-fn.h"
45 #include "gimple-expr.h"
48 #include "gimple-iterator.h"
49 #include "gimple-walk.h"
51 #include "tree-ssa-loop-niter.h"
52 #include "tree-inline.h"
53 #include "tree-pass.h"
54 #include "langhooks.h"
55 #include "ipa-utils.h"
57 #include "diagnostic.h"
58 #include "gimple-pretty-print.h"
59 #include "langhooks.h"
61 #include "lto-streamer.h"
62 #include "data-streamer.h"
63 #include "tree-streamer.h"
65 #include "tree-scalar-evolution.h"
70 /* Lattice values for const and pure functions. Everything starts out
71 being const, then may drop to pure and then neither depending on
73 enum pure_const_state_e
80 const char *pure_const_names
[3] = {"const", "pure", "neither"};
82 /* Holder for the const_state. There is one of these per function
87 enum pure_const_state_e pure_const_state
;
88 /* What user set here; we can be always sure about this. */
89 enum pure_const_state_e state_previously_known
;
90 bool looping_previously_known
;
92 /* True if the function could possibly infinite loop. There are a
93 lot of ways that this could be determined. We are pretty
94 conservative here. While it is possible to cse pure and const
95 calls, it is not legal to have dce get rid of the call if there
96 is a possibility that the call could infinite loop since this is
97 a behavioral change. */
103 /* State used when we know nothing about function. */
104 static struct funct_state_d varying_state
105 = { IPA_NEITHER
, IPA_NEITHER
, true, true, true };
108 typedef struct funct_state_d
* funct_state
;
110 /* The storage of the funct_state is abstracted because there is the
111 possibility that it may be desirable to move this to the cgraph
114 /* Array, indexed by cgraph node uid, of function states. */
116 static vec
<funct_state
> funct_state_vec
;
118 static bool gate_pure_const (void);
122 const pass_data pass_data_ipa_pure_const
=
125 "pure-const", /* name */
126 OPTGROUP_NONE
, /* optinfo_flags */
127 TV_IPA_PURE_CONST
, /* tv_id */
128 0, /* properties_required */
129 0, /* properties_provided */
130 0, /* properties_destroyed */
131 0, /* todo_flags_start */
132 0, /* todo_flags_finish */
135 class pass_ipa_pure_const
: public ipa_opt_pass_d
138 pass_ipa_pure_const(gcc::context
*ctxt
);
140 /* opt_pass methods: */
141 bool gate (function
*) { return gate_pure_const (); }
142 unsigned int execute (function
*fun
);
144 void register_hooks (void);
149 /* Holders of ipa cgraph hooks: */
150 struct cgraph_node_hook_list
*function_insertion_hook_holder
;
151 struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
152 struct cgraph_node_hook_list
*node_removal_hook_holder
;
154 }; // class pass_ipa_pure_const
158 /* Try to guess if function body will always be visible to compiler
159 when compiling the call and whether compiler will be able
160 to propagate the information by itself. */
163 function_always_visible_to_compiler_p (tree decl
)
165 return (!TREE_PUBLIC (decl
) || DECL_DECLARED_INLINE_P (decl
));
168 /* Emit suggestion about attribute ATTRIB_NAME for DECL. KNOWN_FINITE
169 is true if the function is known to be finite. The diagnostic is
170 controlled by OPTION. WARNED_ABOUT is a hash_set<tree> unique for
171 OPTION, this function may initialize it and it is always returned
174 static hash_set
<tree
> *
175 suggest_attribute (int option
, tree decl
, bool known_finite
,
176 hash_set
<tree
> *warned_about
,
177 const char * attrib_name
)
179 if (!option_enabled (option
, &global_options
))
181 if (TREE_THIS_VOLATILE (decl
)
182 || (known_finite
&& function_always_visible_to_compiler_p (decl
)))
186 warned_about
= new hash_set
<tree
>;
187 if (warned_about
->contains (decl
))
189 warned_about
->add (decl
);
190 warning_at (DECL_SOURCE_LOCATION (decl
),
193 ? _("function might be candidate for attribute %<%s%>")
194 : _("function might be candidate for attribute %<%s%>"
195 " if it is known to return normally"), attrib_name
);
199 /* Emit suggestion about __attribute_((pure)) for DECL. KNOWN_FINITE
200 is true if the function is known to be finite. */
203 warn_function_pure (tree decl
, bool known_finite
)
205 static hash_set
<tree
> *warned_about
;
208 = suggest_attribute (OPT_Wsuggest_attribute_pure
, decl
,
209 known_finite
, warned_about
, "pure");
212 /* Emit suggestion about __attribute_((const)) for DECL. KNOWN_FINITE
213 is true if the function is known to be finite. */
216 warn_function_const (tree decl
, bool known_finite
)
218 static hash_set
<tree
> *warned_about
;
220 = suggest_attribute (OPT_Wsuggest_attribute_const
, decl
,
221 known_finite
, warned_about
, "const");
225 warn_function_noreturn (tree decl
)
227 static hash_set
<tree
> *warned_about
;
228 if (!lang_hooks
.missing_noreturn_ok_p (decl
)
229 && targetm
.warn_func_return (decl
))
231 = suggest_attribute (OPT_Wsuggest_attribute_noreturn
, decl
,
232 true, warned_about
, "noreturn");
235 /* Return true if we have a function state for NODE. */
238 has_function_state (struct cgraph_node
*node
)
240 if (!funct_state_vec
.exists ()
241 || funct_state_vec
.length () <= (unsigned int)node
->uid
)
243 return funct_state_vec
[node
->uid
] != NULL
;
246 /* Return the function state from NODE. */
248 static inline funct_state
249 get_function_state (struct cgraph_node
*node
)
251 if (!funct_state_vec
.exists ()
252 || funct_state_vec
.length () <= (unsigned int)node
->uid
253 || !funct_state_vec
[node
->uid
])
254 /* We might want to put correct previously_known state into varying. */
255 return &varying_state
;
256 return funct_state_vec
[node
->uid
];
259 /* Set the function state S for NODE. */
262 set_function_state (struct cgraph_node
*node
, funct_state s
)
264 if (!funct_state_vec
.exists ()
265 || funct_state_vec
.length () <= (unsigned int)node
->uid
)
266 funct_state_vec
.safe_grow_cleared (node
->uid
+ 1);
267 funct_state_vec
[node
->uid
] = s
;
270 /* Check to see if the use (or definition when CHECKING_WRITE is true)
271 variable T is legal in a function that is either pure or const. */
274 check_decl (funct_state local
,
275 tree t
, bool checking_write
, bool ipa
)
277 /* Do not want to do anything with volatile except mark any
278 function that uses one to be not const or pure. */
279 if (TREE_THIS_VOLATILE (t
))
281 local
->pure_const_state
= IPA_NEITHER
;
283 fprintf (dump_file
, " Volatile operand is not const/pure");
287 /* Do not care about a local automatic that is not static. */
288 if (!TREE_STATIC (t
) && !DECL_EXTERNAL (t
))
291 /* If the variable has the "used" attribute, treat it as if it had a
292 been touched by the devil. */
293 if (DECL_PRESERVE_P (t
))
295 local
->pure_const_state
= IPA_NEITHER
;
297 fprintf (dump_file
, " Used static/global variable is not const/pure\n");
301 /* In IPA mode we are not interested in checking actual loads and stores;
302 they will be processed at propagation time using ipa_ref. */
306 /* Since we have dealt with the locals and params cases above, if we
307 are CHECKING_WRITE, this cannot be a pure or constant
311 local
->pure_const_state
= IPA_NEITHER
;
313 fprintf (dump_file
, " static/global memory write is not const/pure\n");
317 if (DECL_EXTERNAL (t
) || TREE_PUBLIC (t
))
319 /* Readonly reads are safe. */
320 if (TREE_READONLY (t
) && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t
)))
321 return; /* Read of a constant, do not change the function state. */
325 fprintf (dump_file
, " global memory read is not const\n");
326 /* Just a regular read. */
327 if (local
->pure_const_state
== IPA_CONST
)
328 local
->pure_const_state
= IPA_PURE
;
333 /* Compilation level statics can be read if they are readonly
335 if (TREE_READONLY (t
))
339 fprintf (dump_file
, " static memory read is not const\n");
340 /* Just a regular read. */
341 if (local
->pure_const_state
== IPA_CONST
)
342 local
->pure_const_state
= IPA_PURE
;
347 /* Check to see if the use (or definition when CHECKING_WRITE is true)
348 variable T is legal in a function that is either pure or const. */
351 check_op (funct_state local
, tree t
, bool checking_write
)
353 t
= get_base_address (t
);
354 if (t
&& TREE_THIS_VOLATILE (t
))
356 local
->pure_const_state
= IPA_NEITHER
;
358 fprintf (dump_file
, " Volatile indirect ref is not const/pure\n");
362 && (INDIRECT_REF_P (t
) || TREE_CODE (t
) == MEM_REF
)
363 && TREE_CODE (TREE_OPERAND (t
, 0)) == SSA_NAME
364 && !ptr_deref_may_alias_global_p (TREE_OPERAND (t
, 0)))
367 fprintf (dump_file
, " Indirect ref to local memory is OK\n");
370 else if (checking_write
)
372 local
->pure_const_state
= IPA_NEITHER
;
374 fprintf (dump_file
, " Indirect ref write is not const/pure\n");
380 fprintf (dump_file
, " Indirect ref read is not const\n");
381 if (local
->pure_const_state
== IPA_CONST
)
382 local
->pure_const_state
= IPA_PURE
;
386 /* compute state based on ECF FLAGS and store to STATE and LOOPING. */
389 state_from_flags (enum pure_const_state_e
*state
, bool *looping
,
390 int flags
, bool cannot_lead_to_return
)
393 if (flags
& ECF_LOOPING_CONST_OR_PURE
)
396 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
397 fprintf (dump_file
, " looping");
399 if (flags
& ECF_CONST
)
402 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
403 fprintf (dump_file
, " const\n");
405 else if (flags
& ECF_PURE
)
408 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
409 fprintf (dump_file
, " pure\n");
411 else if (cannot_lead_to_return
)
415 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
416 fprintf (dump_file
, " ignoring side effects->pure looping\n");
420 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
421 fprintf (dump_file
, " neither\n");
422 *state
= IPA_NEITHER
;
427 /* Merge STATE and STATE2 and LOOPING and LOOPING2 and store
428 into STATE and LOOPING better of the two variants.
429 Be sure to merge looping correctly. IPA_NEITHER functions
430 have looping 0 even if they don't have to return. */
433 better_state (enum pure_const_state_e
*state
, bool *looping
,
434 enum pure_const_state_e state2
, bool looping2
)
438 if (*state
== IPA_NEITHER
)
441 *looping
= MIN (*looping
, looping2
);
444 else if (state2
!= IPA_NEITHER
)
445 *looping
= MIN (*looping
, looping2
);
448 /* Merge STATE and STATE2 and LOOPING and LOOPING2 and store
449 into STATE and LOOPING worse of the two variants. */
452 worse_state (enum pure_const_state_e
*state
, bool *looping
,
453 enum pure_const_state_e state2
, bool looping2
)
455 *state
= MAX (*state
, state2
);
456 *looping
= MAX (*looping
, looping2
);
459 /* Recognize special cases of builtins that are by themselves not pure or const
460 but function using them is. */
462 special_builtin_state (enum pure_const_state_e
*state
, bool *looping
,
465 if (DECL_BUILT_IN_CLASS (callee
) == BUILT_IN_NORMAL
)
466 switch (DECL_FUNCTION_CODE (callee
))
468 case BUILT_IN_RETURN
:
469 case BUILT_IN_UNREACHABLE
:
470 case BUILT_IN_ALLOCA
:
471 case BUILT_IN_ALLOCA_WITH_ALIGN
:
472 case BUILT_IN_STACK_SAVE
:
473 case BUILT_IN_STACK_RESTORE
:
474 case BUILT_IN_EH_POINTER
:
475 case BUILT_IN_EH_FILTER
:
476 case BUILT_IN_UNWIND_RESUME
:
477 case BUILT_IN_CXA_END_CLEANUP
:
478 case BUILT_IN_EH_COPY_VALUES
:
479 case BUILT_IN_FRAME_ADDRESS
:
481 case BUILT_IN_APPLY_ARGS
:
485 case BUILT_IN_PREFETCH
:
495 /* Check the parameters of a function call to CALL_EXPR to see if
496 there are any references in the parameters that are not allowed for
497 pure or const functions. Also check to see if this is either an
498 indirect call, a call outside the compilation unit, or has special
499 attributes that may also effect the purity. The CALL_EXPR node for
500 the entire call expression. */
503 check_call (funct_state local
, gimple call
, bool ipa
)
505 int flags
= gimple_call_flags (call
);
506 tree callee_t
= gimple_call_fndecl (call
);
507 bool possibly_throws
= stmt_could_throw_p (call
);
508 bool possibly_throws_externally
= (possibly_throws
509 && stmt_can_throw_external (call
));
514 for (i
= 0; i
< gimple_num_ops (call
); i
++)
515 if (gimple_op (call
, i
)
516 && tree_could_throw_p (gimple_op (call
, i
)))
518 if (possibly_throws
&& cfun
->can_throw_non_call_exceptions
)
521 fprintf (dump_file
, " operand can throw; looping\n");
522 local
->looping
= true;
524 if (possibly_throws_externally
)
527 fprintf (dump_file
, " operand can throw externally\n");
528 local
->can_throw
= true;
533 /* The const and pure flags are set by a variety of places in the
534 compiler (including here). If someone has already set the flags
535 for the callee, (such as for some of the builtins) we will use
536 them, otherwise we will compute our own information.
538 Const and pure functions have less clobber effects than other
539 functions so we process these first. Otherwise if it is a call
540 outside the compilation unit or an indirect call we punt. This
541 leaves local calls which will be processed by following the call
545 enum pure_const_state_e call_state
;
548 if (special_builtin_state (&call_state
, &call_looping
, callee_t
))
550 worse_state (&local
->pure_const_state
, &local
->looping
,
551 call_state
, call_looping
);
554 /* When bad things happen to bad functions, they cannot be const
556 if (setjmp_call_p (callee_t
))
559 fprintf (dump_file
, " setjmp is not const/pure\n");
560 local
->looping
= true;
561 local
->pure_const_state
= IPA_NEITHER
;
564 if (DECL_BUILT_IN_CLASS (callee_t
) == BUILT_IN_NORMAL
)
565 switch (DECL_FUNCTION_CODE (callee_t
))
567 case BUILT_IN_LONGJMP
:
568 case BUILT_IN_NONLOCAL_GOTO
:
570 fprintf (dump_file
, " longjmp and nonlocal goto is not const/pure\n");
571 local
->pure_const_state
= IPA_NEITHER
;
572 local
->looping
= true;
579 /* When not in IPA mode, we can still handle self recursion. */
581 && recursive_call_p (current_function_decl
, callee_t
))
584 fprintf (dump_file
, " Recursive call can loop.\n");
585 local
->looping
= true;
587 /* Either callee is unknown or we are doing local analysis.
588 Look to see if there are any bits available for the callee (such as by
589 declaration or because it is builtin) and process solely on the basis of
593 enum pure_const_state_e call_state
;
595 if (possibly_throws
&& cfun
->can_throw_non_call_exceptions
)
598 fprintf (dump_file
, " can throw; looping\n");
599 local
->looping
= true;
601 if (possibly_throws_externally
)
605 fprintf (dump_file
, " can throw externally to lp %i\n",
606 lookup_stmt_eh_lp (call
));
608 fprintf (dump_file
, " callee:%s\n",
609 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (callee_t
)));
611 local
->can_throw
= true;
613 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
614 fprintf (dump_file
, " checking flags for call:");
615 state_from_flags (&call_state
, &call_looping
, flags
,
616 ((flags
& (ECF_NORETURN
| ECF_NOTHROW
))
617 == (ECF_NORETURN
| ECF_NOTHROW
))
618 || (!flag_exceptions
&& (flags
& ECF_NORETURN
)));
619 worse_state (&local
->pure_const_state
, &local
->looping
,
620 call_state
, call_looping
);
622 /* Direct functions calls are handled by IPA propagation. */
625 /* Wrapper around check_decl for loads in local more. */
628 check_load (gimple
, tree op
, tree
, void *data
)
631 check_decl ((funct_state
)data
, op
, false, false);
633 check_op ((funct_state
)data
, op
, false);
637 /* Wrapper around check_decl for stores in local more. */
640 check_store (gimple
, tree op
, tree
, void *data
)
643 check_decl ((funct_state
)data
, op
, true, false);
645 check_op ((funct_state
)data
, op
, true);
649 /* Wrapper around check_decl for loads in ipa mode. */
652 check_ipa_load (gimple
, tree op
, tree
, void *data
)
655 check_decl ((funct_state
)data
, op
, false, true);
657 check_op ((funct_state
)data
, op
, false);
661 /* Wrapper around check_decl for stores in ipa mode. */
664 check_ipa_store (gimple
, tree op
, tree
, void *data
)
667 check_decl ((funct_state
)data
, op
, true, true);
669 check_op ((funct_state
)data
, op
, true);
673 /* Look into pointer pointed to by GSIP and figure out what interesting side
676 check_stmt (gimple_stmt_iterator
*gsip
, funct_state local
, bool ipa
)
678 gimple stmt
= gsi_stmt (*gsip
);
680 if (is_gimple_debug (stmt
))
685 fprintf (dump_file
, " scanning: ");
686 print_gimple_stmt (dump_file
, stmt
, 0, 0);
689 if (gimple_has_volatile_ops (stmt
)
690 && !gimple_clobber_p (stmt
))
692 local
->pure_const_state
= IPA_NEITHER
;
694 fprintf (dump_file
, " Volatile stmt is not const/pure\n");
697 /* Look for loads and stores. */
698 walk_stmt_load_store_ops (stmt
, local
,
699 ipa
? check_ipa_load
: check_load
,
700 ipa
? check_ipa_store
: check_store
);
702 if (gimple_code (stmt
) != GIMPLE_CALL
703 && stmt_could_throw_p (stmt
))
705 if (cfun
->can_throw_non_call_exceptions
)
708 fprintf (dump_file
, " can throw; looping\n");
709 local
->looping
= true;
711 if (stmt_can_throw_external (stmt
))
714 fprintf (dump_file
, " can throw externally\n");
715 local
->can_throw
= true;
719 fprintf (dump_file
, " can throw\n");
721 switch (gimple_code (stmt
))
724 check_call (local
, stmt
, ipa
);
727 if (DECL_NONLOCAL (gimple_label_label (stmt
)))
728 /* Target of long jump. */
731 fprintf (dump_file
, " nonlocal label is not const/pure\n");
732 local
->pure_const_state
= IPA_NEITHER
;
736 if (gimple_asm_clobbers_memory_p (stmt
))
739 fprintf (dump_file
, " memory asm clobber is not const/pure\n");
740 /* Abandon all hope, ye who enter here. */
741 local
->pure_const_state
= IPA_NEITHER
;
743 if (gimple_asm_volatile_p (stmt
))
746 fprintf (dump_file
, " volatile is not const/pure\n");
747 /* Abandon all hope, ye who enter here. */
748 local
->pure_const_state
= IPA_NEITHER
;
749 local
->looping
= true;
758 /* This is the main routine for finding the reference patterns for
759 global variables within a function FN. */
762 analyze_function (struct cgraph_node
*fn
, bool ipa
)
764 tree decl
= fn
->decl
;
766 basic_block this_block
;
768 l
= XCNEW (struct funct_state_d
);
769 l
->pure_const_state
= IPA_CONST
;
770 l
->state_previously_known
= IPA_NEITHER
;
771 l
->looping_previously_known
= true;
773 l
->can_throw
= false;
774 state_from_flags (&l
->state_previously_known
, &l
->looping_previously_known
,
775 flags_from_decl_or_type (fn
->decl
),
776 fn
->cannot_return_p ());
778 if (fn
->thunk
.thunk_p
|| fn
->alias
)
780 /* Thunk gets propagated through, so nothing interesting happens. */
787 fprintf (dump_file
, "\n\n local analysis of %s\n ",
791 push_cfun (DECL_STRUCT_FUNCTION (decl
));
793 FOR_EACH_BB_FN (this_block
, cfun
)
795 gimple_stmt_iterator gsi
;
796 struct walk_stmt_info wi
;
798 memset (&wi
, 0, sizeof (wi
));
799 for (gsi
= gsi_start_bb (this_block
);
803 check_stmt (&gsi
, l
, ipa
);
804 if (l
->pure_const_state
== IPA_NEITHER
&& l
->looping
&& l
->can_throw
)
810 if (l
->pure_const_state
!= IPA_NEITHER
)
812 /* Const functions cannot have back edges (an
813 indication of possible infinite loop side
815 if (mark_dfs_back_edges ())
817 /* Preheaders are needed for SCEV to work.
818 Simple latches and recorded exits improve chances that loop will
819 proved to be finite in testcases such as in loop-15.c
821 loop_optimizer_init (LOOPS_HAVE_PREHEADERS
822 | LOOPS_HAVE_SIMPLE_LATCHES
823 | LOOPS_HAVE_RECORDED_EXITS
);
824 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
825 flow_loops_dump (dump_file
, NULL
, 0);
826 if (mark_irreducible_loops ())
829 fprintf (dump_file
, " has irreducible loops\n");
836 FOR_EACH_LOOP (loop
, 0)
837 if (!finite_loop_p (loop
))
840 fprintf (dump_file
, " can not prove finiteness of "
841 "loop %i\n", loop
->num
);
847 loop_optimizer_finalize ();
851 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
852 fprintf (dump_file
, " checking previously known:");
854 better_state (&l
->pure_const_state
, &l
->looping
,
855 l
->state_previously_known
,
856 l
->looping_previously_known
);
857 if (TREE_NOTHROW (decl
))
858 l
->can_throw
= false;
864 fprintf (dump_file
, "Function is locally looping.\n");
866 fprintf (dump_file
, "Function is locally throwing.\n");
867 if (l
->pure_const_state
== IPA_CONST
)
868 fprintf (dump_file
, "Function is locally const.\n");
869 if (l
->pure_const_state
== IPA_PURE
)
870 fprintf (dump_file
, "Function is locally pure.\n");
875 /* Called when new function is inserted to callgraph late. */
877 add_new_function (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
879 if (node
->get_availability () < AVAIL_INTERPOSABLE
)
881 /* There are some shared nodes, in particular the initializers on
882 static declarations. We do not need to scan them more than once
883 since all we would be interested in are the addressof
885 if (node
->get_availability () > AVAIL_INTERPOSABLE
)
886 set_function_state (node
, analyze_function (node
, true));
889 /* Called when new clone is inserted to callgraph late. */
892 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
893 void *data ATTRIBUTE_UNUSED
)
895 if (has_function_state (src
))
897 funct_state l
= XNEW (struct funct_state_d
);
898 gcc_assert (!has_function_state (dst
));
899 memcpy (l
, get_function_state (src
), sizeof (*l
));
900 set_function_state (dst
, l
);
904 /* Called when new clone is inserted to callgraph late. */
907 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
909 if (has_function_state (node
))
911 funct_state l
= get_function_state (node
);
912 if (l
!= &varying_state
)
914 set_function_state (node
, NULL
);
920 pass_ipa_pure_const::
921 register_hooks (void)
928 node_removal_hook_holder
=
929 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
930 node_duplication_hook_holder
=
931 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
932 function_insertion_hook_holder
=
933 symtab
->add_cgraph_insertion_hook (&add_new_function
, NULL
);
937 /* Analyze each function in the cgraph to see if it is locally PURE or
941 pure_const_generate_summary (void)
943 struct cgraph_node
*node
;
945 pass_ipa_pure_const
*pass
= static_cast <pass_ipa_pure_const
*> (current_pass
);
946 pass
->register_hooks ();
948 /* Process all of the functions.
950 We process AVAIL_INTERPOSABLE functions. We can not use the results
951 by default, but the info can be used at LTO with -fwhole-program or
952 when function got cloned and the clone is AVAILABLE. */
954 FOR_EACH_DEFINED_FUNCTION (node
)
955 if (node
->get_availability () >= AVAIL_INTERPOSABLE
)
956 set_function_state (node
, analyze_function (node
, true));
960 /* Serialize the ipa info for lto. */
963 pure_const_write_summary (void)
965 struct cgraph_node
*node
;
966 struct lto_simple_output_block
*ob
967 = lto_create_simple_output_block (LTO_section_ipa_pure_const
);
968 unsigned int count
= 0;
969 lto_symtab_encoder_iterator lsei
;
970 lto_symtab_encoder_t encoder
;
972 encoder
= lto_get_out_decl_state ()->symtab_node_encoder
;
974 for (lsei
= lsei_start_function_in_partition (encoder
); !lsei_end_p (lsei
);
975 lsei_next_function_in_partition (&lsei
))
977 node
= lsei_cgraph_node (lsei
);
978 if (node
->definition
&& has_function_state (node
))
982 streamer_write_uhwi_stream (ob
->main_stream
, count
);
984 /* Process all of the functions. */
985 for (lsei
= lsei_start_function_in_partition (encoder
); !lsei_end_p (lsei
);
986 lsei_next_function_in_partition (&lsei
))
988 node
= lsei_cgraph_node (lsei
);
989 if (node
->definition
&& has_function_state (node
))
994 lto_symtab_encoder_t encoder
;
996 fs
= get_function_state (node
);
998 encoder
= ob
->decl_state
->symtab_node_encoder
;
999 node_ref
= lto_symtab_encoder_encode (encoder
, node
);
1000 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1002 /* Note that flags will need to be read in the opposite
1003 order as we are pushing the bitflags into FLAGS. */
1004 bp
= bitpack_create (ob
->main_stream
);
1005 bp_pack_value (&bp
, fs
->pure_const_state
, 2);
1006 bp_pack_value (&bp
, fs
->state_previously_known
, 2);
1007 bp_pack_value (&bp
, fs
->looping_previously_known
, 1);
1008 bp_pack_value (&bp
, fs
->looping
, 1);
1009 bp_pack_value (&bp
, fs
->can_throw
, 1);
1010 streamer_write_bitpack (&bp
);
1014 lto_destroy_simple_output_block (ob
);
1018 /* Deserialize the ipa info for lto. */
1021 pure_const_read_summary (void)
1023 struct lto_file_decl_data
**file_data_vec
= lto_get_file_decl_data ();
1024 struct lto_file_decl_data
*file_data
;
1027 pass_ipa_pure_const
*pass
= static_cast <pass_ipa_pure_const
*> (current_pass
);
1028 pass
->register_hooks ();
1030 while ((file_data
= file_data_vec
[j
++]))
1034 struct lto_input_block
*ib
1035 = lto_create_simple_input_block (file_data
,
1036 LTO_section_ipa_pure_const
,
1041 unsigned int count
= streamer_read_uhwi (ib
);
1043 for (i
= 0; i
< count
; i
++)
1046 struct cgraph_node
*node
;
1047 struct bitpack_d bp
;
1049 lto_symtab_encoder_t encoder
;
1051 fs
= XCNEW (struct funct_state_d
);
1052 index
= streamer_read_uhwi (ib
);
1053 encoder
= file_data
->symtab_node_encoder
;
1054 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref (encoder
,
1056 set_function_state (node
, fs
);
1058 /* Note that the flags must be read in the opposite
1059 order in which they were written (the bitflags were
1060 pushed into FLAGS). */
1061 bp
= streamer_read_bitpack (ib
);
1062 fs
->pure_const_state
1063 = (enum pure_const_state_e
) bp_unpack_value (&bp
, 2);
1064 fs
->state_previously_known
1065 = (enum pure_const_state_e
) bp_unpack_value (&bp
, 2);
1066 fs
->looping_previously_known
= bp_unpack_value (&bp
, 1);
1067 fs
->looping
= bp_unpack_value (&bp
, 1);
1068 fs
->can_throw
= bp_unpack_value (&bp
, 1);
1071 int flags
= flags_from_decl_or_type (node
->decl
);
1072 fprintf (dump_file
, "Read info for %s/%i ",
1075 if (flags
& ECF_CONST
)
1076 fprintf (dump_file
, " const");
1077 if (flags
& ECF_PURE
)
1078 fprintf (dump_file
, " pure");
1079 if (flags
& ECF_NOTHROW
)
1080 fprintf (dump_file
, " nothrow");
1081 fprintf (dump_file
, "\n pure const state: %s\n",
1082 pure_const_names
[fs
->pure_const_state
]);
1083 fprintf (dump_file
, " previously known state: %s\n",
1084 pure_const_names
[fs
->looping_previously_known
]);
1086 fprintf (dump_file
," function is locally looping\n");
1087 if (fs
->looping_previously_known
)
1088 fprintf (dump_file
," function is previously known looping\n");
1090 fprintf (dump_file
," function is locally throwing\n");
1094 lto_destroy_simple_input_block (file_data
,
1095 LTO_section_ipa_pure_const
,
1103 ignore_edge (struct cgraph_edge
*e
)
1105 return (!e
->can_throw_external
);
1108 /* Return true if NODE is self recursive function.
1109 Indirectly recursive functions appears as non-trivial strongly
1110 connected components, so we need to care about self recursion
1114 self_recursive_p (struct cgraph_node
*node
)
1116 struct cgraph_edge
*e
;
1117 for (e
= node
->callees
; e
; e
= e
->next_callee
)
1118 if (e
->callee
->function_symbol () == node
)
1123 /* Produce transitive closure over the callgraph and compute pure/const
1127 propagate_pure_const (void)
1129 struct cgraph_node
*node
;
1130 struct cgraph_node
*w
;
1131 struct cgraph_node
**order
=
1132 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
1135 struct ipa_dfs_info
* w_info
;
1137 order_pos
= ipa_reduced_postorder (order
, true, false, NULL
);
1140 cgraph_node::dump_cgraph (dump_file
);
1141 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
1144 /* Propagate the local information through the call graph to produce
1145 the global information. All the nodes within a cycle will have
1146 the same info so we collapse cycles first. Then we can do the
1147 propagation in one pass from the leaves to the roots. */
1148 for (i
= 0; i
< order_pos
; i
++ )
1150 enum pure_const_state_e pure_const_state
= IPA_CONST
;
1151 bool looping
= false;
1158 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1159 fprintf (dump_file
, "Starting cycle\n");
1161 /* Find the worst state for any node in the cycle. */
1163 while (w
&& pure_const_state
!= IPA_NEITHER
)
1165 struct cgraph_edge
*e
;
1166 struct cgraph_edge
*ie
;
1168 struct ipa_ref
*ref
= NULL
;
1170 funct_state w_l
= get_function_state (w
);
1171 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1172 fprintf (dump_file
, " Visiting %s/%i state:%s looping %i\n",
1175 pure_const_names
[w_l
->pure_const_state
],
1178 /* First merge in function body properties. */
1179 worse_state (&pure_const_state
, &looping
,
1180 w_l
->pure_const_state
, w_l
->looping
);
1181 if (pure_const_state
== IPA_NEITHER
)
1184 /* For overwritable nodes we can not assume anything. */
1185 if (w
->get_availability () == AVAIL_INTERPOSABLE
)
1187 worse_state (&pure_const_state
, &looping
,
1188 w_l
->state_previously_known
,
1189 w_l
->looping_previously_known
);
1190 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1193 " Overwritable. state %s looping %i\n",
1194 pure_const_names
[w_l
->state_previously_known
],
1195 w_l
->looping_previously_known
);
1202 /* We consider recursive cycles as possibly infinite.
1203 This might be relaxed since infinite recursion leads to stack
1208 /* Now walk the edges and merge in callee properties. */
1209 for (e
= w
->callees
; e
; e
= e
->next_callee
)
1211 enum availability avail
;
1212 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
1213 enum pure_const_state_e edge_state
= IPA_CONST
;
1214 bool edge_looping
= false;
1216 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1223 if (avail
> AVAIL_INTERPOSABLE
)
1225 funct_state y_l
= get_function_state (y
);
1226 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1229 " state:%s looping:%i\n",
1230 pure_const_names
[y_l
->pure_const_state
],
1233 if (y_l
->pure_const_state
> IPA_PURE
1234 && e
->cannot_lead_to_return_p ())
1236 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1238 " Ignoring side effects"
1239 " -> pure, looping\n");
1240 edge_state
= IPA_PURE
;
1241 edge_looping
= true;
1245 edge_state
= y_l
->pure_const_state
;
1246 edge_looping
= y_l
->looping
;
1249 else if (special_builtin_state (&edge_state
, &edge_looping
,
1253 state_from_flags (&edge_state
, &edge_looping
,
1254 flags_from_decl_or_type (y
->decl
),
1255 e
->cannot_lead_to_return_p ());
1257 /* Merge the results with what we already know. */
1258 better_state (&edge_state
, &edge_looping
,
1259 w_l
->state_previously_known
,
1260 w_l
->looping_previously_known
);
1261 worse_state (&pure_const_state
, &looping
,
1262 edge_state
, edge_looping
);
1263 if (pure_const_state
== IPA_NEITHER
)
1266 if (pure_const_state
== IPA_NEITHER
)
1269 /* Now process the indirect call. */
1270 for (ie
= w
->indirect_calls
; ie
; ie
= ie
->next_callee
)
1272 enum pure_const_state_e edge_state
= IPA_CONST
;
1273 bool edge_looping
= false;
1275 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1276 fprintf (dump_file
, " Indirect call");
1277 state_from_flags (&edge_state
, &edge_looping
,
1278 ie
->indirect_info
->ecf_flags
,
1279 ie
->cannot_lead_to_return_p ());
1280 /* Merge the results with what we already know. */
1281 better_state (&edge_state
, &edge_looping
,
1282 w_l
->state_previously_known
,
1283 w_l
->looping_previously_known
);
1284 worse_state (&pure_const_state
, &looping
,
1285 edge_state
, edge_looping
);
1286 if (pure_const_state
== IPA_NEITHER
)
1289 if (pure_const_state
== IPA_NEITHER
)
1292 /* And finally all loads and stores. */
1293 for (i
= 0; w
->iterate_reference (i
, ref
); i
++)
1295 enum pure_const_state_e ref_state
= IPA_CONST
;
1296 bool ref_looping
= false;
1300 /* readonly reads are safe. */
1301 if (TREE_READONLY (ref
->referred
->decl
))
1303 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1304 fprintf (dump_file
, " nonreadonly global var read\n");
1305 ref_state
= IPA_PURE
;
1308 if (ref
->cannot_lead_to_return ())
1310 ref_state
= IPA_NEITHER
;
1311 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1312 fprintf (dump_file
, " global var write\n");
1319 better_state (&ref_state
, &ref_looping
,
1320 w_l
->state_previously_known
,
1321 w_l
->looping_previously_known
);
1322 worse_state (&pure_const_state
, &looping
,
1323 ref_state
, ref_looping
);
1324 if (pure_const_state
== IPA_NEITHER
)
1327 w_info
= (struct ipa_dfs_info
*) w
->aux
;
1328 w
= w_info
->next_cycle
;
1330 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
1331 fprintf (dump_file
, "Result %s looping %i\n",
1332 pure_const_names
[pure_const_state
],
1335 /* Copy back the region's pure_const_state which is shared by
1336 all nodes in the region. */
1340 funct_state w_l
= get_function_state (w
);
1341 enum pure_const_state_e this_state
= pure_const_state
;
1342 bool this_looping
= looping
;
1344 if (w_l
->state_previously_known
!= IPA_NEITHER
1345 && this_state
> w_l
->state_previously_known
)
1347 this_state
= w_l
->state_previously_known
;
1348 this_looping
|= w_l
->looping_previously_known
;
1350 if (!this_looping
&& self_recursive_p (w
))
1351 this_looping
= true;
1352 if (!w_l
->looping_previously_known
)
1353 this_looping
= false;
1355 /* All nodes within a cycle share the same info. */
1356 w_l
->pure_const_state
= this_state
;
1357 w_l
->looping
= this_looping
;
1359 /* Inline clones share declaration with their offline copies;
1360 do not modify their declarations since the offline copy may
1362 if (!w
->global
.inlined_to
)
1366 if (!TREE_READONLY (w
->decl
))
1368 warn_function_const (w
->decl
, !this_looping
);
1370 fprintf (dump_file
, "Function found to be %sconst: %s\n",
1371 this_looping
? "looping " : "",
1374 w
->set_const_flag (true, this_looping
);
1378 if (!DECL_PURE_P (w
->decl
))
1380 warn_function_pure (w
->decl
, !this_looping
);
1382 fprintf (dump_file
, "Function found to be %spure: %s\n",
1383 this_looping
? "looping " : "",
1386 w
->set_pure_flag (true, this_looping
);
1392 w_info
= (struct ipa_dfs_info
*) w
->aux
;
1393 w
= w_info
->next_cycle
;
1397 ipa_free_postorder_info ();
1401 /* Produce transitive closure over the callgraph and compute nothrow
1405 propagate_nothrow (void)
1407 struct cgraph_node
*node
;
1408 struct cgraph_node
*w
;
1409 struct cgraph_node
**order
=
1410 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
1413 struct ipa_dfs_info
* w_info
;
1415 order_pos
= ipa_reduced_postorder (order
, true, false, ignore_edge
);
1418 cgraph_node::dump_cgraph (dump_file
);
1419 ipa_print_order (dump_file
, "reduced for nothrow", order
, order_pos
);
1422 /* Propagate the local information through the call graph to produce
1423 the global information. All the nodes within a cycle will have
1424 the same info so we collapse cycles first. Then we can do the
1425 propagation in one pass from the leaves to the roots. */
1426 for (i
= 0; i
< order_pos
; i
++ )
1428 bool can_throw
= false;
1434 /* Find the worst state for any node in the cycle. */
1438 struct cgraph_edge
*e
, *ie
;
1439 funct_state w_l
= get_function_state (w
);
1442 || w
->get_availability () == AVAIL_INTERPOSABLE
)
1448 for (e
= w
->callees
; e
; e
= e
->next_callee
)
1450 enum availability avail
;
1451 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
1453 if (avail
> AVAIL_INTERPOSABLE
)
1455 funct_state y_l
= get_function_state (y
);
1459 if (y_l
->can_throw
&& !TREE_NOTHROW (w
->decl
)
1460 && e
->can_throw_external
)
1463 else if (e
->can_throw_external
&& !TREE_NOTHROW (y
->decl
))
1466 for (ie
= node
->indirect_calls
; ie
; ie
= ie
->next_callee
)
1467 if (ie
->can_throw_external
)
1472 w_info
= (struct ipa_dfs_info
*) w
->aux
;
1473 w
= w_info
->next_cycle
;
1476 /* Copy back the region's pure_const_state which is shared by
1477 all nodes in the region. */
1481 funct_state w_l
= get_function_state (w
);
1482 if (!can_throw
&& !TREE_NOTHROW (w
->decl
))
1484 /* Inline clones share declaration with their offline copies;
1485 do not modify their declarations since the offline copy may
1487 if (!w
->global
.inlined_to
)
1489 w
->set_nothrow_flag (true);
1491 fprintf (dump_file
, "Function found to be nothrow: %s\n",
1495 else if (can_throw
&& !TREE_NOTHROW (w
->decl
))
1496 w_l
->can_throw
= true;
1497 w_info
= (struct ipa_dfs_info
*) w
->aux
;
1498 w
= w_info
->next_cycle
;
1502 ipa_free_postorder_info ();
1507 /* Produce the global information by preforming a transitive closure
1508 on the local information that was produced by generate_summary. */
1511 pass_ipa_pure_const::
1512 execute (function
*)
1514 struct cgraph_node
*node
;
1516 symtab
->remove_cgraph_insertion_hook (function_insertion_hook_holder
);
1517 symtab
->remove_cgraph_duplication_hook (node_duplication_hook_holder
);
1518 symtab
->remove_cgraph_removal_hook (node_removal_hook_holder
);
1520 /* Nothrow makes more function to not lead to return and improve
1522 propagate_nothrow ();
1523 propagate_pure_const ();
1526 FOR_EACH_FUNCTION (node
)
1527 if (has_function_state (node
))
1528 free (get_function_state (node
));
1529 funct_state_vec
.release ();
1534 gate_pure_const (void)
1536 return (flag_ipa_pure_const
1537 /* Don't bother doing anything if the program has errors. */
1541 pass_ipa_pure_const::pass_ipa_pure_const(gcc::context
*ctxt
)
1542 : ipa_opt_pass_d(pass_data_ipa_pure_const
, ctxt
,
1543 pure_const_generate_summary
, /* generate_summary */
1544 pure_const_write_summary
, /* write_summary */
1545 pure_const_read_summary
, /* read_summary */
1546 NULL
, /* write_optimization_summary */
1547 NULL
, /* read_optimization_summary */
1548 NULL
, /* stmt_fixup */
1549 0, /* function_transform_todo_flags_start */
1550 NULL
, /* function_transform */
1551 NULL
), /* variable_transform */
1553 function_insertion_hook_holder(NULL
),
1554 node_duplication_hook_holder(NULL
),
1555 node_removal_hook_holder(NULL
)
1560 make_pass_ipa_pure_const (gcc::context
*ctxt
)
1562 return new pass_ipa_pure_const (ctxt
);
1565 /* Return true if function should be skipped for local pure const analysis. */
1568 skip_function_for_local_pure_const (struct cgraph_node
*node
)
1570 /* Because we do not schedule pass_fixup_cfg over whole program after early optimizations
1571 we must not promote functions that are called by already processed functions. */
1573 if (function_called_by_processed_nodes_p ())
1576 fprintf (dump_file
, "Function called in recursive cycle; ignoring\n");
1579 if (node
->get_availability () <= AVAIL_INTERPOSABLE
)
1582 fprintf (dump_file
, "Function is not available or overwritable; not analyzing.\n");
1588 /* Simple local pass for pure const discovery reusing the analysis from
1589 ipa_pure_const. This pass is effective when executed together with
1590 other optimization passes in early optimization pass queue. */
1594 const pass_data pass_data_local_pure_const
=
1596 GIMPLE_PASS
, /* type */
1597 "local-pure-const", /* name */
1598 OPTGROUP_NONE
, /* optinfo_flags */
1599 TV_IPA_PURE_CONST
, /* tv_id */
1600 0, /* properties_required */
1601 0, /* properties_provided */
1602 0, /* properties_destroyed */
1603 0, /* todo_flags_start */
1604 0, /* todo_flags_finish */
1607 class pass_local_pure_const
: public gimple_opt_pass
1610 pass_local_pure_const (gcc::context
*ctxt
)
1611 : gimple_opt_pass (pass_data_local_pure_const
, ctxt
)
1614 /* opt_pass methods: */
1615 opt_pass
* clone () { return new pass_local_pure_const (m_ctxt
); }
1616 virtual bool gate (function
*) { return gate_pure_const (); }
1617 virtual unsigned int execute (function
*);
1619 }; // class pass_local_pure_const
1622 pass_local_pure_const::execute (function
*fun
)
1624 bool changed
= false;
1627 struct cgraph_node
*node
;
1629 node
= cgraph_node::get (current_function_decl
);
1630 skip
= skip_function_for_local_pure_const (node
);
1631 if (!warn_suggest_attribute_const
1632 && !warn_suggest_attribute_pure
1636 l
= analyze_function (node
, false);
1638 /* Do NORETURN discovery. */
1639 if (!skip
&& !TREE_THIS_VOLATILE (current_function_decl
)
1640 && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun
)->preds
) == 0)
1642 warn_function_noreturn (fun
->decl
);
1644 fprintf (dump_file
, "Function found to be noreturn: %s\n",
1645 current_function_name ());
1647 /* Update declaration and reduce profile to executed once. */
1648 TREE_THIS_VOLATILE (current_function_decl
) = 1;
1649 if (node
->frequency
> NODE_FREQUENCY_EXECUTED_ONCE
)
1650 node
->frequency
= NODE_FREQUENCY_EXECUTED_ONCE
;
1655 switch (l
->pure_const_state
)
1658 if (!TREE_READONLY (current_function_decl
))
1660 warn_function_const (current_function_decl
, !l
->looping
);
1663 node
->set_const_flag (true, l
->looping
);
1667 fprintf (dump_file
, "Function found to be %sconst: %s\n",
1668 l
->looping
? "looping " : "",
1669 current_function_name ());
1671 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl
)
1676 node
->set_const_flag (true, false);
1680 fprintf (dump_file
, "Function found to be non-looping: %s\n",
1681 current_function_name ());
1686 if (!DECL_PURE_P (current_function_decl
))
1690 node
->set_pure_flag (true, l
->looping
);
1693 warn_function_pure (current_function_decl
, !l
->looping
);
1695 fprintf (dump_file
, "Function found to be %spure: %s\n",
1696 l
->looping
? "looping " : "",
1697 current_function_name ());
1699 else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl
)
1704 node
->set_pure_flag (true, false);
1708 fprintf (dump_file
, "Function found to be non-looping: %s\n",
1709 current_function_name ());
1716 if (!l
->can_throw
&& !TREE_NOTHROW (current_function_decl
))
1718 node
->set_nothrow_flag (true);
1721 fprintf (dump_file
, "Function found to be nothrow: %s\n",
1722 current_function_name ());
1726 return execute_fixup_cfg ();
1734 make_pass_local_pure_const (gcc::context
*ctxt
)
1736 return new pass_local_pure_const (ctxt
);
1739 /* Emit noreturn warnings. */
1743 const pass_data pass_data_warn_function_noreturn
=
1745 GIMPLE_PASS
, /* type */
1746 "*warn_function_noreturn", /* name */
1747 OPTGROUP_NONE
, /* optinfo_flags */
1748 TV_NONE
, /* tv_id */
1749 PROP_cfg
, /* properties_required */
1750 0, /* properties_provided */
1751 0, /* properties_destroyed */
1752 0, /* todo_flags_start */
1753 0, /* todo_flags_finish */
1756 class pass_warn_function_noreturn
: public gimple_opt_pass
1759 pass_warn_function_noreturn (gcc::context
*ctxt
)
1760 : gimple_opt_pass (pass_data_warn_function_noreturn
, ctxt
)
1763 /* opt_pass methods: */
1764 virtual bool gate (function
*) { return warn_suggest_attribute_noreturn
; }
1765 virtual unsigned int execute (function
*fun
)
1767 if (!TREE_THIS_VOLATILE (current_function_decl
)
1768 && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun
)->preds
) == 0)
1769 warn_function_noreturn (current_function_decl
);
1773 }; // class pass_warn_function_noreturn
1778 make_pass_warn_function_noreturn (gcc::context
*ctxt
)
1780 return new pass_warn_function_noreturn (ctxt
);