This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] Fix tree-cfg.c latent bug
- From: law at redhat dot com
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 28 Jul 2003 11:00:13 -0600
- Subject: [tree-ssa] Fix tree-cfg.c latent bug
- Reply-to: law at redhat dot com
Some pending work exposed a problem with our implementation of
move_outgoing_edges (which is used when linearizing COND_EXPRs).
Specifically if the THEN and ELSE arms of the COND_EXPR have a
common destination which has a PHI node, then we can end up with
a PHI node with a NULL edge argument. This in turn causes the
out-of-ssa pass some grief.
Luckily the fix is pretty simple. In the case where make_edge returns
NULL, we merely delete the original edge form the THEN/ELSE block as
we already have an edge from the COND_EXPR to the target block.
This removal should be done with ssa_remove_edge since we want to
remove the PHI arguments associated with the edge from the THEN/ELSE
clause to the target block.
* tree-cfg.c (move_outgoing_edges): Correctly handle case where
an edge already exists from BB1 to BB2's successor.
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.135
diff -c -3 -p -r1.1.4.135 tree-cfg.c
*** tree-cfg.c 25 Jul 2003 12:28:23 -0000 1.1.4.135
--- tree-cfg.c 28 Jul 2003 16:51:26 -0000
*************** move_outgoing_edges (basic_block bb1, ba
*** 4458,4476 ****
old_edge = bb2->succ;
new_edge = make_edge (bb1, old_edge->dest, old_edge->flags);
! /* Update PHI nodes at BB2's successor. The arguments that used to
! come from BB2 now come from BB1. */
! for (phi = phi_nodes (old_edge->dest); phi; phi = TREE_CHAIN (phi))
{
! int i;
! for (i = 0; i < PHI_NUM_ARGS (phi); i++)
! if (PHI_ARG_EDGE (phi, i) == old_edge)
! PHI_ARG_EDGE (phi, i) = new_edge;
}
- /* Note that we shouldn't call ssa_remove_edge here because we've
- already dealt with PHI nodes. */
- remove_edge (old_edge);
}
/* BB2's dominator children are now BB1's. Also, remove BB2 as a
--- 4458,4490 ----
old_edge = bb2->succ;
new_edge = make_edge (bb1, old_edge->dest, old_edge->flags);
! /* If make_edge created a new edge, then we need to update the PHI
! node at BB2's successor. The arguments that used to come from
! BB2 now come from BB1.
!
! If make_edge did not create a new edge, then we already had an
! edge from BB1 to BB2's successor. In this case we want to
! remove the edge and remove its alternative from BB2's successor's
! PHI nodes, hence we use ssa_remove_edge. */
! if (new_edge)
! {
! for (phi = phi_nodes (old_edge->dest); phi; phi = TREE_CHAIN (phi))
! {
! int i;
! for (i = 0; i < PHI_NUM_ARGS (phi); i++)
! if (PHI_ARG_EDGE (phi, i) == old_edge)
! PHI_ARG_EDGE (phi, i) = new_edge;
! }
!
! /* Note that we shouldn't call ssa_remove_edge here because we've
! already dealt with PHI nodes. */
! remove_edge (old_edge);
! }
! else
{
! ssa_remove_edge (old_edge);
}
}
/* BB2's dominator children are now BB1's. Also, remove BB2 as a