OSDN Git Service

* Makefile.in (distclean): Don't try to remove empty directories.
[pf3gnuchains/gcc-fork.git] / gcc / cfglayout.c
index 8a57c68..0c13c56 100644 (file)
@@ -54,7 +54,6 @@ static void change_scope (rtx, tree, tree);
 
 void verify_insn_chain (void);
 static void fixup_fallthru_exit_predecessor (void);
-static rtx duplicate_insn_chain (rtx, rtx);
 static tree insn_scope (rtx);
 static void update_unlikely_executed_notes (basic_block);
 \f
@@ -713,9 +712,15 @@ fixup_reorder_chain (void)
                  if (note
                      && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
                      && invert_jump (bb_end_insn,
-                                     label_for_bb (e_fall->dest), 0))
+                                     (e_fall->dest == EXIT_BLOCK_PTR
+                                      ? NULL_RTX
+                                      : label_for_bb (e_fall->dest)), 0))
                    {
                      e_fall->flags &= ~EDGE_FALLTHRU;
+#ifdef ENABLE_CHECKING
+                     if (!could_fall_through (e_taken->src, e_taken->dest))
+                       abort ();
+#endif
                      e_taken->flags |= EDGE_FALLTHRU;
                      update_br_prob_note (bb);
                      e = e_fall, e_fall = e_taken, e_taken = e;
@@ -730,9 +735,15 @@ fixup_reorder_chain (void)
              /* Otherwise we can try to invert the jump.  This will
                 basically never fail, however, keep up the pretense.  */
              else if (invert_jump (bb_end_insn,
-                                   label_for_bb (e_fall->dest), 0))
+                                   (e_fall->dest == EXIT_BLOCK_PTR
+                                    ? NULL_RTX
+                                    : label_for_bb (e_fall->dest)), 0))
                {
                  e_fall->flags &= ~EDGE_FALLTHRU;
+#ifdef ENABLE_CHECKING
+                 if (!could_fall_through (e_taken->src, e_taken->dest))
+                   abort ();
+#endif
                  e_taken->flags |= EDGE_FALLTHRU;
                  update_br_prob_note (bb);
                  continue;
@@ -771,7 +782,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;
        }
 
@@ -911,14 +922,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;
@@ -927,6 +944,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;
 
@@ -973,7 +1002,7 @@ cfg_layout_can_duplicate_bb_p (basic_block bb)
   return true;
 }
 
-static rtx
+rtx
 duplicate_insn_chain (rtx from, rtx to)
 {
   rtx insn, last;
@@ -1177,7 +1206,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