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 (;;)
+               ;
+       }
+     }
+ }

Reply via email to