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.