basic-block.h (could_fall_through): Declare.
authorJ"orn Rennecke <joern.rennecke@superh.com>
Mon, 14 Jun 2004 12:09:08 +0000 (12:09 +0000)
committerJoern Rennecke <amylaar@gcc.gnu.org>
Mon, 14 Jun 2004 12:09:08 +0000 (13:09 +0100)
* basic-block.h (could_fall_through): Declare.
* cfganal.c (can_fallthru): Succeed if the target is EXIT_BLOCK_PTR.
Fail if the source already has a fallthrough edge to the exit
block pointer.
(could_fall_through): New function.
* cfgbuild.c (make_edges): Check if we already have a fallthrough
edge to the exit block pointer.
* cfglayout.c (fixup_fallthru_exit_predecessor): Check that it is
not called before reload has completed.
Handle special case of first block having a fall-through exit edge.
(cfg_layout_finalize): Don't call it before reload or if we have
rtl epilogues.
(fixup_reorder_chain): A fall through to the exit block does not
require the block to come last.  Add sanity checks.
* cfgrtl.c (rtl_split_edge): Add special handling of fall through
edges to the exit block.
* function.c (cfglayout.h): #include.
(thread_prologue_and_epilogue_insns): If we have neither return nor
epilogue, but a fall through to the exit block from mid-function,
force a non-fall-through exit.
* Makefile.in (function.o): Depend on CFGLAYOUT_H.

From-SVN: r83089

gcc/ChangeLog
gcc/Makefile.in
gcc/basic-block.h
gcc/cfganal.c
gcc/cfgbuild.c
gcc/cfglayout.c
gcc/cfgrtl.c
gcc/function.c

index 7ef4027fc7c528c45928446dddce152a023346b4..24a8365f4613e3ee88bd999e3c79f2929269263a 100644 (file)
@@ -1,3 +1,27 @@
+2004-06-14  J"orn Rennecke <joern.rennecke@superh.com>
+
+       * basic-block.h (could_fall_through): Declare.
+       * cfganal.c (can_fallthru): Succeed if the target is EXIT_BLOCK_PTR.
+       Fail if the source already has a fallthrough edge to the exit
+       block pointer.
+       (could_fall_through): New function.
+       * cfgbuild.c (make_edges): Check if we already have a fallthrough
+       edge to the exit block pointer.
+       * cfglayout.c (fixup_fallthru_exit_predecessor): Check that it is
+       not called before reload has completed.
+       Handle special case of first block having a fall-through exit edge.
+       (cfg_layout_finalize): Don't call it before reload or if we have
+       rtl epilogues.
+       (fixup_reorder_chain): A fall through to the exit block does not
+       require the block to come last.  Add sanity checks.
+       * cfgrtl.c (rtl_split_edge): Add special handling of fall through
+       edges to the exit block.
+       * function.c (cfglayout.h): #include.
+       (thread_prologue_and_epilogue_insns): If we have neither return nor
+       epilogue, but a fall through to the exit block from mid-function,
+       force a non-fall-through exit.
+       * Makefile.in (function.o): Depend on CFGLAYOUT_H.
+
 2004-06-14  Alan Modra  <amodra@bigpond.net.au>
 
        * config/rs6000/rs6000.h (ASM_CPU_SPEC): Handle -mpowerpc64 and -mcpu
index 6b25b343321ba2245293b4c32dbe23ed947c7ed9..0e94fd630f9e1901ac52a7a0e2cff57c3ee2bd9d 100644 (file)
@@ -1759,7 +1759,8 @@ varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_
    flags.h function.h $(EXPR_H) hard-reg-set.h $(REGS_H) \
    output.h c-pragma.h toplev.h xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
    $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h real.h
-function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
+function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+   $(TREE_H) $(CFGLAYOUT_H) \
    flags.h function.h $(EXPR_H) $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h \
    insn-config.h $(RECOG_H) output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) \
    $(TM_P_H) langhooks.h gt-function.h $(TARGET_H) basic-block.h
index 02ca28180ab0e9e326b5578ff2061f31de385268..97f71efef4cdb28781a20c2784db21aee63ef8a0 100644 (file)
@@ -629,6 +629,7 @@ extern void find_sub_basic_blocks (basic_block);
 extern void find_many_sub_basic_blocks (sbitmap);
 extern void rtl_make_eh_edge (sbitmap *, basic_block, rtx);
 extern bool can_fallthru (basic_block, basic_block);
+extern bool could_fall_through (basic_block, basic_block);
 extern void flow_nodes_print (const char *, const sbitmap, FILE *);
 extern void flow_edge_list_print (const char *, const edge *, int, FILE *);
 extern void alloc_aux_for_block (basic_block, int);
index 1a7d280513f7bc1f693ac128dbfa32302d3bf972..c8675dca6e26cd86fb94dc4913769f16ff950ea8 100644 (file)
@@ -103,17 +103,42 @@ bool
 can_fallthru (basic_block src, basic_block target)
 {
   rtx insn = BB_END (src);
-  rtx insn2 = target == EXIT_BLOCK_PTR ? NULL : BB_HEAD (target);
+  rtx insn2;
+  edge e;
 
+  if (target == EXIT_BLOCK_PTR)
+    return true;
   if (src->next_bb != target)
     return 0;
+  for (e = src->succ; e; e = e->succ_next)
+    if (e->dest == EXIT_BLOCK_PTR
+       && e->flags & EDGE_FALLTHRU)
+    return 0;
 
+  insn2 = BB_HEAD (target);
   if (insn2 && !active_insn_p (insn2))
     insn2 = next_active_insn (insn2);
 
   /* ??? Later we may add code to move jump tables offline.  */
   return next_active_insn (insn) == insn2;
 }
+
+/* Return nonzero if we could reach target from src by falling through,
+   if the target was made adjacent.  If we already have a fall-through
+   edge to the exit block, we can't do that.  */
+bool
+could_fall_through (basic_block src, basic_block target)
+{
+  edge e;
+
+  if (target == EXIT_BLOCK_PTR)
+    return true;
+  for (e = src->succ; e; e = e->succ_next)
+    if (e->dest == EXIT_BLOCK_PTR
+       && e->flags & EDGE_FALLTHRU)
+    return 0;
+  return true;
+}
 \f
 /* Mark the back edges in DFS traversal.
    Return nonzero if a loop (natural or otherwise) is present.
index 0cef94eafd3c8f756a665ac52ce33cb1114cda99..8402dad578f8840f1a9cbb687c43af5de49b65e9 100644 (file)
@@ -267,6 +267,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
       rtx insn, x;
       enum rtx_code code;
       int force_fallthru = 0;
+      edge e;
 
       if (GET_CODE (BB_HEAD (bb)) == CODE_LABEL
          && LABEL_ALT_ENTRY_P (BB_HEAD (bb)))
@@ -389,6 +390,12 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
 
       /* Find out if we can drop through to the next block.  */
       insn = NEXT_INSN (insn);
+      for (e = bb->succ; e; e = e->succ_next)
+       if (e->dest == EXIT_BLOCK_PTR && e->flags & EDGE_FALLTHRU)
+         {
+           insn = 0;
+           break;
+         }
       while (insn
             && GET_CODE (insn) == NOTE
             && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
index 899aa1a566518c01942cca65d7ecd8c33fbe62f7..66742686e1625577a01179955c6fafb7e551fef2 100644 (file)
@@ -714,6 +714,10 @@ fixup_reorder_chain (void)
                      && invert_jump (bb_end_insn,
                                      label_for_bb (e_fall->dest), 0))
                    {
+#ifdef ENABLE_CHECKING
+                     if (!could_fall_through (e_taken->src, e_taken->dest))
+                       abort ();
+#endif
                      e_fall->flags &= ~EDGE_FALLTHRU;
                      e_taken->flags |= EDGE_FALLTHRU;
                      update_br_prob_note (bb);
@@ -731,6 +735,10 @@ fixup_reorder_chain (void)
              else if (invert_jump (bb_end_insn,
                                    label_for_bb (e_fall->dest), 0))
                {
+#ifdef ENABLE_CHECKING
+                 if (!could_fall_through (e_taken->src, e_taken->dest))
+                   abort ();
+#endif
                  e_fall->flags &= ~EDGE_FALLTHRU;
                  e_taken->flags |= EDGE_FALLTHRU;
                  update_br_prob_note (bb);
@@ -770,7 +778,7 @@ fixup_reorder_chain (void)
            continue;
 
          /* A fallthru to exit block.  */
-         if (!bb->rbi->next && e_fall->dest == EXIT_BLOCK_PTR)
+         if (e_fall->dest == EXIT_BLOCK_PTR)
            continue;
        }
 
@@ -910,14 +918,20 @@ verify_insn_chain (void)
     abort ();
 }
 \f
-/* The block falling through to exit must be the last one in the
-   reordered chain.  Ensure that this condition is met.  */
+/* If we have assembler epilogues, the block falling through to exit must
+   be the last one in the reordered chain when we reach final.  Ensure
+   that this condition is met.  */
 static void
 fixup_fallthru_exit_predecessor (void)
 {
   edge e;
   basic_block bb = NULL;
 
+  /* This transformation is not valid before reload, because we might separate
+     a call from the instruction that copies the return value.  */
+  if (! reload_completed)
+    abort ();
+
   for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
     if (e->flags & EDGE_FALLTHRU)
       bb = e->src;
@@ -926,6 +940,18 @@ fixup_fallthru_exit_predecessor (void)
     {
       basic_block c = ENTRY_BLOCK_PTR->next_bb;
 
+      /* If the very first block is the one with the fall-through exit
+        edge, we have to split that block.  */
+      if (c == bb)
+       {
+         bb = split_block (bb, NULL)->dest;
+         initialize_bb_rbi (bb);
+         bb->rbi->next = c->rbi->next;
+         c->rbi->next = bb;
+         bb->rbi->footer = c->rbi->footer;
+         c->rbi->footer = NULL;
+       }
+
       while (c->rbi->next != bb)
        c = c->rbi->next;
 
@@ -1176,7 +1202,12 @@ cfg_layout_finalize (void)
   verify_flow_info ();
 #endif
   rtl_register_cfg_hooks ();
-  fixup_fallthru_exit_predecessor ();
+  if (reload_completed
+#ifdef HAVE_epilogue
+      && !HAVE_epilogue
+#endif
+      )
+    fixup_fallthru_exit_predecessor ();
   fixup_reorder_chain ();
 
 #ifdef ENABLE_CHECKING
index cdfde6fba05f2fc0cc8daf2bd55659bf612fb5a2..6e22d80ac84cfd676ff7faed77b2c38949f7bec2 100644 (file)
@@ -1336,7 +1336,19 @@ rtl_split_edge (edge edge_in)
   else
     before = NULL_RTX;
 
-  bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
+  /* If this is a fall through edge to the exit block, the blocks might be
+     not adjacent, and the right place is the after the source.  */
+  if (edge_in->flags & EDGE_FALLTHRU && edge_in->dest == EXIT_BLOCK_PTR)
+    {
+      before = NEXT_INSN (BB_END (edge_in->src));
+      if (before
+         && GET_CODE (before) == NOTE
+         && NOTE_LINE_NUMBER (before) == NOTE_INSN_LOOP_END)
+       before = NEXT_INSN (before);
+      bb = create_basic_block (before, NULL, edge_in->src);
+    }
+  else
+    bb = create_basic_block (before, NULL, edge_in->dest->prev_bb);
 
   /* ??? This info is likely going to be out of date very soon.  */
   if (edge_in->dest->global_live_at_start)
index 00c56e322af369f773a701c0f374c1382d25ff8e..b59da9a4160732a6ca6fd79c80dd9c5baee23203 100644 (file)
@@ -63,6 +63,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "integrate.h"
 #include "langhooks.h"
 #include "target.h"
+#include "cfglayout.h"
 
 #ifndef LOCAL_ALIGNMENT
 #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
@@ -7558,20 +7559,20 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
        }
     }
 #endif
+  /* Find the edge that falls through to EXIT.  Other edges may exist
+     due to RETURN instructions, but those don't need epilogues.
+     There really shouldn't be a mixture -- either all should have
+     been converted or none, however...  */
+
+  for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+    if (e->flags & EDGE_FALLTHRU)
+      break;
+  if (e == NULL)
+    goto epilogue_done;
+
 #ifdef HAVE_epilogue
   if (HAVE_epilogue)
     {
-      /* Find the edge that falls through to EXIT.  Other edges may exist
-        due to RETURN instructions, but those don't need epilogues.
-        There really shouldn't be a mixture -- either all should have
-        been converted or none, however...  */
-
-      for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
-       if (e->flags & EDGE_FALLTHRU)
-         break;
-      if (e == NULL)
-       goto epilogue_done;
-
       start_sequence ();
       epilogue_end = emit_note (NOTE_INSN_EPILOGUE_BEG);
 
@@ -7597,7 +7598,26 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
       insert_insn_on_edge (seq, e);
       inserted = 1;
     }
+  else
 #endif
+    {
+      basic_block cur_bb;
+
+      if (! next_active_insn (BB_END (e->src)))
+       goto epilogue_done;
+      /* We have a fall-through edge to the exit block, the source is not
+         at the end of the function, and there will be an assembler epilogue
+         at the end of the function.
+         We can't use force_nonfallthru here, because that would try to
+         use return.  Inserting a jump 'by hand' is extremely messy, so
+        we take advantage of cfg_layout_finalize using
+       fixup_fallthru_exit_predecessor.  */
+      cfg_layout_initialize ();
+      FOR_EACH_BB (cur_bb)
+       if (cur_bb->index >= 0 && cur_bb->next_bb->index >= 0)
+         cur_bb->rbi->next = cur_bb->next_bb;
+      cfg_layout_finalize ();
+    }
 epilogue_done:
 
   if (inserted)