The following fixes PR69452 - we were using dom order to hoist stmts and PHIs and expected that to preserve proper def order. That obviously doesn't work - the following makes us use RPO order instead.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2016-01-26 Richard Biener <rguent...@suse.de> PR tree-optimization/69452 * tree-ssa-loop-im.c (move_computations_dom_walker): Remove. (move_computations_dom_walker::before_dom_children): Rename to ... (move_computations_worker): This. (move_computations): Perform an RPO rather than a DOM walk. * gcc.dg/torture/pr69452.c: New testcase. Index: gcc/tree-ssa-loop-im.c =================================================================== *** gcc/tree-ssa-loop-im.c (revision 232792) --- gcc/tree-ssa-loop-im.c (working copy) *************** public: *** 1112,1126 **** data stored in LIM_DATA structures associated with each statement. Callback for walk_dominator_tree. */ ! edge ! move_computations_dom_walker::before_dom_children (basic_block bb) { struct loop *level; unsigned cost = 0; struct lim_aux_data *lim_data; if (!loop_outer (bb->loop_father)) ! return NULL; for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi); ) { --- 1112,1127 ---- data stored in LIM_DATA structures associated with each statement. Callback for walk_dominator_tree. */ ! unsigned int ! move_computations_worker (basic_block bb) { struct loop *level; unsigned cost = 0; struct lim_aux_data *lim_data; + unsigned int todo = 0; if (!loop_outer (bb->loop_father)) ! return todo; for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi); ) { *************** move_computations_dom_walker::before_dom *** 1171,1177 **** gimple_cond_lhs (cond), gimple_cond_rhs (cond)); new_stmt = gimple_build_assign (gimple_phi_result (stmt), COND_EXPR, t, arg0, arg1); ! todo_ |= TODO_cleanup_cfg; } if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (new_stmt))) && (!ALWAYS_EXECUTED_IN (bb) --- 1172,1178 ---- gimple_cond_lhs (cond), gimple_cond_rhs (cond)); new_stmt = gimple_build_assign (gimple_phi_result (stmt), COND_EXPR, t, arg0, arg1); ! todo |= TODO_cleanup_cfg; } if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (new_stmt))) && (!ALWAYS_EXECUTED_IN (bb) *************** move_computations_dom_walker::before_dom *** 1266,1272 **** else gsi_insert_on_edge (e, stmt); } ! return NULL; } /* Hoist the statements out of the loops prescribed by data stored in --- 1267,1274 ---- else gsi_insert_on_edge (e, stmt); } ! ! return todo; } /* Hoist the statements out of the loops prescribed by data stored in *************** move_computations_dom_walker::before_dom *** 1275,1288 **** static unsigned int move_computations (void) { ! move_computations_dom_walker walker (CDI_DOMINATORS); ! walker.walk (cfun->cfg->x_entry_block_ptr); gsi_commit_edge_inserts (); if (need_ssa_update_p (cfun)) rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); ! return walker.todo_; } /* Checks whether the statement defining variable *INDEX can be hoisted --- 1277,1296 ---- static unsigned int move_computations (void) { ! int *rpo = XNEWVEC (int, last_basic_block_for_fn (cfun)); ! int n = pre_and_rev_post_order_compute_fn (cfun, NULL, rpo, false); ! unsigned todo = 0; ! ! for (int i = 0; i < n; ++i) ! todo |= move_computations_worker (BASIC_BLOCK_FOR_FN (cfun, rpo[i])); ! ! free (rpo); gsi_commit_edge_inserts (); if (need_ssa_update_p (cfun)) rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa); ! return todo; } /* Checks whether the statement defining variable *INDEX can be hoisted Index: gcc/testsuite/gcc.dg/torture/pr69452.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr69452.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr69452.c (working copy) *************** *** 0 **** --- 1,35 ---- + /* { dg-do compile } */ + + short a, f, h; + struct S0 { + int f0; + } b; + char c, d, e, j, k; + int g; + char fn1(char p1, int p2) { return 7 >> p2 ? p1 : p2; } + void fn2() { + int l, m, n; + struct S0 o = {0}; + for (;;) { + int p = 1, r = e; + unsigned q = 6; + l = r == 0 ? q : q % r; + n = l; + c = f; + k = fn1(p, n ^ e); + char s = k; + j = s / 6; + if (j) { + int t = d, u = m = d ? t : t / d; + h = a || u; + b.f0 = h; + for (; d;) + ; + } else { + b = o; + if (d != g) + for (;;) + ; + } + } + }