Commit 90988f77 by Martin Liska Committed by Martin Liska

cgraph_edge refactoring.

	* cgraph.c (cgraph_edge::remove_callee): Move function to header
	file for being inlined.
	(cgraph_set_edge_callee): Delete.
	(cgraph_edge::redirect_callee): Move function to header file
	for being inlined.
	(cgraph_edge::make_direct): Use new function.
	(cgraph_edge::dump_edge_flags): New function created from
	static dump_edge_flags function.
	(cgraph_node::dump): Use new function.
	(cgraph_edge::verify_count_and_frequency): New function created
	from verify_edge_count_and_frequency.
	(cgraph_edge::verify_corresponds_to_fndecl): New function created
	from verify_edge_corresponds_to_fndecl.
	(verify_edge_corresponds_to_fndecl): Delete.
	(cgraph_node::verify_node): Use new function.
	* cgraph.h (cgraph_edge::set_callee): New function.
	(cgraph_edge::dump_edge_flags): Likewise.
	(cgraph_edge::verify_corresponds_to_fndecl): Likewise.

From-SVN: r219448
parent 6e7bdfac
2015-01-12 Martin Liska <mliska@suse.cz>
* cgraph.c (cgraph_edge::remove_callee): Move function to header
file for being inlined.
(cgraph_set_edge_callee): Delete.
(cgraph_edge::redirect_callee): Move function to header file
for being inlined.
(cgraph_edge::make_direct): Use new function.
(cgraph_edge::dump_edge_flags): New function created from
static dump_edge_flags function.
(cgraph_node::dump): Use new function.
(cgraph_edge::verify_count_and_frequency): New function created
from verify_edge_count_and_frequency.
(cgraph_edge::verify_corresponds_to_fndecl): New function created
from verify_edge_corresponds_to_fndecl.
(verify_edge_corresponds_to_fndecl): Delete.
(cgraph_node::verify_node): Use new function.
* cgraph.h (cgraph_edge::set_callee): New function.
(cgraph_edge::dump_edge_flags): Likewise.
(cgraph_edge::verify_corresponds_to_fndecl): Likewise.
2015-01-11 Jan Hubicka <hubicka@ucw.cz> 2015-01-11 Jan Hubicka <hubicka@ucw.cz>
* ipa-utils.c (estimate_function_body_sizes): Do not * ipa-utils.c (estimate_function_body_sizes): Do not
......
...@@ -965,20 +965,6 @@ cgraph_node::create_indirect_edge (gcall *call_stmt, int ecf_flags, ...@@ -965,20 +965,6 @@ cgraph_node::create_indirect_edge (gcall *call_stmt, int ecf_flags,
return edge; return edge;
} }
/* Remove the edge from the list of the callers of the callee. */
void
cgraph_edge::remove_callee (void)
{
gcc_assert (!indirect_unknown_callee);
if (prev_caller)
prev_caller->next_caller = next_caller;
if (next_caller)
next_caller->prev_caller = prev_caller;
if (!prev_caller)
callee->callers = next_caller;
}
/* Remove the edge from the list of the callees of the caller. */ /* Remove the edge from the list of the callees of the caller. */
void void
...@@ -1037,20 +1023,6 @@ cgraph_edge::remove (void) ...@@ -1037,20 +1023,6 @@ cgraph_edge::remove (void)
symtab->free_edge (this); symtab->free_edge (this);
} }
/* Set callee of call graph edge E and add it to the corresponding set of
callers. */
static void
cgraph_set_edge_callee (cgraph_edge *e, cgraph_node *n)
{
e->prev_caller = NULL;
if (n->callers)
n->callers->prev_caller = e;
e->next_caller = n->callers;
n->callers = e;
e->callee = n;
}
/* Turn edge into speculative call calling N2. Update /* Turn edge into speculative call calling N2. Update
the profile so the direct call is taken COUNT times the profile so the direct call is taken COUNT times
with FREQUENCY. with FREQUENCY.
...@@ -1165,19 +1137,6 @@ cgraph_edge::speculative_call_info (cgraph_edge *&direct, ...@@ -1165,19 +1137,6 @@ cgraph_edge::speculative_call_info (cgraph_edge *&direct,
gcc_assert (e && e2 && ref); gcc_assert (e && e2 && ref);
} }
/* Redirect callee of the edge to N. The function does not update underlying
call expression. */
void
cgraph_edge::redirect_callee (cgraph_node *n)
{
/* Remove from callers list of the current callee. */
remove_callee ();
/* Insert to callers list of the new callee. */
cgraph_set_edge_callee (this, n);
}
/* Speculative call edge turned out to be direct call to CALLE_DECL. /* Speculative call edge turned out to be direct call to CALLE_DECL.
Remove the speculative call sequence and return edge representing the call. Remove the speculative call sequence and return edge representing the call.
It is up to caller to redirect the call as appropriate. */ It is up to caller to redirect the call as appropriate. */
...@@ -1284,7 +1243,7 @@ cgraph_edge::make_direct (cgraph_node *callee) ...@@ -1284,7 +1243,7 @@ cgraph_edge::make_direct (cgraph_node *callee)
caller->callees = edge; caller->callees = edge;
/* Insert to callers list of the new callee. */ /* Insert to callers list of the new callee. */
cgraph_set_edge_callee (edge, callee); edge->set_callee (callee);
if (call_stmt) if (call_stmt)
call_stmt_cannot_inline_p call_stmt_cannot_inline_p
...@@ -1948,24 +1907,22 @@ cgraph_inline_failed_type (cgraph_inline_failed_t reason) ...@@ -1948,24 +1907,22 @@ cgraph_inline_failed_type (cgraph_inline_failed_t reason)
const char * const cgraph_availability_names[] = const char * const cgraph_availability_names[] =
{"unset", "not_available", "overwritable", "available", "local"}; {"unset", "not_available", "overwritable", "available", "local"};
/* Output flags of edge E. */ /* Output flags of edge to a file F. */
static void void
dump_edge_flags (FILE *f, struct cgraph_edge *edge) cgraph_edge::dump_edge_flags (FILE *f)
{ {
if (edge->speculative) if (speculative)
fprintf (f, "(speculative) "); fprintf (f, "(speculative) ");
if (!edge->inline_failed) if (!inline_failed)
fprintf (f, "(inlined) "); fprintf (f, "(inlined) ");
if (edge->indirect_inlining_edge) if (indirect_inlining_edge)
fprintf (f, "(indirect_inlining) "); fprintf (f, "(indirect_inlining) ");
if (edge->count) if (count)
fprintf (f, "(%"PRId64"x) ", fprintf (f, "(%"PRId64"x) ", (int64_t)count);
(int64_t)edge->count); if (frequency)
if (edge->frequency) fprintf (f, "(%.2f per call) ", frequency / (double)CGRAPH_FREQ_BASE);
fprintf (f, "(%.2f per call) ", if (can_throw_external)
edge->frequency / (double)CGRAPH_FREQ_BASE);
if (edge->can_throw_external)
fprintf (f, "(can throw external) "); fprintf (f, "(can throw external) ");
} }
...@@ -2057,7 +2014,7 @@ cgraph_node::dump (FILE *f) ...@@ -2057,7 +2014,7 @@ cgraph_node::dump (FILE *f)
{ {
fprintf (f, "%s/%i ", edge->caller->asm_name (), fprintf (f, "%s/%i ", edge->caller->asm_name (),
edge->caller->order); edge->caller->order);
dump_edge_flags (f, edge); edge->dump_edge_flags (f);
} }
fprintf (f, "\n Calls: "); fprintf (f, "\n Calls: ");
...@@ -2065,7 +2022,7 @@ cgraph_node::dump (FILE *f) ...@@ -2065,7 +2022,7 @@ cgraph_node::dump (FILE *f)
{ {
fprintf (f, "%s/%i ", edge->callee->asm_name (), fprintf (f, "%s/%i ", edge->callee->asm_name (),
edge->callee->order); edge->callee->order);
dump_edge_flags (f, edge); edge->dump_edge_flags (f);
} }
fprintf (f, "\n"); fprintf (f, "\n");
...@@ -2079,7 +2036,7 @@ cgraph_node::dump (FILE *f) ...@@ -2079,7 +2036,7 @@ cgraph_node::dump (FILE *f)
} }
else else
fprintf (f, " Indirect call"); fprintf (f, " Indirect call");
dump_edge_flags (f, edge); edge->dump_edge_flags (f);
if (edge->indirect_info->param_index != -1) if (edge->indirect_info->param_index != -1)
{ {
fprintf (f, " of param:%i", edge->indirect_info->param_index); fprintf (f, " of param:%i", edge->indirect_info->param_index);
...@@ -2638,44 +2595,44 @@ clone_of_p (cgraph_node *node, cgraph_node *node2) ...@@ -2638,44 +2595,44 @@ clone_of_p (cgraph_node *node, cgraph_node *node2)
return node2 != NULL; return node2 != NULL;
} }
/* Verify edge E count and frequency. */ /* Verify edge count and frequency. */
static bool bool
verify_edge_count_and_frequency (cgraph_edge *e) cgraph_edge::verify_count_and_frequency ()
{ {
bool error_found = false; bool error_found = false;
if (e->count < 0) if (count < 0)
{ {
error ("caller edge count is negative"); error ("caller edge count is negative");
error_found = true; error_found = true;
} }
if (e->frequency < 0) if (frequency < 0)
{ {
error ("caller edge frequency is negative"); error ("caller edge frequency is negative");
error_found = true; error_found = true;
} }
if (e->frequency > CGRAPH_FREQ_MAX) if (frequency > CGRAPH_FREQ_MAX)
{ {
error ("caller edge frequency is too large"); error ("caller edge frequency is too large");
error_found = true; error_found = true;
} }
if (gimple_has_body_p (e->caller->decl) if (gimple_has_body_p (caller->decl)
&& !e->caller->global.inlined_to && !caller->global.inlined_to
&& !e->speculative && !speculative
/* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out. /* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out.
Remove this once edges are actually removed from the function at that time. */ Remove this once edges are actually removed from the function at that time. */
&& (e->frequency && (frequency
|| (inline_edge_summary_vec.exists () || (inline_edge_summary_vec.exists ()
&& ((inline_edge_summary_vec.length () <= (unsigned) e->uid) && ((inline_edge_summary_vec.length () <= (unsigned) uid)
|| !inline_edge_summary (e)->predicate))) || !inline_edge_summary (this)->predicate)))
&& (e->frequency && (frequency
!= compute_call_stmt_bb_frequency (e->caller->decl, != compute_call_stmt_bb_frequency (caller->decl,
gimple_bb (e->call_stmt)))) gimple_bb (call_stmt))))
{ {
error ("caller edge frequency %i does not match BB frequency %i", error ("caller edge frequency %i does not match BB frequency %i",
e->frequency, frequency,
compute_call_stmt_bb_frequency (e->caller->decl, compute_call_stmt_bb_frequency (caller->decl,
gimple_bb (e->call_stmt))); gimple_bb (call_stmt)));
error_found = true; error_found = true;
} }
return error_found; return error_found;
...@@ -2700,15 +2657,15 @@ cgraph_debug_gimple_stmt (function *this_cfun, gimple stmt) ...@@ -2700,15 +2657,15 @@ cgraph_debug_gimple_stmt (function *this_cfun, gimple stmt)
current_function_decl = NULL; current_function_decl = NULL;
} }
/* Verify that call graph edge E corresponds to DECL from the associated /* Verify that call graph edge corresponds to DECL from the associated
statement. Return true if the verification should fail. */ statement. Return true if the verification should fail. */
static bool bool
verify_edge_corresponds_to_fndecl (cgraph_edge *e, tree decl) cgraph_edge::verify_corresponds_to_fndecl (tree decl)
{ {
cgraph_node *node; cgraph_node *node;
if (!decl || e->callee->global.inlined_to) if (!decl || callee->global.inlined_to)
return false; return false;
if (symtab->state == LTO_STREAMING) if (symtab->state == LTO_STREAMING)
return false; return false;
...@@ -2722,20 +2679,20 @@ verify_edge_corresponds_to_fndecl (cgraph_edge *e, tree decl) ...@@ -2722,20 +2679,20 @@ verify_edge_corresponds_to_fndecl (cgraph_edge *e, tree decl)
|| node->body_removed || node->body_removed
|| node->in_other_partition || node->in_other_partition
|| node->icf_merged || node->icf_merged
|| e->callee->in_other_partition) || callee->in_other_partition)
return false; return false;
node = node->ultimate_alias_target (); node = node->ultimate_alias_target ();
/* Optimizers can redirect unreachable calls or calls triggering undefined /* Optimizers can redirect unreachable calls or calls triggering undefined
behaviour to builtin_unreachable. */ behaviour to builtin_unreachable. */
if (DECL_BUILT_IN_CLASS (e->callee->decl) == BUILT_IN_NORMAL if (DECL_BUILT_IN_CLASS (callee->decl) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (e->callee->decl) == BUILT_IN_UNREACHABLE) && DECL_FUNCTION_CODE (callee->decl) == BUILT_IN_UNREACHABLE)
return false; return false;
if (e->callee->former_clone_of != node->decl if (callee->former_clone_of != node->decl
&& (node != e->callee->ultimate_alias_target ()) && (node != callee->ultimate_alias_target ())
&& !clone_of_p (node, e->callee)) && !clone_of_p (node, callee))
return true; return true;
else else
return false; return false;
...@@ -2815,7 +2772,7 @@ cgraph_node::verify_node (void) ...@@ -2815,7 +2772,7 @@ cgraph_node::verify_node (void)
bool check_comdat = comdat_local_p (); bool check_comdat = comdat_local_p ();
for (e = callers; e; e = e->next_caller) for (e = callers; e; e = e->next_caller)
{ {
if (verify_edge_count_and_frequency (e)) if (e->verify_count_and_frequency ())
error_found = true; error_found = true;
if (check_comdat if (check_comdat
&& !in_same_comdat_group_p (e->caller)) && !in_same_comdat_group_p (e->caller))
...@@ -2847,7 +2804,7 @@ cgraph_node::verify_node (void) ...@@ -2847,7 +2804,7 @@ cgraph_node::verify_node (void)
} }
} }
for (e = indirect_calls; e; e = e->next_callee) for (e = indirect_calls; e; e = e->next_callee)
if (verify_edge_count_and_frequency (e)) if (e->verify_count_and_frequency ())
error_found = true; error_found = true;
if (!callers && global.inlined_to) if (!callers && global.inlined_to)
{ {
...@@ -3052,7 +3009,7 @@ cgraph_node::verify_node (void) ...@@ -3052,7 +3009,7 @@ cgraph_node::verify_node (void)
} }
if (!e->indirect_unknown_callee) if (!e->indirect_unknown_callee)
{ {
if (verify_edge_corresponds_to_fndecl (e, decl)) if (e->verify_corresponds_to_fndecl (decl))
{ {
error ("edge points to wrong declaration:"); error ("edge points to wrong declaration:");
debug_tree (e->callee->decl); debug_tree (e->callee->decl);
......
...@@ -1524,6 +1524,9 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"), ...@@ -1524,6 +1524,9 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"),
cgraph_edge * clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid, cgraph_edge * clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid,
gcov_type count_scale, int freq_scale, bool update_original); gcov_type count_scale, int freq_scale, bool update_original);
/* Verify edge count and frequency. */
bool verify_count_and_frequency ();
/* Return true when call of edge can not lead to return from caller /* Return true when call of edge can not lead to return from caller
and thus it is safe to ignore its side effects for IPA analysis and thus it is safe to ignore its side effects for IPA analysis
when computing side effects of the caller. */ when computing side effects of the caller. */
...@@ -1606,6 +1609,17 @@ private: ...@@ -1606,6 +1609,17 @@ private:
/* Remove the edge from the list of the callees of the caller. */ /* Remove the edge from the list of the callees of the caller. */
void remove_callee (void); void remove_callee (void);
/* Set callee N of call graph edge and add it to the corresponding set of
callers. */
void set_callee (cgraph_node *n);
/* Output flags of edge to a file F. */
void dump_edge_flags (FILE *f);
/* Verify that call graph edge corresponds to DECL from the associated
statement. Return true if the verification should fail. */
bool verify_corresponds_to_fndecl (tree decl);
}; };
#define CGRAPH_FREQ_BASE 1000 #define CGRAPH_FREQ_BASE 1000
...@@ -2719,6 +2733,33 @@ varpool_node::ultimate_alias_target (availability *availability) ...@@ -2719,6 +2733,33 @@ varpool_node::ultimate_alias_target (availability *availability)
return n; return n;
} }
/* Set callee N of call graph edge and add it to the corresponding set of
callers. */
inline void
cgraph_edge::set_callee (cgraph_node *n)
{
prev_caller = NULL;
if (n->callers)
n->callers->prev_caller = this;
next_caller = n->callers;
n->callers = this;
callee = n;
}
/* Redirect callee of the edge to N. The function does not update underlying
call expression. */
inline void
cgraph_edge::redirect_callee (cgraph_node *n)
{
/* Remove from callers list of the current callee. */
remove_callee ();
/* Insert to callers list of the new callee. */
set_callee (n);
}
/* Return true when the edge represents a direct recursion. */ /* Return true when the edge represents a direct recursion. */
inline bool inline bool
cgraph_edge::recursive_p (void) cgraph_edge::recursive_p (void)
...@@ -2730,6 +2771,20 @@ cgraph_edge::recursive_p (void) ...@@ -2730,6 +2771,20 @@ cgraph_edge::recursive_p (void)
return caller->decl == c->decl; return caller->decl == c->decl;
} }
/* Remove the edge from the list of the callers of the callee. */
inline void
cgraph_edge::remove_callee (void)
{
gcc_assert (!indirect_unknown_callee);
if (prev_caller)
prev_caller->next_caller = next_caller;
if (next_caller)
next_caller->prev_caller = prev_caller;
if (!prev_caller)
callee->callers = next_caller;
}
/* Return true if the TM_CLONE bit is set for a given FNDECL. */ /* Return true if the TM_CLONE bit is set for a given FNDECL. */
static inline bool static inline bool
decl_is_tm_clone (const_tree fndecl) decl_is_tm_clone (const_tree fndecl)
......
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