http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54369
--- Comment #4 from Eric Botcazou <ebotcazou at gcc dot gnu.org> 2012-08-31 14:20:03 UTC --- > I think I see where delete_related_insns is going wrong. We call it > with a JUMP instruction that we want to remove because we are just > jumping to the next instruction (a label) which we would get to anyway > without the jump, then after delete_related_insns removes the jump it > checks the label it was jumping to, and if it finds no uses it calls > delete_related_insns with that label. When delete_related_insns > is called with a label, it assumes it can remove all the code after > that label as unreachable. Only if there is a barrier just before the label though; now this barrier should have been removed one level earlier. The root cause of the problem is that MIPS runs its own version of the dbr pass and doesn't make sure that barriers are correctly placed for it, unlike other targets like SPARC. So the fix is: Index: config/mips/mips.c =================================================================== --- config/mips/mips.c (revision 184886) +++ config/mips/mips.c (working copy) @@ -15083,7 +15083,10 @@ mips_reorg (void) } if (optimize > 0 && flag_delayed_branch) - dbr_schedule (get_insns ()); + { + cleanup_barriers (); + dbr_schedule (get_insns ()); + } mips_reorg_process_insns (); if (!TARGET_MIPS16 && TARGET_EXPLICIT_RELOCS