The following reverts the proper part of the loop depth dependent copy-propagation restriction patch. The canonicalization that record_equality does is important for correctness when threading over backedges (that must be accidential? I can't see how it might not be possible to trigger this without the change).
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Release-checking bootstrap on x86_64-unknown-linux-gnu in progress, bootstrap on i586-linux-gnu in progress. Richard. 2014-07-14 Richard Biener <rguent...@suse.de> PR tree-optimization/61757 PR tree-optimization/61783 * tree-ssa-dom.c (record_equality): Revert canonicalization change and add comment. (propagate_rhs_into_lhs): Revert previous fix, removing loop depth restriction again. * gcc.dg/torture/pr61757.c: New testcase. Index: gcc/testsuite/gcc.dg/torture/pr61757.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr61757.c (revision 0) +++ gcc/testsuite/gcc.dg/torture/pr61757.c (working copy) @@ -0,0 +1,33 @@ +/* { dg-do run } */ + +extern void abort (void); + +struct X { void *p; int res; } a[32]; + +int foo (unsigned i, unsigned n, void *q) +{ + if (i + 1 < n && q == a[i + 1].p) + { + do { + ++i; + } while (i < n && q == a[i].p); + --i; + return a[i].res; + } + else + return a[i].res; +} + +int main () +{ + int x; + a[0].p = &x; + a[0].res = -1; + a[1].p = &x; + a[1].res = 1; + a[2].p = (void *)0; + a[2].res = 0; + if (foo (0, 3, &x) != 1) + abort (); + return 0; +} Index: gcc/tree-ssa-dom.c =================================================================== --- gcc/tree-ssa-dom.c (revision 212510) +++ gcc/tree-ssa-dom.c (working copy) @@ -1589,6 +1589,33 @@ record_const_or_copy (tree x, tree y) record_const_or_copy_1 (x, y, prev_x); } +/* Return the loop depth of the basic block of the defining statement of X. + This number should not be treated as absolutely correct because the loop + information may not be completely up-to-date when dom runs. However, it + will be relatively correct, and as more passes are taught to keep loop info + up to date, the result will become more and more accurate. */ + +static int +loop_depth_of_name (tree x) +{ + gimple defstmt; + basic_block defbb; + + /* If it's not an SSA_NAME, we have no clue where the definition is. */ + if (TREE_CODE (x) != SSA_NAME) + return 0; + + /* Otherwise return the loop depth of the defining statement's bb. + Note that there may not actually be a bb for this statement, if the + ssa_name is live on entry. */ + defstmt = SSA_NAME_DEF_STMT (x); + defbb = gimple_bb (defstmt); + if (!defbb) + return 0; + + return bb_loop_depth (defbb); +} + /* Similarly, but assume that X and Y are the two operands of an EQ_EXPR. This constrains the cases in which we may treat this as assignment. */ @@ -1608,7 +1635,10 @@ record_equality (tree x, tree y) long as we canonicalize on one value. */ if (is_gimple_min_invariant (y)) ; - else if (is_gimple_min_invariant (x)) + else if (is_gimple_min_invariant (x) + /* ??? When threading over backedges the following is important + for correctness. See PR61757. */ + || (loop_depth_of_name (x) <= loop_depth_of_name (y))) prev_x = x, x = y, y = prev_x, prev_x = prev_y; else if (prev_x && is_gimple_min_invariant (prev_x)) x = y, y = prev_x, prev_x = prev_y; @@ -2638,33 +2668,6 @@ get_lhs_or_phi_result (gimple stmt) gcc_unreachable (); } -/* Return the loop depth of the basic block of the defining statement of X. - This number should not be treated as absolutely correct because the loop - information may not be completely up-to-date when dom runs. However, it - will be relatively correct, and as more passes are taught to keep loop info - up to date, the result will become more and more accurate. */ - -static int -loop_depth_of_name (tree x) -{ - gimple defstmt; - basic_block defbb; - - /* If it's not an SSA_NAME, we have no clue where the definition is. */ - if (TREE_CODE (x) != SSA_NAME) - return 0; - - /* Otherwise return the loop depth of the defining statement's bb. - Note that there may not actually be a bb for this statement, if the - ssa_name is live on entry. */ - defstmt = SSA_NAME_DEF_STMT (x); - defbb = gimple_bb (defstmt); - if (!defbb) - return 0; - - return bb_loop_depth (defbb); -} - /* Propagate RHS into all uses of LHS (when possible). RHS and LHS are derived from STMT, which is passed in solely so @@ -2680,8 +2683,7 @@ static void propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_names) { /* First verify that propagation is valid. */ - if (may_propagate_copy (lhs, rhs) - && loop_depth_of_name (lhs) >= loop_depth_of_name (rhs)) + if (may_propagate_copy (lhs, rhs)) { use_operand_p use_p; imm_use_iterator iter;