shrink-wrap: Remove complicated simple_return manipulations
authorSegher Boessenkool <segher@kernel.crashing.org>
Wed, 4 May 2016 20:57:08 +0000 (22:57 +0200)
committerSegher Boessenkool <segher@gcc.gnu.org>
Wed, 4 May 2016 20:57:08 +0000 (22:57 +0200)
Now that cfgcleanup knows how to optimize with return statements, the
epilogue insertion code doesn't have to deal with it itself anymore.

* function.c (emit_use_return_register_into_block): Delete.
(gen_return_pattern): Delete.
(emit_return_into_block): Delete.
(active_insn_between): Delete.
(convert_jumps_to_returns): Delete.
(emit_return_for_exit): Delete.
(thread_prologue_and_epilogue_insns): Delete all code dealing with
simple_return for shrink-wrapped blocks.
* shrink-wrap.c (try_shrink_wrapping): Insert simple_return at the
end of blocks that need one.
(get_unconverted_simple_return): Delete.
(convert_to_simple_return): Delete.
* shrink-wrap.c (get_unconverted_simple_return): Delete declaration.
(convert_to_simple_return): Ditto.

From-SVN: r235905

gcc/ChangeLog
gcc/function.c
gcc/shrink-wrap.c
gcc/shrink-wrap.h

index 584f4e002c9b734bd1224f33c313e2c56360f336..45e90874387adc60448f10b89db09d17f39b4c14 100644 (file)
@@ -1,3 +1,20 @@
+2016-05-04  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * function.c (emit_use_return_register_into_block): Delete.
+       (gen_return_pattern): Delete.
+       (emit_return_into_block): Delete.
+       (active_insn_between): Delete.
+       (convert_jumps_to_returns): Delete.
+       (emit_return_for_exit): Delete.
+       (thread_prologue_and_epilogue_insns): Delete all code dealing with
+       simple_return for shrink-wrapped blocks.
+       * shrink-wrap.c (try_shrink_wrapping): Insert simple_return at the
+       end of blocks that need one.
+       (get_unconverted_simple_return): Delete.
+       (convert_to_simple_return): Delete.
+       * shrink-wrap.c (get_unconverted_simple_return): Delete declaration.
+       (convert_to_simple_return): Ditto.
+
 2016-05-04  Segher Boessenkool  <segher@kernel.crashing.org>
 
        * cfgcleanup.c (bb_is_just_return): New function.
index 43a80b428751f4ad73f9015f0cc38ec28520fbef..70584b95586597e1ec6d1aec2ac902860d7e16e5 100644 (file)
@@ -5753,49 +5753,6 @@ prologue_epilogue_contains (const_rtx insn)
   return 0;
 }
 
-/* Insert use of return register before the end of BB.  */
-
-static void
-emit_use_return_register_into_block (basic_block bb)
-{
-  start_sequence ();
-  use_return_register ();
-  rtx_insn *seq = get_insns ();
-  end_sequence ();
-  rtx_insn *insn = BB_END (bb);
-  if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
-    insn = prev_cc0_setter (insn);
-
-  emit_insn_before (seq, insn);
-}
-
-
-/* Create a return pattern, either simple_return or return, depending on
-   simple_p.  */
-
-static rtx_insn *
-gen_return_pattern (bool simple_p)
-{
-  return (simple_p
-         ? targetm.gen_simple_return ()
-         : targetm.gen_return ());
-}
-
-/* Insert an appropriate return pattern at the end of block BB.  This
-   also means updating block_for_insn appropriately.  SIMPLE_P is
-   the same as in gen_return_pattern and passed to it.  */
-
-void
-emit_return_into_block (bool simple_p, basic_block bb)
-{
-  rtx_jump_insn *jump = emit_jump_insn_after (gen_return_pattern (simple_p),
-                                             BB_END (bb));
-  rtx pat = PATTERN (jump);
-  if (GET_CODE (pat) == PARALLEL)
-    pat = XVECEXP (pat, 0, 0);
-  gcc_assert (ANY_RETURN_P (pat));
-  JUMP_LABEL (jump) = pat;
-}
 
 /* Set JUMP_LABEL for a return insn.  */
 
@@ -5811,135 +5768,6 @@ set_return_jump_label (rtx_insn *returnjump)
     JUMP_LABEL (returnjump) = ret_rtx;
 }
 
-/* Return true if there are any active insns between HEAD and TAIL.  */
-bool
-active_insn_between (rtx_insn *head, rtx_insn *tail)
-{
-  while (tail)
-    {
-      if (active_insn_p (tail))
-       return true;
-      if (tail == head)
-       return false;
-      tail = PREV_INSN (tail);
-    }
-  return false;
-}
-
-/* LAST_BB is a block that exits, and empty of active instructions.
-   Examine its predecessors for jumps that can be converted to
-   (conditional) returns.  */
-vec<edge>
-convert_jumps_to_returns (basic_block last_bb, bool simple_p,
-                         vec<edge> unconverted ATTRIBUTE_UNUSED)
-{
-  int i;
-  basic_block bb;
-  edge_iterator ei;
-  edge e;
-  auto_vec<basic_block> src_bbs (EDGE_COUNT (last_bb->preds));
-
-  FOR_EACH_EDGE (e, ei, last_bb->preds)
-    if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
-      src_bbs.quick_push (e->src);
-
-  rtx_insn *label = BB_HEAD (last_bb);
-
-  FOR_EACH_VEC_ELT (src_bbs, i, bb)
-    {
-      rtx_insn *jump = BB_END (bb);
-
-      if (!JUMP_P (jump) || JUMP_LABEL (jump) != label)
-       continue;
-
-      e = find_edge (bb, last_bb);
-
-      /* If we have an unconditional jump, we can replace that
-        with a simple return instruction.  */
-      if (simplejump_p (jump))
-       {
-         /* The use of the return register might be present in the exit
-            fallthru block.  Either:
-            - removing the use is safe, and we should remove the use in
-            the exit fallthru block, or
-            - removing the use is not safe, and we should add it here.
-            For now, we conservatively choose the latter.  Either of the
-            2 helps in crossjumping.  */
-         emit_use_return_register_into_block (bb);
-
-         emit_return_into_block (simple_p, bb);
-         delete_insn (jump);
-       }
-
-      /* If we have a conditional jump branching to the last
-        block, we can try to replace that with a conditional
-        return instruction.  */
-      else if (condjump_p (jump))
-       {
-         rtx dest;
-
-         if (simple_p)
-           dest = simple_return_rtx;
-         else
-           dest = ret_rtx;
-         if (!redirect_jump (as_a <rtx_jump_insn *> (jump), dest, 0))
-           {
-             if (targetm.have_simple_return () && simple_p)
-               {
-                 if (dump_file)
-                   fprintf (dump_file,
-                            "Failed to redirect bb %d branch.\n", bb->index);
-                 unconverted.safe_push (e);
-               }
-             continue;
-           }
-
-         /* See comment in simplejump_p case above.  */
-         emit_use_return_register_into_block (bb);
-
-         /* If this block has only one successor, it both jumps
-            and falls through to the fallthru block, so we can't
-            delete the edge.  */
-         if (single_succ_p (bb))
-           continue;
-       }
-      else
-       {
-         if (targetm.have_simple_return () && simple_p)
-           {
-             if (dump_file)
-               fprintf (dump_file,
-                        "Failed to redirect bb %d branch.\n", bb->index);
-             unconverted.safe_push (e);
-           }
-         continue;
-       }
-
-      /* Fix up the CFG for the successful change we just made.  */
-      redirect_edge_succ (e, EXIT_BLOCK_PTR_FOR_FN (cfun));
-      e->flags &= ~EDGE_CROSSING;
-    }
-  src_bbs.release ();
-  return unconverted;
-}
-
-/* Emit a return insn for the exit fallthru block.  */
-basic_block
-emit_return_for_exit (edge exit_fallthru_edge, bool simple_p)
-{
-  basic_block last_bb = exit_fallthru_edge->src;
-
-  if (JUMP_P (BB_END (last_bb)))
-    {
-      last_bb = split_edge (exit_fallthru_edge);
-      exit_fallthru_edge = single_succ_edge (last_bb);
-    }
-  emit_barrier_after (BB_END (last_bb));
-  emit_return_into_block (simple_p, last_bb);
-  exit_fallthru_edge->flags &= ~EDGE_FALLTHRU;
-  return last_bb;
-}
-
 
 /* Generate the prologue and epilogue RTL if the machine supports it.  Thread
    this into place with notes indicating where the prologue ends and where
@@ -5993,7 +5821,6 @@ void
 thread_prologue_and_epilogue_insns (void)
 {
   bool inserted;
-  vec<edge> unconverted_simple_returns = vNULL;
   bitmap_head bb_flags;
   rtx_insn *returnjump;
   rtx_insn *epilogue_end ATTRIBUTE_UNUSED;
@@ -6088,40 +5915,8 @@ thread_prologue_and_epilogue_insns (void)
 
   exit_fallthru_edge = find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds);
 
-  if (targetm.have_simple_return () && entry_edge != orig_entry_edge)
-    exit_fallthru_edge
-       = get_unconverted_simple_return (exit_fallthru_edge, bb_flags,
-                                        &unconverted_simple_returns,
-                                        &returnjump);
-  if (targetm.have_return ())
-    {
-      if (exit_fallthru_edge == NULL)
-       goto epilogue_done;
-
-      if (optimize)
-       {
-         basic_block last_bb = exit_fallthru_edge->src;
-
-         if (LABEL_P (BB_HEAD (last_bb))
-             && !active_insn_between (BB_HEAD (last_bb), BB_END (last_bb)))
-           convert_jumps_to_returns (last_bb, false, vNULL);
-
-         if (EDGE_COUNT (last_bb->preds) != 0
-             && single_succ_p (last_bb))
-           {
-             last_bb = emit_return_for_exit (exit_fallthru_edge, false);
-             epilogue_end = returnjump = BB_END (last_bb);
-
-             /* Emitting the return may add a basic block.
-                Fix bb_flags for the added block.  */
-             if (targetm.have_simple_return ()
-                 && last_bb != exit_fallthru_edge->src)
-               bitmap_set_bit (&bb_flags, last_bb->index);
-
-             goto epilogue_done;
-           }
-       }
-    }
+  if (targetm.have_return () && exit_fallthru_edge == NULL)
+    goto epilogue_done;
 
   /* A small fib -- epilogue is not yet completed, but we wish to re-use
      this marker for the splits of EH_RETURN patterns, and nothing else
@@ -6229,10 +6024,6 @@ epilogue_done:
        }
     }
 
-  if (targetm.have_simple_return ())
-    convert_to_simple_return (entry_edge, orig_entry_edge, bb_flags,
-                             returnjump, unconverted_simple_returns);
-
   /* Emit sibling epilogues before any sibling call sites.  */
   for (ei = ei_start (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); (e =
                                                             ei_safe_edge (ei));
index fe795196709810920b20a4ac2610687e8693149f..0ba1fedf161f92312a62e8e0ad114b68042e87b8 100644 (file)
@@ -946,10 +946,9 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with,
        redirect_edge_and_branch_force (e, (basic_block) e->dest->aux);
       }
 
-  /* Change all the exits that should get a simple_return to FAKE.
-     They will be converted later.  */
+  /* Make a simple_return for those exits that run without prologue.  */
 
-  FOR_EACH_BB_FN (bb, cfun)
+  FOR_EACH_BB_REVERSE_FN (bb, cfun)
     if (!bitmap_bit_p (bb_with, bb->index))
       FOR_EACH_EDGE (e, ei, bb->succs)
        if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
@@ -958,7 +957,18 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with,
 
            e->flags &= ~EDGE_FALLTHRU;
            if (!(e->flags & EDGE_SIBCALL))
-             e->flags |= EDGE_FAKE;
+             {
+               rtx_insn *ret = targetm.gen_simple_return ();
+               rtx_insn *end = BB_END (e->src);
+               rtx_jump_insn *start = emit_jump_insn_after (ret, end);
+               JUMP_LABEL (start) = simple_return_rtx;
+               e->flags &= ~EDGE_FAKE;
+
+               if (dump_file)
+                 fprintf (dump_file,
+                          "Made simple_return with UID %d in bb %d\n",
+                          INSN_UID (start), e->src->index);
+             }
 
            emit_barrier_after_bb (e->src);
          }
@@ -996,156 +1006,3 @@ try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_with,
 
   free_dominance_info (CDI_DOMINATORS);
 }
-
-/* If we're allowed to generate a simple return instruction, then by
-   definition we don't need a full epilogue.  If the last basic
-   block before the exit block does not contain active instructions,
-   examine its predecessors and try to emit (conditional) return
-   instructions.  */
-
-edge
-get_unconverted_simple_return (edge exit_fallthru_edge, bitmap_head bb_flags,
-                              vec<edge> *unconverted_simple_returns,
-                              rtx_insn **returnjump)
-{
-  if (optimize)
-    {
-      unsigned i, last;
-
-      /* convert_jumps_to_returns may add to preds of the exit block
-         (but won't remove).  Stop at end of current preds.  */
-      last = EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds);
-      for (i = 0; i < last; i++)
-       {
-         edge e = EDGE_I (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds, i);
-         if (LABEL_P (BB_HEAD (e->src))
-             && !bitmap_bit_p (&bb_flags, e->src->index)
-             && !active_insn_between (BB_HEAD (e->src), BB_END (e->src)))
-           *unconverted_simple_returns
-                 = convert_jumps_to_returns (e->src, true,
-                                             *unconverted_simple_returns);
-       }
-    }
-
-  if (exit_fallthru_edge != NULL
-      && EDGE_COUNT (exit_fallthru_edge->src->preds) != 0
-      && !bitmap_bit_p (&bb_flags, exit_fallthru_edge->src->index))
-    {
-      basic_block last_bb;
-
-      last_bb = emit_return_for_exit (exit_fallthru_edge, true);
-      *returnjump = BB_END (last_bb);
-      exit_fallthru_edge = NULL;
-    }
-  return exit_fallthru_edge;
-}
-
-/* If there were branches to an empty LAST_BB which we tried to
-   convert to conditional simple_returns, but couldn't for some
-   reason, create a block to hold a simple_return insn and redirect
-   those remaining edges.  */
-
-void
-convert_to_simple_return (edge entry_edge, edge orig_entry_edge,
-                         bitmap_head bb_flags, rtx_insn *returnjump,
-                         vec<edge> unconverted_simple_returns)
-{
-  edge e;
-  edge_iterator ei;
-
-  if (!unconverted_simple_returns.is_empty ())
-    {
-      basic_block simple_return_block_hot = NULL;
-      basic_block simple_return_block_cold = NULL;
-      edge pending_edge_hot = NULL;
-      edge pending_edge_cold = NULL;
-      basic_block exit_pred;
-      int i;
-
-      gcc_assert (entry_edge != orig_entry_edge);
-
-      /* See if we can reuse the last insn that was emitted for the
-        epilogue.  */
-      if (returnjump != NULL_RTX
-         && JUMP_LABEL (returnjump) == simple_return_rtx)
-       {
-         e = split_block (BLOCK_FOR_INSN (returnjump), PREV_INSN (returnjump));
-         if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
-           simple_return_block_hot = e->dest;
-         else
-           simple_return_block_cold = e->dest;
-       }
-
-      /* Also check returns we might need to add to tail blocks.  */
-      FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
-       if (EDGE_COUNT (e->src->preds) != 0
-           && (e->flags & EDGE_FAKE) != 0
-           && !bitmap_bit_p (&bb_flags, e->src->index))
-         {
-           if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
-             pending_edge_hot = e;
-           else
-             pending_edge_cold = e;
-         }
-
-      /* Save a pointer to the exit's predecessor BB for use in
-         inserting new BBs at the end of the function.  Do this
-         after the call to split_block above which may split
-         the original exit pred.  */
-      exit_pred = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb;
-
-      FOR_EACH_VEC_ELT (unconverted_simple_returns, i, e)
-       {
-         basic_block *pdest_bb;
-         edge pending;
-
-         if (BB_PARTITION (e->src) == BB_HOT_PARTITION)
-           {
-             pdest_bb = &simple_return_block_hot;
-             pending = pending_edge_hot;
-           }
-         else
-           {
-             pdest_bb = &simple_return_block_cold;
-             pending = pending_edge_cold;
-           }
-
-         if (*pdest_bb == NULL && pending != NULL)
-           {
-             emit_return_into_block (true, pending->src);
-             pending->flags &= ~(EDGE_FALLTHRU | EDGE_FAKE);
-             *pdest_bb = pending->src;
-           }
-         else if (*pdest_bb == NULL)
-           {
-             basic_block bb;
-
-             bb = create_basic_block (NULL, NULL, exit_pred);
-             BB_COPY_PARTITION (bb, e->src);
-             rtx_insn *ret = targetm.gen_simple_return ();
-             rtx_jump_insn *start = emit_jump_insn_after (ret, BB_END (bb));
-             JUMP_LABEL (start) = simple_return_rtx;
-             emit_barrier_after (start);
-
-             *pdest_bb = bb;
-             make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
-           }
-         redirect_edge_and_branch_force (e, *pdest_bb);
-       }
-      unconverted_simple_returns.release ();
-    }
-
-  if (entry_edge != orig_entry_edge)
-    {
-      FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (cfun)->preds)
-       if (EDGE_COUNT (e->src->preds) != 0
-           && (e->flags & EDGE_FAKE) != 0
-           && !bitmap_bit_p (&bb_flags, e->src->index))
-         {
-           e = fix_fake_fallthrough_edge (e);
-
-           emit_return_into_block (true, e->src);
-           e->flags &= ~(EDGE_FALLTHRU | EDGE_FAKE);
-         }
-    }
-}
index 6e7a4f74864b34a2b003e5cb2de46a4c1a7c44ed..4d821d7349961edcb50700e5cdc9f391dcccfa48 100644 (file)
@@ -26,12 +26,6 @@ along with GCC; see the file COPYING3.  If not see
 extern bool requires_stack_frame_p (rtx_insn *, HARD_REG_SET, HARD_REG_SET);
 extern void try_shrink_wrapping (edge *entry_edge, bitmap_head *bb_flags,
                                 rtx_insn *prologue_seq);
-extern edge get_unconverted_simple_return (edge, bitmap_head,
-                                          vec<edge> *, rtx_insn **);
-extern void convert_to_simple_return (edge entry_edge, edge orig_entry_edge,
-                                     bitmap_head bb_flags,
-                                     rtx_insn *returnjump,
-                                     vec<edge> unconverted_simple_returns);
 #define SHRINK_WRAPPING_ENABLED \
   (flag_shrink_wrap && targetm.have_simple_return ())