cgraph.c (cgraph_node::dump): Dump unit_id and merged_extern_inline.
authorJan Hubicka <hubicka@ucw.cz>
Sat, 30 Nov 2019 16:56:45 +0000 (17:56 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 30 Nov 2019 16:56:45 +0000 (16:56 +0000)
* 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.

* 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.

From-SVN: r278876

16 files changed:
gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphclones.c
gcc/ipa-fnsummary.c
gcc/ipa-fnsummary.h
gcc/ipa-inline-analysis.c
gcc/ipa-inline.c
gcc/lto-cgraph.c
gcc/lto-streamer.h
gcc/lto/lto-symtab.c
gcc/symtab.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lto/inline-crossmodule-1.h [new file with mode: 0644]
gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lto/inline-crossmodule-1_1.C [new file with mode: 0644]

index 2a29e1b2b4d7f59326dc055771512737b59663a1..0bfc23996ce5bc1d58a73632dc9c681b5c160aa8 100644 (file)
@@ -1,3 +1,28 @@
+2019-11-30  Jan Hubicka  <hubicka@ucw.cz>
+
+       * 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  <macro@wdc.com>
 
        * gcc.c (process_command): Only warn about an ineffective `-x'
index 180d21e47969800c0382ab9dfed0c760113d4df7..b75430f3f3aab759c5c9052b45ef6db0cd51aee1 100644 (file)
@@ -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)
index 0d2442c997ca298dfb6814aee414e2c8dd2dc433..2aedaaedd611db5bd61d36a1f9a7872bbabc35fc 100644 (file)
@@ -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.  */
index 9aacb0b196cc03473b4ef3d0915b55620426cc19..81c5dfd194f972388f1bb2f902492af9cfd66728 100644 (file)
@@ -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
index 66d2be6677cb0d6ddb0c7947368d99e155768a6a..9d16026658907c9b31faf6b9cd8eb13adb35db0a 100644 (file)
@@ -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);
index 21ecd54293f6ee03f212bd1e8df61d039584cfff..e43003212a82ae7e0799702b1ed9fa9526de07fe 100644 (file)
@@ -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 */
index ae8e5db3d9c8cb983288824eb43bf39d997062e5..75c6399d35d4cda7e79ec6a7b9a3f5a06ed86522 100644 (file)
@@ -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;
index c742a99bcd7f0edd45cbc1714f596bd6976f3268..56ea671c9bc4887e4bc7ae58ac1b63c933f2bd0b 100644 (file)
@@ -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)
        {
index a4a70e7848c46a97b8fc9a549d3d050ffcc0051f..d2a5d5376fe49654220f4e13890e80519e0ed575 100644 (file)
@@ -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)
index 7b712808bd57ecebe7d60d81ecbc534c010f8315..dba195d38844bde8726a70c1b9c56306ed0cfb58 100644 (file)
@@ -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;
index 2fd5b1e8f49bf56787c2ddd5640f04fa074880b3..8dfae6277821001ba48f091d4f40f5699357f6bc 100644 (file)
@@ -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
index 5a3122fc8bb9675fe48b9cb08f479cc1cfade759..6816bd1f884faaf7983a3dbcad5cedc99c74a8e1 100644 (file)
@@ -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 <cgraph_node *> (new_node),
+                  *cnode = dyn_cast <cgraph_node *> (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
     {
index 650866f58c8f10b0eb0b6e908f0b210a1bc20915..4595d664efaf9802c20984ccf4a1ed8b14155640 100644 (file)
@@ -1,3 +1,9 @@
+2019-11-30  Jan Hubicka  <hubicka@ucw.cz>
+
+       * 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  <tkoenig@gcc.gnu.org>
 
        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 (file)
index 0000000..ce34553
--- /dev/null
@@ -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 (file)
index 0000000..a171218
--- /dev/null
@@ -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 (file)
index 0000000..72e4b9b
--- /dev/null
@@ -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;
+}