* Makefile.def (target_modules): Remove libcilkrts. * Makefile.in: Ditto. * configure: Ditto. * configure.ac: Ditto. contrib/ * contrib/gcc_update: Ditto. gcc/ * Makefile.in (cilkplus.def, cilk-builtins.def, c-family/cilk.o, c-family/c-cilkplus.o, c-family/array-notation-common.o, cilk-common.o, cilk.h, cilk-common.c): Remove. * builtin-types.def (BT_FN_INT_PTR_PTR_PTR_FTYPE_BT_INT_BT_PTR_BT_PTR_BT_PTR): Remove. * builtins.c (is_builtin_name): Remove cilkplus condition. (BUILT_IN_CILK_DETACH, BUILT_IN_CILK_POP_FRAME): Remove. * builtins.def (DEF_CILK_BUILTIN_STUB, DEF_CILKPLUS_BUILTIN, cilk-builtins.def, cilkplus.def): Remove. * cif-code.def (CILK_SPAWN): Remove. * cilk-builtins.def: Delete. * cilk-common.c: Ditto. * cilk.h: Ditto. * cilkplus.def: Ditto. * config/darwin.h (fcilkplus): Delete. * cppbuiltin.c: Ditto. * doc/extend.texi: Remove cilkplus doc. * doc/generic.texi: Ditto. * doc/invoke.texi: Ditto. * doc/passes.texi: Ditto. * gcc.c (fcilkplus): Remove. * gengtype.c (cilk.h): Remove. * gimple-pretty-print.c (dump_gimple_omp_for): Remove cilkplus support. * gimple.h (GF_OMP_FOR_KIND_CILKFOR, GF_OMP_FOR_KIND_CILKSIMD): Remove. * gimplify.c (gimplify_return_expr, maybe_fold_stmt, gimplify_call_expr, is_gimple_stmt, gimplify_modify_expr, gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses, gimplify_omp_for, gimplify_expr): Remove cilkplus conditions. * ipa-fnsummary.c (ipa_dump_fn_summary, compute_fn_summary, inline_read_section): Ditto. * ipa-inline-analysis.c (cilk.h): Remove. * ira.c (ira_setup_eliminable_regset): Remove cilkplus support. * lto-wrapper.c (merge_and_complain, append_compiler_options, append_linker_options): Remove condition for fcilkplus. * lto/lto-lang.c (cilk.h): Remove. (lto_init): Remove condition for fcilkplus. * omp-expand.c (expand_cilk_for_call): Delete. (expand_omp_taskreg, expand_omp_for_static_chunk, expand_omp_for): Remove cilkplus conditions. (expand_cilk_for): Delete. * omp-general.c (omp_extract_for_data): Remove cilkplus support. * omp-low.c (scan_sharing_clauses, create_omp_child_function, execute_lower_omp, diagnose_sb_0): Ditto. * omp-simd-clone.c (simd_clone_clauses_extract): Ditto. * tree-core.h (OMP_CLAUSE__CILK_FOR_COUNT_): Delete. * tree-nested.c: Ditto. * tree-pretty-print.c (dump_omp_clause): Remove cilkplus support. (dump_generic_node): Ditto. * tree.c (OMP_CLAUSE__CILK_FOR_COUNT_): Delete. * tree.def (cilk_simd, cilk_for, cilk_spawn_stmt, cilk_sync_stmt): Delete. * tree.h (CILK_SPAWN_FN, EXPR_CILK_SPAWN): Delete. gcc/c-family/ * array-notation-common.c: Delete. * c-cilkplus.c: Ditto. * c-common.c (_Cilk_spawn, _Cilk_sync, _Cilk_for): Remove. * c-common.def (ARRAY_NOTATION_REF): Remove. * c-common.h (RID_CILK_SPAWN, build_array_notation_expr, build_array_notation_ref, C_ORT_CILK, c_check_cilk_loop, c_validate_cilk_plus_loop, cilkplus_an_parts, cilk_ignorable_spawn_rhs_op, cilk_recognize_spawn): Remove. * c-gimplify.c (CILK_SPAWN_STMT): Remove. * c-omp.c: Remove CILK_SIMD check. * c-pragma.c: Ditto. * c-pragma.h: Remove CILK related pragmas. * c-pretty-print.c (c_pretty_printer::postfix_expression): Remove ARRAY_NOTATION_REF condition. (c_pretty_printer::expression): Ditto. * c.opt (fcilkplus): Remove. * cilk.c: Delete. gcc/c/ * Make-lang.in (c/c-array-notation.o): Remove. * c-array-notation.c: Delete. * c-decl.c: Remove cilkplus condition. * c-parser.c (c_parser_cilk_simd, c_parser_cilk_for, c_parser_cilk_verify_simd, c_parser_array_notation, c_parser_cilk_clause_vectorlength, c_parser_cilk_grainsize, c_parser_cilk_simd_fn_vector_attrs, c_finish_cilk_simd_fn_tokens): Delete. (c_parser_declaration_or_fndef): Remove cilkplus condition. (c_parser_direct_declarator_inner): Ditto. (CILK_SIMD_FN_CLAUSE_MASK): Delete. (c_parser_attributes, c_parser_compound_statement, c_parser_statement_after_labels, c_parser_if_statement, c_parser_switch_statement, c_parser_while_statement, c_parser_do_statement, c_parser_for_statement, c_parser_unary_expression, c_parser_postfix_expression, c_parser_postfix_expression_after_primary, c_parser_pragma, c_parser_omp_clause_name, c_parser_omp_all_clauses, c_parser_omp_for_loop, c_finish_omp_declare_simd): Remove cilkplus support. * c-typeck.c (build_array_ref, build_function_call_vec, convert_arguments, lvalue_p, build_compound_expr, c_finish_return, c_finish_if_stmt, c_finish_loop, build_binary_op): Remove cilkplus support. gcc/cp/ * Make-lang.in (cp/cp-array-notation.o, cp/cp-cilkplus.o): Delete. * call.c (convert_for_arg_passing, build_cxx_call): Remove cilkplus. * constexpr.c (potential_constant_expression_1): Ditto. * cp-array-notation.c: Delete. * cp-cilkplus.c: Ditto. * cp-cilkplus.h: Ditto. * cp-gimplify.c (cp_gimplify_expr, cp_fold_r, cp_genericize): Remove cilkplus condition. * cp-objcp-common.c (ARRAY_NOTATION_REF): Delete. * cp-tree.h (cilkplus_an_triplet_types_ok_p): Delete. * decl.c (grokfndecl, finish_function): Remove cilkplus condition. * error.c (dump_decl, dump_expr): Remove ARRAY_NOTATION_REF condition. * lambda.c (cp-cilkplus.h): Remove. * parser.c (cp_parser_cilk_simd, cp_parser_cilk_for, cp_parser_cilk_simd_vectorlength): Delete. (cp_debug_parser, cp_parser_ctor_initializer_opt_and_function_body, cp_parser_postfix_expression, cp_parser_postfix_open_square_expression, cp_parser_statement, cp_parser_jump_statement, cp_parser_direct_declarator, cp_parser_late_return_type_opt, cp_parser_gnu_attribute_list, cp_parser_omp_clause_name, cp_parser_omp_clause_aligned, cp_parser_omp_clause_linear, cp_parser_omp_all_clauses, cp_parser_omp_flush, cp_parser_omp_for_cond, cp_parser_omp_for_incr, cp_parser_omp_for_loop_init, cp_parser_omp_for_loop, cp_parser_omp_declare_simd): Remove cilkplus support. (CILK_SIMD_FN_CLAUSE_MASK, cp_parser_late_parsing_cilk_simd_fn_info, cp_parser_cilk_grainsize): Remove. (cp_parser_pragma, c_parse_file): Remove cilkplus support. (cp_parser_cilk_simd_vectorlength, cp_parser_cilk_simd_linear, cp_parser_cilk_simd_clause_name, cp_parser_cilk_simd_all_clauses, cp_parser_cilk_simd, cp_parser_cilk_for): Remove. * parser.h (IN_CILK_SIMD_FOR, IN_CILK_SPAWN): Remove. * pt.c (tsubst_attribute, tsubst_expr, tsubst_copy_and_build): Remove cilkplus support. * semantics.c (finish_goto_stmt, begin_while_stmt, finish_do_body, finish_init_stmt, finish_switch_cond, simplify_aggr_init_expr, finish_omp_clauses, finish_omp_clauses, finish_omp_for): Remove cilkplus support. * tree.c (lvalue_kind): Remove ARRAY_NOTATION_REF conditon. * typeck.c (cp_build_array_ref, cp_build_compound_expr, check_return_expr): Remove cilkplus support. gcc/testsuite/ * c-c++-common/attr-simd-3.c: Delete. * c-c++-common/cilk-plus/AN/an-if.c: Delete. * c-c++-common/cilk-plus/AN/array_test1.c: Delete. * c-c++-common/cilk-plus/AN/array_test2.c: Delete. * c-c++-common/cilk-plus/AN/array_test_ND.c: Delete. * c-c++-common/cilk-plus/AN/builtin_fn_custom.c: Delete. * c-c++-common/cilk-plus/AN/builtin_fn_mutating.c: Delete. * c-c++-common/cilk-plus/AN/builtin_func_double.c: Delete. * c-c++-common/cilk-plus/AN/builtin_func_double2.c: Delete. * c-c++-common/cilk-plus/AN/comma_exp.c: Delete. * c-c++-common/cilk-plus/AN/conditional.c: Delete. * c-c++-common/cilk-plus/AN/decl-ptr-colon.c: Delete. * c-c++-common/cilk-plus/AN/dimensionless-arrays.c: Delete. * c-c++-common/cilk-plus/AN/exec-once.c: Delete. * c-c++-common/cilk-plus/AN/exec-once2.c: Delete. * c-c++-common/cilk-plus/AN/fn_ptr-2.c: Delete. * c-c++-common/cilk-plus/AN/fn_ptr.c: Delete. * c-c++-common/cilk-plus/AN/fp_triplet_values.c: Delete. * c-c++-common/cilk-plus/AN/gather-scatter-errors.c: Delete. * c-c++-common/cilk-plus/AN/gather_scatter.c: Delete. * c-c++-common/cilk-plus/AN/if_test.c: Delete. * c-c++-common/cilk-plus/AN/if_test_errors.c: Delete. * c-c++-common/cilk-plus/AN/misc.c: Delete. * c-c++-common/cilk-plus/AN/n-ptr-test.c: Delete. * c-c++-common/cilk-plus/AN/parser_errors.c: Delete. * c-c++-common/cilk-plus/AN/parser_errors2.c: Delete. * c-c++-common/cilk-plus/AN/parser_errors3.c: Delete. * c-c++-common/cilk-plus/AN/parser_errors4.c: Delete. * c-c++-common/cilk-plus/AN/pr57457-2.c: Delete. * c-c++-common/cilk-plus/AN/pr57457.c: Delete. * c-c++-common/cilk-plus/AN/pr57490.c: Delete. * c-c++-common/cilk-plus/AN/pr57541-2.c: Delete. * c-c++-common/cilk-plus/AN/pr57541.c: Delete. * c-c++-common/cilk-plus/AN/pr57577.c: Delete. * c-c++-common/cilk-plus/AN/pr58942.c: Delete. * c-c++-common/cilk-plus/AN/pr61191.c: Delete. * c-c++-common/cilk-plus/AN/pr61455-2.c: Delete. * c-c++-common/cilk-plus/AN/pr61455.c: Delete. * c-c++-common/cilk-plus/AN/pr61962.c: Delete. * c-c++-common/cilk-plus/AN/pr61963.c: Delete. * c-c++-common/cilk-plus/AN/pr62008.c: Delete. * c-c++-common/cilk-plus/AN/pr63884.c: Delete. * c-c++-common/cilk-plus/AN/rank_mismatch.c: Delete. * c-c++-common/cilk-plus/AN/rank_mismatch2.c: Delete. * c-c++-common/cilk-plus/AN/rank_mismatch3.c: Delete. * c-c++-common/cilk-plus/AN/sec_implicit.c: Delete. * c-c++-common/cilk-plus/AN/sec_implicit2.c: Delete. * c-c++-common/cilk-plus/AN/sec_implicit_ex.c: Delete. * c-c++-common/cilk-plus/AN/sec_reduce_ind_same_value.c: Delete. * c-c++-common/cilk-plus/AN/sec_reduce_max_min_ind.c: Delete. * c-c++-common/cilk-plus/AN/sec_reduce_return.c: Delete. * c-c++-common/cilk-plus/AN/side-effects-1.c: Delete. * c-c++-common/cilk-plus/AN/test_builtin_return.c: Delete. * c-c++-common/cilk-plus/AN/test_sec_limits.c: Delete. * c-c++-common/cilk-plus/AN/tst_lngth.c: Delete. * c-c++-common/cilk-plus/AN/vla.c: Delete. * c-c++-common/cilk-plus/CK/Wparentheses-1.c: Delete. * c-c++-common/cilk-plus/CK/cilk-for-2.c: Delete. * c-c++-common/cilk-plus/CK/cilk-for-3.c: Delete. * c-c++-common/cilk-plus/CK/cilk-fors.c: Delete. * c-c++-common/cilk-plus/CK/cilk_for_errors.c: Delete. * c-c++-common/cilk-plus/CK/cilk_for_grain.c: Delete. * c-c++-common/cilk-plus/CK/cilk_for_grain_errors.c: Delete. * c-c++-common/cilk-plus/CK/cilk_for_ptr_iter.c: Delete. * c-c++-common/cilk-plus/CK/compound_cilk_spawn.c: Delete. * c-c++-common/cilk-plus/CK/concec_cilk_spawn.c: Delete. * c-c++-common/cilk-plus/CK/errors.c: Delete. * c-c++-common/cilk-plus/CK/fib.c: Delete. * c-c++-common/cilk-plus/CK/fib_init_expr_xy.c: Delete. * c-c++-common/cilk-plus/CK/fib_no_return.c: Delete. * c-c++-common/cilk-plus/CK/fib_no_sync.c: Delete. * c-c++-common/cilk-plus/CK/invalid_spawns.c: Delete. * c-c++-common/cilk-plus/CK/invalid_sync.c: Delete.c * c-c++-common/cilk-plus/CK/nested_cilk_for.c: Delete. * c-c++-common/cilk-plus/CK/no_args_error.c: Delete. * c-c++-common/cilk-plus/CK/pr59631.c: Delete. * c-c++-common/cilk-plus/CK/pr60197-2.c: Delete. * c-c++-common/cilk-plus/CK/pr60197.c: Delete. * c-c++-common/cilk-plus/CK/pr60469.c: Delete. * c-c++-common/cilk-plus/CK/pr60586.c: Delete. * c-c++-common/cilk-plus/CK/pr63307.c: Delete. * c-c++-common/cilk-plus/CK/pr69826-1.c: Delete. * c-c++-common/cilk-plus/CK/pr69826-2.c: Delete. * c-c++-common/cilk-plus/CK/pr79428-4.c: Delete. * c-c++-common/cilk-plus/CK/pr79428-7.c: Delete. * c-c++-common/cilk-plus/CK/spawn_in_return.c: Delete. * c-c++-common/cilk-plus/CK/spawnee_inline.c: Delete. * c-c++-common/cilk-plus/CK/spawner_inline.c: Delete. * c-c++-common/cilk-plus/CK/spawning_arg.c: Delete. * c-c++-common/cilk-plus/CK/steal_check.c: Delete. * c-c++-common/cilk-plus/CK/sync_wo_spawn.c: Delete. * c-c++-common/cilk-plus/CK/test__cilk.c: Delete. * c-c++-common/cilk-plus/CK/varargs_test.c: Delete. * c-c++-common/cilk-plus/PS/Wparentheses-1.c: Delete. * c-c++-common/cilk-plus/PS/body.c: Delete. * c-c++-common/cilk-plus/PS/clauses1.c: Delete. * c-c++-common/cilk-plus/PS/clauses2.c: Delete. * c-c++-common/cilk-plus/PS/clauses3.c: Delete. * c-c++-common/cilk-plus/PS/clauses4.c: Delete. * c-c++-common/cilk-plus/PS/for1.c: Delete. * c-c++-common/cilk-plus/PS/for2.c: Delete. * c-c++-common/cilk-plus/PS/for3.c: Delete. * c-c++-common/cilk-plus/PS/pr69363.c: Delete. * c-c++-common/cilk-plus/PS/reduction-1.c: Delete. * c-c++-common/cilk-plus/PS/reduction-2.c: Delete. * c-c++-common/cilk-plus/PS/reduction-3.c: Delete. * c-c++-common/cilk-plus/PS/run-1.c: Delete. * c-c++-common/cilk-plus/PS/safelen.c: Delete. * c-c++-common/cilk-plus/PS/vectorlength-2.c: Delete. * c-c++-common/cilk-plus/PS/vectorlength-3.c: Delete. * c-c++-common/cilk-plus/PS/vectorlength.c: Delete. * c-c++-common/cilk-plus/SE/ef_error.c: Delete. * c-c++-common/cilk-plus/SE/ef_error2.c: Delete. * c-c++-common/cilk-plus/SE/ef_error3.c: Delete. * c-c++-common/cilk-plus/SE/ef_test.c: Delete. * c-c++-common/cilk-plus/SE/ef_test2.c: Delete. * c-c++-common/cilk-plus/SE/vlength_errors.c: Delete. * g++.dg/cilk-plus/AN/array_function.c: Delete. * g++.dg/cilk-plus/AN/array_test1_tplt.c: Delete. * g++.dg/cilk-plus/AN/array_test2_tplt.c: Delete. * g++.dg/cilk-plus/AN/array_test_ND_tplt.c: Delete. * g++.dg/cilk-plus/AN/braced_list.c: Delete. * g++.dg/cilk-plus/AN/builtin_fn_custom_tplt.c: Delete. * g++.dg/cilk-plus/AN/builtin_fn_mutating_tplt.c: Delete. * g++.dg/cilk-plus/AN/fp_triplet_values_tplt.c: Delete. * g++.dg/cilk-plus/AN/postincr_test.c: Delete. * g++.dg/cilk-plus/AN/preincr_test.c: Delete. * g++.dg/cilk-plus/CK/catch_exc.c: Delete. * g++.dg/cilk-plus/CK/cf3.c: Delete. * g++.dg/cilk-plus/CK/cilk-for-tplt.c: Delete. * g++.dg/cilk-plus/CK/const_spawn.c: Delete. * g++.dg/cilk-plus/CK/fib-opr-overload.c: Delete. * g++.dg/cilk-plus/CK/fib-tplt.c: Delete. * g++.dg/cilk-plus/CK/for1.c: Delete. * g++.dg/cilk-plus/CK/lambda_spawns.c: Delete. * g++.dg/cilk-plus/CK/lambda_spawns_tplt.c: Delete. * g++.dg/cilk-plus/CK/pr60586.c: Delete. * g++.dg/cilk-plus/CK/pr66326.c: Delete. * g++.dg/cilk-plus/CK/pr68001.c: Delete. * g++.dg/cilk-plus/CK/pr68997.c: Delete. * g++.dg/cilk-plus/CK/pr69024.c: Delete. * g++.dg/cilk-plus/CK/pr69048.c: Delete. * g++.dg/cilk-plus/CK/pr69267.c: Delete. * g++.dg/cilk-plus/CK/pr80038.c: Delete. * g++.dg/cilk-plus/CK/stl_iter.c: Delete. * g++.dg/cilk-plus/CK/stl_rev_iter.c: Delete. * g++.dg/cilk-plus/CK/stl_test.c: Delete. * g++.dg/cilk-plus/cilk-plus.exp * g++.dg/cilk-plus/ef_test.C: Delete. * g++.dg/cilk-plus/for.C: Delete. * g++.dg/cilk-plus/for2.C: Delete. * g++.dg/cilk-plus/for3.C: Delete. * g++.dg/cilk-plus/for4.C: Delete. * g++.dg/cilk-plus/pr60967.C: Delete. * g++.dg/cilk-plus/pr69028.C: Delete. * g++.dg/cilk-plus/pr70565.C: Delete. * g++.dg/pr57662.C: Delete. * gcc.dg/cilk-plus/cilk-plus.exp * gcc.dg/cilk-plus/for1.c: Delete. * gcc.dg/cilk-plus/for2.c: Delete. * gcc.dg/cilk-plus/jump-openmp.c: Delete. * gcc.dg/cilk-plus/jump.c: Delete. * gcc.dg/cilk-plus/pr69798-1.c: Delete. * gcc.dg/cilk-plus/pr69798-2.c: Delete. * gcc.dg/cilk-plus/pr78306.c: Delete. * gcc.dg/cilk-plus/pr79116.c: Delete. * gcc.dg/graphite/id-28.c: Delete. * lib/cilk-plus-dg.exp: Delete. * lib/target-supports.exp (cilkplus_runtime): Delete. Co-Authored-By: Sebastian Peryt <sebastian.peryt@intel.com> From-SVN: r255195
460 lines
13 KiB
C
460 lines
13 KiB
C
/* Analysis used by inlining decision heuristics.
|
|
Copyright (C) 2003-2017 Free Software Foundation, Inc.
|
|
Contributed by Jan Hubicka
|
|
|
|
This file is part of GCC.
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free
|
|
Software Foundation; either version 3, or (at your option) any later
|
|
version.
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GCC; see the file COPYING3. If not see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#include "coretypes.h"
|
|
#include "backend.h"
|
|
#include "tree.h"
|
|
#include "gimple.h"
|
|
#include "alloc-pool.h"
|
|
#include "tree-pass.h"
|
|
#include "ssa.h"
|
|
#include "tree-streamer.h"
|
|
#include "cgraph.h"
|
|
#include "diagnostic.h"
|
|
#include "fold-const.h"
|
|
#include "print-tree.h"
|
|
#include "tree-inline.h"
|
|
#include "gimple-pretty-print.h"
|
|
#include "params.h"
|
|
#include "cfganal.h"
|
|
#include "gimple-iterator.h"
|
|
#include "tree-cfg.h"
|
|
#include "tree-ssa-loop-niter.h"
|
|
#include "tree-ssa-loop.h"
|
|
#include "symbol-summary.h"
|
|
#include "ipa-prop.h"
|
|
#include "ipa-fnsummary.h"
|
|
#include "ipa-inline.h"
|
|
#include "cfgloop.h"
|
|
#include "tree-scalar-evolution.h"
|
|
#include "ipa-utils.h"
|
|
#include "cfgexpand.h"
|
|
#include "gimplify.h"
|
|
|
|
/* Cached node/edge growths. */
|
|
vec<edge_growth_cache_entry> edge_growth_cache;
|
|
static struct cgraph_edge_hook_list *edge_removal_hook_holder;
|
|
|
|
|
|
/* Give initial reasons why inlining would fail on EDGE. This gets either
|
|
nullified or usually overwritten by more precise reasons later. */
|
|
|
|
void
|
|
initialize_inline_failed (struct cgraph_edge *e)
|
|
{
|
|
struct cgraph_node *callee = e->callee;
|
|
|
|
if (e->inline_failed && e->inline_failed != CIF_BODY_NOT_AVAILABLE
|
|
&& cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
|
|
;
|
|
else if (e->indirect_unknown_callee)
|
|
e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
|
|
else if (!callee->definition)
|
|
e->inline_failed = CIF_BODY_NOT_AVAILABLE;
|
|
else if (callee->local.redefined_extern_inline)
|
|
e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
|
|
else
|
|
e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
|
|
gcc_checking_assert (!e->call_stmt_cannot_inline_p
|
|
|| cgraph_inline_failed_type (e->inline_failed)
|
|
== CIF_FINAL_ERROR);
|
|
}
|
|
|
|
|
|
/* Keep edge cache consistent across edge removal. */
|
|
|
|
static void
|
|
inline_edge_removal_hook (struct cgraph_edge *edge,
|
|
void *data ATTRIBUTE_UNUSED)
|
|
{
|
|
reset_edge_growth_cache (edge);
|
|
}
|
|
|
|
|
|
/* Initialize growth caches. */
|
|
|
|
void
|
|
initialize_growth_caches (void)
|
|
{
|
|
if (!edge_removal_hook_holder)
|
|
edge_removal_hook_holder =
|
|
symtab->add_edge_removal_hook (&inline_edge_removal_hook, NULL);
|
|
if (symtab->edges_max_uid)
|
|
edge_growth_cache.safe_grow_cleared (symtab->edges_max_uid);
|
|
}
|
|
|
|
|
|
/* Free growth caches. */
|
|
|
|
void
|
|
free_growth_caches (void)
|
|
{
|
|
if (edge_removal_hook_holder)
|
|
{
|
|
symtab->remove_edge_removal_hook (edge_removal_hook_holder);
|
|
edge_removal_hook_holder = NULL;
|
|
}
|
|
edge_growth_cache.release ();
|
|
}
|
|
|
|
/* Return hints derrived from EDGE. */
|
|
|
|
int
|
|
simple_edge_hints (struct cgraph_edge *edge)
|
|
{
|
|
int hints = 0;
|
|
struct cgraph_node *to = (edge->caller->global.inlined_to
|
|
? edge->caller->global.inlined_to : edge->caller);
|
|
struct cgraph_node *callee = edge->callee->ultimate_alias_target ();
|
|
if (ipa_fn_summaries->get (to)->scc_no
|
|
&& ipa_fn_summaries->get (to)->scc_no
|
|
== ipa_fn_summaries->get (callee)->scc_no
|
|
&& !edge->recursive_p ())
|
|
hints |= INLINE_HINT_same_scc;
|
|
|
|
if (callee->lto_file_data && edge->caller->lto_file_data
|
|
&& edge->caller->lto_file_data != callee->lto_file_data
|
|
&& !callee->merged_comdat && !callee->icf_merged)
|
|
hints |= INLINE_HINT_cross_module;
|
|
|
|
return hints;
|
|
}
|
|
|
|
/* Estimate the time cost for the caller when inlining EDGE.
|
|
Only to be called via estimate_edge_time, that handles the
|
|
caching mechanism.
|
|
|
|
When caching, also update the cache entry. Compute both time and
|
|
size, since we always need both metrics eventually. */
|
|
|
|
sreal
|
|
do_estimate_edge_time (struct cgraph_edge *edge)
|
|
{
|
|
sreal time, nonspec_time;
|
|
int size;
|
|
ipa_hints hints;
|
|
struct cgraph_node *callee;
|
|
clause_t clause, nonspec_clause;
|
|
vec<tree> known_vals;
|
|
vec<ipa_polymorphic_call_context> known_contexts;
|
|
vec<ipa_agg_jump_function_p> known_aggs;
|
|
struct ipa_call_summary *es = ipa_call_summaries->get (edge);
|
|
int min_size;
|
|
|
|
callee = edge->callee->ultimate_alias_target ();
|
|
|
|
gcc_checking_assert (edge->inline_failed);
|
|
evaluate_properties_for_edge (edge, true,
|
|
&clause, &nonspec_clause, &known_vals,
|
|
&known_contexts, &known_aggs);
|
|
estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals,
|
|
known_contexts, known_aggs, &size, &min_size,
|
|
&time, &nonspec_time, &hints, es->param);
|
|
|
|
/* When we have profile feedback, we can quite safely identify hot
|
|
edges and for those we disable size limits. Don't do that when
|
|
probability that caller will call the callee is low however, since it
|
|
may hurt optimization of the caller's hot path. */
|
|
if (edge->count.ipa ().initialized_p () && edge->maybe_hot_p ()
|
|
&& (edge->count.ipa ().apply_scale (2, 1)
|
|
> (edge->caller->global.inlined_to
|
|
? edge->caller->global.inlined_to->count.ipa ()
|
|
: edge->caller->count.ipa ())))
|
|
hints |= INLINE_HINT_known_hot;
|
|
|
|
known_vals.release ();
|
|
known_contexts.release ();
|
|
known_aggs.release ();
|
|
gcc_checking_assert (size >= 0);
|
|
gcc_checking_assert (time >= 0);
|
|
|
|
/* When caching, update the cache entry. */
|
|
if (edge_growth_cache.exists ())
|
|
{
|
|
ipa_fn_summaries->get (edge->callee)->min_size = min_size;
|
|
if ((int) edge_growth_cache.length () <= edge->uid)
|
|
edge_growth_cache.safe_grow_cleared (symtab->edges_max_uid);
|
|
edge_growth_cache[edge->uid].time = time;
|
|
edge_growth_cache[edge->uid].nonspec_time = nonspec_time;
|
|
|
|
edge_growth_cache[edge->uid].size = size + (size >= 0);
|
|
hints |= simple_edge_hints (edge);
|
|
edge_growth_cache[edge->uid].hints = hints + 1;
|
|
}
|
|
return time;
|
|
}
|
|
|
|
|
|
/* Return estimated callee growth after inlining EDGE.
|
|
Only to be called via estimate_edge_size. */
|
|
|
|
int
|
|
do_estimate_edge_size (struct cgraph_edge *edge)
|
|
{
|
|
int size;
|
|
struct cgraph_node *callee;
|
|
clause_t clause, nonspec_clause;
|
|
vec<tree> known_vals;
|
|
vec<ipa_polymorphic_call_context> known_contexts;
|
|
vec<ipa_agg_jump_function_p> known_aggs;
|
|
|
|
/* When we do caching, use do_estimate_edge_time to populate the entry. */
|
|
|
|
if (edge_growth_cache.exists ())
|
|
{
|
|
do_estimate_edge_time (edge);
|
|
size = edge_growth_cache[edge->uid].size;
|
|
gcc_checking_assert (size);
|
|
return size - (size > 0);
|
|
}
|
|
|
|
callee = edge->callee->ultimate_alias_target ();
|
|
|
|
/* Early inliner runs without caching, go ahead and do the dirty work. */
|
|
gcc_checking_assert (edge->inline_failed);
|
|
evaluate_properties_for_edge (edge, true,
|
|
&clause, &nonspec_clause,
|
|
&known_vals, &known_contexts,
|
|
&known_aggs);
|
|
estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals,
|
|
known_contexts, known_aggs, &size, NULL, NULL,
|
|
NULL, NULL, vNULL);
|
|
known_vals.release ();
|
|
known_contexts.release ();
|
|
known_aggs.release ();
|
|
return size;
|
|
}
|
|
|
|
|
|
/* Estimate the growth of the caller when inlining EDGE.
|
|
Only to be called via estimate_edge_size. */
|
|
|
|
ipa_hints
|
|
do_estimate_edge_hints (struct cgraph_edge *edge)
|
|
{
|
|
ipa_hints hints;
|
|
struct cgraph_node *callee;
|
|
clause_t clause, nonspec_clause;
|
|
vec<tree> known_vals;
|
|
vec<ipa_polymorphic_call_context> known_contexts;
|
|
vec<ipa_agg_jump_function_p> known_aggs;
|
|
|
|
/* When we do caching, use do_estimate_edge_time to populate the entry. */
|
|
|
|
if (edge_growth_cache.exists ())
|
|
{
|
|
do_estimate_edge_time (edge);
|
|
hints = edge_growth_cache[edge->uid].hints;
|
|
gcc_checking_assert (hints);
|
|
return hints - 1;
|
|
}
|
|
|
|
callee = edge->callee->ultimate_alias_target ();
|
|
|
|
/* Early inliner runs without caching, go ahead and do the dirty work. */
|
|
gcc_checking_assert (edge->inline_failed);
|
|
evaluate_properties_for_edge (edge, true,
|
|
&clause, &nonspec_clause,
|
|
&known_vals, &known_contexts,
|
|
&known_aggs);
|
|
estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals,
|
|
known_contexts, known_aggs, NULL, NULL,
|
|
NULL, NULL, &hints, vNULL);
|
|
known_vals.release ();
|
|
known_contexts.release ();
|
|
known_aggs.release ();
|
|
hints |= simple_edge_hints (edge);
|
|
return hints;
|
|
}
|
|
|
|
/* Estimate the size of NODE after inlining EDGE which should be an
|
|
edge to either NODE or a call inlined into NODE. */
|
|
|
|
int
|
|
estimate_size_after_inlining (struct cgraph_node *node,
|
|
struct cgraph_edge *edge)
|
|
{
|
|
struct ipa_call_summary *es = ipa_call_summaries->get (edge);
|
|
if (!es->predicate || *es->predicate != false)
|
|
{
|
|
int size = ipa_fn_summaries->get (node)->size + estimate_edge_growth (edge);
|
|
gcc_assert (size >= 0);
|
|
return size;
|
|
}
|
|
return ipa_fn_summaries->get (node)->size;
|
|
}
|
|
|
|
|
|
struct growth_data
|
|
{
|
|
struct cgraph_node *node;
|
|
bool self_recursive;
|
|
bool uninlinable;
|
|
int growth;
|
|
};
|
|
|
|
|
|
/* Worker for do_estimate_growth. Collect growth for all callers. */
|
|
|
|
static bool
|
|
do_estimate_growth_1 (struct cgraph_node *node, void *data)
|
|
{
|
|
struct cgraph_edge *e;
|
|
struct growth_data *d = (struct growth_data *) data;
|
|
|
|
for (e = node->callers; e; e = e->next_caller)
|
|
{
|
|
gcc_checking_assert (e->inline_failed);
|
|
|
|
if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR
|
|
|| !opt_for_fn (e->caller->decl, optimize))
|
|
{
|
|
d->uninlinable = true;
|
|
continue;
|
|
}
|
|
|
|
if (e->recursive_p ())
|
|
{
|
|
d->self_recursive = true;
|
|
continue;
|
|
}
|
|
d->growth += estimate_edge_growth (e);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/* Estimate the growth caused by inlining NODE into all callees. */
|
|
|
|
int
|
|
estimate_growth (struct cgraph_node *node)
|
|
{
|
|
struct growth_data d = { node, false, false, 0 };
|
|
struct ipa_fn_summary *info = ipa_fn_summaries->get (node);
|
|
|
|
node->call_for_symbol_and_aliases (do_estimate_growth_1, &d, true);
|
|
|
|
/* For self recursive functions the growth estimation really should be
|
|
infinity. We don't want to return very large values because the growth
|
|
plays various roles in badness computation fractions. Be sure to not
|
|
return zero or negative growths. */
|
|
if (d.self_recursive)
|
|
d.growth = d.growth < info->size ? info->size : d.growth;
|
|
else if (DECL_EXTERNAL (node->decl) || d.uninlinable)
|
|
;
|
|
else
|
|
{
|
|
if (node->will_be_removed_from_program_if_no_direct_calls_p ())
|
|
d.growth -= info->size;
|
|
/* COMDAT functions are very often not shared across multiple units
|
|
since they come from various template instantiations.
|
|
Take this into account. */
|
|
else if (DECL_COMDAT (node->decl)
|
|
&& node->can_remove_if_no_direct_calls_p ())
|
|
d.growth -= (info->size
|
|
* (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY))
|
|
+ 50) / 100;
|
|
}
|
|
|
|
return d.growth;
|
|
}
|
|
|
|
/* Verify if there are fewer than MAX_CALLERS. */
|
|
|
|
static bool
|
|
check_callers (cgraph_node *node, int *max_callers)
|
|
{
|
|
ipa_ref *ref;
|
|
|
|
if (!node->can_remove_if_no_direct_calls_and_refs_p ())
|
|
return true;
|
|
|
|
for (cgraph_edge *e = node->callers; e; e = e->next_caller)
|
|
{
|
|
(*max_callers)--;
|
|
if (!*max_callers
|
|
|| cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
|
|
return true;
|
|
}
|
|
|
|
FOR_EACH_ALIAS (node, ref)
|
|
if (check_callers (dyn_cast <cgraph_node *> (ref->referring), max_callers))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/* Make cheap estimation if growth of NODE is likely positive knowing
|
|
EDGE_GROWTH of one particular edge.
|
|
We assume that most of other edges will have similar growth
|
|
and skip computation if there are too many callers. */
|
|
|
|
bool
|
|
growth_likely_positive (struct cgraph_node *node,
|
|
int edge_growth)
|
|
{
|
|
int max_callers;
|
|
struct cgraph_edge *e;
|
|
gcc_checking_assert (edge_growth > 0);
|
|
|
|
/* First quickly check if NODE is removable at all. */
|
|
if (DECL_EXTERNAL (node->decl))
|
|
return true;
|
|
if (!node->can_remove_if_no_direct_calls_and_refs_p ()
|
|
|| node->address_taken)
|
|
return true;
|
|
|
|
max_callers = ipa_fn_summaries->get (node)->size * 4 / edge_growth + 2;
|
|
|
|
for (e = node->callers; e; e = e->next_caller)
|
|
{
|
|
max_callers--;
|
|
if (!max_callers
|
|
|| cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
|
|
return true;
|
|
}
|
|
|
|
ipa_ref *ref;
|
|
FOR_EACH_ALIAS (node, ref)
|
|
if (check_callers (dyn_cast <cgraph_node *> (ref->referring), &max_callers))
|
|
return true;
|
|
|
|
/* Unlike for functions called once, we play unsafe with
|
|
COMDATs. We can allow that since we know functions
|
|
in consideration are small (and thus risk is small) and
|
|
moreover grow estimates already accounts that COMDAT
|
|
functions may or may not disappear when eliminated from
|
|
current unit. With good probability making aggressive
|
|
choice in all units is going to make overall program
|
|
smaller. */
|
|
if (DECL_COMDAT (node->decl))
|
|
{
|
|
if (!node->can_remove_if_no_direct_calls_p ())
|
|
return true;
|
|
}
|
|
else if (!node->will_be_removed_from_program_if_no_direct_calls_p ())
|
|
return true;
|
|
|
|
return estimate_growth (node) > 0;
|
|
}
|