]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
flow.c (flow_delete_insn, [...]): Export.
authorRichard Henderson <rth@cygnus.com>
Sun, 6 Feb 2000 13:01:03 +0000 (05:01 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 6 Feb 2000 13:01:03 +0000 (05:01 -0800)
        * flow.c (flow_delete_insn, make_edge, remove_edge): Export.
        * basic-block.h: Declare them.
        * emit-rtl.h (active_insn_p): New.
        (next_active_insn, prev_active_insn): Use it.
        * rtl.h: Declare it.
        * function.c (emit_return_into_block): New.
        (thread_prologue_and_epilogue_insns): Insert return insns instead
        of epilogues when possible.
        * jump.c (jump_optimize_1): Remove code to insert a return insn
        on the fallthru to the exit block.

From-SVN: r31826

gcc/ChangeLog
gcc/basic-block.h
gcc/emit-rtl.c
gcc/flow.c
gcc/function.c
gcc/jump.c
gcc/rtl.h

index 3831f59b51863f47d48dcc9949d7f3ffb2947c9f..ac0c6433a0ed1cc810f477d4e348e959b1ad6374 100644 (file)
@@ -1,3 +1,16 @@
+2000-02-06  Richard Henderson  <rth@cygnus.com>
+
+       * flow.c (flow_delete_insn, make_edge, remove_edge): Export.
+       * basic-block.h: Declare them.
+       * emit-rtl.h (active_insn_p): New.
+       (next_active_insn, prev_active_insn): Use it.
+       * rtl.h: Declare it.
+       * function.c (emit_return_into_block): New.
+       (thread_prologue_and_epilogue_insns): Insert return insns instead
+       of epilogues when possible.
+       * jump.c (jump_optimize_1): Remove code to insert a return insn
+       on the fallthru to the exit block.
+
 2000-02-06  Richard Henderson  <rth@cygnus.com>
 
        * simplify-rtx.c (simplify_relational_operation): Canonicalize
index 57fb2a7f3eecdcdc65dbe008b0af7d21f695c770..5f95c3103d020d10c6a9a670fad772d21d50f9a2 100644 (file)
@@ -222,7 +222,11 @@ extern void insert_insn_on_edge            PARAMS ((rtx, edge));
 extern void commit_edge_insertions     PARAMS ((void));
 extern void remove_fake_edges          PARAMS ((void));
 extern void add_noreturn_fake_exit_edges       PARAMS ((void));
+extern rtx flow_delete_insn            PARAMS ((rtx));
 extern void flow_delete_insn_chain     PARAMS ((rtx, rtx));
+extern void make_edge                  PARAMS ((sbitmap *, basic_block,
+                                                basic_block, int));
+extern void remove_edge                        PARAMS ((edge));
 
 
 /* Structure to hold information for each natural loop.  */
index 7a40b82238b65c18e0f38d7f84fd75ff8a5e53d7..26bfc44e777471a5e7507b68afa13dbc875f5e2a 100644 (file)
@@ -2084,6 +2084,17 @@ prev_real_insn (insn)
    does not look inside SEQUENCEs.  Until reload has completed, this is the
    same as next_real_insn.  */
 
+int
+active_insn_p (insn)
+     rtx insn;
+{
+  return (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
+         || (GET_CODE (insn) == INSN
+             && (! reload_completed
+                 || (GET_CODE (PATTERN (insn)) != USE
+                     && GET_CODE (PATTERN (insn)) != CLOBBER))));
+}
+
 rtx
 next_active_insn (insn)
      rtx insn;
@@ -2091,12 +2102,7 @@ next_active_insn (insn)
   while (insn)
     {
       insn = NEXT_INSN (insn);
-      if (insn == 0
-         || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
-         || (GET_CODE (insn) == INSN
-             && (! reload_completed
-                 || (GET_CODE (PATTERN (insn)) != USE
-                     && GET_CODE (PATTERN (insn)) != CLOBBER))))
+      if (insn == 0 || active_insn_p (insn))
        break;
     }
 
@@ -2114,12 +2120,7 @@ prev_active_insn (insn)
   while (insn)
     {
       insn = PREV_INSN (insn);
-      if (insn == 0
-         || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
-         || (GET_CODE (insn) == INSN
-             && (! reload_completed
-                 || (GET_CODE (PATTERN (insn)) != USE
-                     && GET_CODE (PATTERN (insn)) != CLOBBER))))
+      if (insn == 0 || active_insn_p (insn))
        break;
     }
 
index aa8745181abf141504884131962f21eec684a108..1ce45f0d475d889d4240a1bfa87feb2bddbe3476 100644 (file)
@@ -285,8 +285,6 @@ static rtx find_basic_blocks_1              PARAMS ((rtx));
 static void create_basic_block         PARAMS ((int, rtx, rtx, rtx));
 static void clear_edges                        PARAMS ((void));
 static void make_edges                 PARAMS ((rtx));
-static void make_edge                  PARAMS ((sbitmap *, basic_block,
-                                                basic_block, int));
 static void make_label_edge            PARAMS ((sbitmap *, basic_block,
                                                 rtx, int));
 static void make_eh_edge               PARAMS ((sbitmap *, eh_nesting_info *,
@@ -302,7 +300,6 @@ static void delete_eh_regions               PARAMS ((void));
 static int can_delete_note_p           PARAMS ((rtx));
 static int delete_block                        PARAMS ((basic_block));
 static void expunge_block              PARAMS ((basic_block));
-static rtx flow_delete_insn            PARAMS ((rtx));
 static int can_delete_label_p          PARAMS ((rtx));
 static int merge_blocks_move_predecessor_nojumps PARAMS ((basic_block,
                                                          basic_block));
@@ -346,7 +343,6 @@ static void count_reg_sets_1                PARAMS ((rtx));
 static void count_reg_sets             PARAMS ((rtx));
 static void count_reg_references       PARAMS ((rtx));
 static void invalidate_mems_from_autoinc PARAMS ((rtx));
-static void remove_edge                        PARAMS ((edge));
 static void remove_fake_successors     PARAMS ((basic_block));
 static void flow_nodes_print   PARAMS ((const char *, const sbitmap, FILE *));
 static void flow_exits_print PARAMS ((const char *, const edge *, int, FILE *));
@@ -1056,7 +1052,7 @@ make_edges (label_value_list)
 /* Create an edge between two basic blocks.  FLAGS are auxiliary information
    about the edge that is accumulated between calls.  */
 
-static void
+void
 make_edge (edge_cache, src, dst, flags)
      sbitmap *edge_cache;
      basic_block src, dst;
@@ -1982,7 +1978,7 @@ expunge_block (b)
 
 /* Delete INSN by patching it out.  Return the next insn.  */
 
-static rtx
+rtx
 flow_delete_insn (insn)
      rtx insn;
 {
@@ -6215,7 +6211,7 @@ find_edge_index (edge_list, pred, succ)
 }
 
 /* This function will remove an edge from the flow graph.  */
-static void
+void
 remove_edge (e)
      edge e;
 {
index d466db848b794db219fd7640e2ad08db63090931..9b2182eb16a6a3ea9aab6fd6b72c290361f0a0ed 100644 (file)
@@ -271,6 +271,7 @@ static int all_blocks               PARAMS ((tree, tree *));
    can always export `prologue_epilogue_contains'.  */
 static int *record_insns       PARAMS ((rtx)) ATTRIBUTE_UNUSED;
 static int contains            PARAMS ((rtx, int *));
+static void emit_return_into_block PARAMS ((basic_block));
 static void put_addressof_into_stack PARAMS ((rtx, struct hash_table *));
 static boolean purge_addressof_1 PARAMS ((rtx *, rtx, int, int, 
                                          struct hash_table *));
@@ -6577,6 +6578,27 @@ prologue_epilogue_contains (insn)
   return 0;
 }
 
+/* Insert gen_return at the end of block BB.  This also means updating
+   block_for_insn appropriately.  */
+
+static void
+emit_return_into_block (bb)
+     basic_block bb;
+{
+  rtx p, end;
+
+  end = emit_jump_insn_after (gen_return (), bb->end);
+  p = NEXT_INSN (bb->end); 
+  while (1)
+    {
+      set_block_for_insn (p, bb);
+      if (p == end)
+       break;
+      p = NEXT_INSN (p);
+    }
+  bb->end = end;
+}
+
 /* Generate the prologue and epilogue RTL if the machine supports it.  Thread
    this into place with notes indicating where the prologue ends and where
    the epilogue begins.  Update the basic block information when possible.  */
@@ -6629,6 +6651,93 @@ thread_prologue_and_epilogue_insns (f)
   if (e == NULL)
     goto epilogue_done;
 
+#ifdef HAVE_return
+  if (optimize && HAVE_return)
+    {
+      /* If we're allowed to generate a simple return instruction,
+        then by definition we don't need a full epilogue.  Examine
+        the block that falls through to EXIT.   If it does not 
+        contain any code, examine its predecessors and try to 
+        emit (conditional) return instructions.  */
+
+      basic_block last;
+      edge e_next;
+      rtx label;
+
+      for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+       if (e->flags & EDGE_FALLTHRU)
+         break;
+      if (e == NULL)
+       goto epilogue_done;
+      last = e->src;
+
+      /* Verify that there are no active instructions in the last block.  */
+      label = last->end;
+      while (label && GET_CODE (label) != CODE_LABEL)
+       {
+         if (active_insn_p (label))
+           break;
+         label = PREV_INSN (label);
+       }
+
+      if (last->head == label && GET_CODE (label) == CODE_LABEL)
+       {
+         for (e = last->pred; e ; e = e_next)
+           {
+             basic_block bb = e->src;
+             rtx jump;
+
+             e_next = e->pred_next;
+             if (bb == ENTRY_BLOCK_PTR)
+               continue;
+
+             jump = bb->end;
+             if (GET_CODE (jump) != JUMP_INSN)
+               continue;
+
+             /* If we have an unconditional jump, we can replace that
+                with a simple return instruction.  */
+             if (simplejump_p (jump))
+               {
+                 emit_return_into_block (bb);
+                 flow_delete_insn (jump);
+               }
+
+             /* If we have a conditional jump, we can try to replace
+                that with a conditional return instruction.  */
+             else if (condjump_p (jump))
+               {
+                 rtx ret, *loc;
+
+                 ret = SET_SRC (PATTERN (jump));
+                 if (GET_CODE (XEXP (ret, 1)) == LABEL_REF)
+                   loc = &XEXP (ret, 1);
+                 else
+                   loc = &XEXP (ret, 2);
+                 ret = gen_rtx_RETURN (VOIDmode);
+
+                 if (! validate_change (jump, loc, ret, 0))
+                   continue;
+                 if (JUMP_LABEL (jump))
+                   LABEL_NUSES (JUMP_LABEL (jump))--;
+               }
+             else
+               continue;
+
+             /* Fix up the CFG for the successful change we just made.  */
+             remove_edge (e);
+             make_edge (NULL, bb, EXIT_BLOCK_PTR, 0);
+           }
+       }
+
+      /* Emit a return insn for the exit fallthru block.  Whether
+        this is still reachable will be determined later.  */
+
+      emit_barrier_after (last->end);
+      emit_return_into_block (last);
+      goto epilogue_done;
+    }
+#endif
 #ifdef HAVE_epilogue
   if (HAVE_epilogue)
     {
index ad213bc2f63c12161f1109fae2f9dc7104f56708..417425d5c82740a7bbedc92b3b0c38c31dc41b1b 100644 (file)
@@ -232,25 +232,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan, mark_labels_only)
 
   last_insn = delete_unreferenced_labels (f);
 
-#ifdef HAVE_return
-  if (optimize && HAVE_return)
-    {
-      /* If we fall through to the epilogue, see if we can insert a RETURN insn
-        in front of it.  If the machine allows it at this point (we might be
-        after reload for a leaf routine), it will improve optimization for it
-        to be there.  */
-      insn = get_last_insn ();
-      while (insn && GET_CODE (insn) == NOTE)
-       insn = PREV_INSN (insn);
-
-      if (insn && GET_CODE (insn) != BARRIER)
-       {
-         emit_jump_insn (gen_return ());
-         emit_barrier ();
-       }
-    }
-#endif
-
   if (noop_moves)
     delete_noop_moves (f);
 
@@ -2142,26 +2123,6 @@ jump_optimize_1 (f, cross_jump, noop_moves, after_regscan, mark_labels_only)
        }
   }
 
-#ifdef HAVE_return
-  if (HAVE_return)
-    {
-      /* If we fall through to the epilogue, see if we can insert a RETURN insn
-        in front of it.  If the machine allows it at this point (we might be
-        after reload for a leaf routine), it will improve optimization for it
-        to be there.  We do this both here and at the start of this pass since
-        the RETURN might have been deleted by some of our optimizations.  */
-      insn = get_last_insn ();
-      while (insn && GET_CODE (insn) == NOTE)
-       insn = PREV_INSN (insn);
-
-      if (insn && GET_CODE (insn) != BARRIER)
-       {
-         emit_jump_insn (gen_return ());
-         emit_barrier ();
-       }
-    }
-#endif
-
   /* CAN_REACH_END is persistent for each function.  Once set it should
      not be cleared.  This is especially true for the case where we
      delete the NOTE_FUNCTION_END note.  CAN_REACH_END is cleared by
index f068fab367beb90ae908e98d95e0c1ae28e6e6ad..15185125a316316b591a7f203ed582bd76f970e8 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1051,6 +1051,7 @@ extern rtx prev_real_insn         PARAMS ((rtx));
 extern rtx next_real_insn              PARAMS ((rtx));
 extern rtx prev_active_insn            PARAMS ((rtx));
 extern rtx next_active_insn            PARAMS ((rtx));
+extern int active_insn_p               PARAMS ((rtx));
 extern rtx prev_label                  PARAMS ((rtx));
 extern rtx next_label                  PARAMS ((rtx));
 extern rtx next_cc0_user               PARAMS ((rtx));