From 71cfcaa271c7c822fdef32927fe6793ae69efc8f Mon Sep 17 00:00:00 2001 From: rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Fri, 22 Sep 2006 10:02:47 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 +++ gcc/testsuite/ChangeLog | 19 +++--- gcc/testsuite/gcc.dg/pr28888.c | 21 +++++++ gcc/tree-cfg.c | 13 ++++ gcc/tree-if-conv.c | 110 ++++++++++++++++----------------- 5 files changed, 106 insertions(+), 64 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr28888.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 11c8865ee188..311f26bd4273 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 80097ac33a51..a560131e2a63 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 000000000000..c65a26a08748 --- /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 52e71a72d54b..67d049130e80 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 6e16a40a9c36..3a50741aff52 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); } } -- GitLab