2005-Mar-01 Richard Guenther * cgraph.h (struct cgraph_edge): Add prev_caller and prev_callee fields. * cgraph.c (cgraph_create_edge): Initialize prev_caller and prev_callee. (cgraph_edge_remove_callee): New function. (cgraph_edge_remove_caller): Likewise. (cgraph_remove_edge): Use. (cgraph_redirect_edge_callee): Likewise. (cgraph_node_remove_callees): New function. (cgraph_node_remove_callers): Likewise. (cgraph_remove_node): Use. Index: cgraph.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v retrieving revision 1.64 diff -c -3 -p -r1.64 cgraph.c *** cgraph.c 23 Jan 2005 19:17:09 -0000 1.64 --- cgraph.c 1 Mar 2005 12:34:31 -0000 *************** cgraph_create_edge (struct cgraph_node * *** 289,318 **** edge->caller = caller; edge->callee = callee; edge->call_expr = call_expr; edge->next_caller = callee->callers; edge->next_callee = caller->callees; caller->callees = edge; callee->callers = edge; return edge; } ! /* Remove the edge E the cgraph. */ void cgraph_remove_edge (struct cgraph_edge *e) { ! struct cgraph_edge **edge, **edge2; ! for (edge = &e->callee->callers; *edge && *edge != e; ! edge = &((*edge)->next_caller)) ! continue; ! gcc_assert (*edge); ! *edge = (*edge)->next_caller; ! for (edge2 = &e->caller->callees; *edge2 && *edge2 != e; ! edge2 = &(*edge2)->next_callee) ! continue; ! gcc_assert (*edge2); ! *edge2 = (*edge2)->next_callee; } /* Redirect callee of E to N. The function does not update underlying --- 289,343 ---- edge->caller = caller; edge->callee = callee; edge->call_expr = call_expr; + edge->prev_caller = NULL; edge->next_caller = callee->callers; + if (callee->callers) + callee->callers->prev_caller = edge; + edge->prev_callee = NULL; edge->next_callee = caller->callees; + if (caller->callees) + caller->callees->prev_callee = edge; caller->callees = edge; callee->callers = edge; return edge; } ! /* Remove the edge E from the list of the callers of the callee. */ ! ! inline void ! cgraph_edge_remove_callee (struct cgraph_edge *e) ! { ! if (e->prev_caller) ! e->prev_caller->next_caller = e->next_caller; ! if (e->next_caller) ! e->next_caller->prev_caller = e->prev_caller; ! if (!e->prev_caller) ! e->callee->callers = e->next_caller; ! } ! ! /* Remove the edge E from the list of the callees of the caller. */ ! ! inline void ! cgraph_edge_remove_caller (struct cgraph_edge *e) ! { ! if (e->prev_callee) ! e->prev_callee->next_callee = e->next_callee; ! if (e->next_callee) ! e->next_callee->prev_callee = e->prev_callee; ! if (!e->prev_callee) ! e->caller->callees = e->next_callee; ! } ! ! /* Remove the edge E in the cgraph. */ void cgraph_remove_edge (struct cgraph_edge *e) { ! /* Remove from callers list of the callee. */ ! cgraph_edge_remove_callee (e); ! /* Remove from callees list of the callers. */ ! cgraph_edge_remove_caller (e); } /* Redirect callee of E to N. The function does not update underlying *************** cgraph_remove_edge (struct cgraph_edge * *** 321,336 **** void cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n) { ! struct cgraph_edge **edge; ! for (edge = &e->callee->callers; *edge && *edge != e; ! edge = &((*edge)->next_caller)) ! continue; ! gcc_assert (*edge); ! *edge = (*edge)->next_caller; ! e->callee = n; e->next_caller = n->callers; n->callers = e; } /* Remove the node from cgraph. */ --- 346,391 ---- void cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n) { ! /* Remove from callers list of the current callee. */ ! cgraph_edge_remove_callee (e); ! /* Insert to callers list of the new callee. */ ! e->prev_caller = NULL; ! if (n->callers) ! n->callers->prev_caller = e; e->next_caller = n->callers; n->callers = e; + e->callee = n; + } + + /* Remove all callees from the node. */ + + void + cgraph_node_remove_callees (struct cgraph_node *node) + { + struct cgraph_edge *e; + + /* It is sufficient to remove the edges from the lists of callers of + the callees. The callee list of the node can be zapped with one + assignment. */ + for (e = node->callees; e; e = e->next_callee) + cgraph_edge_remove_callee (e); + node->callees = NULL; + } + + /* Remove all callers from the node. */ + + void + cgraph_node_remove_callers (struct cgraph_node *node) + { + struct cgraph_edge *e; + + /* It is sufficient to remove the edges from the lists of callees of + the callers. The caller list of the node can be zapped with one + assignment. */ + for (e = node->callers; e; e = e->next_caller) + cgraph_edge_remove_caller (e); + node->callers = NULL; } /* Remove the node from cgraph. */ *************** cgraph_remove_node (struct cgraph_node * *** 341,350 **** void **slot; bool check_dead = 1; ! while (node->callers) ! cgraph_remove_edge (node->callers); ! while (node->callees) ! cgraph_remove_edge (node->callees); while (node->nested) cgraph_remove_node (node->nested); if (node->origin) --- 396,403 ---- void **slot; bool check_dead = 1; ! cgraph_node_remove_callers (node); ! cgraph_node_remove_callees (node); while (node->nested) cgraph_remove_node (node->nested); if (node->origin) Index: cgraph.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v retrieving revision 1.44 diff -c -3 -p -r1.44 cgraph.h *** cgraph.h 23 Jan 2005 19:17:09 -0000 1.44 --- cgraph.h 1 Mar 2005 12:34:31 -0000 *************** struct cgraph_edge GTY((chain_next ("%h. *** 123,129 **** --- 123,131 ---- { struct cgraph_node *caller; struct cgraph_node *callee; + struct cgraph_edge *prev_caller; struct cgraph_edge *next_caller; + struct cgraph_edge *prev_callee; struct cgraph_edge *next_callee; tree call_expr; PTR GTY ((skip (""))) aux;