summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2006-09-22 10:02:47 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2006-09-22 10:02:47 +0000
commit71cfcaa271c7c822fdef32927fe6793ae69efc8f (patch)
treea53cb50ab23e9f4afc3a543ca0bdbc9e862012bd
parent5a7c611911fc9748381b0128d63a1d9d27e18d0b (diff)
downloadgcc-71cfcaa271c7c822fdef32927fe6793ae69efc8f.tar.gz
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. * gcc.dg/pr28888.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@117135 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog19
-rw-r--r--gcc/testsuite/gcc.dg/pr28888.c21
-rw-r--r--gcc/tree-cfg.c13
-rw-r--r--gcc/tree-if-conv.c110
5 files changed, 106 insertions, 64 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 11c8865ee18..311f26bd427 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2006-09-22 Zdenek Dvorak <dvorakz@suse.cz>
+
+ 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.
+
2006-09-22 Jakub Jelinek <jakub@redhat.com>
* tree-ssa-propagate.c (set_rhs): Copy EXPR_LOCATION if
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 80097ac33a5..a560131e2a6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-09-22 Zdenek Dvorak <dvorakz@suse.cz>
+
+ PR tree-optimization/28888
+ * gcc.dg/pr28888.c: New test.
+
2006-09-21 Mark Mitchell <mark@codesourcery.com>
PR c++/29016
@@ -5,15 +10,15 @@
2006-09-21 Lee Millward <lee.millward@codesourcery.com>
- PR c++/28861
- * g++.dg/template/spec32.C: New test.
- * g++.dg/parse/crash9.C: Adjust error markers.
+ PR c++/28861
+ * g++.dg/template/spec32.C: New test.
+ * g++.dg/parse/crash9.C: Adjust error markers.
PR c++/28303
- * g++.dg/template/typedef6.C: New test.
- * g++.dg/init/error1.C: Adjust error markers.
- * g++.dg/parse/crash9.C: Likewise.
- * g++.dg/template/crash55.C: Likewise.
+ * g++.dg/template/typedef6.C: New test.
+ * g++.dg/init/error1.C: Adjust error markers.
+ * g++.dg/parse/crash9.C: Likewise.
+ * g++.dg/template/crash55.C: Likewise.
2006-09-21 Janis Johnson <janis187@us.ibm.com>
diff --git a/gcc/testsuite/gcc.dg/pr28888.c b/gcc/testsuite/gcc.dg/pr28888.c
new file mode 100644
index 00000000000..c65a26a0874
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr28888.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+static const unsigned char _c30[] =
+ "statistic of allocated integer registers:";
+Allocate__WriteStats (void)
+{
+ register int i0, i1, i2, i3, i4, i5;
+l0:i1 = (int) (i5 << 2);
+ if (i0)
+ i4 = i5;
+l1:i2 += i1;
+ if (i1)
+ goto l0;
+l3:i0 = i1 == 255;
+ i1++;
+ Out__LongInt ((int) i0, (int) 0);
+ i0 = i4 >= i1;
+ if (i0)
+ goto l3;
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 52e71a72d54..67d049130e8 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3757,6 +3757,19 @@ tree_verify_flow_info (void)
}
}
+ 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:
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 6e16a40a9c3..3a50741aff5 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -866,71 +866,73 @@ combine_blocks (struct loop *loop)
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;
+ edge e;
+ edge_iterator ei;
- exits = get_loop_exit_edges (loop, &n_exits);
- free (exits);
/* 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);
- /* 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)
+ for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
{
- edge_iterator 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 (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;
+ make_edge (loop->header, exit_bb, EDGE_FALLTHRU);
+ set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header);
}
- if (bb == loop->latch && empty_block_p (bb))
- continue;
+ /* 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);
+ }
- /* It is time to remove this basic block. First remove edges. */
- while (EDGE_COUNT (bb->preds) > 0)
- remove_edge (EDGE_PRED (bb, 0));
+ merge_target_bb = loop->header;
+ for (i = 1; i < orig_loop_num_nodes; i++)
+ {
+ block_stmt_iterator bsi;
+ tree_stmt_iterator last;
- /* 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;
- }
+ bb = ifc_bbs[i];
- while (EDGE_COUNT (bb->succs) > 0)
- remove_edge (EDGE_SUCC (bb, 0));
+ 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); )
@@ -956,8 +958,6 @@ combine_blocks (struct loop *loop)
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);
}
@@ -966,15 +966,11 @@ combine_blocks (struct loop *loop)
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))
+ && exit_bb != loop->header
+ && can_merge_blocks_p (loop->header, exit_bb))
{
- if (can_merge_blocks_p (loop->header, exit_bb))
- {
- remove_bb_from_loops (exit_bb);
- merge_blocks (loop->header, exit_bb);
- }
+ remove_bb_from_loops (exit_bb);
+ merge_blocks (loop->header, exit_bb);
}
}