diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d03fcf914f29..3cb960effd83 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2005-04-02 Alexandre Oliva + + PR tree-optimization/20640 + * tree-ssa-dce.c (remove_dead_stmt): Don't redirect edge to + post-dominator if it has phi nodes. + (eliminate_unnecessary_stmts): Remove dead phis in all blocks + before dead statements. + 2005-04-02 Alexandre Oliva PR middle-end/20491 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c2a49280c144..1264cf7879bc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-04-02 Alexandre Oliva + + PR tree-optimization/20640 + * gcc.dg/torture/tree-loop-1.c: New. + 2005-04-02 Alexandre Oliva PR rtl-optimization/20290 diff --git a/gcc/testsuite/gcc.dg/torture/tree-loop-1.c b/gcc/testsuite/gcc.dg/torture/tree-loop-1.c new file mode 100644 index 000000000000..1d38691780a5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/tree-loop-1.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/20640 */ + +/* After unrolling the loop, we'd turn some conditional branches into + unconditional ones, but branch redirection would fail to compute + the PHI args for the PHI nodes in the replacement edge + destination, so they'd remain NULL causing crashes later on. */ + +/* { dg-do compile } */ + +static int a = 0; +extern int foo (void); +extern int *bar (void) __attribute__ ((__const__)); + +void +test (int x) +{ + int b = 10; + while (foo () == -1 && *bar () == 4 && b > 0) + --b; + a = x; +} diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index f8946bcbd92b..dc388ee7a877 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -637,7 +637,10 @@ eliminate_unnecessary_stmts (void) { /* Remove dead PHI nodes. */ remove_dead_phis (bb); + } + FOR_EACH_BB (bb) + { /* Remove dead statements. */ for (i = bsi_start (bb); ! bsi_end_p (i) ; ) { @@ -724,6 +727,7 @@ remove_dead_stmt (block_stmt_iterator *i, basic_block bb) if (is_ctrl_stmt (t)) { basic_block post_dom_bb; + /* The post dominance info has to be up-to-date. */ gcc_assert (dom_computed[CDI_POST_DOMINATORS] == DOM_OK); /* Get the immediate post dominator of bb. */ @@ -737,9 +741,20 @@ remove_dead_stmt (block_stmt_iterator *i, basic_block bb) return; } - /* Redirect the first edge out of BB to reach POST_DOM_BB. */ - redirect_edge_and_branch (EDGE_SUCC (bb, 0), post_dom_bb); - PENDING_STMT (EDGE_SUCC (bb, 0)) = NULL; + /* If the post dominator block has PHI nodes, we might be unable + to compute the right PHI args for them. Since the control + statement is unnecessary, all edges can be regarded as + equivalent, but we have to get rid of the condition, since it + might reference a variable that was determined to be + unnecessary and thus removed. */ + if (phi_nodes (post_dom_bb)) + post_dom_bb = EDGE_SUCC (bb, 0)->dest; + else + { + /* Redirect the first edge out of BB to reach POST_DOM_BB. */ + redirect_edge_and_branch (EDGE_SUCC (bb, 0), post_dom_bb); + PENDING_STMT (EDGE_SUCC (bb, 0)) = NULL; + } EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE; EDGE_SUCC (bb, 0)->count = bb->count;