]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cgraph.h (tree_function_versioning): Update prototype.
authorJan Hubicka <jh@suse.cz>
Tue, 1 Jun 2010 15:43:27 +0000 (17:43 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Tue, 1 Jun 2010 15:43:27 +0000 (15:43 +0000)
* cgraph.h (tree_function_versioning): Update prototype.
(cgraph_function_versioning): Update prototype.
* cgraphunit.c (cgraph_copy_node_for_versioning): Accept bbs_to_copy
bitmap.
(cgraph_function_versioning): Accept new_entry_block and bbs_to_copy.
(cgraph_materialize_clone, save_inline_function_body): Update use of
tree_function_versioning.
* tree-inline.c (copy_bb): Look for previous copied block to link after;
fix debug output.
(copy_cfg_body): Accept new_entry_block and bbs_to_copy.
(copy_body): Likewise.
(expand_call_inline): Update use of copy_body.
(tree_function_versioning): Update use of copy body; accept
blocks_to_copy and new_entry.

From-SVN: r160110

gcc/ChangeLog
gcc/cgraph.h
gcc/cgraphunit.c
gcc/testsuite/gcc.dg/lto/noreturn-1_0.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/lto/noreturn-1_1.c [new file with mode: 0644]
gcc/tree-inline.c

index c1317965b86b7e4ec7aefe2cf87d3cb2bb3bd7f3..0ff31f1281b6f341c4b6eec5b4bb37c9623031e9 100644 (file)
@@ -1,3 +1,20 @@
+2010-06-01  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.h (tree_function_versioning): Update prototype.
+       (cgraph_function_versioning): Update prototype.
+       * cgraphunit.c (cgraph_copy_node_for_versioning): Accept bbs_to_copy
+       bitmap.
+       (cgraph_function_versioning): Accept new_entry_block and bbs_to_copy. 
+       (cgraph_materialize_clone, save_inline_function_body): Update use of
+       tree_function_versioning.
+       * tree-inline.c (copy_bb): Look for previous copied block to link after;
+       fix debug output.
+       (copy_cfg_body): Accept new_entry_block and bbs_to_copy.
+       (copy_body): Likewise.
+       (expand_call_inline): Update use of copy_body.
+       (tree_function_versioning): Update use of copy body; accept
+       blocks_to_copy and new_entry.
+
 2010-06-01  Jan Hubicka  <jh@suse.cz>
 
        * gegenrtl.c: Remove unnecesary prototypes.
index 3c91f0498c8e291159312c1a3c472d1bcea3ee9c..c82fc181ebef64bab9de49f810c91909371570cf 100644 (file)
@@ -616,8 +616,10 @@ void init_cgraph (void);
 struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
                                                VEC(cgraph_edge_p,heap)*,
                                                VEC(ipa_replace_map_p,gc)*,
-                                               bitmap, const char *);
-void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, bitmap);
+                                               bitmap, bitmap, basic_block,
+                                               const char *);
+void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, bitmap,
+                              bitmap, basic_block);
 struct cgraph_node *save_inline_function_body (struct cgraph_node *);
 void record_references_in_initializer (tree, bool);
 bool cgraph_process_new_functions (void);
index 1d5ed0d5ed877b94edec7242932cde1ccb1b0f26..47686a4212aa6931c3e04dd20256a3e943fceaf2 100644 (file)
@@ -2102,13 +2102,18 @@ update_call_expr (struct cgraph_node *new_version)
    edges which should be redirected to point to
    NEW_VERSION.  ALL the callees edges of OLD_VERSION
    are cloned to the new version node.  Return the new
-   version node.  */
+   version node. 
+
+   If non-NULL BLOCK_TO_COPY determine what basic blocks 
+   was copied to prevent duplications of calls that are dead
+   in the clone.  */
 
 static struct cgraph_node *
 cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
                                 tree new_decl,
-                                VEC(cgraph_edge_p,heap) *redirect_callers)
-{
+                                VEC(cgraph_edge_p,heap) *redirect_callers,
+                                bitmap bbs_to_copy)
+ {
    struct cgraph_node *new_version;
    struct cgraph_edge *e;
    unsigned i;
@@ -2128,15 +2133,19 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
    new_version->count = old_version->count;
 
    for (e = old_version->callees; e; e=e->next_callee)
-     cgraph_clone_edge (e, new_version, e->call_stmt,
-                       e->lto_stmt_uid, REG_BR_PROB_BASE,
-                       CGRAPH_FREQ_BASE,
-                       e->loop_nest, true);
+     if (!bbs_to_copy
+        || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
+       cgraph_clone_edge (e, new_version, e->call_stmt,
+                         e->lto_stmt_uid, REG_BR_PROB_BASE,
+                         CGRAPH_FREQ_BASE,
+                         e->loop_nest, true);
    for (e = old_version->indirect_calls; e; e=e->next_callee)
-     cgraph_clone_edge (e, new_version, e->call_stmt,
-                       e->lto_stmt_uid, REG_BR_PROB_BASE,
-                       CGRAPH_FREQ_BASE,
-                       e->loop_nest, true);
+     if (!bbs_to_copy
+        || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
+       cgraph_clone_edge (e, new_version, e->call_stmt,
+                         e->lto_stmt_uid, REG_BR_PROB_BASE,
+                         CGRAPH_FREQ_BASE,
+                         e->loop_nest, true);
    for (i = 0; VEC_iterate (cgraph_edge_p, redirect_callers, i, e); i++)
      {
        /* Redirect calls to the old version node to point to its new
@@ -2159,14 +2168,18 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
     new ones (according to results of prior analysis).
     OLD_VERSION_NODE is the node that is versioned.
     It returns the new version's cgraph node.
-    ARGS_TO_SKIP lists arguments to be omitted from functions
-    */
+    If non-NULL ARGS_TO_SKIP determine function parameters to remove
+    from new version.
+    If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
+    If non_NULL NEW_ENTRY determine new entry BB of the clone.  */
 
 struct cgraph_node *
 cgraph_function_versioning (struct cgraph_node *old_version_node,
                            VEC(cgraph_edge_p,heap) *redirect_callers,
                            VEC (ipa_replace_map_p,gc)* tree_map,
                            bitmap args_to_skip,
+                           bitmap bbs_to_copy,
+                           basic_block new_entry_block,
                            const char *clone_name)
 {
   tree old_decl = old_version_node->decl;
@@ -2193,10 +2206,11 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
      and update the edges of the new node. */
   new_version_node =
     cgraph_copy_node_for_versioning (old_version_node, new_decl,
-                                    redirect_callers);
+                                    redirect_callers, bbs_to_copy);
 
   /* Copy the OLD_VERSION_NODE function tree to the new version.  */
-  tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip);
+  tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip,
+                           bbs_to_copy, new_entry_block);
 
   /* Update the new version's properties.
      Make The new version visible only within this translation unit.  Make sure
@@ -2267,7 +2281,8 @@ save_inline_function_body (struct cgraph_node *node)
       }
 
   /* Copy the OLD_VERSION_NODE function tree to the new version.  */
-  tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL);
+  tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL,
+                           NULL, NULL);
 
   DECL_EXTERNAL (first_clone->decl) = 0;
   DECL_COMDAT_GROUP (first_clone->decl) = NULL_TREE;
@@ -2296,7 +2311,7 @@ cgraph_materialize_clone (struct cgraph_node *node)
   /* Copy the OLD_VERSION_NODE function tree to the new version.  */
   tree_function_versioning (node->clone_of->decl, node->decl,
                            node->clone.tree_map, true,
-                           node->clone.args_to_skip);
+                           node->clone.args_to_skip, NULL, NULL);
   if (cgraph_dump_file)
     {
       dump_function_to_file (node->clone_of->decl, cgraph_dump_file, dump_flags);
diff --git a/gcc/testsuite/gcc.dg/lto/noreturn-1_0.c b/gcc/testsuite/gcc.dg/lto/noreturn-1_0.c
new file mode 100644 (file)
index 0000000..eb71c64
--- /dev/null
@@ -0,0 +1,21 @@
+void exit (int);
+__attribute__ ((noreturn))
+int
+call_me (void)
+{
+  exit (0);
+}
+void exit (int);
+__attribute__ ((noreturn))
+int
+call_me (void)
+{
+  exit (0);
+}
+void exit (int);
+__attribute__ ((noreturn))
+int
+call_me (void)
+{
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/lto/noreturn-1_1.c b/gcc/testsuite/gcc.dg/lto/noreturn-1_1.c
new file mode 100644 (file)
index 0000000..8e8b060
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options {{-O2 -fwhopr} } } */
+
+int call_me (void);
+int
+main(void)
+{
+ return call_me ();
+}
+/* { dg-lto-do run } */
+/* { dg-lto-options {{-O2 -fwhopr} } } */
+
+int call_me (void);
+int
+main(void)
+{
+ return call_me ();
+}
+/* { dg-lto-do run } */
+/* { dg-lto-options {{-O2 -fwhopr} } } */
+
+int call_me (void);
+int
+main(void)
+{
+ return call_me ();
+}
index 4ac1b3fb71d9d2e15083ffe7b1b5b549717f10cd..fce6ae54a6ba98f425e4c9794aa6e771612819b0 100644 (file)
@@ -1488,11 +1488,17 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
   basic_block copy_basic_block;
   tree decl;
   gcov_type freq;
+  basic_block prev;
+
+  /* Search for previous copied basic block.  */
+  prev = bb->prev_bb;
+  while (!prev->aux)
+    prev = prev->prev_bb;
 
   /* create_basic_block() will append every new block to
      basic_block_info automatically.  */
   copy_basic_block = create_basic_block (NULL, (void *) 0,
-                                         (basic_block) bb->prev_bb->aux);
+                                         (basic_block) prev->aux);
   copy_basic_block->count = bb->count * count_scale / REG_BR_PROB_BASE;
 
   /* We are going to rebuild frequencies from scratch.  These values
@@ -1728,7 +1734,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
                      = CIF_ORIGINALLY_INDIRECT_CALL;
                  if (dump_file)
                    {
-                     fprintf (dump_file, "Created new direct edge to %s",
+                     fprintf (dump_file, "Created new direct edge to %s\n",
                               cgraph_node_name (dest));
                    }
                }
@@ -2131,7 +2137,8 @@ maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb)
 
 static tree
 copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
-              basic_block entry_block_map, basic_block exit_block_map)
+              basic_block entry_block_map, basic_block exit_block_map,
+              bitmap blocks_to_copy, basic_block new_entry)
 {
   tree callee_fndecl = id->src_fn;
   /* Original cfun for the callee, doesn't change.  */
@@ -2170,32 +2177,46 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
 
   /* Use aux pointers to map the original blocks to copy.  */
   FOR_EACH_BB_FN (bb, cfun_to_copy)
-    {
-      basic_block new_bb = copy_bb (id, bb, frequency_scale, count_scale);
-      bb->aux = new_bb;
-      new_bb->aux = bb;
-    }
+    if (!blocks_to_copy || bitmap_bit_p (blocks_to_copy, bb->index))
+      {
+       basic_block new_bb = copy_bb (id, bb, frequency_scale, count_scale);
+       bb->aux = new_bb;
+       new_bb->aux = bb;
+      }
 
   last = last_basic_block;
 
   /* Now that we've duplicated the blocks, duplicate their edges.  */
   FOR_ALL_BB_FN (bb, cfun_to_copy)
-    need_debug_cleanup |= copy_edges_for_bb (bb, count_scale, exit_block_map);
+    if (!blocks_to_copy
+        || (bb->index > 0 && bitmap_bit_p (blocks_to_copy, bb->index)))
+      need_debug_cleanup |= copy_edges_for_bb (bb, count_scale, exit_block_map);
 
   if (gimple_in_ssa_p (cfun))
     FOR_ALL_BB_FN (bb, cfun_to_copy)
-      copy_phis_for_bb (bb, id);
+      if (!blocks_to_copy
+         || (bb->index > 0 && bitmap_bit_p (blocks_to_copy, bb->index)))
+       copy_phis_for_bb (bb, id);
 
-  FOR_ALL_BB_FN (bb, cfun_to_copy)
+  if (new_entry)
     {
-      if (need_debug_cleanup
-         && bb->index != ENTRY_BLOCK
-         && bb->index != EXIT_BLOCK)
-       maybe_move_debug_stmts_to_successors (id, (basic_block) bb->aux);
-      ((basic_block)bb->aux)->aux = NULL;
-      bb->aux = NULL;
+      edge e;
+      e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU);
+      e->probability = REG_BR_PROB_BASE;
+      e->count = entry_block_map->count;
     }
 
+  FOR_ALL_BB_FN (bb, cfun_to_copy)
+    if (bb->aux)
+      {
+       if (need_debug_cleanup
+           && bb->index != ENTRY_BLOCK
+           && bb->index != EXIT_BLOCK)
+         maybe_move_debug_stmts_to_successors (id, (basic_block) bb->aux);
+       ((basic_block)bb->aux)->aux = NULL;
+       bb->aux = NULL;
+      }
+
   /* Zero out AUX fields of newly created block during EH edge
      insertion. */
   for (; last < last_basic_block; last++)
@@ -2317,14 +2338,16 @@ copy_tree_body (copy_body_data *id)
 
 static tree
 copy_body (copy_body_data *id, gcov_type count, int frequency_scale,
-          basic_block entry_block_map, basic_block exit_block_map)
+          basic_block entry_block_map, basic_block exit_block_map,
+          bitmap blocks_to_copy, basic_block new_entry)
 {
   tree fndecl = id->src_fn;
   tree body;
 
   /* If this body has a CFG, walk CFG and copy.  */
   gcc_assert (ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (fndecl)));
-  body = copy_cfg_body (id, count, frequency_scale, entry_block_map, exit_block_map);
+  body = copy_cfg_body (id, count, frequency_scale, entry_block_map, exit_block_map,
+                       blocks_to_copy, new_entry);
   copy_debug_stmts (id);
 
   return body;
@@ -3924,7 +3947,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
      duplicate our body before altering anything.  */
   copy_body (id, bb->count,
             cg_edge->frequency * REG_BR_PROB_BASE / CGRAPH_FREQ_BASE,
-            bb, return_block);
+            bb, return_block, NULL, NULL);
 
   /* Reset the escaped solution.  */
   if (cfun->gimple_df)
@@ -4957,11 +4980,18 @@ update_clone_info (copy_body_data * id)
    tree with another tree while duplicating the function's
    body, TREE_MAP represents the mapping between these
    trees. If UPDATE_CLONES is set, the call_stmt fields
-   of edges of clones of the function will be updated.  */
+   of edges of clones of the function will be updated.  
+
+   If non-NULL ARGS_TO_SKIP determine function parameters to remove
+   from new version.
+   If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
+   If non_NULL NEW_ENTRY determine new entry BB of the clone.
+*/
 void
 tree_function_versioning (tree old_decl, tree new_decl,
                          VEC(ipa_replace_map_p,gc)* tree_map,
-                         bool update_clones, bitmap args_to_skip)
+                         bool update_clones, bitmap args_to_skip,
+                         bitmap blocks_to_copy, basic_block new_entry)
 {
   struct cgraph_node *old_version_node;
   struct cgraph_node *new_version_node;
@@ -5113,7 +5143,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
 
   /* Copy the Function's body.  */
   copy_body (&id, old_entry_block->count, REG_BR_PROB_BASE,
-            ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR);
+            ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, blocks_to_copy, new_entry);
 
   if (DECL_RESULT (old_decl) != NULL_TREE)
     {