aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/cgraph.c2
-rw-r--r--gcc/cgraph.h13
-rw-r--r--gcc/cgraphunit.c1
-rw-r--r--gcc/ipa.c21
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/unreachable.c15
-rw-r--r--gcc/tree-inline.c1
-rw-r--r--gcc/tree-profile.c2
9 files changed, 68 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0decfd8..f6b1554 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2010-05-12 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.c (cgraph_mark_address_taken_node): No longer imply needed flag.
+ * cgraph.h (cgraph_only_called_directly_p,
+ cgraph_can_remove_if_no_direct_calls_p): test address_taken flag.
+ (cgraph_can_remove_if_no_direct_calls_and_refs_p): New function.
+ * cgraphunit.c (cgraph_mark_functions_to_output): Test address_taken.
+ (assemble
+ * ipa.c (cgraph_remove_unreachable_nodes): Use
+ cgraph_can_remove_if_no_direct_calls_and_refs_p; clear address_taken flags.
+ * tree-inline.c (copy_bb): Check address_taken flag.
+ * tree-profile.c (tree_gen_ic_func_profiler): Check address_taken and
+ externally_visible flag.
+
2010-05-12 Jason Merrill <jason@redhat.com>
PR bootstrap/44048
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index b16a10d..82ce0e8 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1686,8 +1686,8 @@ cgraph_mark_needed_node (struct cgraph_node *node)
void
cgraph_mark_address_taken_node (struct cgraph_node *node)
{
+ cgraph_mark_reachable_node (node);
node->address_taken = 1;
- cgraph_mark_needed_node (node);
}
/* Return local info for the compiled function. */
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index dbfc89f..1ccae09 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -856,19 +856,28 @@ varpool_node_set_nonempty_p (varpool_node_set set)
static inline bool
cgraph_only_called_directly_p (struct cgraph_node *node)
{
- return !node->needed && !node->local.externally_visible;
+ return !node->needed && !node->address_taken && !node->local.externally_visible;
}
/* Return true when function NODE can be removed from callgraph
if all direct calls are eliminated. */
static inline bool
-cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
+cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
{
return (!node->needed && !node->reachable_from_other_partition
&& (DECL_COMDAT (node->decl) || !node->local.externally_visible));
}
+/* Return true when function NODE can be removed from callgraph
+ if all direct calls are eliminated. */
+
+static inline bool
+cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node)
+{
+ return !node->address_taken && cgraph_can_remove_if_no_direct_calls_and_refs_p (node);
+}
+
/* Constant pool accessor function. */
htab_t constant_pool_htab (void);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index cacb90c..b97a33e 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1201,6 +1201,7 @@ cgraph_mark_functions_to_output (void)
if (node->analyzed
&& !node->global.inlined_to
&& (node->needed || node->reachable_from_other_partition
+ || node->address_taken
|| (e && node->reachable))
&& !TREE_ASM_WRITTEN (decl)
&& !DECL_EXTERNAL (decl))
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 1fc3fdd..2512177 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -207,7 +207,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
#endif
varpool_reset_queue ();
for (node = cgraph_nodes; node; node = node->next)
- if (!cgraph_can_remove_if_no_direct_calls_p (node)
+ if (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
&& ((!DECL_EXTERNAL (node->decl))
|| before_inlining_p))
{
@@ -405,6 +405,25 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
varpool_remove_node (vnode);
}
}
+ if (file)
+ fprintf (file, "\nClearing address taken flags:");
+ for (node = cgraph_nodes; node; node = node->next)
+ if (node->address_taken
+ && !node->reachable_from_other_partition)
+ {
+ int i;
+ struct ipa_ref *ref;
+ bool found = false;
+ for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref)
+ && !found; i++)
+ found = true;
+ if (!found)
+ {
+ if (file)
+ fprintf (file, " %s", cgraph_node_name (node));
+ node->address_taken = false;
+ }
+ }
#ifdef ENABLE_CHECKING
verify_cgraph ();
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e62336b..8f18143 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2010-05-12 Jan Hubicka <jh@suse.cz>
+
+ * tree-ssa/unreachable.c: New test.
+
2010-05-12 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/sfinae1.C: New.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/unreachable.c b/gcc/testsuite/gcc.dg/tree-ssa/unreachable.c
new file mode 100644
index 0000000..279a277
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/unreachable.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+static void bad_boy()
+{
+}
+int
+main()
+{
+ void *t=(void *)bad_boy;
+ if (!t)
+ return 1;
+ return 0;
+}
+/* { dg-final { scan-tree-dump-not "bad_boy" "optimized"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 302d36b..03b013c 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1711,6 +1711,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
other cases we hit a bug (incorrect node sharing is the
most common reason for missing edges). */
gcc_assert (dest->needed || !dest->analyzed
+ || dest->address_taken
|| !id->src_node->analyzed);
if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
cgraph_create_edge_including_clones
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
index a907510..6c2d1bd 100644
--- a/gcc/tree-profile.c
+++ b/gcc/tree-profile.c
@@ -345,7 +345,7 @@ tree_gen_ic_func_profiler (void)
gimple stmt1, stmt2;
tree tree_uid, cur_func;
- if (!c_node->needed)
+ if (cgraph_only_called_directly_p (c_node))
return;
tree_init_edge_profiler ();