diff mbox

Delete dead jump tables in cfglayout mode

Message ID CABu31nOJ9J3w_KNGxJiFQKWsoe7kqY4jNd1V_2oNi0NSC2ZEkQ@mail.gmail.com
State New
Headers show

Commit Message

Steven Bosscher Nov. 20, 2013, 8:59 p.m. UTC
Hello,

With the attached patch, dead jump tables are deleted if a
CLEANUP_EXPENSIVE is performed in cfglayout mode. This helps remove
labels and merge basic blocks, and brings the CFG out of cfglayout
mode more cleanly. It also fixes bugs in LABEL_NUSES updating, which
was broken for cfglayout, and which was done in the wrong place for
IRA.

Bootstrapped&tested on powerpc64-unknown-linux-gnu. The patch needs
patching for the EXIT_BLOCK_PTR/ENTRY_BLOCK_PTR changes but what's
attached is what I tested. If the patch is OK, I'll make the necessary
changes and re-test before committing.

OK for trunk?

Ciao!
Steven
* jump.c (reset_insn_reg_label_operand_notes): New function,
	split out from ...
	(init_label_info): ... here.  Reset LABEL_NUSES in cfglayout mode.
	* cfgcleanup.c (delete_dead_jump_tables_between): New function,
	split out from ...
	(delete_dead_jumptables): ... here.  Handle cfglayout mode.
	(cleanup_cfg): Delete dead jump tables in cfglayout mode if an
	expensive CFG cleanup is called for.
	* cfgrtl.c (fixup_reorder_chain): Remove BARRIERs from fallthru paths.
	(cfg_layout_finalize): Delete dead jump tables before re-building
	the insns chain.
	* ira.c (ira): Rebuild jump labels *after* deleting unreachable
	basic blocks, not before.
	* loop-init.c (rtl_loop_done): Call for an expensive CFG cleanup.

	* modulo-sched.c (sms_schedule): Do not look for BARRIERs in the
	insns chain of a scheduling extended basic block, they cannot appear
	there in cfglayout mode.

Comments

Jeff Law Nov. 21, 2013, 3:34 a.m. UTC | #1
On 11/20/13 13:59, Steven Bosscher wrote:
>
> 	* jump.c (reset_insn_reg_label_operand_notes): New function,
> 	split out from ...
> 	(init_label_info): ... here.  Reset LABEL_NUSES in cfglayout mode.
> 	* cfgcleanup.c (delete_dead_jump_tables_between): New function,
> 	split out from ...
> 	(delete_dead_jumptables): ... here.  Handle cfglayout mode.
> 	(cleanup_cfg): Delete dead jump tables in cfglayout mode if an
> 	expensive CFG cleanup is called for.
> 	* cfgrtl.c (fixup_reorder_chain): Remove BARRIERs from fallthru paths.
> 	(cfg_layout_finalize): Delete dead jump tables before re-building
> 	the insns chain.
> 	* ira.c (ira): Rebuild jump labels*after*  deleting unreachable
> 	basic blocks, not before.
> 	* loop-init.c (rtl_loop_done): Call for an expensive CFG cleanup.
>
> 	* modulo-sched.c (sms_schedule): Do not look for BARRIERs in the
> 	insns chain of a scheduling extended basic block, they cannot appear
> 	there in cfglayout mode.
Code is fine from a cursory review -- you're as well versed in this code 
as anyone, so I'm going to assume it's a step in the right direction.

My comments are just whitespace and spelling nits.


>
> @@ -186,34 +214,40 @@ init_label_info (rtx f)
>   {
>     rtx insn;
>
> -  for (insn = f; insn; insn = NEXT_INSN (insn))
> -    {
> -      if (LABEL_P (insn))
> -	LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
> -
> -      /* REG_LABEL_TARGET notes (including the JUMP_LABEL field) are
> -	 sticky and not reset here; that way we won't lose association
> -	 with a label when e.g. the source for a target register
> -	 disappears out of reach for targets that may use jump-target
> -	 registers.  Jump transformations are supposed to transform
> -	 any REG_LABEL_TARGET notes.  The target label reference in a
> -	 branch may disappear from the branch (and from the
> -	 instruction before it) for other reasons, like register
> -	 allocation.  */
> -
> -      if (INSN_P (insn))
> -	{
> -	  rtx note, next;
> -
> -	  for (note = REG_NOTES (insn); note; note = next)
> -	    {
> -	      next = XEXP (note, 1);
> -	      if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
> -		  && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
> -		remove_note (insn, note);
> -	    }
> -	}
> -    }
> +  if (current_ir_type () == IR_RTL_CFGLAYOUT)
> +    {
> +      basic_block bb;
> +
> +      FOR_EACH_BB (bb)
> +	{
> +	  /* Labels only appear between BB_HEAD and the basic block note,
> +	     and in the basic block header and footer.  */
> +	  for (insn = BB_HEAD (bb);
> +	       insn && LABEL_P (insn);
> +	       insn = NEXT_INSN (insn))
> +	    LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
> +	  for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn))
> +	    if (LABEL_P (insn))
> +	      LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
> +	  for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn))
> +	    if (LABEL_P (insn))
> +	      LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
This seems quite busy to my eyes.  Perhaps vertical whitespace between 
the loops.
>
> -  /* Don't call delete_dead_jumptables in cfglayout mode, because
> -     that function assumes that jump tables are in the insns stream.
> -     But we also don't_have_  to delete dead jumptables in cfglayout
                         ^^^ horizontal whitespace.


>> +  /* Annoying special case - stray barriers left in the code.  This happens
> +     if a tablejump is transformed to a simpe or confitional jump, or if a
> +     basic block ending in a tablejump is removed but the jump table itself
s/simpe/simple/


Nits fixed and it's good to go.

jeff
H.J. Lu Nov. 24, 2013, 8:26 p.m. UTC | #2
On Wed, Nov 20, 2013 at 12:59 PM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
> Hello,
>
> With the attached patch, dead jump tables are deleted if a
> CLEANUP_EXPENSIVE is performed in cfglayout mode. This helps remove
> labels and merge basic blocks, and brings the CFG out of cfglayout
> mode more cleanly. It also fixes bugs in LABEL_NUSES updating, which
> was broken for cfglayout, and which was done in the wrong place for
> IRA.
>
> Bootstrapped&tested on powerpc64-unknown-linux-gnu. The patch needs
> patching for the EXIT_BLOCK_PTR/ENTRY_BLOCK_PTR changes but what's
> attached is what I tested. If the patch is OK, I'll make the necessary
> changes and re-test before committing.
>
> OK for trunk?

It breaks bootstrap on x86 with java enabled:

/export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:
In class 'gnu.xml.aelfred2.XmlParser':
/export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:
In method 'gnu.xml.aelfred2.XmlParser.parseXMLDecl(boolean)':
In file included from
/export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:5804:0,
                 from
/export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/SAXDriver.java:1509,
                 from
/export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:5793,
                 from
/export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/SAXDriver.java:1605,
                 from
/export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:5813,
                 from <built-in>:14:
/export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:844:0:
internal compiler error: in remove_insn, at emit-rtl.c:3981
     return encodingName;
 ^
0x66b1f3 remove_insn(rtx_def*)
    ../../src-trunk/gcc/emit-rtl.c:3981
0x5cf31b delete_insn(rtx_def*)
    ../../src-trunk/gcc/cfgrtl.c:170
0xd5d7ae delete_dead_jump_tables_between
    ../../src-trunk/gcc/cfgcleanup.c:2971
0xd60511 delete_dead_jumptables()
    ../../src-trunk/gcc/cfgcleanup.c:2997
0xd617a2 cleanup_cfg(int)
    ../../src-trunk/gcc/cfgcleanup.c:3084
0xdbd15a rest_of_handle_if_conversion
    ../../src-trunk/gcc/ifcvt.c:4482
0xdbd15a execute
    ../../src-trunk/gcc/ifcvt.c:4516
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.
make[8]: *** [gnu-xml-aelfred2.lo] Error 1
H.J. Lu Nov. 24, 2013, 8:39 p.m. UTC | #3
On Sun, Nov 24, 2013 at 12:26 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Wed, Nov 20, 2013 at 12:59 PM, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
>> Hello,
>>
>> With the attached patch, dead jump tables are deleted if a
>> CLEANUP_EXPENSIVE is performed in cfglayout mode. This helps remove
>> labels and merge basic blocks, and brings the CFG out of cfglayout
>> mode more cleanly. It also fixes bugs in LABEL_NUSES updating, which
>> was broken for cfglayout, and which was done in the wrong place for
>> IRA.
>>
>> Bootstrapped&tested on powerpc64-unknown-linux-gnu. The patch needs
>> patching for the EXIT_BLOCK_PTR/ENTRY_BLOCK_PTR changes but what's
>> attached is what I tested. If the patch is OK, I'll make the necessary
>> changes and re-test before committing.
>>
>> OK for trunk?
>
> It breaks bootstrap on x86 with java enabled:
>
> /export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:
> In class 'gnu.xml.aelfred2.XmlParser':
> /export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:
> In method 'gnu.xml.aelfred2.XmlParser.parseXMLDecl(boolean)':
> In file included from
> /export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:5804:0,
>                  from
> /export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/SAXDriver.java:1509,
>                  from
> /export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:5793,
>                  from
> /export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/SAXDriver.java:1605,
>                  from
> /export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:5813,
>                  from <built-in>:14:
> /export/gnu/import/git/gcc-test-intel64/src-trunk/libjava/classpath/gnu/xml/aelfred2/XmlParser.java:844:0:
> internal compiler error: in remove_insn, at emit-rtl.c:3981
>      return encodingName;
>  ^
> 0x66b1f3 remove_insn(rtx_def*)
>     ../../src-trunk/gcc/emit-rtl.c:3981
> 0x5cf31b delete_insn(rtx_def*)
>     ../../src-trunk/gcc/cfgrtl.c:170
> 0xd5d7ae delete_dead_jump_tables_between
>     ../../src-trunk/gcc/cfgcleanup.c:2971
> 0xd60511 delete_dead_jumptables()
>     ../../src-trunk/gcc/cfgcleanup.c:2997
> 0xd617a2 cleanup_cfg(int)
>     ../../src-trunk/gcc/cfgcleanup.c:3084
> 0xdbd15a rest_of_handle_if_conversion
>     ../../src-trunk/gcc/ifcvt.c:4482
> 0xdbd15a execute
>     ../../src-trunk/gcc/ifcvt.c:4516
> Please submit a full bug report,
> with preprocessed source if appropriate.
> Please include the complete backtrace with any bug report.
> See <http://gcc.gnu.org/bugs.html> for instructions.
> make[8]: *** [gnu-xml-aelfred2.lo] Error 1
>

I opened:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59279
Steven Bosscher Nov. 24, 2013, 10:01 p.m. UTC | #4
On Sun, Nov 24, 2013 at 9:39 PM, H.J. Lu wrote:
> I opened:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59279


Thanks for the report. I can't reproduce it on powerpc64.

This isn't the time to leave the trunk broken, so I've reverted the
patch for now.

Ciao!
Steven
diff mbox

Patch

Index: jump.c
===================================================================
--- jump.c	(revision 204829)
+++ jump.c	(working copy)
@@ -177,6 +177,34 @@  make_pass_cleanup_barriers (gcc::context *ctxt)
 }
 
 
+/* Remove all REG_LABEL_OPERAND notes from INSN.
+
+   REG_LABEL_TARGET notes (including the JUMP_LABEL field) are sticky and
+   not reset here; that way we won't lose association with a label when
+   e.g. the source for a target register disappears out of reach for targets
+   that may use jump-target registers.  Jump transformations are supposed to
+   transform any REG_LABEL_TARGET notes.  The target label reference in a
+   branch may disappear from the branch (and from the instruction before it)
+   for other reasons, like register allocation.  */
+
+static void
+reset_insn_reg_label_operand_notes (rtx insn)
+{
+  if (INSN_P (insn))
+    {
+      rtx note, next;
+
+      for (note = REG_NOTES (insn); note; note = next)
+	{
+	  next = XEXP (note, 1);
+	  if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
+	      && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
+	    remove_note (insn, note);
+	}
+    }
+}
+
+
 /* Initialize LABEL_NUSES and JUMP_LABEL fields, add REG_LABEL_TARGET
    for remaining targets for JUMP_P.  Delete any REG_LABEL_OPERAND
    notes whose labels don't occur in the insn any more.  */
@@ -186,34 +214,40 @@  init_label_info (rtx f)
 {
   rtx insn;
 
-  for (insn = f; insn; insn = NEXT_INSN (insn))
-    {
-      if (LABEL_P (insn))
-	LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
-
-      /* REG_LABEL_TARGET notes (including the JUMP_LABEL field) are
-	 sticky and not reset here; that way we won't lose association
-	 with a label when e.g. the source for a target register
-	 disappears out of reach for targets that may use jump-target
-	 registers.  Jump transformations are supposed to transform
-	 any REG_LABEL_TARGET notes.  The target label reference in a
-	 branch may disappear from the branch (and from the
-	 instruction before it) for other reasons, like register
-	 allocation.  */
-
-      if (INSN_P (insn))
-	{
-	  rtx note, next;
-
-	  for (note = REG_NOTES (insn); note; note = next)
-	    {
-	      next = XEXP (note, 1);
-	      if (REG_NOTE_KIND (note) == REG_LABEL_OPERAND
-		  && ! reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
-		remove_note (insn, note);
-	    }
-	}
-    }
+  if (current_ir_type () == IR_RTL_CFGLAYOUT)
+    {
+      basic_block bb;
+
+      FOR_EACH_BB (bb)
+	{
+	  /* Labels only appear between BB_HEAD and the basic block note,
+	     and in the basic block header and footer.  */
+	  for (insn = BB_HEAD (bb);
+	       insn && LABEL_P (insn);
+	       insn = NEXT_INSN (insn))
+	    LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
+	  for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn))
+	    if (LABEL_P (insn))
+	      LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
+	  for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn))
+	    if (LABEL_P (insn))
+	      LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
+
+	  FOR_BB_INSNS (bb, insn)
+	    if (INSN_P (insn))
+	      reset_insn_reg_label_operand_notes (insn);
+	}
+    }
+  else
+    {
+      for (insn = f; insn; insn = NEXT_INSN (insn))
+	{
+	  if (LABEL_P (insn))
+	    LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
+	  if (INSN_P (insn))
+	    reset_insn_reg_label_operand_notes (insn);
+	}
+    }
 }
 
 /* A subroutine of mark_all_labels.  Trivially propagate a simple label
Index: cfgcleanup.c
===================================================================
--- cfgcleanup.c	(revision 204829)
+++ cfgcleanup.c	(working copy)
@@ -2926,41 +2926,66 @@  delete_unreachable_blocks (void)
   return changed;
 }
 
-/* Delete any jump tables never referenced.  We can't delete them at the
-   time of removing tablejump insn as they are referenced by the preceding
-   insns computing the destination, so we delay deleting and garbagecollect
-   them once life information is computed.  */
-void
-delete_dead_jumptables (void)
-{
-  basic_block bb;
-
-  /* A dead jump table does not belong to any basic block.  Scan insns
-     between two adjacent basic blocks.  */
-  FOR_EACH_BB (bb)
-    {
-      rtx insn, next;
-
-      for (insn = NEXT_INSN (BB_END (bb));
-	   insn && !NOTE_INSN_BASIC_BLOCK_P (insn);
-	   insn = next)
-	{
-	  next = NEXT_INSN (insn);
-	  if (LABEL_P (insn)
-	      && LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn)
-	      && JUMP_TABLE_DATA_P (next))
-	    {
-	      rtx label = insn, jump = next;
-
-	      if (dump_file)
-		fprintf (dump_file, "Dead jumptable %i removed\n",
-			 INSN_UID (insn));
-
-	      next = NEXT_INSN (next);
-	      delete_insn (jump);
-	      delete_insn (label);
-	    }
-	}
+
+/* Look for, and delete, any dead jumptables between START and END.  */
+
+static void
+delete_dead_jump_tables_between (rtx start, rtx end)
+{
+  rtx insn, next;
+
+  for (insn = start; insn != end; insn = next)
+    {
+      next = NEXT_INSN (insn);
+      if (next != NULL_RTX
+	  && LABEL_P (insn)
+	  && LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn)
+	  && JUMP_TABLE_DATA_P (next))
+	{
+	  rtx label = insn, jump = next;
+
+	  if (dump_file)
+	    fprintf (dump_file, "Dead jumptable %i removed\n",
+		     INSN_UID (insn));
+
+	  next = NEXT_INSN (next);
+	  delete_insn (jump);
+	  delete_insn (label);
+	}
+    }
+}
+
+
+/* Delete any jump tables never referenced.  We can't delete them at the
+   time of removing tablejump insn as the label preceding the jump table
+   data may be referenced by the preceding insns computing the destination.
+   So we delay deleting and garbage-collect them from time to time, after
+   a CFG cleanup.  */
+
+void
+delete_dead_jumptables (void)
+{
+  basic_block bb;
+
+  /* Label reference count must up-to-date to detect dead jump tables.  */
+  rebuild_jump_labels (get_insns ());
+
+  FOR_EACH_BB (bb)
+    {
+      if (current_ir_type () == IR_RTL_CFGLAYOUT)
+	{
+	  /* Jump tables only appear in the header or footer of BB.  */
+	  delete_dead_jump_tables_between (BB_HEADER (bb), NULL_RTX);
+	  delete_dead_jump_tables_between (BB_FOOTER (bb), NULL_RTX);
+	}
+      else
+	{
+	  /* Jump tables are in the insns chain between basic blocks.  */
+	  rtx start = NEXT_INSN (BB_END (bb));
+	  rtx end = (bb->next_bb == EXIT_BLOCK_PTR)
+	    ? NULL_RTX : BB_HEAD (bb->next_bb);
+	  delete_dead_jump_tables_between (start, end);
+	}
     }
 }
 
@@ -3031,13 +3056,13 @@  cleanup_cfg (int mode)
   if (mode & CLEANUP_CROSSJUMP)
     remove_fake_exit_edges ();
 
-  /* Don't call delete_dead_jumptables in cfglayout mode, because
-     that function assumes that jump tables are in the insns stream.
-     But we also don't _have_ to delete dead jumptables in cfglayout
-     mode because we shouldn't even be looking at things that are
-     not in a basic block.  Dead jumptables are cleaned up when
-     going out of cfglayout mode.  */
-  if (!(mode & CLEANUP_CFGLAYOUT))
+  /* Don't always call delete_dead_jumptables in cfglayout mode, because
+     jump tables can only appear in the headers and footers of basic blocks
+     and we usually are not interested in anything hiding there.
+     But if an expensive cleanup is called for, garbage-collect the dead
+     jump tables to get label reference counts right.  This sometimes
+     allows some labels to be removed and more basic blocks to be merged.  */
+  if (!(mode & CLEANUP_CFGLAYOUT) || (mode & CLEANUP_EXPENSIVE))
     delete_dead_jumptables ();
 
   /* ???  We probably do this way too often.  */
Index: cfgrtl.c
===================================================================
--- cfgrtl.c	(revision 204829)
+++ cfgrtl.c	(working copy)
@@ -3685,7 +3685,7 @@  fixup_reorder_chain (void)
 #endif
 
   /* Now add jumps and labels as needed to match the blocks new
-     outgoing edges.  */
+     outgoing edges.  Fixup missing or redundant BARRIERs.  */
 
   for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = (basic_block) bb->aux)
     {
@@ -3839,13 +3839,26 @@  fixup_reorder_chain (void)
 
   relink_block_chain (/*stay_in_cfglayout_mode=*/false);
 
-  /* Annoying special case - jump around dead jumptables left in the code.  */
-  FOR_EACH_BB (bb)
-    {
-      edge e = find_fallthru_edge (bb->succs);
-
-      if (e && !can_fallthru (e->src, e->dest))
-	force_nonfallthru (e);
+  /* Annoying special case - stray barriers left in the code.  This happens
+     if a tablejump is transformed to a simpe or confitional jump, or if a
+     basic block ending in a tablejump is removed but the jump table itself
+     is not.  */
+  FOR_EACH_BB (bb)
+    {
+      edge e = find_fallthru_edge (bb->succs);
+
+      if (e && e->dest != EXIT_BLOCK_PTR)
+	{
+	  rtx insn, next;
+	  for (insn = NEXT_INSN (BB_END (e->src));
+	       insn != BB_HEAD (e->dest);
+	       insn = next)
+	    {
+	      next = NEXT_INSN (insn);
+	      if (BARRIER_P (insn))
+		remove_insn (insn);
+	    }
+	}
     }
 
   /* Ensure goto_locus from edges has some instructions with that locus
@@ -4249,7 +4262,7 @@  break_superblocks (void)
 }
 
 /* Finalize the changes: reorder insn list according to the sequence specified
-   by aux pointers, enter compensation code, rebuild scope forest.  */
+   by aux pointers, enter compensation code.  */
 
 void
 cfg_layout_finalize (void)
@@ -4257,6 +4270,7 @@  cfg_layout_finalize (void)
 #ifdef ENABLE_CHECKING
   verify_flow_info ();
 #endif
+  delete_dead_jumptables ();
   force_one_exit_fallthru ();
   rtl_register_cfg_hooks ();
   if (reload_completed
@@ -4267,9 +4281,6 @@  cfg_layout_finalize (void)
     fixup_fallthru_exit_predecessor ();
   fixup_reorder_chain ();
 
-  rebuild_jump_labels (get_insns ());
-  delete_dead_jumptables ();
-
 #ifdef ENABLE_CHECKING
   verify_insn_chain ();
   verify_flow_info ();
Index: ira.c
===================================================================
--- ira.c	(revision 204829)
+++ ira.c	(working copy)
@@ -5220,9 +5220,9 @@  ira (FILE *f)
   if (optimize && rebuild_p)
     {
       timevar_push (TV_JUMP);
-      rebuild_jump_labels (get_insns ());
       if (purge_all_dead_edges ())
 	delete_unreachable_blocks ();
+      rebuild_jump_labels (get_insns ());
       timevar_pop (TV_JUMP);
     }
 
Index: loop-init.c
===================================================================
--- loop-init.c	(revision 204829)
+++ loop-init.c	(working copy)
@@ -419,7 +419,7 @@  rtl_loop_done (void)
   loop_optimizer_finalize ();
   free_dominance_info (CDI_DOMINATORS);
 
-  cleanup_cfg (0);
+  cleanup_cfg (CLEANUP_EXPENSIVE);
   if (dump_file)
     {
       dump_reg_info (dump_file);
Index: modulo-sched.c
===================================================================
--- modulo-sched.c	(revision 204829)
+++ modulo-sched.c	(working copy)
@@ -1472,7 +1472,7 @@  sms_schedule (void)
 	continue;
       }
 
-      /* Don't handle BBs with calls or barriers
+      /* Don't handle BBs with calls
 	 or !single_set with the exception of instructions that include
 	 count_reg---these instructions are part of the control part
 	 that do-loop recognizes.
@@ -1482,7 +1482,6 @@  sms_schedule (void)
          rtx set;
 
         if (CALL_P (insn)
-            || BARRIER_P (insn)
             || (NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
                 && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE
                 && !reg_mentioned_p (count_reg, insn))
@@ -1497,8 +1496,6 @@  sms_schedule (void)
 	    {
 	      if (CALL_P (insn))
 		fprintf (dump_file, "SMS loop-with-call\n");
-	      else if (BARRIER_P (insn))
-		fprintf (dump_file, "SMS loop-with-barrier\n");
               else if ((NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
                 && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE))
                 fprintf (dump_file, "SMS loop-with-not-single-set\n");