This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] for PR 28888
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 30 Aug 2006 12:34:30 +0200
- Subject: [patch] for PR 28888
Hello,
if conversion leaves edges after non-control statements marked with
EDGE_TRUE/FALSE_VALUE, which confuses simplify_using_initial_conditions
and causes this ICE. The code in combine_blocks that is responsible for
the cfg manipulations during if conversion turned out to be a bit
strange (checking for things like loop latch having an exit, which
cannot happen since we require that loop latch has only one successor;
and possibly generating wrong cfg in some cases); hence, I have
rewritten it almost completely in the progress of fixing the bug.
Bootstrapped & regtested on x86_64.
Zdenek
PR tree-optimization/28888
* tree-if-conv.c (combine_blocks): Rewritten.
* tree-cfg.c (tree_verify_flow_info): Check that edges with
EDGE_TRUE/FALSE_VALUE follow COND_EXPR.
Index: tree-if-conv.c
===================================================================
*** tree-if-conv.c (revision 116570)
--- tree-if-conv.c (working copy)
*************** combine_blocks (struct loop *loop)
*** 863,933 ****
basic_block bb, exit_bb, merge_target_bb;
unsigned int orig_loop_num_nodes = loop->num_nodes;
unsigned int i;
! unsigned int n_exits;
! edge *exits;
- exits = get_loop_exit_edges (loop, &n_exits);
- free (exits);
/* Process phi nodes to prepare blocks for merge. */
process_phi_nodes (loop);
exit_bb = NULL;
- /* Merge basic blocks */
- merge_target_bb = loop->header;
for (i = 1; i < orig_loop_num_nodes; i++)
{
- edge e;
- block_stmt_iterator bsi;
- tree_stmt_iterator last;
-
bb = ifc_bbs[i];
! if (!exit_bb && bb_with_exit_edge_p (loop, bb))
! exit_bb = bb;
!
! if (bb == exit_bb)
{
! edge_iterator ei;
/* Connect this node with loop header. */
! make_edge (ifc_bbs[0], bb, EDGE_FALLTHRU);
! set_immediate_dominator (CDI_DOMINATORS, bb, ifc_bbs[0]);
! if (exit_bb != loop->latch)
! {
! /* Redirect non-exit edge to loop->latch. */
! FOR_EACH_EDGE (e, ei, bb->succs)
! {
! if (!loop_exit_edge_p (loop, e))
! {
! redirect_edge_and_branch (e, loop->latch);
! set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb);
! }
! }
! }
! continue;
}
! if (bb == loop->latch && empty_block_p (bb))
! continue;
! /* It is time to remove this basic block. First remove edges. */
! while (EDGE_COUNT (bb->preds) > 0)
! remove_edge (EDGE_PRED (bb, 0));
!
! /* This is loop latch and loop does not have exit then do not
! delete this basic block. Just remove its PREDS and reconnect
! loop->header and loop->latch blocks. */
! if (bb == loop->latch && n_exits == 0)
! {
! make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
! set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
! continue;
! }
! while (EDGE_COUNT (bb->succs) > 0)
! remove_edge (EDGE_SUCC (bb, 0));
/* Remove labels and make stmts member of loop->header. */
for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
--- 863,935 ----
basic_block bb, exit_bb, merge_target_bb;
unsigned int orig_loop_num_nodes = loop->num_nodes;
unsigned int i;
! edge e;
! edge_iterator ei;
/* Process phi nodes to prepare blocks for merge. */
process_phi_nodes (loop);
+ /* Merge basic blocks. First remove all the edges in the loop, except
+ for those from the exit block. */
exit_bb = NULL;
+ for (i = 0; i < orig_loop_num_nodes; i++)
+ {
+ bb = ifc_bbs[i];
+ if (bb_with_exit_edge_p (loop, bb))
+ {
+ exit_bb = bb;
+ break;
+ }
+ }
+ gcc_assert (exit_bb != loop->latch);
for (i = 1; i < orig_loop_num_nodes; i++)
{
bb = ifc_bbs[i];
! for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
{
! if (e->src == exit_bb)
! ei_next (&ei);
! else
! remove_edge (e);
! }
! }
+ if (exit_bb != NULL)
+ {
+ if (exit_bb != loop->header)
+ {
/* Connect this node with loop header. */
! make_edge (loop->header, exit_bb, EDGE_FALLTHRU);
! set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header);
! }
! /* Redirect non-exit edges to loop->latch. */
! FOR_EACH_EDGE (e, ei, exit_bb->succs)
! {
! if (!loop_exit_edge_p (loop, e))
! redirect_edge_and_branch (e, loop->latch);
}
+ set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb);
+ }
+ else
+ {
+ /* If the loop does not have exit then reconnect header and latch. */
+ make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
+ set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
+ }
! merge_target_bb = loop->header;
! for (i = 1; i < orig_loop_num_nodes; i++)
! {
! block_stmt_iterator bsi;
! tree_stmt_iterator last;
! bb = ifc_bbs[i];
! if (bb == exit_bb || bb == loop->latch)
! continue;
/* Remove labels and make stmts member of loop->header. */
for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
*************** combine_blocks (struct loop *loop)
*** 953,960 ****
delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
/* Remove basic block. */
- if (bb == loop->latch)
- loop->latch = merge_target_bb;
remove_bb_from_loops (bb);
expunge_block (bb);
}
--- 955,960 ----
*************** combine_blocks (struct loop *loop)
*** 963,977 ****
This reduces number of basic blocks to 2. Auto vectorizer addresses
loops with two nodes only. FIXME: Use cleanup_tree_cfg(). */
if (exit_bb
! && loop->header != loop->latch
! && exit_bb != loop->latch
! && empty_block_p (loop->latch))
{
! if (can_merge_blocks_p (loop->header, exit_bb))
! {
! remove_bb_from_loops (exit_bb);
! merge_blocks (loop->header, exit_bb);
! }
}
}
--- 963,973 ----
This reduces number of basic blocks to 2. Auto vectorizer addresses
loops with two nodes only. FIXME: Use cleanup_tree_cfg(). */
if (exit_bb
! && exit_bb != loop->header
! && can_merge_blocks_p (loop->header, exit_bb))
{
! remove_bb_from_loops (exit_bb);
! merge_blocks (loop->header, exit_bb);
}
}
Index: tree-cfg.c
===================================================================
*** tree-cfg.c (revision 116570)
--- tree-cfg.c (working copy)
*************** tree_verify_flow_info (void)
*** 3757,3762 ****
--- 3757,3775 ----
}
}
+ if (TREE_CODE (stmt) != COND_EXPR)
+ {
+ /* Verify that there are no edges with EDGE_TRUE/FALSE_FLAG set
+ after anything else but if statement. */
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE))
+ {
+ error ("true/false edge after a non-COND_EXPR in bb %d",
+ bb->index);
+ err = 1;
+ }
+ }
+
switch (TREE_CODE (stmt))
{
case COND_EXPR: