Commit 91382288 by Jan Hubicka Committed by Jan Hubicka

cgraph.h (tree_function_versioning): Update prototype.

	* 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
parent 6ac9d3a3
2010-06-01 Jan Hubicka <jh@suse.cz> 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. * gegenrtl.c: Remove unnecesary prototypes.
(gendecl): Remove. (gendecl): Remove.
(gendef): Produce static inline. (gendef): Produce static inline.
......
...@@ -616,8 +616,10 @@ void init_cgraph (void); ...@@ -616,8 +616,10 @@ void init_cgraph (void);
struct cgraph_node *cgraph_function_versioning (struct cgraph_node *, struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
VEC(cgraph_edge_p,heap)*, VEC(cgraph_edge_p,heap)*,
VEC(ipa_replace_map_p,gc)*, VEC(ipa_replace_map_p,gc)*,
bitmap, const char *); bitmap, bitmap, basic_block,
void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, bitmap); 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 *); struct cgraph_node *save_inline_function_body (struct cgraph_node *);
void record_references_in_initializer (tree, bool); void record_references_in_initializer (tree, bool);
bool cgraph_process_new_functions (void); bool cgraph_process_new_functions (void);
......
...@@ -2102,13 +2102,18 @@ update_call_expr (struct cgraph_node *new_version) ...@@ -2102,13 +2102,18 @@ update_call_expr (struct cgraph_node *new_version)
edges which should be redirected to point to edges which should be redirected to point to
NEW_VERSION. ALL the callees edges of OLD_VERSION NEW_VERSION. ALL the callees edges of OLD_VERSION
are cloned to the new version node. Return the new 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 * static struct cgraph_node *
cgraph_copy_node_for_versioning (struct cgraph_node *old_version, cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
tree new_decl, 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_node *new_version;
struct cgraph_edge *e; struct cgraph_edge *e;
unsigned i; unsigned i;
...@@ -2128,15 +2133,19 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version, ...@@ -2128,15 +2133,19 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
new_version->count = old_version->count; new_version->count = old_version->count;
for (e = old_version->callees; e; e=e->next_callee) for (e = old_version->callees; e; e=e->next_callee)
cgraph_clone_edge (e, new_version, e->call_stmt, if (!bbs_to_copy
e->lto_stmt_uid, REG_BR_PROB_BASE, || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
CGRAPH_FREQ_BASE, cgraph_clone_edge (e, new_version, e->call_stmt,
e->loop_nest, true); 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) for (e = old_version->indirect_calls; e; e=e->next_callee)
cgraph_clone_edge (e, new_version, e->call_stmt, if (!bbs_to_copy
e->lto_stmt_uid, REG_BR_PROB_BASE, || bitmap_bit_p (bbs_to_copy, gimple_bb (e->call_stmt)->index))
CGRAPH_FREQ_BASE, cgraph_clone_edge (e, new_version, e->call_stmt,
e->loop_nest, true); 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++) 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 /* 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, ...@@ -2159,14 +2168,18 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
new ones (according to results of prior analysis). new ones (according to results of prior analysis).
OLD_VERSION_NODE is the node that is versioned. OLD_VERSION_NODE is the node that is versioned.
It returns the new version's cgraph node. 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 * struct cgraph_node *
cgraph_function_versioning (struct cgraph_node *old_version_node, cgraph_function_versioning (struct cgraph_node *old_version_node,
VEC(cgraph_edge_p,heap) *redirect_callers, VEC(cgraph_edge_p,heap) *redirect_callers,
VEC (ipa_replace_map_p,gc)* tree_map, VEC (ipa_replace_map_p,gc)* tree_map,
bitmap args_to_skip, bitmap args_to_skip,
bitmap bbs_to_copy,
basic_block new_entry_block,
const char *clone_name) const char *clone_name)
{ {
tree old_decl = old_version_node->decl; tree old_decl = old_version_node->decl;
...@@ -2193,10 +2206,11 @@ cgraph_function_versioning (struct cgraph_node *old_version_node, ...@@ -2193,10 +2206,11 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
and update the edges of the new node. */ and update the edges of the new node. */
new_version_node = new_version_node =
cgraph_copy_node_for_versioning (old_version_node, new_decl, 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. */ /* 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. /* Update the new version's properties.
Make The new version visible only within this translation unit. Make sure Make The new version visible only within this translation unit. Make sure
...@@ -2267,7 +2281,8 @@ save_inline_function_body (struct cgraph_node *node) ...@@ -2267,7 +2281,8 @@ save_inline_function_body (struct cgraph_node *node)
} }
/* Copy the OLD_VERSION_NODE function tree to the new version. */ /* 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_EXTERNAL (first_clone->decl) = 0;
DECL_COMDAT_GROUP (first_clone->decl) = NULL_TREE; DECL_COMDAT_GROUP (first_clone->decl) = NULL_TREE;
...@@ -2296,7 +2311,7 @@ cgraph_materialize_clone (struct cgraph_node *node) ...@@ -2296,7 +2311,7 @@ cgraph_materialize_clone (struct cgraph_node *node)
/* Copy the OLD_VERSION_NODE function tree to the new version. */ /* Copy the OLD_VERSION_NODE function tree to the new version. */
tree_function_versioning (node->clone_of->decl, node->decl, tree_function_versioning (node->clone_of->decl, node->decl,
node->clone.tree_map, true, node->clone.tree_map, true,
node->clone.args_to_skip); node->clone.args_to_skip, NULL, NULL);
if (cgraph_dump_file) if (cgraph_dump_file)
{ {
dump_function_to_file (node->clone_of->decl, cgraph_dump_file, dump_flags); dump_function_to_file (node->clone_of->decl, cgraph_dump_file, dump_flags);
......
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);
}
/* { 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 ();
}
...@@ -1488,11 +1488,17 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, ...@@ -1488,11 +1488,17 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
basic_block copy_basic_block; basic_block copy_basic_block;
tree decl; tree decl;
gcov_type freq; 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 /* create_basic_block() will append every new block to
basic_block_info automatically. */ basic_block_info automatically. */
copy_basic_block = create_basic_block (NULL, (void *) 0, 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; copy_basic_block->count = bb->count * count_scale / REG_BR_PROB_BASE;
/* We are going to rebuild frequencies from scratch. These values /* 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, ...@@ -1728,7 +1734,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
= CIF_ORIGINALLY_INDIRECT_CALL; = CIF_ORIGINALLY_INDIRECT_CALL;
if (dump_file) 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)); cgraph_node_name (dest));
} }
} }
...@@ -2131,7 +2137,8 @@ maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb) ...@@ -2131,7 +2137,8 @@ maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb)
static tree static tree
copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale, 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; tree callee_fndecl = id->src_fn;
/* Original cfun for the callee, doesn't change. */ /* 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, ...@@ -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. */ /* Use aux pointers to map the original blocks to copy. */
FOR_EACH_BB_FN (bb, cfun_to_copy) FOR_EACH_BB_FN (bb, cfun_to_copy)
{ 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; basic_block new_bb = copy_bb (id, bb, frequency_scale, count_scale);
new_bb->aux = bb; bb->aux = new_bb;
} new_bb->aux = bb;
}
last = last_basic_block; last = last_basic_block;
/* Now that we've duplicated the blocks, duplicate their edges. */ /* Now that we've duplicated the blocks, duplicate their edges. */
FOR_ALL_BB_FN (bb, cfun_to_copy) 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)) if (gimple_in_ssa_p (cfun))
FOR_ALL_BB_FN (bb, cfun_to_copy) 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 edge e;
&& bb->index != ENTRY_BLOCK e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU);
&& bb->index != EXIT_BLOCK) e->probability = REG_BR_PROB_BASE;
maybe_move_debug_stmts_to_successors (id, (basic_block) bb->aux); e->count = entry_block_map->count;
((basic_block)bb->aux)->aux = NULL;
bb->aux = NULL;
} }
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 /* Zero out AUX fields of newly created block during EH edge
insertion. */ insertion. */
for (; last < last_basic_block; last++) for (; last < last_basic_block; last++)
...@@ -2317,14 +2338,16 @@ copy_tree_body (copy_body_data *id) ...@@ -2317,14 +2338,16 @@ copy_tree_body (copy_body_data *id)
static tree static tree
copy_body (copy_body_data *id, gcov_type count, int frequency_scale, 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 fndecl = id->src_fn;
tree body; tree body;
/* If this body has a CFG, walk CFG and copy. */ /* If this body has a CFG, walk CFG and copy. */
gcc_assert (ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (fndecl))); 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); copy_debug_stmts (id);
return body; return body;
...@@ -3924,7 +3947,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) ...@@ -3924,7 +3947,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
duplicate our body before altering anything. */ duplicate our body before altering anything. */
copy_body (id, bb->count, copy_body (id, bb->count,
cg_edge->frequency * REG_BR_PROB_BASE / CGRAPH_FREQ_BASE, cg_edge->frequency * REG_BR_PROB_BASE / CGRAPH_FREQ_BASE,
bb, return_block); bb, return_block, NULL, NULL);
/* Reset the escaped solution. */ /* Reset the escaped solution. */
if (cfun->gimple_df) if (cfun->gimple_df)
...@@ -4957,11 +4980,18 @@ update_clone_info (copy_body_data * id) ...@@ -4957,11 +4980,18 @@ update_clone_info (copy_body_data * id)
tree with another tree while duplicating the function's tree with another tree while duplicating the function's
body, TREE_MAP represents the mapping between these body, TREE_MAP represents the mapping between these
trees. If UPDATE_CLONES is set, the call_stmt fields 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 void
tree_function_versioning (tree old_decl, tree new_decl, tree_function_versioning (tree old_decl, tree new_decl,
VEC(ipa_replace_map_p,gc)* tree_map, 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 *old_version_node;
struct cgraph_node *new_version_node; struct cgraph_node *new_version_node;
...@@ -5113,7 +5143,7 @@ tree_function_versioning (tree old_decl, tree new_decl, ...@@ -5113,7 +5143,7 @@ tree_function_versioning (tree old_decl, tree new_decl,
/* Copy the Function's body. */ /* Copy the Function's body. */
copy_body (&id, old_entry_block->count, REG_BR_PROB_BASE, 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) if (DECL_RESULT (old_decl) != NULL_TREE)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment