Some GC marking inefficiency with chain_next and chain_prev
S. Bosscher
S.Bosscher@student.tudelft.nl
Wed Dec 10 11:28:00 GMT 2003
Hi,
While investigating why marking for GC takes up much more time
for tree-ssa than for mainline, I noticed this cute piece of
inefficiency in gtype-desc.c:
void
gt_ggc_mx_tree_statement_list_node (void *x_p)
{
struct tree_statement_list_node * x = (struct tree_statement_list_node
*)x_p;
struct tree_statement_list_node * xlimit = x;
while (ggc_test_and_set_mark (xlimit))
xlimit = ((*xlimit).next);
if (x != xlimit)
for (;;)
{
struct tree_statement_list_node * const xprev = ((*x).prev);
if (xprev == NULL) break;
x = xprev;
(void) ggc_test_and_set_mark (xprev);
}
while (x != xlimit)
{
gt_ggc_m_24tree_statement_list_node ((*x).prev);
gt_ggc_m_24tree_statement_list_node ((*x).next);
gt_ggc_m_9tree_node ((*x).stmt);
x = ((*x).next);
}
}
where in gtype-desc.h the field marked is defined as:
#define gt_ggc_m_24tree_statement_list_node(X) do { \
if (X != NULL) gt_ggc_mx_tree_statement_list_node (X);\
} while (0)
Recall the definition of a STATEMENT_LIST node:
struct tree_statement_list_node
GTY ((chain_next ("%h.next"), chain_prev ("%h.prev")))
{
struct tree_statement_list_node *prev;
struct tree_statement_list_node *next;
tree stmt;
};
In other words, first we go over the next and prev chains because
of the GTY markers "chain_next" and "chain_prev". Then we look
at those fields again in the loop, calling ggc_set_mark() on the
prev and next fields again, but this has no effect since we've
already marked them.
We seem to do this for every struct that has a "chain_next" and
"chain_prev" GTY marker. The effect is that we call ggc_set_mark
twice for a field that is also used in one of those markers. This
happens on mainline at least for cgraph_edges, and on the tree-ssa
branch also for edges, basic_blocks, and tree_stmt_lists. These
calls are completely redundant, but they do cause some (probably
non-negligible) call overhead.
I don't know gengtype.c well enough to propose a fix, but it seems
that we could save ourselves a few ggc_set_mark calls if someone
can fix this.
Gr.
Steven
P.S. ggc_test_and_set_mark is testing every pointer for "(void *) 0"
and "(void *) 1". Most of these checks are also redundant, perhaps
we can avoid some of these checks if they're somehow moved into
gengtype...
More information about the Gcc
mailing list