]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
jump.c (reset_insn_reg_label_operand_notes): New function, split out from ...
authorSteven Bosscher <steven@gcc.gnu.org>
Sun, 24 Nov 2013 19:15:36 +0000 (19:15 +0000)
committerSteven Bosscher <steven@gcc.gnu.org>
Sun, 24 Nov 2013 19:15:36 +0000 (19:15 +0000)
* 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.

From-SVN: r205337

gcc/ChangeLog
gcc/cfgcleanup.c
gcc/cfgrtl.c
gcc/ira.c
gcc/jump.c
gcc/loop-init.c
gcc/modulo-sched.c

index 903725782d0d54f8042aaa4b60921363c9b773b9..29ac53cb0fd402868821de0f7f74660720716f7b 100644 (file)
@@ -1,3 +1,24 @@
+2013-11-24  Steven Bosscher  <steven@gcc.gnu.org>
+
+       * 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.
+
 2013-11-24  Tobias Burnus  <burnus@net-b.de>
 
        * doc/invoke.texi (-fsanitize=leak): Add link to the wiki page.
index 234e5b64fe7954d211a0c8e5012e5fc1d629a594..e909b03253dc0061d8dd889a3c20c133d74738ee 100644 (file)
@@ -2944,40 +2944,65 @@ delete_unreachable_blocks (void)
   return changed;
 }
 
+\f
+/* 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 they are referenced by the preceding
-   insns computing the destination, so we delay deleting and garbagecollect
-   them once life information is computed.  */
+   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;
 
-  /* A dead jump table does not belong to any basic block.  Scan insns
-     between two adjacent basic blocks.  */
+  /* Label reference count must up-to-date to detect dead jump tables.  */
+  rebuild_jump_labels (get_insns ());
+
   FOR_EACH_BB (bb)
     {
-      rtx insn, next;
-
-      for (insn = NEXT_INSN (BB_END (bb));
-          insn && !NOTE_INSN_BASIC_BLOCK_P (insn);
-          insn = next)
+      if (current_ir_type () == IR_RTL_CFGLAYOUT)
        {
-         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);
-           }
+         /* 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_FOR_FN (cfun))
+           ? NULL_RTX : BB_HEAD (bb->next_bb);
+         delete_dead_jump_tables_between (start, end);
        }
     }
 }
@@ -3049,13 +3074,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 63f44afbbae1eb15c41ba6970e328881005fd2eb..4ce7273834c4e3b49aec62b52a2da66c0a6261de 100644 (file)
@@ -3696,10 +3696,10 @@ 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_FOR_FN (cfun)->next_bb; bb ; bb = (basic_block)
-       bb->aux)
+  for (bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; bb ;
+       bb = (basic_block) bb->aux)
     {
       edge e_fall, e_taken, e;
       rtx bb_end_insn;
@@ -3853,13 +3853,26 @@ fixup_reorder_chain (void)
 
   relink_block_chain (/*stay_in_cfglayout_mode=*/false);
 
-  /* Annoying special case - jump around dead jumptables left in the code.  */
+  /* 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 && !can_fallthru (e->src, e->dest))
-       force_nonfallthru (e);
+      if (e && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
+       {
+         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
@@ -4273,7 +4286,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)
@@ -4281,6 +4294,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
@@ -4291,9 +4305,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 2902ebe0a8bed29171944593891f146ad938d639..43f98d4d69a6d7620ed80a24c825c7c0b71d004f 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -5273,9 +5273,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 a27aaa94b8daac5a252493ec196140d69f09a9bd..87f9619d7510b3097921a24e7a2432d32b7af608 100644 (file)
@@ -177,6 +177,34 @@ make_pass_cleanup_barriers (gcc::context *ctxt)
 }
 
 \f
+/* 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,32 +214,38 @@ init_label_info (rtx f)
 {
   rtx insn;
 
-  for (insn = f; insn; insn = NEXT_INSN (insn))
+  if (current_ir_type () == IR_RTL_CFGLAYOUT)
     {
-      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))
+      basic_block bb;
+
+      FOR_EACH_BB (bb)
        {
-         rtx note, next;
+         /* 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 (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);
-           }
+         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);
        }
     }
 }
index 664b1ace4273baf86e731b954ef2f64289d5dcc5..0d8e43837445d6693daa8cb61094f5599581da73 100644 (file)
@@ -415,7 +415,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 f3130449909873d4238dcc61150aaf1a3b63d4fa..444ffda34e9b624390dd26f7fb969daf3ec75d0f 100644 (file)
@@ -1471,7 +1471,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.
@@ -1481,7 +1481,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))
@@ -1496,8 +1495,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");