Commit 9187e02d by Jan Hubicka Committed by Jan Hubicka

cgraphbuild.c (compute_call_stmt_bb_frequency): Accept function argument; handle…

cgraphbuild.c (compute_call_stmt_bb_frequency): Accept function argument; handle correctly when profile is absent.

	* cgraphbuild.c (compute_call_stmt_bb_frequency): Accept function argument;
	handle correctly when profile is absent.
	(build_cgraph_edges): Update.
	(rebuild_cgraph_edges): Update.
	* cgraph.c: Do not include varrau.h 
	(cgraph_set_call_stmt_including_clones, cgraph_create_edge_including_clones):
	New function
	(cgraph_update_edges_for_call_stmt_node): New stati cfunction.
	(cgraph_update_edges_for_call_stmt): Handle clones.
	(cgraph_remove_node): Handle clone tree.
	(cgraph_remove_node_and_inline_clones): New function.
	(dump_cgraph_node): Dump clone tree.
	(cgraph_clone_node): Handle clone tree.
	(clone_function_name): Bring here from tree-inline.c
	(cgraph_create_virtual_clone): New function.
	* cgraph.h (ipa_replace_map): Move ehre from ipa.h
	(cgraph_clone_info): New function
	(strut cgraph_node): Add clone_info and new clone tree pointers.
	(cgraph_remove_node_and_inline_clones, cgraph_set_call_stmt_including_clones,
	cgraph_create_edge_including_clones, cgraph_create_virtual_clone): Declare.
	(cgraph_function_versioning): Use VEC argument.
	(compute_call_stmt_bb_frequency): Update prototype.
	(cgraph_materialize_all_clones): New function.
	* ipa-cp.c (ipcp_update_cloned_node): Remove.
	(ipcp_create_replace_map): Update to VECtors.
	(ipcp_update_callgraph): Use virtual clones.
	(ipcp_update_bb_counts, ipcp_update_edges_counts): Remove.
	(ipcp_update_profiling): Do not update local profiling.
	(ipcp_insert_stage): Use VECtors and virtual clones.
	* cgraphunit.c (verify_cgraph_node): Verify clone tree.
	(clone_of_p): New function.
	(cgraph_preserve_function_body_p): Use clone tree.
	(cgraph_optimize): Materialize clones.
	(cgraph_function_versioning): Update for VECtors.
	(save_inline_function_body): Use clone tree.
	(cgraph_materialize_clone, cgraph_materialize_all_clones): New functions.
	* ipa-inline.c (cgraph_default_inline_p): Use analyzed flags.
	* ipa.c: Include gimple.h.
	(cgraph_remove_unreachable_nodes): Use clone tree.
	* ipa-prop.c (ipa_note_param_call): Update call of compute_call_stmt_bb_frequency.
	* ipa-prop.h (ipa_replace_map): Move to cgraph.h.
	* tree-inline.c: Do not include varray.h; do not include gt-tree-inline.h
	(copy_bb): Handle updating of clone tree; add new edge when new call
	appears.
	(expand_call_inline): Be strict about every call having edge.
	(clone_fn_id_num, clone_function_name): Move to cgraph.c.
	(delete_unreachable_blocks_update_callgraph): New function.
	(tree_function_versioning): Use VECtors; always remove unreachable blocks
	and fold conditionals.
	* tree-inline.h: Do not include varray.h
	(tree_function_versioning): Remove.
	* Makefile.in (GTFILES): Remove tree-inline.c
	* passes.c (do_per_function): Do only functions having body.
	* ipa-struct-reorg.c (do_reorg_1, collect_data_accesses): Handle cone tree.

From-SVN: r147294
parent 9b86d6bb
2009-05-08 Jan Hubicka <jh@suse.cz>
* cgraphbuild.c (compute_call_stmt_bb_frequency): Accept function argument;
handle correctly when profile is absent.
(build_cgraph_edges): Update.
(rebuild_cgraph_edges): Update.
* cgraph.c: Do not include varrau.h
(cgraph_set_call_stmt_including_clones, cgraph_create_edge_including_clones):
New function
(cgraph_update_edges_for_call_stmt_node): New stati cfunction.
(cgraph_update_edges_for_call_stmt): Handle clones.
(cgraph_remove_node): Handle clone tree.
(cgraph_remove_node_and_inline_clones): New function.
(dump_cgraph_node): Dump clone tree.
(cgraph_clone_node): Handle clone tree.
(clone_function_name): Bring here from tree-inline.c
(cgraph_create_virtual_clone): New function.
* cgraph.h (ipa_replace_map): Move ehre from ipa.h
(cgraph_clone_info): New function
(strut cgraph_node): Add clone_info and new clone tree pointers.
(cgraph_remove_node_and_inline_clones, cgraph_set_call_stmt_including_clones,
cgraph_create_edge_including_clones, cgraph_create_virtual_clone): Declare.
(cgraph_function_versioning): Use VEC argument.
(compute_call_stmt_bb_frequency): Update prototype.
(cgraph_materialize_all_clones): New function.
* ipa-cp.c (ipcp_update_cloned_node): Remove.
(ipcp_create_replace_map): Update to VECtors.
(ipcp_update_callgraph): Use virtual clones.
(ipcp_update_bb_counts, ipcp_update_edges_counts): Remove.
(ipcp_update_profiling): Do not update local profiling.
(ipcp_insert_stage): Use VECtors and virtual clones.
* cgraphunit.c (verify_cgraph_node): Verify clone tree.
(clone_of_p): New function.
(cgraph_preserve_function_body_p): Use clone tree.
(cgraph_optimize): Materialize clones.
(cgraph_function_versioning): Update for VECtors.
(save_inline_function_body): Use clone tree.
(cgraph_materialize_clone, cgraph_materialize_all_clones): New functions.
* ipa-inline.c (cgraph_default_inline_p): Use analyzed flags.
* ipa.c: Include gimple.h.
(cgraph_remove_unreachable_nodes): Use clone tree.
* ipa-prop.c (ipa_note_param_call): Update call of compute_call_stmt_bb_frequency.
* ipa-prop.h (ipa_replace_map): Move to cgraph.h.
* tree-inline.c: Do not include varray.h; do not include gt-tree-inline.h
(copy_bb): Handle updating of clone tree; add new edge when new call
appears.
(expand_call_inline): Be strict about every call having edge.
(clone_fn_id_num, clone_function_name): Move to cgraph.c.
(delete_unreachable_blocks_update_callgraph): New function.
(tree_function_versioning): Use VECtors; always remove unreachable blocks
and fold conditionals.
* tree-inline.h: Do not include varray.h
(tree_function_versioning): Remove.
* Makefile.in (GTFILES): Remove tree-inline.c
* passes.c (do_per_function): Do only functions having body.
* ipa-struct-reorg.c (do_reorg_1, collect_data_accesses): Handle cone tree.
2009-05-08 H.J. Lu <hongjiu.lu@intel.com>
Andrew Morrow <acm@google.com>
......
......@@ -3342,7 +3342,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/tree-ssa-propagate.c \
$(srcdir)/tree-phinodes.c \
$(srcdir)/ipa-reference.c \
$(srcdir)/tree-ssa-structalias.c $(srcdir)/tree-inline.c \
$(srcdir)/tree-ssa-structalias.c \
$(srcdir)/tree-ssa-alias.h \
@all_gtfiles@
......
......@@ -119,6 +119,29 @@ struct GTY(()) cgraph_rtl_info {
unsigned int preferred_incoming_stack_boundary;
};
/* Represent which DECL tree (or reference to such tree)
will be replaced by another tree while versioning. */
struct GTY(()) ipa_replace_map
{
/* The tree that will be replaced. */
tree old_tree;
/* The new (replacing) tree. */
tree new_tree;
/* True when a substitution should be done, false otherwise. */
bool replace_p;
/* True when we replace a reference to old_tree. */
bool ref_p;
};
typedef struct ipa_replace_map *ipa_replace_map_p;
DEF_VEC_P(ipa_replace_map_p);
DEF_VEC_ALLOC_P(ipa_replace_map_p,gc);
struct GTY(()) cgraph_clone_info
{
VEC(ipa_replace_map_p,gc)* tree_map;
bitmap args_to_skip;
};
/* The cgraph data structure.
Each function decl has assigned cgraph_node listing callees and callers. */
......@@ -137,8 +160,10 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
/* Pointer to the next function in cgraph_nodes_queue. */
struct cgraph_node *next_needed;
/* Pointer to the next clone. */
struct cgraph_node *next_clone;
struct cgraph_node *prev_clone;
struct cgraph_node *next_sibling_clone;
struct cgraph_node *prev_sibling_clone;
struct cgraph_node *clones;
struct cgraph_node *clone_of;
/* For functions with many calls sites it holds map from call expression
to the edge to speed up cgraph_edge function. */
htab_t GTY((param_is (struct cgraph_edge))) call_site_hash;
......@@ -148,6 +173,7 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
struct cgraph_local_info local;
struct cgraph_global_info global;
struct cgraph_rtl_info rtl;
struct cgraph_clone_info clone;
/* Expected number of executions: calculated in profile.c. */
gcov_type count;
......@@ -344,6 +370,7 @@ void debug_cgraph_node (struct cgraph_node *);
void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
void cgraph_remove_edge (struct cgraph_edge *);
void cgraph_remove_node (struct cgraph_node *);
void cgraph_remove_node_and_inline_clones (struct cgraph_node *);
void cgraph_release_function_body (struct cgraph_node *);
void cgraph_node_remove_callees (struct cgraph_node *node);
struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
......@@ -353,6 +380,11 @@ struct cgraph_node *cgraph_node (tree);
struct cgraph_node *cgraph_node_for_asm (tree asmname);
struct cgraph_edge *cgraph_edge (struct cgraph_node *, gimple);
void cgraph_set_call_stmt (struct cgraph_edge *, gimple);
void cgraph_set_call_stmt_including_clones (struct cgraph_node *, gimple, gimple);
void cgraph_create_edge_including_clones (struct cgraph_node *,
struct cgraph_node *,
gimple, gcov_type, int, int,
cgraph_inline_failed_t);
void cgraph_update_edges_for_call_stmt (gimple, gimple);
struct cgraph_local_info *cgraph_local_info (tree);
struct cgraph_global_info *cgraph_global_info (tree);
......@@ -374,6 +406,10 @@ void cgraph_unnest_node (struct cgraph_node *);
enum availability cgraph_function_body_availability (struct cgraph_node *);
void cgraph_add_new_function (tree, bool);
const char* cgraph_inline_failed_string (cgraph_inline_failed_t);
struct cgraph_node * cgraph_create_virtual_clone (struct cgraph_node *old_node,
VEC(cgraph_edge_p,heap)*,
VEC(ipa_replace_map_p,gc)* tree_map,
bitmap args_to_skip);
/* In cgraphunit.c */
void cgraph_finalize_function (tree, bool);
......@@ -391,8 +427,9 @@ void cgraph_reset_static_var_maps (void);
void init_cgraph (void);
struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
VEC(cgraph_edge_p,heap)*,
varray_type,
VEC(ipa_replace_map_p,gc)*,
bitmap);
void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, bitmap);
void cgraph_analyze_function (struct cgraph_node *);
struct cgraph_node *save_inline_function_body (struct cgraph_node *);
void record_references_in_initializer (tree);
......@@ -421,10 +458,11 @@ struct cgraph_2edge_hook_list *cgraph_add_edge_duplication_hook (cgraph_2edge_ho
void cgraph_remove_edge_duplication_hook (struct cgraph_2edge_hook_list *);
struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_hook, void *);
void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *);
void cgraph_materialize_all_clones (void);
/* In cgraphbuild.c */
unsigned int rebuild_cgraph_edges (void);
int compute_call_stmt_bb_frequency (basic_block bb);
int compute_call_stmt_bb_frequency (tree, basic_block bb);
/* In ipa.c */
bool cgraph_remove_unreachable_nodes (bool, FILE *);
......
......@@ -81,11 +81,14 @@ record_reference (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
/* Computes the frequency of the call statement so that it can be stored in
cgraph_edge. BB is the basic block of the call statement. */
int
compute_call_stmt_bb_frequency (basic_block bb)
compute_call_stmt_bb_frequency (tree decl, basic_block bb)
{
int entry_freq = ENTRY_BLOCK_PTR->frequency;
int freq = bb->frequency;
if (profile_status_for_function (DECL_STRUCT_FUNCTION (decl)) == PROFILE_ABSENT)
return CGRAPH_FREQ_BASE;
if (!entry_freq)
entry_freq = 1, freq++;
......@@ -121,7 +124,7 @@ build_cgraph_edges (void)
size_t i;
size_t n = gimple_call_num_args (stmt);
cgraph_create_edge (node, cgraph_node (decl), stmt,
bb->count, compute_call_stmt_bb_frequency (bb),
bb->count, compute_call_stmt_bb_frequency (current_function_decl, bb),
bb->loop_depth);
for (i = 0; i < n; i++)
walk_tree (gimple_call_arg_ptr (stmt, i), record_reference,
......@@ -224,7 +227,9 @@ rebuild_cgraph_edges (void)
if (is_gimple_call (stmt) && (decl = gimple_call_fndecl (stmt)))
cgraph_create_edge (node, cgraph_node (decl), stmt,
bb->count, compute_call_stmt_bb_frequency (bb),
bb->count,
compute_call_stmt_bb_frequency
(current_function_decl, bb),
bb->loop_depth);
}
......
......@@ -548,12 +548,20 @@ cgraph_mark_if_needed (tree decl)
cgraph_mark_needed_node (node);
}
/* Return TRUE if NODE2 is equivalent to NODE or its clone. */
static bool
clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
{
while (node != node2 && node2)
node2 = node2->clone_of;
return node2 != NULL;
}
/* Verify cgraph nodes of given cgraph node. */
void
verify_cgraph_node (struct cgraph_node *node)
{
struct cgraph_edge *e;
struct cgraph_node *main_clone;
struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl);
struct function *saved_cfun = cfun;
basic_block this_block;
......@@ -629,17 +637,53 @@ verify_cgraph_node (struct cgraph_node *node)
error_found = true;
}
for (main_clone = cgraph_node (node->decl); main_clone;
main_clone = main_clone->next_clone)
if (main_clone == node)
break;
if (!cgraph_node (node->decl))
{
error ("node not found in cgraph_hash");
error_found = true;
}
if (node->analyzed
if (node->clone_of)
{
struct cgraph_node *n;
for (n = node->clone_of->clones; n; n = n->next_sibling_clone)
if (n == node)
break;
if (!n)
{
error ("node has wrong clone_of");
error_found = true;
}
}
if (node->clones)
{
struct cgraph_node *n;
for (n = node->clones; n; n = n->next_sibling_clone)
if (n->clone_of != node)
break;
if (n)
{
error ("node has wrong clone list");
error_found = true;
}
}
if ((node->prev_sibling_clone || node->next_sibling_clone) && !node->clone_of)
{
error ("node is in clone list but it is not clone");
error_found = true;
}
if (!node->prev_sibling_clone && node->clone_of && node->clone_of->clones != node)
{
error ("node has wrong prev_clone pointer");
error_found = true;
}
if (node->prev_sibling_clone && node->prev_sibling_clone->next_sibling_clone != node)
{
error ("double linked list of clones corrupted");
error_found = true;
}
if (node->analyzed && gimple_has_body_p (node->decl)
&& !TREE_ASM_WRITTEN (node->decl)
&& (!DECL_EXTERNAL (node->decl) || node->global.inlined_to))
{
......@@ -668,8 +712,8 @@ verify_cgraph_node (struct cgraph_node *node)
debug_gimple_stmt (stmt);
error_found = true;
}
if (e->callee->decl != cgraph_node (decl)->decl
&& e->inline_failed)
if (!clone_of_p (cgraph_node (decl), e->callee)
&& !e->callee->global.inlined_to)
{
error ("edge points to wrong declaration:");
debug_tree (e->callee->decl);
......@@ -1227,9 +1271,9 @@ cgraph_preserve_function_body_p (tree decl)
gcc_assert (cgraph_global_info_ready);
/* Look if there is any clone around. */
for (node = cgraph_node (decl); node; node = node->next_clone)
if (node->global.inlined_to)
return true;
node = cgraph_node (decl);
if (node->clones)
return true;
return false;
}
......@@ -1312,6 +1356,7 @@ cgraph_optimize (void)
verify_cgraph ();
#endif
cgraph_materialize_all_clones ();
cgraph_mark_functions_to_output ();
cgraph_state = CGRAPH_STATE_EXPANSION;
......@@ -1528,7 +1573,7 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
struct cgraph_node *
cgraph_function_versioning (struct cgraph_node *old_version_node,
VEC(cgraph_edge_p,heap) *redirect_callers,
varray_type tree_map,
VEC (ipa_replace_map_p,gc)* tree_map,
bitmap args_to_skip)
{
tree old_decl = old_version_node->decl;
......@@ -1581,19 +1626,50 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
struct cgraph_node *
save_inline_function_body (struct cgraph_node *node)
{
struct cgraph_node *first_clone;
struct cgraph_node *first_clone, *n;
gcc_assert (node == cgraph_node (node->decl));
cgraph_lower_function (node);
first_clone = node->next_clone;
first_clone = node->clones;
first_clone->decl = copy_node (node->decl);
node->next_clone = NULL;
first_clone->prev_clone = NULL;
cgraph_insert_node_to_hashtable (first_clone);
gcc_assert (first_clone == cgraph_node (first_clone->decl));
if (first_clone->next_sibling_clone)
{
for (n = first_clone->next_sibling_clone; n->next_sibling_clone; n = n->next_sibling_clone)
n->clone_of = first_clone;
n->clone_of = first_clone;
n->next_sibling_clone = first_clone->clones;
if (first_clone->clones)
first_clone->clones->prev_sibling_clone = n;
first_clone->clones = first_clone->next_sibling_clone;
first_clone->next_sibling_clone->prev_sibling_clone = NULL;
first_clone->next_sibling_clone = NULL;
gcc_assert (!first_clone->prev_sibling_clone);
}
first_clone->clone_of = NULL;
node->clones = NULL;
if (first_clone->clones)
for (n = first_clone->clones; n != first_clone;)
{
gcc_assert (n->decl == node->decl);
n->decl = first_clone->decl;
if (n->clones)
n = n->clones;
else if (n->next_sibling_clone)
n = n->next_sibling_clone;
else
{
while (n != first_clone && !n->next_sibling_clone)
n = n->clone_of;
if (n != first_clone)
n = n->next_sibling_clone;
}
}
/* Copy the OLD_VERSION_NODE function tree to the new version. */
tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL);
......@@ -1603,12 +1679,136 @@ save_inline_function_body (struct cgraph_node *node)
TREE_PUBLIC (first_clone->decl) = 0;
DECL_COMDAT (first_clone->decl) = 0;
for (node = first_clone->next_clone; node; node = node->next_clone)
node->decl = first_clone->decl;
#ifdef ENABLE_CHECKING
verify_cgraph_node (first_clone);
#endif
return first_clone;
}
/* Given virtual clone, turn it into actual clone. */
static void
cgraph_materialize_clone (struct cgraph_node *node)
{
bitmap_obstack_initialize (NULL);
/* 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);
/* Function is no longer clone. */
if (node->next_sibling_clone)
node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
if (node->prev_sibling_clone)
node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
else
node->clone_of->clones = node->next_sibling_clone;
node->next_sibling_clone = NULL;
node->prev_sibling_clone = NULL;
node->clone_of = NULL;
bitmap_obstack_release (NULL);
}
/* Once all functions from compilation unit are in memory, produce all clones
and update all calls.
We might also do this on demand if we don't want to bring all functions to
memory prior compilation, but current WHOPR implementation does that and it is
is bit easier to keep everything right in this order. */
void
cgraph_materialize_all_clones (void)
{
struct cgraph_node *node;
bool stabilized = false;
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Materializing clones\n");
#ifdef ENABLE_CHECKING
verify_cgraph ();
#endif
/* We can also do topological order, but number of iterations should be
bounded by number of IPA passes since single IPA pass is probably not
going to create clones of clones it created itself. */
while (!stabilized)
{
stabilized = true;
for (node = cgraph_nodes; node; node = node->next)
{
if (node->clone_of && node->decl != node->clone_of->decl
&& !gimple_has_body_p (node->decl))
{
if (gimple_has_body_p (node->clone_of->decl))
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file, " clonning %s to %s",
cgraph_node_name (node->clone_of),
cgraph_node_name (node));
cgraph_materialize_clone (node);
}
else
stabilized = false;
}
}
}
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "Updating call sites\n");
for (node = cgraph_nodes; node; node = node->next)
if (node->analyzed && gimple_has_body_p (node->decl)
&& (!node->clone_of || node->clone_of->decl != node->decl))
{
struct cgraph_edge *e;
current_function_decl = node->decl;
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
for (e = node->callees; e; e = e->next_callee)
{
tree decl = gimple_call_fndecl (e->call_stmt);
if (decl != e->callee->decl)
{
gimple new_stmt;
gimple_stmt_iterator gsi;
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "updating call of %s in %s:",
cgraph_node_name (node),
cgraph_node_name (e->callee));
print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
}
if (e->callee->clone.args_to_skip)
new_stmt = gimple_call_copy_skip_args (e->call_stmt,
e->callee->clone.args_to_skip);
else
new_stmt = e->call_stmt;
if (gimple_vdef (new_stmt)
&& TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
gimple_call_set_fndecl (new_stmt, e->callee->decl);
gsi = gsi_for_stmt (e->call_stmt);
gsi_replace (&gsi, new_stmt, true);
/* Update EH information too, just in case. */
if (!stmt_could_throw_p (new_stmt)
&& lookup_stmt_eh_region (new_stmt))
remove_stmt_from_eh_region (new_stmt);
cgraph_set_call_stmt_including_clones (node, e->call_stmt, new_stmt);
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, " updated to:");
print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
}
}
}
pop_cfun ();
current_function_decl = NULL;
#ifdef ENABLE_CHECKING
verify_cgraph_node (node);
#endif
}
cgraph_remove_unreachable_nodes (false, cgraph_dump_file);
}
#include "gt-cgraphunit.h"
......@@ -433,7 +433,7 @@ cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason)
return false;
}
if (!DECL_STRUCT_FUNCTION (decl)->cfg)
if (!n->analyzed)
{
if (reason)
*reason = CIF_BODY_NOT_AVAILABLE;
......
......@@ -653,7 +653,7 @@ ipa_note_param_call (struct ipa_node_params *info, int formal_id,
note->formal_id = formal_id;
note->stmt = stmt;
note->count = bb->count;
note->frequency = compute_call_stmt_bb_frequency (bb);
note->frequency = compute_call_stmt_bb_frequency (current_function_decl, bb);
note->next = info->param_calls;
info->param_calls = note;
......
......@@ -99,20 +99,6 @@ struct ipcp_lattice
tree constant;
};
/* Represent which DECL tree (or reference to such tree)
will be replaced by another tree while versioning. */
struct ipa_replace_map
{
/* The tree that will be replaced. */
tree old_tree;
/* The new (replacing) tree. */
tree new_tree;
/* True when a substitution should be done, false otherwise. */
bool replace_p;
/* True when we replace a reference to old_tree. */
bool ref_p;
};
/* Each instance of the following structure describes a statement that calls a
function parameter. Those referring to statements within the same function
are linked in a list. */
......
......@@ -3641,7 +3641,7 @@ do_reorg_1 (void)
bitmap_obstack_initialize (NULL);
for (node = cgraph_nodes; node; node = node->next)
if (node->analyzed && node->decl && !node->next_clone)
if (node->analyzed && node->decl)
{
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
current_function_decl = node->decl;
......@@ -3809,8 +3809,7 @@ collect_data_accesses (void)
{
struct function *func = DECL_STRUCT_FUNCTION (c_node->decl);
if (!c_node->next_clone)
collect_accesses_in_func (func);
collect_accesses_in_func (func);
exclude_alloc_and_field_accs (c_node);
}
}
......
......@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "tree-pass.h"
#include "timevar.h"
#include "gimple.h"
#include "ggc.h"
/* Fill array order with all nodes with output flag set in the reverse
......@@ -143,6 +144,12 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
e->callee->aux = first;
first = e->callee;
}
while (node->clone_of && !node->clone_of->aux && !gimple_has_body_p (node->decl))
{
node = node->clone_of;
node->aux = first;
first = node;
}
}
/* Remove unreachable nodes. Extern inline functions need special care;
......@@ -168,25 +175,29 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
{
struct cgraph_edge *e;
/* See if there is reachable caller. */
for (e = node->callers; e; e = e->next_caller)
if (e->caller->aux)
break;
/* If so, we need to keep node in the callgraph. */
if (e || node->needed)
{
struct cgraph_node *clone;
for (clone = node->next_clone; clone;
clone = clone->next_clone)
/* If there are still clones, we must keep body around.
Otherwise we can just remove the body but keep the clone. */
for (clone = node->clones; clone;
clone = clone->next_sibling_clone)
if (clone->aux)
break;
if (!clone)
{
cgraph_release_function_body (node);
cgraph_node_remove_callees (node);
node->analyzed = false;
node->local.inlinable = false;
}
cgraph_node_remove_callees (node);
node->analyzed = false;
node->local.inlinable = false;
}
else
cgraph_remove_node (node);
......@@ -195,7 +206,18 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
}
}
for (node = cgraph_nodes; node; node = node->next)
node->aux = NULL;
{
/* Inline clones might be kept around so their materializing allows further
cloning. If the function the clone is inlined into is removed, we need
to turn it into normal cone. */
if (node->global.inlined_to
&& !node->callers)
{
gcc_assert (node->clones);
node->global.inlined_to = false;
}
node->aux = NULL;
}
#ifdef ENABLE_CHECKING
verify_cgraph ();
#endif
......
......@@ -846,7 +846,7 @@ do_per_function (void (*callback) (void *data), void *data)
{
struct cgraph_node *node;
for (node = cgraph_nodes; node; node = node->next)
if (node->analyzed)
if (node->analyzed && gimple_has_body_p (node->decl))
{
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
current_function_decl = node->decl;
......
......@@ -7074,7 +7074,7 @@ struct gimple_opt_pass pass_split_crit_edges =
PROP_no_crit_edges, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func /* todo_flags_finish */
TODO_dump_func | TODO_verify_flow /* todo_flags_finish */
}
};
......
......@@ -21,7 +21,6 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TREE_INLINE_H
#define GCC_TREE_INLINE_H
#include "varray.h"
#include "pointer-set.h"
......@@ -156,7 +155,6 @@ int estimate_num_insns (gimple, eni_weights *);
int estimate_num_insns_fn (tree, eni_weights *);
int count_insns_seq (gimple_seq, eni_weights *);
bool tree_versionable_function_p (tree);
void tree_function_versioning (tree, tree, varray_type, bool, bitmap);
bool tree_can_inline_p (tree, tree);
extern gimple_seq remap_gimple_seq (gimple_seq, copy_body_data *);
......
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