diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2a29e1b2b4d..0bfc23996ce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2019-11-30 Jan Hubicka + + * cgraph.c (cgraph_node::dump): Dump unit_id and merged_extern_inline. + * cgraph.h (cgraph_node): Add unit_id and + merged_extern_inline. + (symbol_table): Add max_unit. + (symbol_table::symbol_table): Initialize it. + * cgraphclones.c (duplicate_thunk_for_node): Copy unit_id. + merged_comdat, merged_extern_inline. + (cgraph_node::create_clone): Likewise. + (cgraph_node::create_version_clone): Likewise. + * ipa-fnsummary.c (dump_ipa_call_summary): Dump info about cross module + calls. + * ipa-fnsummary.h (cross_module_call_p): New inline function. + * ipa-inline-analyssi.c (simple_edge_hints): Use it. + * ipa-inline.c (inline_small_functions): Likewise. + * lto-symtab.c (lto_cgraph_replace_node): Record merged_extern_inline; + copy merged_comdat and merged_extern_inline. + * lto-cgraph.c (lto_output_node): Stream out merged_comdat, + merged_extern_inline and unit_id. + (input_overwrite_node): Stream in these. + (input_cgraph_1): Set unit_base. + * lto-streamer.h (lto_file_decl_data): Add unit_base. + * symtab.c (symtab_node::make_decl_local): Record former_comdat. + 2019-11-30 Maciej W. Rozycki * gcc.c (process_command): Only warn about an ineffective `-x' diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 180d21e4796..b75430f3f3a 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1923,6 +1923,9 @@ cgraph_node::dump (FILE *f) if (profile_id) fprintf (f, " Profile id: %i\n", profile_id); + if (unit_id) + fprintf (f, " Unit id: %i\n", + unit_id); cgraph_function_version_info *vi = function_version (); if (vi != NULL) { @@ -1973,6 +1976,8 @@ cgraph_node::dump (FILE *f) fprintf (f, " icf_merged"); if (merged_comdat) fprintf (f, " merged_comdat"); + if (merged_extern_inline) + fprintf (f, " merged_extern_inline"); if (split_part) fprintf (f, " split_part"); if (indirect_call_target) diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 0d2442c997c..2aedaaedd61 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1433,6 +1433,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node int count_materialization_scale; /* ID assigned by the profiling. */ unsigned int profile_id; + /* ID of the translation unit. */ + int unit_id; /* Time profiler: first run of function. */ int tp_first_run; @@ -1469,6 +1471,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node unsigned nonfreeing_fn : 1; /* True if there was multiple COMDAT bodies merged by lto-symtab. */ unsigned merged_comdat : 1; + /* True if this def was merged with extern inlines. */ + unsigned merged_extern_inline : 1; /* True if function was created to be executed in parallel. */ unsigned parallelized_function : 1; /* True if function is part split out by ipa-split. */ @@ -2090,7 +2094,7 @@ public: edges_count (0), edges_max_uid (1), edges_max_summary_id (0), cgraph_released_summary_ids (), edge_released_summary_ids (), nodes (NULL), asmnodes (NULL), asm_last_node (NULL), - order (0), global_info_ready (false), state (PARSING), + order (0), max_unit (0), global_info_ready (false), state (PARSING), function_flags_ready (false), cpp_implicit_aliases_done (false), section_hash (NULL), assembler_name_hash (NULL), init_priority_hash (NULL), dump_file (NULL), ipa_clones_dump_file (NULL), cloned_nodes (), @@ -2355,6 +2359,9 @@ public: them, to support -fno-toplevel-reorder. */ int order; + /* Maximal unit ID used. */ + int max_unit; + /* Set when whole unit has been analyzed so we can access global info. */ bool global_info_ready; /* What state callgraph is in right now. */ diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index 9aacb0b196c..81c5dfd194f 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -234,6 +234,9 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node) new_thunk->unique_name = in_lto_p; new_thunk->former_clone_of = thunk->decl; new_thunk->clone.param_adjustments = node->clone.param_adjustments; + new_thunk->unit_id = thunk->unit_id; + new_thunk->merged_comdat = thunk->merged_comdat; + new_thunk->merged_extern_inline = thunk->merged_extern_inline; cgraph_edge *e = new_thunk->create_edge (node, NULL, new_thunk->count); symtab->call_edge_duplication_hooks (thunk->callees, e); @@ -383,6 +386,9 @@ cgraph_node::create_clone (tree new_decl, profile_count prof_count, new_node->icf_merged = icf_merged; new_node->merged_comdat = merged_comdat; new_node->thunk = thunk; + new_node->unit_id = unit_id; + new_node->merged_comdat = merged_comdat; + new_node->merged_extern_inline = merged_extern_inline; if (param_adjustments) new_node->clone.param_adjustments = param_adjustments; @@ -888,6 +894,9 @@ cgraph_node::create_version_clone (tree new_decl, new_version->inlined_to = inlined_to; new_version->rtl = rtl; new_version->count = count; + new_version->unit_id = unit_id; + new_version->merged_comdat = merged_comdat; + new_version->merged_extern_inline = merged_extern_inline; for (e = callees; e; e=e->next_callee) if (!bbs_to_copy diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c index 66d2be6677c..9d160266589 100644 --- a/gcc/ipa-fnsummary.c +++ b/gcc/ipa-fnsummary.c @@ -913,6 +913,9 @@ dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node, ? "inlined" : cgraph_inline_failed_string (edge-> inline_failed), indent, "", edge->sreal_frequency ().to_double ()); + if (cross_module_call_p (edge)) + fprintf (f, " cross module"); + if (es) fprintf (f, " loop depth:%2i size:%2i time: %2i", es->loop_depth, es->call_stmt_size, es->call_stmt_time); diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h index 21ecd54293f..e43003212a8 100644 --- a/gcc/ipa-fnsummary.h +++ b/gcc/ipa-fnsummary.h @@ -375,4 +375,21 @@ void ipa_fnsummary_c_finalize (void); HOST_WIDE_INT ipa_get_stack_frame_offset (struct cgraph_node *node); void ipa_remove_from_growth_caches (struct cgraph_edge *edge); +/* Return true if EDGE is a cross module call. */ + +static inline bool +cross_module_call_p (struct cgraph_edge *edge) +{ + /* Here we do not want to walk to alias target becuase ICF may create + cross-unit aliases. */ + if (edge->caller->unit_id == edge->callee->unit_id) + return false; + /* If the call is to a (former) comdat function or s symbol with mutiple + extern inline definitions then treat is as in-module call. */ + if (edge->callee->merged_extern_inline || edge->callee->merged_comdat + || DECL_COMDAT (edge->callee->decl)) + return false; + return true; +} + #endif /* GCC_IPA_FNSUMMARY_H */ diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index ae8e5db3d9c..75c6399d35d 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -163,9 +163,7 @@ simple_edge_hints (struct cgraph_edge *edge) if (to_scc_no && to_scc_no == 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) + if (cross_module_call_p (edge)) hints |= INLINE_HINT_cross_module; return hints; diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index c742a99bcd7..56ea671c9bc 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -2257,11 +2257,12 @@ inline_small_functions (void) dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, edge->call_stmt, " Inlined %C into %C which now has time %f and " - "size %i, net change of %s.\n", + "size %i, net change of %s%s.\n", edge->callee, edge->caller, s->time.to_double (), ipa_size_summaries->get (edge->caller)->size, - buf_net_change); + buf_net_change, + cross_module_call_p (edge) ? " (cross module)":""); } if (min_size > overall_size) { diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index a4a70e7848c..d2a5d5376fe 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -533,6 +533,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, bp_pack_value (&bp, node->calls_comdat_local, 1); bp_pack_value (&bp, node->icf_merged, 1); bp_pack_value (&bp, node->nonfreeing_fn, 1); + bp_pack_value (&bp, node->merged_comdat, 1); + bp_pack_value (&bp, node->merged_extern_inline, 1); bp_pack_value (&bp, node->thunk.thunk_p, 1); bp_pack_value (&bp, node->parallelized_function, 1); bp_pack_enum (&bp, ld_plugin_symbol_resolution, @@ -559,6 +561,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, streamer_write_uhwi_stream (ob->main_stream, node->thunk.indirect_offset); } streamer_write_hwi_stream (ob->main_stream, node->profile_id); + streamer_write_hwi_stream (ob->main_stream, node->unit_id); if (DECL_STATIC_CONSTRUCTOR (node->decl)) streamer_write_hwi_stream (ob->main_stream, node->get_init_priority ()); if (DECL_STATIC_DESTRUCTOR (node->decl)) @@ -1177,6 +1180,8 @@ input_overwrite_node (struct lto_file_decl_data *file_data, node->calls_comdat_local = bp_unpack_value (bp, 1); node->icf_merged = bp_unpack_value (bp, 1); node->nonfreeing_fn = bp_unpack_value (bp, 1); + node->merged_comdat = bp_unpack_value (bp, 1); + node->merged_extern_inline = bp_unpack_value (bp, 1); node->thunk.thunk_p = bp_unpack_value (bp, 1); node->parallelized_function = bp_unpack_value (bp, 1); node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution, @@ -1310,6 +1315,9 @@ input_node (struct lto_file_decl_data *file_data, if (node->alias && !node->analyzed && node->weakref) node->alias_target = get_alias_symbol (node->decl); node->profile_id = streamer_read_hwi (ib); + node->unit_id = streamer_read_hwi (ib) + file_data->unit_base; + if (symtab->max_unit < node->unit_id) + symtab->max_unit = node->unit_id; if (DECL_STATIC_CONSTRUCTOR (node->decl)) node->set_init_priority (streamer_read_hwi (ib)); if (DECL_STATIC_DESTRUCTOR (node->decl)) @@ -1502,6 +1510,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag); file_data->order_base = symtab->order; + file_data->unit_base = symtab->max_unit + 1; while (tag) { if (tag == LTO_symtab_edge) diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 7b712808bd5..dba195d3884 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -626,6 +626,8 @@ struct GTY(()) lto_file_decl_data lto_section lto_section_header; int order_base; + + int unit_base; }; typedef struct lto_file_decl_data *lto_file_decl_data_ptr; diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c index 2fd5b1e8f49..8dfae627782 100644 --- a/gcc/lto/lto-symtab.c +++ b/gcc/lto/lto-symtab.c @@ -69,6 +69,13 @@ lto_cgraph_replace_node (struct cgraph_node *node, if (node->definition && prevailing_node->definition && DECL_COMDAT (node->decl) && DECL_COMDAT (prevailing_node->decl)) prevailing_node->merged_comdat = true; + else if ((node->definition || node->body_removed) + && DECL_DECLARED_INLINE_P (node->decl) + && DECL_EXTERNAL (node->decl) + && prevailing_node->definition) + prevailing_node->merged_extern_inline = true; + prevailing_node->merged_comdat |= node->merged_comdat; + prevailing_node->merged_extern_inline |= node->merged_extern_inline; /* Redirect all incoming edges. */ compatible_p diff --git a/gcc/symtab.c b/gcc/symtab.c index 5a3122fc8bb..6816bd1f884 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -1863,6 +1863,13 @@ symtab_node::noninterposable_alias (void) DECL_STATIC_CONSTRUCTOR (new_decl) = 0; DECL_STATIC_DESTRUCTOR (new_decl) = 0; new_node = cgraph_node::create_alias (new_decl, node->decl); + + cgraph_node *new_cnode = dyn_cast (new_node), + *cnode = dyn_cast (node); + + new_cnode->unit_id = cnode->unit_id; + new_cnode->merged_comdat = cnode->merged_comdat; + new_cnode->merged_extern_inline = cnode->merged_extern_inline; } else { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 650866f58c8..4595d664efa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-11-30 Jan Hubicka + + * g++.dg/lto/inline-crossmodule-1.h: New testcase. + * g++.dg/lto/inline-crossmodule-1_0.C: New testcase. + * g++.dg/lto/inline-crossmodule-1_1.C: New testcase. + 2019-11-30 Thomas Koenig PR fortran/91783 diff --git a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1.h b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1.h new file mode 100644 index 00000000000..ce345532a68 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1.h @@ -0,0 +1,15 @@ +struct a +{ + int ret1 () + { + return 1; + } + int key (); +}; +struct b +{ + int ret2 () + { + return 2; + } +}; diff --git a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C new file mode 100644 index 00000000000..a1712187010 --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C @@ -0,0 +1,11 @@ +// { dg-lto-do link } +/* { dg-lto-options { "-O2 -fno-early-inlining -flto -fdump-ipa-inline" } } */ +#include "inline-crossmodule-1.h" +int a::key () +{ + return 0; +} +/* { dg-final { scan-wpa-ipa-times "Inlined ret1" 1 "inlined" } } */ +/* { dg-final { scan-wpa-ipa-times "Inlined ret2" 1 "inlined" } } */ +/* { dg-final { scan-wpa-ipa-times "Inlined key\[^\\n\]*(cross module)" 1 "inlined" } } */ +/* { dg-final { scan-wpa-ipa-times "(cross module)" 1 "inlined" } } */ diff --git a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_1.C b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_1.C new file mode 100644 index 00000000000..72e4b9beedd --- /dev/null +++ b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_1.C @@ -0,0 +1,8 @@ +#include "inline-crossmodule-1.h" +int +main() +{ + struct a a; + struct b b; + return a.key () + a.ret1 () + b.ret2() - 3; +}