Introduce -fdump-ipa-clones dump output
authorMartin Liska <mliska@suse.cz>
Wed, 30 Nov 2016 09:28:19 +0000 (10:28 +0100)
committerMartin Liska <marxin@gcc.gnu.org>
Wed, 30 Nov 2016 09:28:19 +0000 (09:28 +0000)
* cgraph.c (symbol_table::initialize): Initialize
ipa_clones_dump_file.
(cgraph_node::remove): Report to ipa_clones_dump_file.
* cgraph.h: Add new argument (suffix) to cloning methods.
* cgraphclones.c (dump_callgraph_transformation): New function.
(cgraph_node::create_clone): New argument.
(cgraph_node::create_virtual_clone): Likewise.
(cgraph_node::create_version_clone): Likewise.
* dumpfile.c: Add .ipa-clones dump file.
* dumpfile.h (enum tree_dump_index): Add TDI_clones
* ipa-inline-transform.c (clone_inlined_nodes): Report operation
to dump_callgraph_transformation.

From-SVN: r243004

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphclones.c
gcc/dumpfile.c
gcc/dumpfile.h
gcc/ipa-inline-transform.c

index c68d3c95005ef9df50b5d9ccd643e419e000035b..da94944da1d34050db8807f6d5e14564edf3f49d 100644 (file)
@@ -1,3 +1,18 @@
+2016-11-30  Martin Liska  <mliska@suse.cz>
+
+       * cgraph.c (symbol_table::initialize): Initialize
+       ipa_clones_dump_file.
+       (cgraph_node::remove): Report to ipa_clones_dump_file.
+       * cgraph.h: Add new argument (suffix) to cloning methods.
+       * cgraphclones.c (dump_callgraph_transformation): New function.
+       (cgraph_node::create_clone): New argument.
+       (cgraph_node::create_virtual_clone): Likewise.
+       (cgraph_node::create_version_clone): Likewise.
+       * dumpfile.c: Add .ipa-clones dump file.
+       * dumpfile.h (enum tree_dump_index): Add TDI_clones
+       * ipa-inline-transform.c (clone_inlined_nodes): Report operation
+       to dump_callgraph_transformation.
+
 2016-11-30  Martin Liska  <mliska@suse.cz>
 
        PR sanitizer/78541
index b702a7cd5eaa7b3e761b93eab314154679c9b679..867e371a3f9a6710084cb41aa9ec20a871e77505 100644 (file)
@@ -263,6 +263,9 @@ symbol_table::initialize (void)
 {
   if (!dump_file)
     dump_file = dump_begin (TDI_cgraph, NULL);
+
+  if (!ipa_clones_dump_file)
+    ipa_clones_dump_file = dump_begin (TDI_clones, NULL);
 }
 
 /* Allocate new callgraph node and insert it into basic data structures.  */
@@ -1815,6 +1818,12 @@ cgraph_node::remove (void)
   cgraph_node *n;
   int uid = this->uid;
 
+  if (symtab->ipa_clones_dump_file && symtab->cloned_nodes.contains (this))
+    fprintf (symtab->ipa_clones_dump_file,
+            "Callgraph removal;%s;%d;%s;%d;%d\n", asm_name (), order,
+            DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl),
+            DECL_SOURCE_COLUMN (decl));
+
   symtab->call_cgraph_removal_hooks (this);
   remove_callers ();
   remove_callees ();
index cc730d2faf169cceb6ebafac8fd24ac728bde2f3..3feed7a8d8057b60afb7bd5ed9e4d0cba2ee2548 100644 (file)
@@ -906,13 +906,14 @@ public:
      If the new node is being inlined into another one, NEW_INLINED_TO should be
      the outline function the new one is (even indirectly) inlined to.
      All hooks will see this in node's global.inlined_to, when invoked.
-     Can be NULL if the node is not inlined.  */
+     Can be NULL if the node is not inlined.  SUFFIX is string that is appended
+     to the original name.  */
   cgraph_node *create_clone (tree decl, gcov_type count, int freq,
                             bool update_original,
                             vec<cgraph_edge *> redirect_callers,
                             bool call_duplication_hook,
                             cgraph_node *new_inlined_to,
-                            bitmap args_to_skip);
+                            bitmap args_to_skip, const char *suffix = NULL);
 
   /* Create callgraph node clone with new declaration.  The actual body will
      be copied later at compilation stage.  */
@@ -933,11 +934,14 @@ public:
 
      If non-NULL BLOCK_TO_COPY determine what basic blocks
      was copied to prevent duplications of calls that are dead
-     in the clone.  */
+     in the clone.
+
+     SUFFIX is string that is appended to the original name.  */
 
   cgraph_node *create_version_clone (tree new_decl,
                                    vec<cgraph_edge *> redirect_callers,
-                                   bitmap bbs_to_copy);
+                                   bitmap bbs_to_copy,
+                                   const char *suffix = NULL);
 
   /* Perform function versioning.
      Function versioning includes copying of the tree and
@@ -2223,6 +2227,10 @@ public:
   /* Return symbol used to separate symbol name from suffix.  */
   static char symbol_suffix_separator ();
 
+  FILE* GTY ((skip)) ipa_clones_dump_file;
+
+  hash_set <const cgraph_node *> GTY ((skip)) cloned_nodes;
+
 private:
   /* Allocate new callgraph node.  */
   inline cgraph_node * allocate_cgraph_symbol (void);
@@ -2313,6 +2321,10 @@ tree clone_function_name (tree decl, const char *);
 void tree_function_versioning (tree, tree, vec<ipa_replace_map *, va_gc> *,
                               bool, bitmap, bool, bitmap, basic_block);
 
+void dump_callgraph_transformation (const cgraph_node *original,
+                                   const cgraph_node *clone,
+                                   const char *suffix);
+
 /* In cgraphbuild.c  */
 int compute_call_stmt_bb_frequency (tree, basic_block bb);
 void record_references_in_initializer (tree, bool);
index 686c28900210c73e924902f6401fd403a1f46f35..349892dab67bfee6d94f6cd65a0c145fa74f481e 100644 (file)
@@ -381,6 +381,28 @@ cgraph_node::expand_all_artificial_thunks ()
       e = e->next_caller;
 }
 
+void
+dump_callgraph_transformation (const cgraph_node *original,
+                              const cgraph_node *clone,
+                              const char *suffix)
+{
+  if (symtab->ipa_clones_dump_file)
+    {
+      fprintf (symtab->ipa_clones_dump_file,
+              "Callgraph clone;%s;%d;%s;%d;%d;%s;%d;%s;%d;%d;%s\n",
+              original->asm_name (), original->order,
+              DECL_SOURCE_FILE (original->decl),
+              DECL_SOURCE_LINE (original->decl),
+              DECL_SOURCE_COLUMN (original->decl), clone->asm_name (),
+              clone->order, DECL_SOURCE_FILE (clone->decl),
+              DECL_SOURCE_LINE (clone->decl), DECL_SOURCE_COLUMN (clone->decl),
+              suffix);
+
+      symtab->cloned_nodes.add (original);
+      symtab->cloned_nodes.add (clone);
+    }
+}
+
 /* Create node representing clone of N executed COUNT times.  Decrease
    the execution counts from original node too.
    The new clone will have decl set to DECL that may or may not be the same
@@ -403,13 +425,16 @@ cgraph_node::create_clone (tree new_decl, gcov_type gcov_count, int freq,
                           vec<cgraph_edge *> redirect_callers,
                           bool call_duplication_hook,
                           cgraph_node *new_inlined_to,
-                          bitmap args_to_skip)
+                          bitmap args_to_skip, const char *suffix)
 {
   cgraph_node *new_node = symtab->create_empty ();
   cgraph_edge *e;
   gcov_type count_scale;
   unsigned i;
 
+  if (new_inlined_to)
+    dump_callgraph_transformation (this, new_inlined_to, "inlining to");
+
   new_node->decl = new_decl;
   new_node->register_symbol ();
   new_node->origin = origin;
@@ -495,6 +520,10 @@ cgraph_node::create_clone (tree new_decl, gcov_type gcov_count, int freq,
 
   if (call_duplication_hook)
     symtab->call_cgraph_duplication_hooks (this, new_node);
+
+  if (!new_inlined_to)
+    dump_callgraph_transformation (this, new_node, suffix);
+
   return new_node;
 }
 
@@ -575,7 +604,7 @@ cgraph_node::create_virtual_clone (vec<cgraph_edge *> redirect_callers,
   SET_DECL_RTL (new_decl, NULL);
 
   new_node = create_clone (new_decl, count, CGRAPH_FREQ_BASE, false,
-                          redirect_callers, false, NULL, args_to_skip);
+                          redirect_callers, false, NULL, args_to_skip, suffix);
 
   /* Update the properties.
      Make clone visible only within this translation unit.  Make sure
@@ -863,7 +892,8 @@ update_call_expr (cgraph_node *new_version)
 cgraph_node *
 cgraph_node::create_version_clone (tree new_decl,
                                  vec<cgraph_edge *> redirect_callers,
-                                 bitmap bbs_to_copy)
+                                 bitmap bbs_to_copy,
+                                 const char *suffix)
  {
    cgraph_node *new_version;
    cgraph_edge *e;
@@ -904,6 +934,8 @@ cgraph_node::create_version_clone (tree new_decl,
 
    symtab->call_cgraph_duplication_hooks (this, new_version);
 
+   dump_callgraph_transformation (this, new_version, suffix);
+
    return new_version;
  }
 
@@ -931,7 +963,7 @@ cgraph_node::create_version_clone_with_body
   (vec<cgraph_edge *> redirect_callers,
    vec<ipa_replace_map *, va_gc> *tree_map, bitmap args_to_skip,
    bool skip_return, bitmap bbs_to_copy, basic_block new_entry_block,
-   const char *clone_name)
+   const char *suffix)
 {
   tree old_decl = decl;
   cgraph_node *new_version_node = NULL;
@@ -950,7 +982,7 @@ cgraph_node::create_version_clone_with_body
       = build_function_decl_skip_args (old_decl, args_to_skip, skip_return);
 
   /* Generate a new name for the new version. */
-  DECL_NAME (new_decl) = clone_function_name (old_decl, clone_name);
+  DECL_NAME (new_decl) = clone_function_name (old_decl, suffix);
   SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
   SET_DECL_RTL (new_decl, NULL);
 
@@ -961,7 +993,7 @@ cgraph_node::create_version_clone_with_body
   /* Create the new version's call-graph node.
      and update the edges of the new node. */
   new_version_node = create_version_clone (new_decl, redirect_callers,
-                                         bbs_to_copy);
+                                         bbs_to_copy, suffix);
 
   if (ipa_transforms_to_apply.exists ())
     new_version_node->ipa_transforms_to_apply
index 5b23c3f77a8e97e17904c6851af122a2ec864d19..291d2ef905b83ad771e9bd3634ef6a5e9403af07 100644 (file)
@@ -55,6 +55,8 @@ static struct dump_file_info dump_files[TDI_end] =
    0, 0, 0, 0, 0, false, false},
   {".type-inheritance", "ipa-type-inheritance", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
    0, 0, 0, 0, 0, false, false},
+  {".ipa-clones", "ipa-clones", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
+   0, 0, 0, 0, 0, false, false},
   {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
    0, 0, 0, 0, 1, false, false},
   {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
index f366228f465a51c77808ee0a24f324e0e0fc28b7..9ef457048821ce95ae0f8fc7024f14c7895716aa 100644 (file)
@@ -29,6 +29,7 @@ enum tree_dump_index
   TDI_none,                    /* No dump */
   TDI_cgraph,                   /* dump function call graph.  */
   TDI_inheritance,              /* dump type inheritance graph.  */
+  TDI_clones,                  /* dump IPA cloning decisions.  */
   TDI_tu,                      /* dump the whole translation unit.  */
   TDI_class,                   /* dump class hierarchy.  */
   TDI_original,                        /* dump each function before optimizing it */
index efe7421f31d69a909cb96fa5e9f5eff996eb3eac..68750800f1a700c73359040125c24f159162cd7d 100644 (file)
@@ -209,6 +209,9 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
          duplicate = false;
          e->callee->externally_visible = false;
           update_noncloned_frequencies (e->callee, e->frequency);
+
+         dump_callgraph_transformation (e->callee, inlining_into,
+                                        "inlining to");
        }
       else
        {