]> gcc.gnu.org Git - gcc.git/commitdiff
basic-block.h (basic_block): Add eh_beg, eh_end.
authorRichard Henderson <rth@cygnus.com>
Tue, 21 Sep 1999 21:15:37 +0000 (14:15 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 21 Sep 1999 21:15:37 +0000 (14:15 -0700)
        * basic-block.h (basic_block): Add eh_beg, eh_end.
        * flow.c (entry_exit_blocks): Update.
        (find_basic_blocks): Don't allocate bb_eh_end, or pass it around.
        Call new functions.
        (find_basic_blocks_1): Don't record eh_list at each bb.  Use
        lists.c functions to allocate insn lists.
        (make_edges): Use eh_beg+eh_end, not the lists.  Split out EH
        edge creation ...
        (make_eh_edge): ... here.  New.
        (move_stray_eh_region_notes): New.
        (record_active_eh_regions): New.
        (delete_unreachable_blocks): Split out block merging ...
        (try_merge_blocks): ... here.  New.
        (merge_blocks_move_predecessor_nojumps): Remove edge arg.
        Dump debugging data.
        (merge_blocks_move_successor_nojumps): Likewise.
        (merge_blocks): Use eh_beg+eh_end to validate block movement.

From-SVN: r29565

gcc/ChangeLog
gcc/basic-block.h
gcc/flow.c

index 3cf9abe92913634960b2a0925fd08b0759300533..b1034766903f3069d0cc8eaaadbdacff96da9e95 100644 (file)
@@ -1,3 +1,23 @@
+Tue Sep 21 14:14:50 1999  Richard Henderson  <rth@cygnus.com>
+
+       * basic-block.h (basic_block): Add eh_beg, eh_end.
+       * flow.c (entry_exit_blocks): Update.
+       (find_basic_blocks): Don't allocate bb_eh_end, or pass it around.
+       Call new functions.
+       (find_basic_blocks_1): Don't record eh_list at each bb.  Use
+       lists.c functions to allocate insn lists.
+       (make_edges): Use eh_beg+eh_end, not the lists.  Split out EH
+       edge creation ...
+       (make_eh_edge): ... here.  New.
+       (move_stray_eh_region_notes): New.
+       (record_active_eh_regions): New.
+       (delete_unreachable_blocks): Split out block merging ...
+       (try_merge_blocks): ... here.  New.
+       (merge_blocks_move_predecessor_nojumps): Remove edge arg.
+       Dump debugging data.
+       (merge_blocks_move_successor_nojumps): Likewise.
+       (merge_blocks): Use eh_beg+eh_end to validate block movement.
+
 Tue Sep 21 11:15:03 1999  Martin v. Löwis  <loewis@informatik.hu-berlin.de>
 
        * extend.texi (Bound member functions): Document unbound pmf
index 26b509cccf72f5b0166eaba95f06db0a318faf6d..13f8c47e080c9f9d4f4c8b0a18fa3031ee4a3bf3 100644 (file)
@@ -144,6 +144,9 @@ typedef struct basic_block_def {
   int index;
   /* The loop depth of this block plus one.  */
   int loop_depth;
+
+  /* The active eh region before head and after end.  */
+  int eh_beg, eh_end;
 } *basic_block;
 
 /* Number of basic blocks in the current function.  */
index bfdff14b828f777d7b94358dd27e04231c12ab96..b4970e3eb4b38c63686c381e8c7be62fcb7d95c1 100644 (file)
@@ -178,7 +178,8 @@ struct basic_block_def entry_exit_blocks[2] =
     NULL,                      /* global_live_at_end */
     NULL,                      /* aux */
     ENTRY_BLOCK,               /* index */
-    0                          /* loop_depth */
+    0,                         /* loop_depth */
+    -1, -1                     /* eh_beg, eh_end */
   },
   {
     NULL,                      /* head */
@@ -190,7 +191,8 @@ struct basic_block_def entry_exit_blocks[2] =
     NULL,                      /* global_live_at_end */
     NULL,                      /* aux */
     EXIT_BLOCK,                        /* index */
-    0                          /* loop_depth */
+    0,                         /* loop_depth */
+    -1, -1                     /* eh_beg, eh_end */
   }
 };
 
@@ -274,13 +276,17 @@ static bitmap uid_volatile;
 
 /* Forward declarations */
 static int count_basic_blocks          PROTO((rtx));
-static rtx find_basic_blocks_1         PROTO((rtx, rtx*));
+static rtx find_basic_blocks_1         PROTO((rtx));
 static void create_basic_block         PROTO((int, rtx, rtx, rtx));
 static void clear_edges                        PROTO((void));
-static void make_edges                 PROTO((rtx, rtx*));
+static void make_edges                 PROTO((rtx));
 static void make_edge                  PROTO((basic_block, basic_block, int));
 static void make_label_edge            PROTO((basic_block, rtx, int));
+static void make_eh_edge               PROTO((eh_nesting_info *, basic_block,
+                                              rtx, int));
 static void mark_critical_edges                PROTO((void));
+static void move_stray_eh_region_notes PROTO((void));
+static void record_active_eh_regions   PROTO((rtx));
 
 static void commit_one_edge_insertion  PROTO((edge));
 
@@ -292,8 +298,13 @@ static int delete_block                    PROTO((basic_block));
 static void expunge_block              PROTO((basic_block));
 static rtx flow_delete_insn            PROTO((rtx));
 static int can_delete_label_p          PROTO((rtx));
+static int merge_blocks_move_predecessor_nojumps PROTO((basic_block,
+                                                       basic_block));
+static int merge_blocks_move_successor_nojumps PROTO((basic_block,
+                                                     basic_block));
 static void merge_blocks_nomove                PROTO((basic_block, basic_block));
 static int merge_blocks                        PROTO((edge,basic_block,basic_block));
+static void try_merge_blocks           PROTO((void));
 static void tidy_fallthru_edge         PROTO((edge,basic_block,basic_block));
 static void calculate_loop_depth       PROTO((rtx));
 
@@ -354,7 +365,6 @@ find_basic_blocks (f, nregs, file, do_cleanup)
      FILE *file ATTRIBUTE_UNUSED;
      int do_cleanup;
 {
-  rtx *bb_eh_end;
   int max_uid;
 
   /* Flush out existing data.  */
@@ -385,11 +395,7 @@ find_basic_blocks (f, nregs, file, do_cleanup)
 
   VARRAY_BB_INIT (basic_block_info, n_basic_blocks, "basic_block_info");
 
-  /* An array to record the active exception region at the end of each
-     basic block.  It is filled in by find_basic_blocks_1 for make_edges.  */
-  bb_eh_end = (rtx *) alloca (n_basic_blocks * sizeof (rtx));
-
-  label_value_list = find_basic_blocks_1 (f, bb_eh_end);
+  label_value_list = find_basic_blocks_1 (f);
   
   /* Record the block to which an insn belongs.  */
   /* ??? This should be done another way, by which (perhaps) a label is
@@ -407,12 +413,18 @@ find_basic_blocks (f, nregs, file, do_cleanup)
 
   /* Discover the edges of our cfg.  */
 
-  make_edges (label_value_list, bb_eh_end);
+  record_active_eh_regions (f);
+  make_edges (label_value_list);
 
-  /* Delete unreachable blocks.  */
+  /* Delete unreachable blocks, then merge blocks when possible.  */
 
   if (do_cleanup)
-    delete_unreachable_blocks ();
+    {
+      delete_unreachable_blocks ();
+      move_stray_eh_region_notes ();
+      record_active_eh_regions (f);
+      try_merge_blocks ();
+    }
 
   /* Mark critical edges.  */
 
@@ -513,20 +525,13 @@ count_basic_blocks (f)
 }
 
 /* Find all basic blocks of the function whose first insn is F.
-   Store the correct data in the tables that describe the basic blocks,
-   set up the chains of references for each CODE_LABEL, and
-   delete any entire basic blocks that cannot be reached.
-
-   NONLOCAL_LABEL_LIST is a list of non-local labels in the function.  Blocks
-   that are otherwise unreachable may be reachable with a non-local goto.
 
-   BB_EH_END is an array in which we record the list of exception regions
-   active at the end of every basic block.  */
+   Collect and return a list of labels whose addresses are taken.  This
+   will be used in make_edges for use with computed gotos.  */
 
 static rtx
-find_basic_blocks_1 (f, bb_eh_end)
+find_basic_blocks_1 (f)
      rtx f;
-     rtx *bb_eh_end;
 {
   register rtx insn, next;
   int call_has_abnormal_edge = 0;
@@ -541,7 +546,7 @@ find_basic_blocks_1 (f, bb_eh_end)
      previously.  This is so that we see a NOTE_BASIC_BLOCK after we have
      closed out the previous block, so that it gets attached at the proper
      place.  Since this form should be equivalent to the previous,
-     find_basic_blocks_0 continues to use the old form as a check.  */
+     count_basic_blocks continues to use the old form as a check.  */
 
   for (insn = f; insn; insn = next)
     {
@@ -577,9 +582,13 @@ find_basic_blocks_1 (f, bb_eh_end)
 
            /* Keep a LIFO list of the currently active exception notes.  */
            if (kind == NOTE_INSN_EH_REGION_BEG)
-             eh_list = gen_rtx_INSN_LIST (VOIDmode, insn, eh_list);
+             eh_list = alloc_INSN_LIST (insn, eh_list);
            else if (kind == NOTE_INSN_EH_REGION_END)
-             eh_list = XEXP (eh_list, 1);
+             {
+               rtx t = eh_list;
+               eh_list = XEXP (eh_list, 1);
+               free_INSN_LIST_node (t);
+             }
 
            /* Look for basic block notes with which to keep the 
               basic_block_info pointers stable.  Unthread the note now;
@@ -611,7 +620,6 @@ find_basic_blocks_1 (f, bb_eh_end)
                  end = emit_insn_after (nop, end);
                }
 
-             bb_eh_end[i] = eh_list;
              create_basic_block (i++, head, end, bb_note);
              bb_note = NULL_RTX;
            }
@@ -676,7 +684,6 @@ find_basic_blocks_1 (f, bb_eh_end)
              end = insn;
 
            new_bb_exclusive:
-             bb_eh_end[i] = eh_list;
              create_basic_block (i++, head, end, bb_note);
              head = end = NULL_RTX;
              bb_note = NULL_RTX;
@@ -728,10 +735,7 @@ find_basic_blocks_1 (f, bb_eh_end)
     }
 
   if (head != NULL_RTX)
-    {
-      bb_eh_end[i] = eh_list;
-      create_basic_block (i++, head, end, bb_note);
-    }
+    create_basic_block (i++, head, end, bb_note);
 
   if (i != n_basic_blocks)
     abort ();
@@ -870,9 +874,8 @@ clear_edges ()
    the list of exception regions active at the end of the basic block.  */
 
 static void
-make_edges (label_value_list, bb_eh_end)
+make_edges (label_value_list)
      rtx label_value_list;
-     rtx *bb_eh_end;
 {
   int i;
   eh_nesting_info *eh_nest_info = init_eh_nesting_info ();
@@ -886,26 +889,11 @@ make_edges (label_value_list, bb_eh_end)
   for (i = 0; i < n_basic_blocks; ++i)
     {
       basic_block bb = BASIC_BLOCK (i);
-      rtx insn, x, eh_list;
+      rtx insn, x;
       enum rtx_code code;
       int force_fallthru = 0;
 
-      /* If we have asynchronous exceptions, scan the notes for all exception
-        regions active in the block.  In the normal case, we only need the
-        one active at the end of the block, which is bb_eh_end[i].  */
-
-      eh_list = bb_eh_end[i];
-      if (asynchronous_exceptions)
-       {
-         for (insn = bb->end; insn != bb->head; insn = PREV_INSN (insn))
-           {
-             if (GET_CODE (insn) == NOTE
-                 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
-               eh_list = gen_rtx_INSN_LIST (VOIDmode, insn, eh_list);
-           }
-       }
-
-      /* Now examine the last instruction of the block, and discover the
+      /* Examine the last instruction of the block, and discover the
         ways we can leave the block.  */
 
       insn = bb->end;
@@ -984,20 +972,27 @@ make_edges (label_value_list, bb_eh_end)
 
       if (code == CALL_INSN || asynchronous_exceptions)
        {
-         int is_call = (code == CALL_INSN ? EDGE_ABNORMAL_CALL : 0);
-         handler_info **handler_list;
-         int eh_region = -1;
-         int num;
-
-         if (eh_list)
-           eh_region = NOTE_EH_HANDLER (XEXP (eh_list, 0));
-
-         num = reachable_handlers (eh_region, eh_nest_info,
-                                   insn, &handler_list);
-         for ( ; num > 0; num--)
+         /* If there's an EH region active at the end of a block,
+            add the appropriate edges.  */
+         if (bb->eh_end >= 0)
+           make_eh_edge (eh_nest_info, bb, insn, bb->eh_end);
+
+         /* If we have asynchronous exceptions, do the same for *all*
+            exception regions active in the block.  */
+         if (asynchronous_exceptions
+             && bb->eh_beg != bb->eh_end)
            {
-             make_label_edge (bb, handler_list[num - 1]->handler_label,
-                              EDGE_ABNORMAL | EDGE_EH | is_call);
+             if (bb->eh_beg >= 0)
+               make_eh_edge (eh_nest_info, bb, NULL_RTX, bb->eh_beg);
+
+             for (x = bb->head; x != bb->end; x = PREV_INSN (x))
+               if (GET_CODE (x) == NOTE
+                   && (NOTE_LINE_NUMBER (x) == NOTE_INSN_EH_REGION_BEG
+                       || NOTE_LINE_NUMBER (x) == NOTE_INSN_EH_REGION_END))
+                 {
+                   int region = NOTE_EH_HANDLER (x);
+                   make_eh_edge (eh_nest_info, bb, NULL_RTX, region);
+                 }
            }
 
          if (code == CALL_INSN && nonlocal_goto_handler_labels)
@@ -1096,7 +1091,119 @@ make_label_edge (src, label, flags)
   make_edge (src, BLOCK_FOR_INSN (label), flags);
 }
 
+/* Create the edges generated by INSN in REGION.  */
+
+static void
+make_eh_edge (eh_nest_info, src, insn, region)
+     eh_nesting_info *eh_nest_info;
+     basic_block src;
+     rtx insn;
+     int region;
+{
+  handler_info **handler_list;
+  int num, is_call;
+
+  is_call = (insn && GET_CODE (insn) == CALL_INSN ? EDGE_ABNORMAL_CALL : 0);
+  num = reachable_handlers (region, eh_nest_info, insn, &handler_list);
+  while (--num >= 0)
+    {
+      make_label_edge (src, handler_list[num]->handler_label,
+                      EDGE_ABNORMAL | EDGE_EH | is_call);
+    }
+}
+
+/* EH_REGION notes appearing between basic blocks is ambiguous, and even
+   dangerous if we intend to move basic blocks around.  Move such notes
+   into the following block.  */
+
+static void
+move_stray_eh_region_notes ()
+{
+  int i;
+  basic_block b1, b2;
+
+  if (n_basic_blocks < 2)
+    return;
+
+  b2 = BASIC_BLOCK (n_basic_blocks - 1);
+  for (i = n_basic_blocks - 2; i >= 0; --i, b2 = b1)
+    {
+      rtx insn, next, list = NULL_RTX;
+
+      b1 = BASIC_BLOCK (i);
+      for (insn = NEXT_INSN (b1->end); insn != b2->head; insn = next)
+       {
+         next = NEXT_INSN (insn);
+         if (GET_CODE (insn) == NOTE
+             && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
+                 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
+           {
+             /* Unlink from the insn chain.  */
+             NEXT_INSN (PREV_INSN (insn)) = next;
+             PREV_INSN (next) = PREV_INSN (insn);
+
+             /* Queue it.  */
+             NEXT_INSN (insn) = list;
+             list = insn;
+           }
+       }
+
+      if (list == NULL_RTX)
+       continue;
+
+      /* Find where to insert these things.  */
+      insn = b2->head;
+      if (GET_CODE (insn) == CODE_LABEL)
+       insn = NEXT_INSN (insn);
+
+      while (list)
+       {
+         next = NEXT_INSN (list);
+         add_insn_after (list, insn);
+         list = next;
+       }
+    }
+}
+
+/* Recompute eh_beg/eh_end for each basic block.  */
+
+static void
+record_active_eh_regions (f)
+     rtx f;
+{
+  rtx insn, eh_list = NULL_RTX;
+  int i = 0;
+  basic_block bb = BASIC_BLOCK (0);
+
+  for (insn = f; insn ; insn = NEXT_INSN (insn))
+    {
+      if (bb->head == insn)
+       bb->eh_beg = (eh_list ? NOTE_EH_HANDLER (XEXP (eh_list, 0)) : -1);
+
+      if (GET_CODE (insn) == NOTE)
+       {
+         int kind = NOTE_LINE_NUMBER (insn);
+         if (kind == NOTE_INSN_EH_REGION_BEG)
+           eh_list = alloc_INSN_LIST (insn, eh_list);
+         else if (kind == NOTE_INSN_EH_REGION_END)
+           {
+             rtx t = XEXP (eh_list, 1);
+             free_INSN_LIST_node (eh_list);
+             eh_list = t;
+           }
+       }
+
+      if (bb->end == insn)
+       {
+         bb->eh_end = (eh_list ? NOTE_EH_HANDLER (XEXP (eh_list, 0)) : -1);
+         i += 1;
+         bb = BASIC_BLOCK (i);
+       }
+    }
+}
+
 /* Identify critical edges and set the bits appropriately.  */
+
 static void
 mark_critical_edges ()
 {
@@ -1575,31 +1682,6 @@ delete_unreachable_blocks ()
        tidy_fallthru_edge (s, b, c);
     }
 
-  /* Attempt to merge blocks as made possible by edge removal.  If a block
-     has only one successor, and the successor has only one predecessor, 
-     they may be combined.  */
-
-  for (i = 0; i < n_basic_blocks; )
-    {
-      basic_block c, b = BASIC_BLOCK (i);
-      edge s;
-
-      /* A loop because chains of blocks might be combineable.  */
-      while ((s = b->succ) != NULL
-            && s->succ_next == NULL
-            && (s->flags & EDGE_EH) == 0
-            && (c = s->dest) != EXIT_BLOCK_PTR
-            && c->pred->pred_next == NULL
-            /* If the jump insn has side effects, we can't kill the edge.  */
-            && (GET_CODE (b->end) != JUMP_INSN
-                || onlyjump_p (b->end))
-            && merge_blocks (s, b, c))
-       continue;
-
-      /* Don't get confused by the index shift caused by deleting blocks.  */
-      i = b->index + 1;
-    }
-
   /* If we deleted an exception handler, we may have EH region begin/end
      blocks to remove as well. */
   if (deleted_handler)
@@ -1858,8 +1940,7 @@ can_delete_label_p (label)
    any jumps (aside from the jump from A to B).  */
 
 static int
-merge_blocks_move_predecessor_nojumps (e, a, b)
-     edge e;
+merge_blocks_move_predecessor_nojumps (a, b)
      basic_block a, b;
 {
   rtx start, end, insertpoint, barrier;
@@ -1896,6 +1977,13 @@ merge_blocks_move_predecessor_nojumps (e, a, b)
 
   /* Now blocks A and B are contiguous.  Merge them.  */
   merge_blocks_nomove (a, b);
+
+  if (rtl_dump_file)
+    {
+      fprintf (rtl_dump_file, "Moved block %d before %d and merged.\n",
+              a->index, b->index);
+    }
+
   return 1;
 }
 
@@ -1904,8 +1992,7 @@ merge_blocks_move_predecessor_nojumps (e, a, b)
    any jumps (aside from the jump from A to B).  */
 
 static int
-merge_blocks_move_successor_nojumps (e, a, b)
-     edge e;
+merge_blocks_move_successor_nojumps (a, b)
      basic_block a, b;
 {
   rtx start, end, insertpoint, barrier;
@@ -1942,6 +2029,13 @@ merge_blocks_move_successor_nojumps (e, a, b)
 
   /* Now blocks A and B are contiguous.  Merge them.  */
   merge_blocks_nomove (a, b);
+
+  if (rtl_dump_file)
+    {
+      fprintf (rtl_dump_file, "Moved block %d after %d and merged.\n",
+              b->index, a->index);
+    }
+
   return 1;
 }
 
@@ -2042,35 +2136,46 @@ merge_blocks (e, b, c)
      basic_block b, c;
 {
   /* If B has a fallthru edge to C, no need to move anything.  */
-  if (!(e->flags & EDGE_FALLTHRU))
+  if (e->flags & EDGE_FALLTHRU)
     {
-      edge tmp_edge;
-      int c_has_outgoing_fallthru;
-      int b_has_incoming_fallthru;
-
-      /* ??? From here on out we must make sure to not munge nesting
-        of exception regions and lexical blocks.
+      /* If a label still appears somewhere and we cannot delete the label,
+        then we cannot merge the blocks.  The edge was tidied already.  */
 
-        A few notes on the subject:
+      rtx insn, stop = NEXT_INSN (c->head);
+      for (insn = NEXT_INSN (b->end); insn != stop; insn = NEXT_INSN (insn))
+       if (GET_CODE (insn) == CODE_LABEL && !can_delete_label_p (insn))
+         return 0;
 
-         Not only do we have to be careful not to lose the nesting of
-         exception regions or lexical blocks, we also have to be careful
-         about merging blocks which are in different EH regions.
+      merge_blocks_nomove (b, c);
 
-         A call that throws may end a block.  The insn to copy the return
-         value from its hard reg into a pseudo could end up in a
-         different block than the call.  Moving either block might cause
-         problems for SMALL_REGISTER_CLASS machines.
+      if (rtl_dump_file)
+       {
+         fprintf (rtl_dump_file, "Merged %d and %d without moving.\n",
+                  b->index, c->index);
+       }
 
-         A throw/catch edge (or any abnormal edge) should be rarely
-         executed and we may want to treat blocks which have two out
-         edges, one normal, one abnormal as only having one edge for
-         block merging purposes.
+      return 1;
+    }
+  else
+    {
+      edge tmp_edge;
+      basic_block d;
+      int c_has_outgoing_fallthru;
+      int b_has_incoming_fallthru;
 
-         For now we avoid the EH issues by not allowing any physical
-         block movement when exception handling is enabled.  */
-      if (flag_exceptions)
-       return 0;
+      /* We must make sure to not munge nesting of exception regions,
+        lexical blocks, and loop notes.
+  
+        The first is taken care of by requiring that the active eh
+        region at the end of one block always matches the active eh
+        region at the beginning of the next block.
+  
+        The later two are taken care of by squeezing out all the notes.  */
+  
+      /* ???  A throw/catch edge (or any abnormal edge) should be rarely
+        executed and we may want to treat blocks which have two out
+        edges, one normal, one abnormal as only having one edge for
+        block merging purposes.  */
 
       for (tmp_edge = c->succ; tmp_edge ; tmp_edge = tmp_edge->succ_next)
        if (tmp_edge->flags & EDGE_FALLTHRU)
@@ -2082,33 +2187,66 @@ merge_blocks (e, b, c)
          break;
       b_has_incoming_fallthru = (tmp_edge != NULL);
 
-      /* If B does not have an incoming fallthru, then it can be moved
-        immediately before C without introducing or modifying jumps.
-
-        Else if C does not have an outgoing fallthru, then it can be moved
-        immediately after B without introducing or modifying jumps.
+      /* If B does not have an incoming fallthru, and the exception regions
+        match, then it can be moved immediately before C without introducing
+        or modifying jumps.  */
+      d = BASIC_BLOCK (c->index - 1);
+      if (! b_has_incoming_fallthru
+         && d->eh_end == b->eh_beg
+         && b->eh_end == c->eh_beg)
+       return merge_blocks_move_predecessor_nojumps (b, c);
+
+      /* Otherwise, we're going to try to move C after B.  Make sure the
+        exception regions match.  */
+      d = BASIC_BLOCK (b->index + 1);
+      if (b->eh_end == c->eh_beg
+         && c->eh_end == d->eh_beg)
+       {
+         /* If C does not have an outgoing fallthru, then it can be moved
+            immediately after B without introducing or modifying jumps.  */
+         if (! c_has_outgoing_fallthru)
+           return merge_blocks_move_successor_nojumps (b, c);
+
+         /* Otherwise, we'll need to insert an extra jump, and possibly
+            a new block to contain it.  */
+         /* ??? Not implemented yet.  */
+       }
 
-        Else move C after B, which will likely require insertion of a
-        new jump.  ??? Not implemented yet.  */
-      if (! b_has_incoming_fallthru)
-       return merge_blocks_move_predecessor_nojumps (e, b, c);
-      else if (! c_has_outgoing_fallthru)
-       return merge_blocks_move_successor_nojumps (e, b, c);
-      else
-       return 0;
+      return 0;
     }
+}
 
-  /* If a label still appears somewhere and we cannot delete the label,
-     then we cannot merge the blocks.  The edge was tidied already.  */
-  {
-    rtx insn, stop = NEXT_INSN (c->head);
-    for (insn = NEXT_INSN (b->end); insn != stop; insn = NEXT_INSN (insn))
-      if (GET_CODE (insn) == CODE_LABEL && !can_delete_label_p (insn))
-       return 0;
-  }
+/* Top level driver for merge_blocks.  */
 
-  merge_blocks_nomove (b, c);
-  return 1;
+static void
+try_merge_blocks ()
+{
+  int i;
+
+  /* Attempt to merge blocks as made possible by edge removal.  If a block
+     has only one successor, and the successor has only one predecessor, 
+     they may be combined.  */
+
+  for (i = 0; i < n_basic_blocks; )
+    {
+      basic_block c, b = BASIC_BLOCK (i);
+      edge s;
+
+      /* A loop because chains of blocks might be combineable.  */
+      while ((s = b->succ) != NULL
+            && s->succ_next == NULL
+            && (s->flags & EDGE_EH) == 0
+            && (c = s->dest) != EXIT_BLOCK_PTR
+            && c->pred->pred_next == NULL
+            /* If the jump insn has side effects, we can't kill the edge.  */
+            && (GET_CODE (b->end) != JUMP_INSN
+                || onlyjump_p (b->end))
+            && merge_blocks (s, b, c))
+       continue;
+
+      /* Don't get confused by the index shift caused by deleting blocks.  */
+      i = b->index + 1;
+    }
 }
 
 /* The given edge should potentially a fallthru edge.  If that is in
This page took 0.099953 seconds and 5 git commands to generate.