aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/cgraph.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/cgraph.c')
-rw-r--r--gcc-4.9/gcc/cgraph.c67
1 files changed, 58 insertions, 9 deletions
diff --git a/gcc-4.9/gcc/cgraph.c b/gcc-4.9/gcc/cgraph.c
index be3661af6..180a63656 100644
--- a/gcc-4.9/gcc/cgraph.c
+++ b/gcc-4.9/gcc/cgraph.c
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see
#include "rtl.h"
#include "ipa-utils.h"
#include "lto-streamer.h"
+#include "l-ipo.h"
#include "ipa-inline.h"
#include "cfgloop.h"
#include "gimple-pretty-print.h"
@@ -773,7 +774,9 @@ cgraph_edge (struct cgraph_node *node, gimple call_stmt)
{
node->call_site_hash = htab_create_ggc (120, edge_hash, edge_eq, NULL);
for (e2 = node->callees; e2; e2 = e2->next_callee)
- cgraph_add_edge_to_call_site_hash (e2);
+ /* Skip fake edges. */
+ if (e2->call_stmt)
+ cgraph_add_edge_to_call_site_hash (e2);
for (e2 = node->indirect_calls; e2; e2 = e2->next_callee)
cgraph_add_edge_to_call_site_hash (e2);
}
@@ -822,6 +825,8 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt,
/* Constant propagation (and possibly also inlining?) can turn an
indirect call into a direct one. */
struct cgraph_node *new_callee = cgraph_get_node (decl);
+ if (L_IPO_COMP_MODE && cgraph_pre_profiling_inlining_done)
+ new_callee = cgraph_lipo_get_resolved_node (decl);
gcc_checking_assert (new_callee);
e = cgraph_make_edge_direct (e, new_callee);
@@ -1026,7 +1031,7 @@ cgraph_edge_remove_caller (struct cgraph_edge *e)
else
e->caller->callees = e->next_callee;
}
- if (e->caller->call_site_hash)
+ if (e->caller->call_site_hash && e->call_stmt)
htab_remove_elt_with_hash (e->caller->call_site_hash,
e->call_stmt,
htab_hash_pointer (e->call_stmt));
@@ -1068,6 +1073,26 @@ cgraph_remove_edge (struct cgraph_edge *e)
cgraph_free_edge (e);
}
+/* Remove fake cgraph edges for indirect calls. NODE is the callee
+ of the edges. */
+
+void
+cgraph_remove_fake_indirect_call_in_edges (struct cgraph_node *node)
+{
+ struct cgraph_edge *f, *e;
+
+ if (!L_IPO_COMP_MODE)
+ return;
+
+ for (e = node->callers; e; e = f)
+ {
+ f = e->next_caller;
+ if (!e->call_stmt)
+ cgraph_remove_edge (e);
+ }
+}
+
+
/* Set callee of call graph edge E and add it to the corresponding set of
callers. */
@@ -1472,6 +1497,12 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
new_stmt = e->call_stmt;
gimple_call_set_fndecl (new_stmt, e->callee->decl);
update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt);
+ if (L_IPO_COMP_MODE)
+ {
+ int lp_nr = lookup_stmt_eh_lp (e->call_stmt);
+ if (lp_nr != 0 && !stmt_could_throw_p (e->call_stmt))
+ remove_stmt_from_eh_lp (e->call_stmt);
+ }
}
/* If the call becomes noreturn, remove the lhs. */
@@ -1679,6 +1710,10 @@ cgraph_node_remove_callers (struct cgraph_node *node)
void
release_function_body (tree decl)
{
+ if (cgraph_get_node (decl)
+ && cgraph_is_aux_decl_external (cgraph_get_node (decl)))
+ DECL_EXTERNAL (decl) = 1;
+
if (DECL_STRUCT_FUNCTION (decl))
{
push_cfun (DECL_STRUCT_FUNCTION (decl));
@@ -1820,7 +1855,9 @@ cgraph_remove_node (struct cgraph_node *node)
cgraph_release_function_body (node);
}
+ cgraph_remove_link_node (node);
node->decl = NULL;
+
if (node->call_site_hash)
{
htab_delete (node->call_site_hash);
@@ -1837,6 +1874,7 @@ cgraph_remove_node (struct cgraph_node *node)
free_nodes = node;
}
+
/* Likewise indicate that a node is having address taken. */
void
@@ -1978,6 +2016,9 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
if (node->count)
fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
(HOST_WIDEST_INT)node->count);
+ if (node->max_bb_count)
+ fprintf (f, " hottest bb executed "HOST_WIDEST_INT_PRINT_DEC"x",
+ (HOST_WIDEST_INT)node->max_bb_count);
if (node->origin)
fprintf (f, " nested in: %s", node->origin->asm_name ());
if (gimple_has_body_p (node->decl))
@@ -2566,11 +2607,16 @@ clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
skipped_thunk = true;
}
- if (skipped_thunk
- && (!node2->clone_of
- || !node2->clone.args_to_skip
- || !bitmap_bit_p (node2->clone.args_to_skip, 0)))
- return false;
+ if (skipped_thunk)
+ {
+ if (!node2->clone.args_to_skip
+ || !bitmap_bit_p (node2->clone.args_to_skip, 0))
+ return false;
+ if (node2->former_clone_of == node->decl)
+ return true;
+ else if (!node2->clone_of)
+ return false;
+ }
while (node != node2 && node2)
node2 = node2->clone_of;
@@ -2599,6 +2645,7 @@ verify_edge_count_and_frequency (struct cgraph_edge *e)
error_found = true;
}
if (gimple_has_body_p (e->caller->decl)
+ && e->call_stmt
&& !e->caller->global.inlined_to
&& !e->speculative
/* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out.
@@ -2855,7 +2902,9 @@ verify_cgraph_node (struct cgraph_node *node)
error ("Alias has non-alias reference");
error_found = true;
}
- else if (ref_found)
+ else if (ref_found
+ /* in LIPO mode, the alias can refer to the real target also */
+ && !L_IPO_COMP_MODE)
{
error ("Alias has more than one alias reference");
error_found = true;
@@ -2969,7 +3018,7 @@ verify_cgraph_node (struct cgraph_node *node)
for (e = node->callees; e; e = e->next_callee)
{
- if (!e->aux)
+ if (!e->aux && e->call_stmt)
{
error ("edge %s->%s has no corresponding call_stmt",
identifier_to_locale (e->caller->name ()),