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