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

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

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

--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
Hmm, no.  The issue seems to be that the outer loop is head-controlled which
means unrolling duplicates the exit check in the middle of the fused loop.
I think we miss a check for an empty header of the outer loop, the
perfect nest check is too simplistic here.  We have

  b = 0;
  do
    {
       if (b > 2)
         break;
       c = 0;
       do
         {
           a[c] ^= 1;
           ++c
         }
       while (c <= 2);
       ++b;
    }
  while (1);

and fusing ends up with something like

  b = 0;
  do
    {
       c = 0;
       do
         {
           a[c] ^= 1;
           if (b > 2)
             break;
           a[c] ^= 1;
         }
       while (c <= 2);
       b+=2;
    }
  while (1);

in particular the comment in bb_prevents_fusion_p saying

  /* BB is duplicated by outer unrolling and then all N-1 first copies
     move into the body of the fused inner loop.  If BB exits the outer loop
     the last copy still does so, and the first N-1 copies are cancelled
     by loop unrolling, so also after fusion it's the exit block.

looks wrong.  Yes, the first is cancelled but the remaining is not the
exit block.

Reply via email to