PR tree-optimization/21417
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Feb 2006 02:36:33 +0000 (02:36 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Feb 2006 02:36:33 +0000 (02:36 +0000)
* tree-ssa-threadedge.c (thread_across_edge): Reject threading
across a backedge if the control statement at the end of the
block is data dependent on other statements in the same block.
(record_temporary_equivalences_from_stmts): Remove over-conservative
test for threading across backedges.

* gcc.dg/tree-ssa/pr21417.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110785 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr21417.c [new file with mode: 0644]
gcc/tree-ssa-threadedge.c

index 5f7e20c..9aef9b8 100644 (file)
@@ -1,5 +1,12 @@
 2006-02-08  Jeff Law  <law@redhat.com>
 
+       PR tree-optimization/21417
+       * tree-ssa-threadedge.c (thread_across_edge): Reject threading
+       across a backedge if the control statement at the end of the
+       block is data dependent on other statements in the same block.
+       (record_temporary_equivalences_from_stmts): Remove over-conservative
+       test for threading across backedges.
+
        * tree-ssa-dce.c (remove_dead_statement): When removing a dead
        control statement, handle all three special cases in the same
        manner as they all have the same desired solution.  No longer
index 4d6908f..ad136b3 100644 (file)
@@ -1,3 +1,7 @@
+2006-02-08  Jeff Law  <law@redhat.com>
+
+       * gcc.dg/tree-ssa/pr21417.c: New test.
+
 2006-02-08  Paolo Bonzini  <bonzini@gnu.org>
 
        * lib/scantree.exp (scan-tree-dump, scan-tree-dump-times,
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21417.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21417.c
new file mode 100644 (file)
index 0000000..e632007
--- /dev/null
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dom3-details" } */
+
+struct tree_common 
+{ 
+  int code; 
+}; 
+union tree_node 
+{ 
+  struct tree_common common; 
+}; 
+typedef union tree_node *tree; 
+extern tree test (tree, int, int); 
+extern tree foo (void); 
+extern void abort (void) __attribute__ ((__noreturn__)); 
+tree 
+test (tree expr, int t, int D17630) 
+{ 
+  int __i; 
+L0: 
+  if (expr->common.code != 142) goto L23; else goto L2; 
+L2: 
+  __i = 0; 
+  goto L10; 
+L10: 
+  __i = __i + 1; 
+  if (D17630 != __i) goto L8; else goto L19; 
+L8: 
+  if (t) goto L15; else goto L10; 
+L15: 
+  expr = foo (); 
+  if (expr->common.code != 142) goto L23; else goto L0; 
+L19: 
+  abort (); 
+L23: 
+  return expr; 
+} 
+
+
+/* We should thread the backedge to the top of the loop; ie we only
+   execute the if (expr->common.code != 142) test once per loop
+   iteration.  */
+/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "dom3" } } */
+/* { dg-final { cleanup-tree-dump "dom3" } } */
+
index bd78c6b..b8d4b13 100644 (file)
@@ -231,15 +231,6 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
       if (IS_EMPTY_STMT (stmt) || TREE_CODE (stmt) == LABEL_EXPR)
        continue;
 
-      /* Safely handle threading across loop backedges.  Only allowing
-        a conditional at the target of the backedge is over conservative,
-        but still allows us to capture the majority of the cases where
-        we can thread across a loop backedge.  */
-      if ((e->flags & EDGE_DFS_BACK) != 0
-         && TREE_CODE (stmt) != COND_EXPR
-         && TREE_CODE (stmt) != SWITCH_EXPR)
-       return NULL;
-
       /* If the statement has volatile operands, then we assume we
         can not thread through this block.  This is overly
         conservative in some ways.  */
@@ -496,6 +487,27 @@ thread_across_edge (tree dummy_cond,
 {
   tree stmt;
 
+  /* If E is a backedge, then we want to verify that the COND_EXPR,
+     SWITCH_EXPR or GOTO_EXPR at the end of e->dest is not affected
+     by any statements in e->dest.  If it is affected, then it is not
+     safe to thread this edge.  */
+  if (e->flags & EDGE_DFS_BACK)
+    {
+      ssa_op_iter iter;
+      use_operand_p use_p;
+      tree last = bsi_stmt (bsi_last (e->dest));
+
+      FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE)
+       {
+         tree use = USE_FROM_PTR (use_p);
+
+          if (TREE_CODE (use) == SSA_NAME
+             && TREE_CODE (SSA_NAME_DEF_STMT (use)) != PHI_NODE
+             && bb_for_stmt (SSA_NAME_DEF_STMT (use)) == e->dest)
+           goto fail;
+       }
+    }
+     
   stmt_count = 0;
 
   /* PHIs create temporary equivalences.  */