https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85615

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |law at gcc dot gnu.org

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
It looks like loop structure is already broken to the extent that
loop->num_nodes
cannot be trusted and thus

  bblocks = XCNEWVEC (basic_block, loop->num_nodes);
  dbds_ce_stop = loop->header;
  nblocks = dfs_enumerate_from (loop->latch, 1, dbds_continue_enumeration_p,
                                bblocks, loop->num_nodes, bb);

breaks (not enough space in bblocks, thus bb is not reachable from
loop->latch).
In fact loop structure looks totally broken to me :/

We seem to thread through always true/false conditions that are left over from
VRP substitute-and-fold which relies on CFG cleanup to cleanup things here.

When we thread through block 12,

Breakpoint 5, thread_block_1 (bb=<basic_block 0x7ffff689f750 (12)>, 
    noloop_only=true, joiners=false)

we have threaded through the loop header which in the end wrecks things.
We do not hit

          /* One case occurs when there was loop header buried in a jump
             threading path that crosses loop boundaries.  We do not try
             and thread this elsewhere, so just cancel the jump threading
             request by clearing the AUX field now.  */
          if (bb->loop_father != e2->src->loop_father
              && !loop_exit_edge_p (e2->src->loop_father, e2))
            {

nor

          /* Another case occurs when trying to thread through our
             own loop header, possibly from inside the loop.  We will
             thread these later.  */
          unsigned int i;
          for (i = 1; i < path->length (); i++)
            {

but the case involves a very long path (6 edges) where we thread through
the header of an outer loop into an inner loop and finally through the
exit of the inner loop.  I guess we should hit the first case by allowing
the exit threading only if the exit is to bb->loop_father.  Otherwise
we create an alternate entry (which is what happens here).  Like by
making the check consisted with the others.

I'm testing the following.

Index: gcc/tree-ssa-threadupdate.c
===================================================================
--- gcc/tree-ssa-threadupdate.c (revision 259879)
+++ gcc/tree-ssa-threadupdate.c (working copy)
@@ -1309,7 +1309,7 @@ thread_block_1 (basic_block bb, bool nol
             and thread this elsewhere, so just cancel the jump threading
             request by clearing the AUX field now.  */
          if (bb->loop_father != e2->src->loop_father
-             && !loop_exit_edge_p (e2->src->loop_father, e2))
+             && !loop_exit_edge_p (bb->loop_father, e2))
            {
              /* Since this case is not handled by our special code
                 to thread through a loop header, we must explicitly

Reply via email to