http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47612

           Summary: RTL crash when cc0 setter moved away from cc0 user
           Product: gcc
           Version: 4.6.0
            Status: UNCONFIRMED
          Keywords: ice-on-valid-code
          Severity: normal
          Priority: P3
         Component: rtl-optimization
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: i...@airs.com


Consider this C file:

extern void e (int) __attribute__ ((noreturn));
void
f (char *p, int a, int b, int c)
{
  int i, j;

  j = 0;
  for (i = 0; i < 10; ++i)
    {
      switch (a)
    {
    case 0:
      p[i] = 0;
      break;
    case 1:
      if (c == 1)
        {
          if (j < 0 | b <= j)
        e (0);
          p[j] = 0;
        }
      else
        {
          if (j < 0 | b <= j)
        e (0);
          p[j] = 0;
        }
      j++;
    }
    }
}

When I use a compiler built for the m68k-rtems4.11 target, the compiler crashes
when I compile this file with the options -O2 -mcpu=5206 -fwrapv.

/home/iant/gcc/m68k-rtems-objdir/./gcc/xgcc
-B/home/iant/gcc/m68k-rtems-objdir/./gcc/ -O2 -mcpu=5206 -S -fwrapv foo.c
foo.c: In function 'f':
foo.c:31:1: internal compiler error: in maybe_add_or_update_dep_1, at
sched-deps.c:845
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.

I will describe what I think is happening, although I have not proved it.  The
crash occurs because try_head_merge_bb in cfgcleanup.c moves a CC0-setter away
from the CC0-user.  It finds a common sequence in two basic blocks--I believe
it is the finding of this common sequence which makes this test requires the
-mcpu=5206 -fwrapv options.  Finding the common sequence respects CC0
requirements.  However, it then calls can_move_insns_across.  That returns
false, because there is a register conflict--d0 is used by the predecessor
block and the common sequence.  However, can_move_insns_across also returns
move_upto, indicating which insns may be moved.  can_move_insns_across does not
check for cc0 when setting move_upto, and try_head_merge_bb doesn't check for
it when using move_upto.  The effect is that the cc0 setter is moved, leaving
the cc0 user behind.  This leads to the later crash.

Reply via email to