* 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
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
+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,
--- /dev/null
+/* { 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" } } */
+
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. */
{
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. */