Partial clonning

Richard Guenther richard.guenther@gmail.com
Sat May 29 19:36:00 GMT 2010


On Sat, May 29, 2010 at 8:42 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> this patch adds support to tree_function_versioning to copy just selected region of function.
> This is done by passing bitmap of basic blocks to copy and new entry of the function.
> I use it for function splitting pass.
>
> Bootstrapped/regtested x86_64-linux, OK?
>
> Honza
>
>        * 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.
> Index: cgraph.h
> ===================================================================
> --- cgraph.h    (revision 160017)
> +++ cgraph.h    (working copy)
> @@ -615,8 +615,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: cgraphunit.c
> ===================================================================
> --- cgraphunit.c        (revision 160017)
> +++ cgraphunit.c        (working copy)
> @@ -2105,8 +2105,9 @@ update_call_expr (struct cgraph_node *ne
>  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)

New parameters need adjustment of the comment.

> + {
>    struct cgraph_node *new_version;
>    struct cgraph_edge *e;
>    unsigned i;
> @@ -2126,15 +2127,19 @@ cgraph_copy_node_for_versioning (struct
>    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
> @@ -2165,6 +2170,8 @@ cgraph_function_versioning (struct cgrap
>                            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)

Likewise.

>  {
>   tree old_decl = old_version_node->decl;
> @@ -2191,10 +2198,11 @@ cgraph_function_versioning (struct cgrap
>      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
> @@ -2265,7 +2273,8 @@ save_inline_function_body (struct cgraph
>       }
>
>   /* 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;
> @@ -2294,7 +2303,7 @@ cgraph_materialize_clone (struct cgraph_
>   /* 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);
> Index: tree-inline.c
> ===================================================================
> --- tree-inline.c       (revision 160017)
> +++ tree-inline.c       (working copy)
> @@ -1488,11 +1488,17 @@ copy_bb (copy_body_data *id, basic_block
>   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
>                      = 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));
>                    }
>                }
> @@ -2064,7 +2070,8 @@ initialize_cfun (tree new_fndecl, tree c
>
>  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)

Likewise.

>  {
>   tree callee_fndecl = id->src_fn;
>   /* Original cfun for the callee, doesn't change.  */
> @@ -2102,27 +2109,41 @@ copy_cfg_body (copy_body_data * id, gcov
>
>   /* 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)
> -    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)))
> +      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);
> +
> +  if (new_entry)
> +    {
> +      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)
> -    {
> -      ((basic_block)bb->aux)->aux = NULL;
> -      bb->aux = NULL;
> -    }
> +    if (bb->aux)
> +      {
> +       ((basic_block)bb->aux)->aux = NULL;
> +       bb->aux = NULL;
> +      }
>
>   /* Zero out AUX fields of newly created block during EH edge
>      insertion. */
> @@ -2241,14 +2262,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)

Likewise.

>  {
>   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;
> @@ -3838,7 +3861,7 @@ expand_call_inline (basic_block bb, gimp
>      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)
> @@ -4875,7 +4898,8 @@ update_clone_info (copy_body_data * id)
>  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)

Likewise.

I wonder if new_entry handling cannot be done here rather than
in copy_cfg_body?

Thanks,
Richard.

>  {
>   struct cgraph_node *old_version_node;
>   struct cgraph_node *new_version_node;
> @@ -5027,7 +5051,7 @@ tree_function_versioning (tree old_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)
>     {
>



More information about the Gcc-patches mailing list