Mercurial > hg > CbC > CbC_gcc
diff gcc/ipa-pure-const.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/ipa-pure-const.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/ipa-pure-const.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* Callgraph based analysis of static variables. - Copyright (C) 2004-2018 Free Software Foundation, Inc. + Copyright (C) 2004-2020 Free Software Foundation, Inc. Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> This file is part of GCC. @@ -122,17 +122,18 @@ enum malloc_state_e malloc_state; }; -typedef struct funct_state_d * funct_state; +typedef class funct_state_d * funct_state; /* The storage of the funct_state is abstracted because there is the possibility that it may be desirable to move this to the cgraph local info. */ -class funct_state_summary_t: public function_summary <funct_state_d *> +class funct_state_summary_t: + public fast_function_summary <funct_state_d *, va_heap> { public: funct_state_summary_t (symbol_table *symtab): - function_summary <funct_state_d *> (symtab) {} + fast_function_summary <funct_state_d *, va_heap> (symtab) {} virtual void insert (cgraph_node *, funct_state_d *state); virtual void duplicate (cgraph_node *src_node, cgraph_node *dst_node, @@ -198,7 +199,7 @@ hash_set<tree> *warned_about, const char * attrib_name) { - if (!option_enabled (option, &global_options)) + if (!option_enabled (option, lang_hooks.option_lang_mask (), &global_options)) return warned_about; if (TREE_THIS_VOLATILE (decl) || (known_finite && function_always_visible_to_compiler_p (decl))) @@ -339,7 +340,7 @@ if (DECL_EXTERNAL (t) || TREE_PUBLIC (t)) { /* Readonly reads are safe. */ - if (TREE_READONLY (t) && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t))) + if (TREE_READONLY (t)) return; /* Read of a constant, do not change the function state. */ else { @@ -499,7 +500,7 @@ { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Dropping state to PURE because call to %s may not " - "bind to current def.\n", to->name ()); + "bind to current def.\n", to->dump_name ()); state2 = IPA_PURE; } *state = MAX (*state, state2); @@ -510,35 +511,34 @@ but function using them is. */ static bool special_builtin_state (enum pure_const_state_e *state, bool *looping, - tree callee) + tree callee) { if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (callee)) { - case BUILT_IN_RETURN: - case BUILT_IN_UNREACHABLE: - CASE_BUILT_IN_ALLOCA: - case BUILT_IN_STACK_SAVE: - case BUILT_IN_STACK_RESTORE: - case BUILT_IN_EH_POINTER: - case BUILT_IN_EH_FILTER: - case BUILT_IN_UNWIND_RESUME: - case BUILT_IN_CXA_END_CLEANUP: - case BUILT_IN_EH_COPY_VALUES: - case BUILT_IN_FRAME_ADDRESS: - case BUILT_IN_APPLY: - case BUILT_IN_APPLY_ARGS: - case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT: - case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT: - *looping = false; - *state = IPA_CONST; - return true; - case BUILT_IN_PREFETCH: - *looping = true; - *state = IPA_CONST; - return true; - default: - break; + case BUILT_IN_RETURN: + case BUILT_IN_UNREACHABLE: + CASE_BUILT_IN_ALLOCA: + case BUILT_IN_STACK_SAVE: + case BUILT_IN_STACK_RESTORE: + case BUILT_IN_EH_POINTER: + case BUILT_IN_EH_FILTER: + case BUILT_IN_UNWIND_RESUME: + case BUILT_IN_CXA_END_CLEANUP: + case BUILT_IN_EH_COPY_VALUES: + case BUILT_IN_FRAME_ADDRESS: + case BUILT_IN_APPLY_ARGS: + case BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT: + case BUILT_IN_ASAN_AFTER_DYNAMIC_INIT: + *looping = false; + *state = IPA_CONST; + return true; + case BUILT_IN_PREFETCH: + *looping = true; + *state = IPA_CONST; + return true; + default: + break; } return false; } @@ -623,9 +623,10 @@ case BUILT_IN_LONGJMP: case BUILT_IN_NONLOCAL_GOTO: if (dump_file) - fprintf (dump_file, " longjmp and nonlocal goto is not const/pure\n"); + fprintf (dump_file, + " longjmp and nonlocal goto is not const/pure\n"); local->pure_const_state = IPA_NEITHER; - local->looping = true; + local->looping = true; break; default: break; @@ -873,14 +874,17 @@ { \ if (dump_file && (dump_flags & TDF_DETAILS)) \ fprintf (dump_file, "\n%s is not a malloc candidate, reason: %s\n", \ - (node->name()), (reason)); \ + (node->dump_name ()), (reason)); \ return false; \ } static bool -malloc_candidate_p_1 (function *fun, tree retval, gimple *ret_stmt, bool ipa) +malloc_candidate_p_1 (function *fun, tree retval, gimple *ret_stmt, bool ipa, + bitmap visited) { cgraph_node *node = cgraph_node::get_create (fun->decl); + if (!bitmap_set_bit (visited, SSA_NAME_VERSION (retval))) + return true; if (!check_retval_uses (retval, ret_stmt)) DUMP_AND_RETURN("Return value has uses outside return stmt" @@ -925,7 +929,7 @@ gimple *arg_def = SSA_NAME_DEF_STMT (arg); if (is_a<gphi *> (arg_def)) { - if (!malloc_candidate_p_1 (fun, arg, phi, ipa)) + if (!malloc_candidate_p_1 (fun, arg, phi, ipa, visited)) DUMP_AND_RETURN ("nested phi fail") continue; } @@ -971,6 +975,7 @@ || !flag_delete_null_pointer_checks) return false; + auto_bitmap visited; FOR_EACH_EDGE (e, ei, exit_block->preds) { gimple_stmt_iterator gsi = gsi_last_bb (e->src); @@ -987,7 +992,7 @@ || TREE_CODE (TREE_TYPE (retval)) != POINTER_TYPE) DUMP_AND_RETURN("Return value is not SSA_NAME or not a pointer type.") - if (!malloc_candidate_p_1 (fun, retval, ret_stmt, ipa)) + if (!malloc_candidate_p_1 (fun, retval, ret_stmt, ipa, visited)) return false; } @@ -1009,7 +1014,7 @@ funct_state l; basic_block this_block; - l = XCNEW (struct funct_state_d); + l = XCNEW (class funct_state_d); l->pure_const_state = IPA_CONST; l->state_previously_known = IPA_NEITHER; l->looping_previously_known = true; @@ -1032,7 +1037,7 @@ if (dump_file) { fprintf (dump_file, "\n\n local analysis of %s\n ", - fn->name ()); + fn->dump_name ()); } push_cfun (DECL_STRUCT_FUNCTION (decl)); @@ -1081,13 +1086,13 @@ } else { - struct loop *loop; + class loop *loop; scev_initialize (); FOR_EACH_LOOP (loop, 0) if (!finite_loop_p (loop)) { if (dump_file) - fprintf (dump_file, " can not prove finiteness of " + fprintf (dump_file, " cannot prove finiteness of " "loop %i\n", loop->num); l->looping =true; break; @@ -1186,7 +1191,7 @@ /* Process all of the functions. - We process AVAIL_INTERPOSABLE functions. We can not use the results + We process AVAIL_INTERPOSABLE functions. We cannot use the results by default, but the info can be used at LTO with -fwhole-program or when function got cloned and the clone is AVAILABLE. */ @@ -1274,7 +1279,7 @@ { const char *data; size_t len; - struct lto_input_block *ib + class lto_input_block *ib = lto_create_simple_input_block (file_data, LTO_section_ipa_pure_const, &data, &len); @@ -1356,12 +1361,14 @@ return true; enum availability avail; - cgraph_node *n = e->callee->function_or_virtual_thunk_symbol (&avail, - e->caller); - if (avail <= AVAIL_INTERPOSABLE || TREE_NOTHROW (n->decl)) + cgraph_node *ultimate_target + = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller); + if (avail <= AVAIL_INTERPOSABLE || TREE_NOTHROW (ultimate_target->decl)) return true; - return opt_for_fn (e->callee->decl, flag_non_call_exceptions) - && !e->callee->binds_to_current_def_p (e->caller); + return ((opt_for_fn (e->callee->decl, flag_non_call_exceptions) + && !e->callee->binds_to_current_def_p (e->caller)) + || !opt_for_fn (e->caller->decl, flag_ipa_pure_const) + || !opt_for_fn (ultimate_target->decl, flag_ipa_pure_const)); } /* Return true if NODE is self recursive function. @@ -1391,17 +1398,22 @@ return false; } -/* We only propagate across edges with non-interposable callee. */ +/* Skip edges from and to nodes without ipa_pure_const enabled. + Ignore not available symbols. */ static bool ignore_edge_for_pure_const (struct cgraph_edge *e) { enum availability avail; - e->callee->function_or_virtual_thunk_symbol (&avail, e->caller); - return (avail <= AVAIL_INTERPOSABLE); + cgraph_node *ultimate_target + = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller); + + return (avail <= AVAIL_INTERPOSABLE + || !opt_for_fn (e->caller->decl, flag_ipa_pure_const) + || !opt_for_fn (ultimate_target->decl, + flag_ipa_pure_const)); } - /* Produce transitive closure over the callgraph and compute pure/const attributes. */ @@ -1418,7 +1430,7 @@ bool remove_p = false; bool has_cdtor; - order_pos = ipa_reduced_postorder (order, true, false, + order_pos = ipa_reduced_postorder (order, true, ignore_edge_for_pure_const); if (dump_file) { @@ -1494,7 +1506,8 @@ } if (avail > AVAIL_INTERPOSABLE) { - funct_state y_l = funct_state_summaries->get (y); + funct_state y_l = funct_state_summaries->get_create (y); + if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, @@ -1519,7 +1532,7 @@ } } else if (special_builtin_state (&edge_state, &edge_looping, - y->decl)) + y->decl)) ; else state_from_flags (&edge_state, &edge_looping, @@ -1644,7 +1657,7 @@ w->nonfreeing_fn = !can_free; if (!can_free && dump_file) fprintf (dump_file, "Function found not to call free: %s\n", - w->name ()); + w->dump_name ()); if (w_l->state_previously_known != IPA_NEITHER && this_state > w_l->state_previously_known) @@ -1665,7 +1678,7 @@ /* Inline clones share declaration with their offline copies; do not modify their declarations since the offline copy may be different. */ - if (!w->global.inlined_to) + if (!w->inlined_to) switch (this_state) { case IPA_CONST: @@ -1675,7 +1688,7 @@ if (dump_file) fprintf (dump_file, "Function found to be %sconst: %s\n", this_looping ? "looping " : "", - w->name ()); + w->dump_name ()); } /* Turning constructor or destructor to non-looping const/pure enables us to possibly remove the function completely. */ @@ -1690,7 +1703,7 @@ fprintf (dump_file, "Declaration updated to be %sconst: %s\n", this_looping ? "looping " : "", - w->name ()); + w->dump_name ()); remove_p |= has_cdtor; } break; @@ -1702,7 +1715,7 @@ if (dump_file) fprintf (dump_file, "Function found to be %spure: %s\n", this_looping ? "looping " : "", - w->name ()); + w->dump_name ()); } if (this_looping) has_cdtor = false; @@ -1715,7 +1728,7 @@ fprintf (dump_file, "Declaration updated to be %spure: %s\n", this_looping ? "looping " : "", - w->name ()); + w->dump_name ()); remove_p |= has_cdtor; } break; @@ -1747,7 +1760,7 @@ int i; struct ipa_dfs_info * w_info; - order_pos = ipa_reduced_postorder (order, true, false, + order_pos = ipa_reduced_postorder (order, true, ignore_edge_for_nothrow); if (dump_file) { @@ -1792,8 +1805,8 @@ function_or_virtual_thunk_symbol (&avail, e->caller); - /* We can use info about the callee only if we know it can - not be interposed. + /* We can use info about the callee only if we know it + cannot be interposed. When callee is compiled with non-call exceptions we also must check that the declaration is bound to current body as other semantically equivalent body may still @@ -1826,12 +1839,12 @@ /* Inline clones share declaration with their offline copies; do not modify their declarations since the offline copy may be different. */ - if (!w->global.inlined_to) + if (!w->inlined_to) { w->set_nothrow_flag (true); if (dump_file) fprintf (dump_file, "Function found to be nothrow: %s\n", - w->name ()); + w->dump_name ()); } } else if (can_throw && !TREE_NOTHROW (w->decl)) @@ -1860,7 +1873,7 @@ { funct_state fs = funct_state_summaries->get (node); if (fs) - fprintf (dump_file, "%s: %s\n", node->name (), + fprintf (dump_file, "%s: %s\n", node->dump_name (), malloc_state_names[fs->malloc_state]); } } @@ -1953,11 +1966,11 @@ funct_state l = funct_state_summaries->get (node); if (!node->alias && l->malloc_state == STATE_MALLOC - && !node->global.inlined_to) + && !node->inlined_to) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Function %s found to be malloc\n", - node->name ()); + node->dump_name ()); bool malloc_decl_p = DECL_IS_MALLOC (node->decl); node->set_malloc_flag (true); @@ -2186,7 +2199,7 @@ changed = true; if (dump_file) fprintf (dump_file, "Function found to be malloc: %s\n", - node->name ()); + node->dump_name ()); } free (l); @@ -2292,7 +2305,7 @@ node = cgraph_node::get (current_function_decl); - /* We run during lowering, we can not really use availability yet. */ + /* We run during lowering, we cannot really use availability yet. */ if (cgraph_node::get (current_function_decl)->get_availability () <= AVAIL_INTERPOSABLE) {