This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Partial clonning


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)
> ? ? {
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]