Partial clonning
Richard Guenther
richard.guenther@gmail.com
Tue Jun 1 14:50:00 GMT 2010
2010/6/1 Jan Hubicka <hubicka@ucw.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.
>>
>> New parameters need adjustment of the comment.
> Fixed.
>>
>> I wonder if new_entry handling cannot be done here rather than
>> in copy_cfg_body?
>
> It can not, sicne we destroy the old->new basic block map before returning.
> Here is updated patch with comments for function arguments. OK?
Ok.
Thanks,
Richard.
> Honza
>
> 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)
> @@ -2100,13 +2100,18 @@ update_call_expr (struct cgraph_node *ne
> 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;
> @@ -2126,15 +2131,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
> @@ -2157,14 +2166,18 @@ cgraph_copy_node_for_versioning (struct
> 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;
> @@ -2191,10 +2204,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 +2279,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 +2309,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)
> {
> 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)
> {
> 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)
> @@ -4871,11 +4894,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;
> @@ -5027,7 +5057,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