This patch widens the scope of the PR54838 fix (and reverts one
of my earlier kludges).  Like on the GIMPLE level threading
an edge through a loop header is seldomly a good idea as it may
create multiple-entry loops (not handled at all), create
irreducible regions (not handled at all).

In theory threading the latch is possible (see the hoops
tree-ssa-threadupdate.c jumps through).  But instead of
replicating all this on RTL the easiest thing is to simply
not thread through loop headers when loops are to be preserved.
It again unleashes the full powers before earlier patches
when loops are not preserved (there is at least one rtl-cprop
pass after rtl loop opts).

Bootstrap and regtest pending on x86_64-unknown-linux-gnu.

I've committed the testcase already as I wasn't able to reproduce
the issue (had a local patch to fix it ...).

Thanks,
Richard.

2012-12-21  Richard Biener  <rguent...@suse.de>

        PR rtl-optimization/52996
        * cprop.c (bypass_block): When loops are to be preserved
        do not bypass loop headers.  Revert earlier kludge to remove
        loops when doing that.

Index: gcc/cprop.c
===================================================================
*** gcc/cprop.c (revision 194658)
--- gcc/cprop.c (working copy)
*************** bypass_block (basic_block bb, rtx setcc,
*** 1496,1502 ****
    rtx insn, note;
    edge e, edest;
    int change;
!   int may_be_loop_header;
    unsigned removed_p;
    unsigned i;
    edge_iterator ei;
--- 1496,1502 ----
    rtx insn, note;
    edge e, edest;
    int change;
!   int may_be_loop_header = false;
    unsigned removed_p;
    unsigned i;
    edge_iterator ei;
*************** bypass_block (basic_block bb, rtx setcc,
*** 1510,1536 ****
    if (note)
      find_used_regs (&XEXP (note, 0), NULL);
  
-   /* Determine whether there are more latch edges.  Threading through
-      a loop header with more than one latch is delicate, see e.g.
-      tree-ssa-threadupdate.c:thread_through_loop_header.  */
    if (current_loops)
      {
!       may_be_loop_header = bb == bb->loop_father->header;
!       if (may_be_loop_header
!         && bb->loop_father->latch == NULL)
        return 0;
      }
    else
      {
-       unsigned n_back_edges = 0;
        FOR_EACH_EDGE (e, ei, bb->preds)
        if (e->flags & EDGE_DFS_BACK)
!         n_back_edges++;
! 
!       may_be_loop_header = n_back_edges > 0;
! 
!       if (n_back_edges > 1)
!         return 0;
      }
  
    change = 0;
--- 1510,1531 ----
    if (note)
      find_used_regs (&XEXP (note, 0), NULL);
  
    if (current_loops)
      {
!       /* If we are to preserve loop structure then do not bypass
!          a loop header.  This will either rotate the loop, create
!        multiple entry loops or even irreducible regions.  */
!       if (bb == bb->loop_father->header)
        return 0;
      }
    else
      {
        FOR_EACH_EDGE (e, ei, bb->preds)
        if (e->flags & EDGE_DFS_BACK)
!         {
!           may_be_loop_header = true;
!           break;
!         }
      }
  
    change = 0;
*************** bypass_block (basic_block bb, rtx setcc,
*** 1619,1635 ****
              && dest != old_dest
              && dest != EXIT_BLOCK_PTR)
              {
-             if (current_loops != NULL
-                 && e->src->loop_father->latch == e->src)
-               {
-                 /* ???  Now we are creating (or may create) a loop
-                    with multiple entries.  Simply mark it for
-                    removal.  Alternatively we could not do this
-                    threading.  */
-                 e->src->loop_father->header = NULL;
-                 e->src->loop_father->latch = NULL;
-               }
- 
              redirect_edge_and_branch_force (e, dest);
  
              /* Copy the register setter to the redirected edge.
--- 1614,1619 ----

Reply via email to