aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2009-05-10 17:11:01 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2009-05-10 15:11:01 +0000
commit39ff5a967693c3aa56e8abf0e9c75fabe3335d8d (patch)
tree74ceb2f1c2ecc5f55f8c3f84dd6a925d1b0918c4 /gcc
parent9a0c61875533558e047cb5ef140d9836ed475ab9 (diff)
downloadgcc-39ff5a967693c3aa56e8abf0e9c75fabe3335d8d.zip
gcc-39ff5a967693c3aa56e8abf0e9c75fabe3335d8d.tar.gz
gcc-39ff5a967693c3aa56e8abf0e9c75fabe3335d8d.tar.bz2
cgraphbuild.c (record_reference): Use cgraph_mark_address_taken_node.
* cgraphbuild.c (record_reference): Use cgraph_mark_address_taken_node. * cgraph.c (cgraph_mark_address_taken_node): New function. (dump_cgraph_node): Dump new flag. * cgraph.h (struct cgraph_node): Add address_taken. (cgraph_mark_address_taken_node): New function. * cp/decl2.c (cxx_callgraph_analyze_expr): Use cgraph_mark_address_taken. * ipa.c (cgraph_postorder): Prioritize functions with address taken since new direct calls can be born. From-SVN: r147342
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/cgraph.c11
-rw-r--r--gcc/cgraph.h3
-rw-r--r--gcc/cgraphbuild.c2
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/ipa.c79
6 files changed, 70 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7ea0881..935aaa4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2009-05-10 Jan Hubicka <jh@suse.cz>
+
+ * cgraphbuild.c (record_reference): Use cgraph_mark_address_taken_node.
+ * cgraph.c (cgraph_mark_address_taken_node): New function.
+ (dump_cgraph_node): Dump new flag.
+ * cgraph.h (struct cgraph_node): Add address_taken.
+ (cgraph_mark_address_taken_node): New function.
+ * cp/decl2.c (cxx_callgraph_analyze_expr): Use
+ cgraph_mark_address_taken.
+ * ipa.c (cgraph_postorder): Prioritize functions with address taken
+ since new direct calls can be born.
+
2009-05-10 Joseph Myers <joseph@codesourcery.com>
* c-lex.c (c_lex_with_flags): Expect cpp_hashnode in
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 5d2cc1d..60ff168 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1293,6 +1293,15 @@ cgraph_mark_needed_node (struct cgraph_node *node)
cgraph_mark_reachable_node (node);
}
+/* Likewise indicate that a node is having address taken. */
+
+void
+cgraph_mark_address_taken_node (struct cgraph_node *node)
+{
+ node->address_taken = 1;
+ cgraph_mark_needed_node (node);
+}
+
/* Return local info for the compiled function. */
struct cgraph_local_info *
@@ -1397,6 +1406,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
if (node->needed)
fprintf (f, " needed");
+ if (node->address_taken)
+ fprintf (f, " address_taken");
else if (node->reachable)
fprintf (f, " reachable");
if (gimple_has_body_p (node->decl))
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index c1a1a0a..2e4201e 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -189,6 +189,8 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
/* Set when function must be output - it is externally visible
or its address is taken. */
unsigned needed : 1;
+ /* Set when function has address taken. */
+ unsigned address_taken : 1;
/* Set when decl is an abstract function pointed to by the
ABSTRACT_DECL_ORIGIN of a reachable function. */
unsigned abstract_and_needed : 1;
@@ -417,6 +419,7 @@ void cgraph_mark_if_needed (tree);
void cgraph_finalize_compilation_unit (void);
void cgraph_optimize (void);
void cgraph_mark_needed_node (struct cgraph_node *);
+void cgraph_mark_address_taken_node (struct cgraph_node *);
void cgraph_mark_reachable_node (struct cgraph_node *);
bool cgraph_inline_p (struct cgraph_edge *, cgraph_inline_failed_t *reason);
bool cgraph_preserve_function_body_p (tree);
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index fb56ce5..a7a8bd2 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -58,7 +58,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
functions reachable unconditionally. */
decl = TREE_OPERAND (*tp, 0);
if (TREE_CODE (decl) == FUNCTION_DECL)
- cgraph_mark_needed_node (cgraph_node (decl));
+ cgraph_mark_address_taken_node (cgraph_node (decl));
break;
default:
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 8196b54..1f8e848 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3250,11 +3250,11 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED)
{
case PTRMEM_CST:
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
- cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
+ cgraph_mark_address_taken_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
break;
case BASELINK:
if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
- cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t)));
+ cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
break;
case VAR_DECL:
if (DECL_VTABLE_OR_VTT_P (t))
diff --git a/gcc/ipa.c b/gcc/ipa.c
index b51c219..fb3c749 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -38,6 +38,7 @@ cgraph_postorder (struct cgraph_node **order)
int stack_size = 0;
int order_pos = 0;
struct cgraph_edge *edge, last;
+ int pass;
struct cgraph_node **stack =
XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
@@ -48,44 +49,46 @@ cgraph_postorder (struct cgraph_node **order)
right through inline functions. */
for (node = cgraph_nodes; node; node = node->next)
node->aux = NULL;
- for (node = cgraph_nodes; node; node = node->next)
- if (!node->aux)
- {
- node2 = node;
- if (!node->callers)
- node->aux = &last;
- else
- node->aux = node->callers;
- while (node2)
- {
- while (node2->aux != &last)
- {
- edge = (struct cgraph_edge *) node2->aux;
- if (edge->next_caller)
- node2->aux = edge->next_caller;
- else
- node2->aux = &last;
- if (!edge->caller->aux)
- {
- if (!edge->caller->callers)
- edge->caller->aux = &last;
- else
- edge->caller->aux = edge->caller->callers;
- stack[stack_size++] = node2;
- node2 = edge->caller;
- break;
- }
- }
- if (node2->aux == &last)
- {
- order[order_pos++] = node2;
- if (stack_size)
- node2 = stack[--stack_size];
- else
- node2 = NULL;
- }
- }
- }
+ for (pass = 0; pass < 2; pass++)
+ for (node = cgraph_nodes; node; node = node->next)
+ if (!node->aux
+ && (pass || (node->needed && !node->address_taken)))
+ {
+ node2 = node;
+ if (!node->callers)
+ node->aux = &last;
+ else
+ node->aux = node->callers;
+ while (node2)
+ {
+ while (node2->aux != &last)
+ {
+ edge = (struct cgraph_edge *) node2->aux;
+ if (edge->next_caller)
+ node2->aux = edge->next_caller;
+ else
+ node2->aux = &last;
+ if (!edge->caller->aux)
+ {
+ if (!edge->caller->callers)
+ edge->caller->aux = &last;
+ else
+ edge->caller->aux = edge->caller->callers;
+ stack[stack_size++] = node2;
+ node2 = edge->caller;
+ break;
+ }
+ }
+ if (node2->aux == &last)
+ {
+ order[order_pos++] = node2;
+ if (stack_size)
+ node2 = stack[--stack_size];
+ else
+ node2 = NULL;
+ }
+ }
+ }
free (stack);
for (node = cgraph_nodes; node; node = node->next)
node->aux = NULL;