Avoid loop in cgraph_remove_node
Jan Hubicka
jh@suse.cz
Fri Mar 18 01:04:00 GMT 2005
Hi,
this patch avoids one of loops in cgraph_remove_node Richard complained
about. It does not reduce the performance in any thrilling way as the
loop iterates at most once in mainline for already quite a some time,
but I found a related but while working on it - in non-unit-at-a-time we
can't release the body of inlinable function even if it seems unused
right now. THe real quadratic bottleneck is the next_node linked list,
that can be replaced by doubly linked list like we did in other cases,
but I will deal with this incrementally.
Bootstrapped/regtested i686-pc-gnu-linux and ppc-linux and I am going to commit it to
mainline now. I think this can go to 4.0 branch too, as missing inline
oppurtunities in non-unit-at-a-time mode is a bug and tester reports
following testcases to start passing:
libmudflap.cth/pass40-frag.c (-static -DSTATIC) execution test
libmudflap.cth/pass40-frag.c (-static -DSTATIC) output pattern test
(I have to look whether this is just bug in tester or real)
Honza
2005-03-18 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_remove_node): Reorganize killing of dead bodies.
Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.65
diff -c -3 -p -r1.65 cgraph.c
*** cgraph.c 2 Mar 2005 11:09:47 -0000 1.65
--- cgraph.c 17 Mar 2005 16:10:28 -0000
*************** void
*** 398,404 ****
cgraph_remove_node (struct cgraph_node *node)
{
void **slot;
! bool check_dead = 1;
cgraph_node_remove_callers (node);
cgraph_node_remove_callees (node);
--- 398,404 ----
cgraph_remove_node (struct cgraph_node *node)
{
void **slot;
! bool kill_body = false;
cgraph_node_remove_callers (node);
cgraph_node_remove_callees (node);
*************** cgraph_remove_node (struct cgraph_node *
*** 426,437 ****
else
{
htab_clear_slot (cgraph_hash, slot);
! if (!dump_enabled_p (TDI_tree_all))
! {
! DECL_SAVED_TREE (node->decl) = NULL;
! DECL_STRUCT_FUNCTION (node->decl) = NULL;
! }
! check_dead = false;
}
}
else
--- 426,432 ----
else
{
htab_clear_slot (cgraph_hash, slot);
! kill_body = true;
}
}
else
*************** cgraph_remove_node (struct cgraph_node *
*** 443,465 ****
n->next_clone = node->next_clone;
}
! /* Work out whether we still need a function body (either there is inline
! clone or there is out of line function whose body is not written). */
! if (check_dead && flag_unit_at_a_time)
! {
! struct cgraph_node *n;
!
! for (n = *slot; n; n = n->next_clone)
! if (n->global.inlined_to
! || (!n->global.inlined_to
! && !TREE_ASM_WRITTEN (n->decl) && !DECL_EXTERNAL (n->decl)))
! break;
! if (!n && !dump_enabled_p (TDI_tree_all))
! {
! DECL_SAVED_TREE (node->decl) = NULL;
! DECL_STRUCT_FUNCTION (node->decl) = NULL;
! DECL_INITIAL (node->decl) = error_mark_node;
! }
}
cgraph_n_nodes--;
/* Do not free the structure itself so the walk over chain can continue. */
--- 438,460 ----
n->next_clone = node->next_clone;
}
! /* While all the clones are removed after being proceeded, the function
! itself is kept in the cgraph even after it is compiled. Check whether
! we are done with this body and reclaim it proactively if this is the case.
! */
! if (!kill_body && *slot)
! {
! struct cgraph_node *n = *slot;
! if (!n->next_clone && !n->global.inlined_to
! && (TREE_ASM_WRITTEN (n->decl) || DECL_EXTERNAL (n->decl)))
! kill_body = true;
! }
!
! if (kill_body && !dump_enabled_p (TDI_tree_all) && flag_unit_at_a_time)
! {
! DECL_SAVED_TREE (node->decl) = NULL;
! DECL_STRUCT_FUNCTION (node->decl) = NULL;
! DECL_INITIAL (node->decl) = error_mark_node;
}
cgraph_n_nodes--;
/* Do not free the structure itself so the walk over chain can continue. */
More information about the Gcc-patches
mailing list