basic-block.h (BB_REACHABLE): Renumber.
authorJan Hubicka <jh@suse.cz>
Thu, 28 Feb 2002 10:11:01 +0000 (10:11 +0000)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 28 Feb 2002 10:11:01 +0000 (10:11 +0000)
* basic-block.h (BB_REACHABLE): Renumber.
(BB_DIRTY, BB_NEW): New flags.
(clear_bb_flags): Declare.
(update_life_info_in_dirty_blocks): Declare.
* cfg.c (clear_bb_flags): New function.
* cfgrtl.c (create_basic_block_structure): Set flags to BB_NEW.
* emit-rtl.c (add_insn_after, add_insn_before, remove_insn,
reorder_insns, emit_insn_after): Mark block as dirty.
* flow.c (update_life_info): Fix clearing of PROP_LOG_LINKS.
(update_life_info_in_dirty_blocks): New function.
* recog.c (apply_change_group): Dirtify block.

* cse.c (cse_insn): Reorder emitting of jump insn to keep
cfg consistent.
* gcse.c (delete_null_pointer_checks): Likewise.

* toplev.c (dump_file_index): Move cse2 after bp,
add DFI_null
(dump_file_info): Similary.
(rest_of_compilation): Avoid most of CFG rebuilds;
do first if converision after null pointer checks, do cse2
after branch prediction; avoid full liveness rebuild after
initializing subregs.
* invoke.texi (-d options): Document -du, renumber.

* cfgcleanup.c (bb_flags): Remove BB_UPDATE_LIFE.
(notice_new_block): Do not set BB_UPDATE_LIFE.
(try_forward_edges, merge_blocks_move_predecessor_nojumps,
 merge_blocks_move_successor_nojumps, merge_blocks,
 try_crossjump_to_edge): Likewise.
(try_optimize_cfg): Likewise; use update_life_info_in_dirty_blocks.
* cfgrtl.c (merge_blocks_nomove): Copy b's flags to a.
* ifcvt.c (SET_UPDATE_LIFE, UPDATE_LIFE): Kill.
(merge_of_block): Do not use life_data_ok.
(find_if_case_1): Do not use SET_UPDATE_LIFE.
(if_convert): Use BB_DIRTY mechanizm to update life.
* lcm.c (optimize_mode_switching): Update
update_life_info_in_dirty_blocks

From-SVN: r50127

14 files changed:
gcc/ChangeLog
gcc/basic-block.h
gcc/cfg.c
gcc/cfgcleanup.c
gcc/cfgrtl.c
gcc/cse.c
gcc/doc/invoke.texi
gcc/emit-rtl.c
gcc/flow.c
gcc/gcse.c
gcc/ifcvt.c
gcc/lcm.c
gcc/recog.c
gcc/toplev.c

index 3074e4b..d757905 100644 (file)
@@ -1,3 +1,44 @@
+Don Feb 28 11:07:36 CET 2002  Jan Hubicka  <jh@suse.cz>
+
+       * basic-block.h (BB_REACHABLE): Renumber.
+       (BB_DIRTY, BB_NEW): New flags.
+       (clear_bb_flags): Declare.
+       (update_life_info_in_dirty_blocks): Declare.
+       * cfg.c (clear_bb_flags): New function.
+       * cfgrtl.c (create_basic_block_structure): Set flags to BB_NEW.
+       * emit-rtl.c (add_insn_after, add_insn_before, remove_insn,
+       reorder_insns, emit_insn_after): Mark block as dirty.
+       * flow.c (update_life_info): Fix clearing of PROP_LOG_LINKS.
+       (update_life_info_in_dirty_blocks): New function.
+       * recog.c (apply_change_group): Dirtify block.
+
+       * cse.c (cse_insn): Reorder emitting of jump insn to keep
+       cfg consistent.
+       * gcse.c (delete_null_pointer_checks): Likewise.
+
+       * toplev.c (dump_file_index): Move cse2 after bp,
+       add DFI_null
+       (dump_file_info): Similary.
+       (rest_of_compilation): Avoid most of CFG rebuilds;
+       do first if converision after null pointer checks, do cse2
+       after branch prediction; avoid full liveness rebuild after
+       initializing subregs.
+       * invoke.texi (-d options): Document -du, renumber.
+
+       * cfgcleanup.c (bb_flags): Remove BB_UPDATE_LIFE.
+       (notice_new_block): Do not set BB_UPDATE_LIFE.
+       (try_forward_edges, merge_blocks_move_predecessor_nojumps,
+        merge_blocks_move_successor_nojumps, merge_blocks,
+        try_crossjump_to_edge): Likewise.
+       (try_optimize_cfg): Likewise; use update_life_info_in_dirty_blocks.
+       * cfgrtl.c (merge_blocks_nomove): Copy b's flags to a.
+       * ifcvt.c (SET_UPDATE_LIFE, UPDATE_LIFE): Kill.
+       (merge_of_block): Do not use life_data_ok.
+       (find_if_case_1): Do not use SET_UPDATE_LIFE.
+       (if_convert): Use BB_DIRTY mechanizm to update life.
+       * lcm.c (optimize_mode_switching): Update
+       update_life_info_in_dirty_blocks
+
 2002-02-28  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * Makefile.in (integrate.o): Update.
index 1bc1d78..39e24c8 100644 (file)
@@ -221,7 +221,9 @@ typedef struct basic_block_def {
 #define BB_FREQ_MAX 10000
 
 /* Masks for basic_block.flags.  */
-#define BB_REACHABLE           1
+#define BB_DIRTY               1
+#define BB_NEW                 2
+#define BB_REACHABLE           4
 
 /* Number of basic blocks in the current function.  */
 
@@ -311,6 +313,7 @@ extern void redirect_edge_pred              PARAMS ((edge, basic_block));
 extern basic_block create_basic_block_structure PARAMS ((int, rtx, rtx, rtx));
 extern basic_block create_basic_block  PARAMS ((int, rtx, rtx));
 extern int flow_delete_block           PARAMS ((basic_block));
+extern void clear_bb_flags             PARAMS ((void));
 extern void merge_blocks_nomove                PARAMS ((basic_block, basic_block));
 extern void tidy_fallthru_edge         PARAMS ((edge, basic_block,
                                                 basic_block));
@@ -587,6 +590,8 @@ enum update_life_extent
 extern void life_analysis      PARAMS ((rtx, FILE *, int));
 extern void update_life_info   PARAMS ((sbitmap, enum update_life_extent,
                                         int));
+extern void update_life_info_in_dirty_blocks PARAMS ((enum update_life_extent,
+                                                     int));
 extern int count_or_remove_death_notes PARAMS ((sbitmap, int));
 extern int propagate_block     PARAMS ((basic_block, regset, regset, regset,
                                         int));
index 8adcef6..a33beff 100644 (file)
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -38,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
         dump_flow_info, debug_flow_info, dump_edge_info
      - Allocation of AUX fields for basic blocks
         alloc_aux_for_blocks, free_aux_for_blocks, alloc_aux_for_block
+     - clear_bb_flags
  */
 \f
 #include "config.h"
@@ -440,6 +441,16 @@ redirect_edge_pred (e, new_pred)
   new_pred->succ = e;
   e->src = new_pred;
 }
+
+void
+clear_bb_flags ()
+{
+  int i;
+  ENTRY_BLOCK_PTR->flags = 0;
+  EXIT_BLOCK_PTR->flags = 0;
+  for (i = 0; i < n_basic_blocks; i++)
+    BASIC_BLOCK (i)->flags = 0;
+}
 \f
 void
 dump_flow_info (file)
index d9f9cf2..017a4aa 100644 (file)
@@ -52,11 +52,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 enum bb_flags
 {
-    /* Set if life info needs to be recomputed for given BB.  */
-    BB_UPDATE_LIFE = 1,
     /* Set if BB is the forwarder block to avoid too many
        forwarder_block_p calls.  */
-    BB_FORWARDER_BLOCK = 2
+    BB_FORWARDER_BLOCK = 1
 };
 
 #define BB_FLAGS(BB) (enum bb_flags) (BB)->aux
@@ -101,7 +99,6 @@ notice_new_block (bb)
   if (!bb)
     return;
 
-  BB_SET_FLAG (bb, BB_UPDATE_LIFE);
   if (forwarder_block_p (bb))
     BB_SET_FLAG (bb, BB_FORWARDER_BLOCK);
 }
@@ -519,7 +516,6 @@ try_forward_edges (mode, b)
 
          if (!FORWARDER_BLOCK_P (b) && forwarder_block_p (b))
            BB_SET_FLAG (b, BB_FORWARDER_BLOCK);
-         BB_SET_FLAG (b, BB_UPDATE_LIFE);
 
          do
            {
@@ -663,7 +659,7 @@ merge_blocks_move_predecessor_nojumps (a, b)
   /* Scramble the insn chain.  */
   if (a->end != PREV_INSN (b->head))
     reorder_insns_nobb (a->head, a->end, PREV_INSN (b->head));
-  BB_SET_FLAG (a, BB_UPDATE_LIFE);
+  a->flags |= BB_DIRTY;
 
   if (rtl_dump_file)
     fprintf (rtl_dump_file, "Moved block %d before %d and merged.\n",
@@ -731,7 +727,6 @@ merge_blocks_move_successor_nojumps (a, b)
 
   /* Now blocks A and B are contiguous.  Merge them.  */
   merge_blocks_nomove (a, b);
-  BB_SET_FLAG (a, BB_UPDATE_LIFE);
 
   if (rtl_dump_file)
     fprintf (rtl_dump_file, "Moved block %d after %d and merged.\n",
@@ -760,12 +755,6 @@ merge_blocks (e, b, c, mode)
   if (e->flags & EDGE_FALLTHRU)
     {
       int b_index = b->index, c_index = c->index;
-      /* We need to update liveness in case C already has broken liveness
-        or B ends by conditional jump to next instructions that will be
-        removed.  */
-      if ((BB_FLAGS (c) & BB_UPDATE_LIFE)
-         || GET_CODE (b->end) == JUMP_INSN)
-       BB_SET_FLAG (b, BB_UPDATE_LIFE);
       merge_blocks_nomove (b, c);
       update_forwarder_flag (b);
 
@@ -831,8 +820,6 @@ merge_blocks (e, b, c, mode)
          bb = force_nonfallthru (b_fallthru_edge);
          if (bb)
            notice_new_block (bb);
-         else
-           BB_SET_FLAG (b_fallthru_edge->src, BB_UPDATE_LIFE);
        }
 
       merge_blocks_move_predecessor_nojumps (b, c);
@@ -1418,7 +1405,6 @@ try_crossjump_to_edge (mode, e1, e2)
     remove_edge (src1->succ);
   make_single_succ_edge (src1, redirect_to, 0);
 
-  BB_SET_FLAG (src1, BB_UPDATE_LIFE);
   update_forwarder_flag (src1);
 
   return true;
@@ -1532,6 +1518,9 @@ try_optimize_cfg (mode)
   for (i = 0; i < n_basic_blocks; i++)
     update_forwarder_flag (BASIC_BLOCK (i));
 
+  if (mode & CLEANUP_UPDATE_LIFE)
+    clear_bb_flags ();
+
   if (! (* targetm.cannot_modify_jumps_p) ())
     {
       /* Attempt to merge blocks as made possible by edge removal.  If
@@ -1633,10 +1622,7 @@ try_optimize_cfg (mode)
 
              /* Simplify branch over branch.  */
              if ((mode & CLEANUP_EXPENSIVE) && try_simplify_condjump (b))
-               {
-                 BB_SET_FLAG (b, BB_UPDATE_LIFE);
-                 changed_here = true;
-               }
+               changed_here = true;
 
              /* If B has a single outgoing edge, but uses a
                 non-trivial jump instruction without side-effects, we
@@ -1649,7 +1635,6 @@ try_optimize_cfg (mode)
                  && onlyjump_p (b->end)
                  && redirect_edge_and_branch (b->succ, b->succ->dest))
                {
-                 BB_SET_FLAG (b, BB_UPDATE_LIFE);
                  update_forwarder_flag (b);
                  changed_here = true;
                }
@@ -1689,24 +1674,9 @@ try_optimize_cfg (mode)
     remove_fake_edges ();
 
   if ((mode & CLEANUP_UPDATE_LIFE) && changed_overall)
-    {
-      bool found = 0;
-
-      blocks = sbitmap_alloc (n_basic_blocks);
-      sbitmap_zero (blocks);
-      for (i = 0; i < n_basic_blocks; i++)
-       if (BB_FLAGS (BASIC_BLOCK (i)) & BB_UPDATE_LIFE)
-         {
-           found = 1;
-           SET_BIT (blocks, i);
-         }
-
-      if (found)
-       update_life_info (blocks, UPDATE_LIFE_GLOBAL,
-                         PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
-                         | PROP_KILL_DEAD_CODE);
-      sbitmap_free (blocks);
-    }
+    update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL,
+                                     PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
+                                     | PROP_KILL_DEAD_CODE | PROP_LOG_LINKS);
 
   for (i = 0; i < n_basic_blocks; i++)
     BASIC_BLOCK (i)->aux = NULL;
index 5b99ab2..1b00a61 100644 (file)
@@ -271,6 +271,7 @@ create_basic_block_structure (index, head, end, bb_note)
   bb->head = head;
   bb->end = end;
   bb->index = index;
+  bb->flags = BB_NEW;
   BASIC_BLOCK (index) = bb;
   if (basic_block_for_insn)
     update_bb_for_insn (bb);
@@ -592,6 +593,7 @@ merge_blocks_nomove (a, b)
   for (e = b->succ; e; e = e->succ_next)
     e->src = a;
   a->succ = b->succ;
+  a->flags |= b->flags;
 
   /* B hasn't quite yet ceased to exist.  Attempt to prevent mishap.  */
   b->pred = b->succ = NULL;
index a607b0c..557e808 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -5800,10 +5800,11 @@ cse_insn (insn, libcall_insn)
             and hope for the best.  */
          if (n_sets == 1)
            {
-             rtx new = emit_jump_insn_before (gen_jump (XEXP (src, 0)), insn);
+             rtx new = emit_jump_insn_after (gen_jump (XEXP (src, 0)), insn);
 
              JUMP_LABEL (new) = XEXP (src, 0);
              LABEL_NUSES (XEXP (src, 0))++;
+             delete_insn (insn);
              insn = new;
 
              /* Now emit a BARRIER after the unconditional jump.  */
index 90df7de..8dab7a0 100644 (file)
@@ -2853,19 +2853,19 @@ Here are the possible letters for use in @var{letters}, and their meanings:
 Annotate the assembler output with miscellaneous debugging information.
 @item b
 @opindex db
-Dump after computing branch probabilities, to @file{@var{file}.14.bp}.
+Dump after computing branch probabilities, to @file{@var{file}.15.bp}.
 @item B
 @opindex dB
-Dump after block reordering, to @file{@var{file}.29.bbro}.
+Dump after block reordering, to @file{@var{file}.30.bbro}.
 @item c
 @opindex dc
-Dump after instruction combination, to the file @file{@var{file}.16.combine}.
+Dump after instruction combination, to the file @file{@var{file}.17.combine}.
 @item C
 @opindex dC
-Dump after the first if conversion, to the file @file{@var{file}.17.ce}.
+Dump after the first if conversion, to the file @file{@var{file}.18.ce}.
 @item d
 @opindex dd
-Dump after delayed branch scheduling, to @file{@var{file}.31.dbr}.
+Dump after delayed branch scheduling, to @file{@var{file}.32.dbr}.
 @item D
 @opindex dD
 Dump all macro definitions, at the end of preprocessing, in addition to
@@ -2876,28 +2876,28 @@ Dump after SSA optimizations, to @file{@var{file}.04.ssa} and
 @file{@var{file}.07.ussa}.
 @item E
 @opindex dE
-Dump after the second if conversion, to @file{@var{file}.26.ce2}.
+Dump after the second if conversion, to @file{@var{file}.27.ce2}.
 @item f
 @opindex df
-Dump after life analysis, to @file{@var{file}.15.life}.
+Dump after life analysis, to @file{@var{file}.16.life}.
 @item F
 @opindex dF
-Dump after purging @code{ADDRESSOF} codes, to @file{@var{file}.09.addressof}.
+Dump after purging @code{ADDRESSOF} codes, to @file{@var{file}.10.addressof}.
 @item g
 @opindex dg
-Dump after global register allocation, to @file{@var{file}.21.greg}.
+Dump after global register allocation, to @file{@var{file}.22.greg}.
 @item h
 @opindex dh
 Dump after finalization of EH handling code, to @file{@var{file}.02.eh}.
 @item k
 @opindex dk
-Dump after reg-to-stack conversion, to @file{@var{file}.28.stack}.
+Dump after reg-to-stack conversion, to @file{@var{file}.29.stack}.
 @item o
 @opindex do
-Dump after post-reload optimizations, to @file{@var{file}.22.postreload}.
+Dump after post-reload optimizations, to @file{@var{file}.23.postreload}.
 @item G
 @opindex dG
-Dump after GCSE, to @file{@var{file}.10.gcse}.
+Dump after GCSE, to @file{@var{file}.11.gcse}.
 @item i
 @opindex di
 Dump after sibling call optimizations, to @file{@var{file}.01.sibling}.
@@ -2906,49 +2906,52 @@ Dump after sibling call optimizations, to @file{@var{file}.01.sibling}.
 Dump after the first jump optimization, to @file{@var{file}.03.jump}.
 @item k
 @opindex dk
-Dump after conversion from registers to stack, to @file{@var{file}.32.stack}.
+Dump after conversion from registers to stack, to @file{@var{file}.33.stack}.
 @item l
 @opindex dl
-Dump after local register allocation, to @file{@var{file}.20.lreg}.
+Dump after local register allocation, to @file{@var{file}.21.lreg}.
 @item L
 @opindex dL
-Dump after loop optimization, to @file{@var{file}.11.loop}.
+Dump after loop optimization, to @file{@var{file}.12.loop}.
 @item M
 @opindex dM
 Dump after performing the machine dependent reorganisation pass, to
-@file{@var{file}.30.mach}.
+@file{@var{file}.31.mach}.
 @item n
 @opindex dn
-Dump after register renumbering, to @file{@var{file}.25.rnreg}.
+Dump after register renumbering, to @file{@var{file}.26.rnreg}.
 @item N
 @opindex dN
-Dump after the register move pass, to @file{@var{file}.18.regmove}.
+Dump after the register move pass, to @file{@var{file}.19.regmove}.
 @item r
 @opindex dr
 Dump after RTL generation, to @file{@var{file}.00.rtl}.
 @item R
 @opindex dR
-Dump after the second scheduling pass, to @file{@var{file}.27.sched2}.
+Dump after the second scheduling pass, to @file{@var{file}.28.sched2}.
 @item s
 @opindex ds
 Dump after CSE (including the jump optimization that sometimes follows
-CSE), to @file{@var{file}.08.cse}.
+CSE), to @file{@var{file}.09.cse}.
 @item S
 @opindex dS
-Dump after the first scheduling pass, to @file{@var{file}.19.sched}.
+Dump after the first scheduling pass, to @file{@var{file}.20.sched}.
 @item t
 @opindex dt
 Dump after the second CSE pass (including the jump optimization that
-sometimes follows CSE), to @file{@var{file}.12.cse2}.
+sometimes follows CSE), to @file{@var{file}.13.cse2}.
+@item u
+@opindex du
+Dump after null pointer ellimination pass ti @file{@var{file}.08.null}.
 @item w
 @opindex dw
-Dump after the second flow pass, to @file{@var{file}.23.flow2}.
+Dump after the second flow pass, to @file{@var{file}.24.flow2}.
 @item X
 @opindex dX
 Dump after SSA dead code elimination, to @file{@var{file}.06.ssadce}.
 @item z
 @opindex dz
-Dump after the peephole pass, to @file{@var{file}.24.peephole2}.
+Dump after the peephole pass, to @file{@var{file}.25.peephole2}.
 @item a
 @opindex da
 Produce all the dumps listed above.
index 492888f..e248af1 100644 (file)
@@ -3276,6 +3276,8 @@ add_insn_after (insn, after)
       && (bb = BLOCK_FOR_INSN (after)))
     {
       set_block_for_insn (insn, bb);
+      if (INSN_P (insn))
+        bb->flags |= BB_DIRTY;
       /* Should not happen as first in the BB is always
         either NOTE or LABEL.  */
       if (bb->end == after
@@ -3343,6 +3345,8 @@ add_insn_before (insn, before)
       && (bb = BLOCK_FOR_INSN (before)))
     {
       set_block_for_insn (insn, bb);
+      if (INSN_P (insn))
+        bb->flags |= BB_DIRTY;
       /* Should not happen as first in the BB is always
         either NOTE or LABEl.  */
       if (bb->head == insn
@@ -3420,6 +3424,8 @@ remove_insn (insn)
       && (unsigned int)INSN_UID (insn) < basic_block_for_insn->num_elements
       && (bb = BLOCK_FOR_INSN (insn)))
     {
+      if (INSN_P (insn))
+        bb->flags |= BB_DIRTY;
       if (bb->head == insn)
        {
          /* Never ever delete the basic block note without deleting whole basic
@@ -3497,6 +3503,7 @@ reorder_insns (from, to, after)
       && (bb = BLOCK_FOR_INSN (after)))
     {
       rtx x;
+      bb->flags |= BB_DIRTY;
  
       if (basic_block_for_insn
          && (unsigned int)INSN_UID (from) < basic_block_for_insn->num_elements
@@ -3504,6 +3511,7 @@ reorder_insns (from, to, after)
        {
          if (bb2->end == to)
            bb2->end = prev;
+         bb2->flags |= BB_DIRTY;
        }
 
       if (bb->end == after)
@@ -4028,6 +4036,7 @@ emit_insns_after (first, after)
       && (unsigned int)INSN_UID (after) < basic_block_for_insn->num_elements
       && (bb = BLOCK_FOR_INSN (after)))
     {
+      bb->flags |= BB_DIRTY;
       for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
        set_block_for_insn (last, bb);
       set_block_for_insn (last, bb);
index 6c3cd56..54985d9 100644 (file)
@@ -645,10 +645,6 @@ update_life_info (blocks, extent, prop_flags)
       && (extent == UPDATE_LIFE_LOCAL || blocks))
     abort ();
 
-  /* Clear log links in case we are asked to (re)compute them.  */
-  if (prop_flags & PROP_LOG_LINKS)
-    clear_log_links (blocks);
-
   /* For a global update, we go through the relaxation process again.  */
   if (extent != UPDATE_LIFE_LOCAL)
     {
@@ -685,6 +681,10 @@ update_life_info (blocks, extent, prop_flags)
        count_or_remove_death_notes (blocks, 1);
     }
 
+  /* Clear log links in case we are asked to (re)compute them.  */
+  if (prop_flags & PROP_LOG_LINKS)
+    clear_log_links (blocks);
+
   if (blocks)
     {
       EXECUTE_IF_SET_IN_SBITMAP (blocks, 0, i,
@@ -746,6 +746,31 @@ update_life_info (blocks, extent, prop_flags)
               ? TV_LIFE_UPDATE : TV_LIFE);
 }
 
+/* Update life information in all blocks where BB_DIRTY is set.  */
+
+void
+update_life_info_in_dirty_blocks (extent, prop_flags)
+     enum update_life_extent extent;
+     int prop_flags;
+{
+  sbitmap update_life_blocks = sbitmap_alloc (n_basic_blocks);
+  int block_num;
+  int n = 0;
+
+  sbitmap_zero (update_life_blocks);
+  for (block_num = 0; block_num < n_basic_blocks; block_num++)
+    if (BASIC_BLOCK (block_num)->flags & BB_DIRTY)
+      {
+       SET_BIT (update_life_blocks, block_num);
+       n++;
+      }
+
+  if (n)
+    update_life_info (update_life_blocks, extent, prop_flags);
+
+  sbitmap_free (update_life_blocks);
+}
+
 /* Free the variables allocated by find_basic_blocks.
 
    KEEP_HEAD_END_P is non-zero if basic_block_info is not to be freed.  */
index b7b08f2..52013c1 100644 (file)
@@ -5330,8 +5330,8 @@ delete_null_pointer_checks_1 (block_reg, nonnull_avin,
        {
          rtx new_jump;
 
-         new_jump = emit_jump_insn_before (gen_jump (JUMP_LABEL (last_insn)),
-                                           last_insn);
+         new_jump = emit_jump_insn_after (gen_jump (JUMP_LABEL (last_insn)),
+                                          last_insn);
          JUMP_LABEL (new_jump) = JUMP_LABEL (last_insn);
          LABEL_NUSES (JUMP_LABEL (new_jump))++;
          emit_barrier_after (new_jump);
index a7860e3..038b8c5 100644 (file)
@@ -113,10 +113,8 @@ static void noce_emit_move_insn            PARAMS ((rtx, rtx));
    as well as a flag indicating that the block should be rescaned for
    life analysis.  */
 
-#define SET_ORIG_INDEX(BB,I)   ((BB)->aux = (void *)((size_t)(I) << 1))
-#define ORIG_INDEX(BB)         ((size_t)(BB)->aux >> 1)
-#define SET_UPDATE_LIFE(BB)    ((BB)->aux = (void *)((size_t)(BB)->aux | 1))
-#define UPDATE_LIFE(BB)                ((size_t)(BB)->aux & 1)
+#define SET_ORIG_INDEX(BB,I)   ((BB)->aux = (void *)((size_t)(I)))
+#define ORIG_INDEX(BB)         ((size_t)(BB)->aux)
 
 \f
 /* Count the number of non-jump active insns in BB.  */
@@ -1845,7 +1843,7 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
   /* First merge TEST block into THEN block.  This is a no-brainer since
      the THEN block did not have a code label to begin with.  */
 
-  if (life_data_ok)
+  if (combo_bb->global_live_at_end)
     COPY_REG_SET (combo_bb->global_live_at_end, then_bb->global_live_at_end);
   merge_blocks_nomove (combo_bb, then_bb);
   num_removed_blocks++;
@@ -1886,7 +1884,7 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
           && join_bb != EXIT_BLOCK_PTR)
     {
       /* We can merge the JOIN.  */
-      if (life_data_ok)
+      if (combo_bb->global_live_at_end)
        COPY_REG_SET (combo_bb->global_live_at_end,
                      join_bb->global_live_at_end);
       merge_blocks_nomove (combo_bb, join_bb);
@@ -1907,9 +1905,6 @@ merge_if_block (test_bb, then_bb, else_bb, join_bb)
         tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
     }
 
-  /* Make sure we update life info properly.  */
-  SET_UPDATE_LIFE (combo_bb);
-
   num_updated_if_blocks++;
 }
 \f
@@ -2324,7 +2319,6 @@ find_if_case_1 (test_bb, then_edge, else_edge)
   /* Conversion went ok, including moving the insns and fixing up the
      jump.  Adjust the CFG to match.  */
 
-  SET_UPDATE_LIFE (test_bb);
   bitmap_operation (test_bb->global_live_at_end,
                    else_bb->global_live_at_start,
                    then_bb->global_live_at_end, BITMAP_IOR);
@@ -2333,10 +2327,7 @@ find_if_case_1 (test_bb, then_edge, else_edge)
   /* Make rest of code believe that the newly created block is the THEN_BB
      block we are going to remove.  */
   if (new_bb)
-    {
-      new_bb->aux = then_bb->aux;
-      SET_UPDATE_LIFE (then_bb);
-    }
+    new_bb->aux = then_bb->aux;
   flow_delete_block (then_bb);
   /* We've possibly created jump to next insn, cleanup_cfg will solve that
      later.  */
@@ -2403,7 +2394,6 @@ find_if_case_2 (test_bb, then_edge, else_edge)
   /* Conversion went ok, including moving the insns and fixing up the
      jump.  Adjust the CFG to match.  */
 
-  SET_UPDATE_LIFE (test_bb);
   bitmap_operation (test_bb->global_live_at_end,
                    then_bb->global_live_at_start,
                    else_bb->global_live_at_end, BITMAP_IOR);
@@ -2718,6 +2708,8 @@ if_convert (x_life_data_ok)
       post_dominators = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
       calculate_dominance_info (NULL, post_dominators, CDI_POST_DOMINATORS);
     }
+  if (life_data_ok)
+    clear_bb_flags ();
 
   /* Record initial block numbers.  */
   for (block_num = 0; block_num < n_basic_blocks; block_num++)
@@ -2742,28 +2734,15 @@ if_convert (x_life_data_ok)
   /* Rebuild life info for basic blocks that require it.  */
   if (num_removed_blocks && life_data_ok)
     {
-      sbitmap update_life_blocks = sbitmap_alloc (n_basic_blocks);
-      sbitmap_zero (update_life_blocks);
-
       /* If we allocated new pseudos, we must resize the array for sched1.  */
       if (max_regno < max_reg_num ())
        {
          max_regno = max_reg_num ();
          allocate_reg_info (max_regno, FALSE, FALSE);
        }
-
-      for (block_num = 0; block_num < n_basic_blocks; block_num++)
-       if (UPDATE_LIFE (BASIC_BLOCK (block_num)))
-         SET_BIT (update_life_blocks, block_num);
-
-      count_or_remove_death_notes (update_life_blocks, 1);
-      /* ??? See about adding a mode that verifies that the initial
-       set of blocks don't let registers come live.  */
-      update_life_info (update_life_blocks, UPDATE_LIFE_GLOBAL,
-                       PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
-                       | PROP_KILL_DEAD_CODE);
-
-      sbitmap_free (update_life_blocks);
+      update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+                                       PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
+                                       | PROP_KILL_DEAD_CODE);
     }
   clear_aux_for_blocks ();
 
index 0a8a7ce..f64c7ad 100644 (file)
--- a/gcc/lcm.c
+++ b/gcc/lcm.c
@@ -1031,6 +1031,7 @@ optimize_mode_switching (file)
   int max_num_modes = 0;
   bool emited = false;
 
+  clear_bb_flags ();
 #ifdef NORMAL_MODE
   /* Increment n_basic_blocks before allocating bb_info.  */
   n_basic_blocks++;
@@ -1398,16 +1399,11 @@ optimize_mode_switching (file)
   if (!need_commit && !emited)
     return 0;
 
-  /* Ideally we'd figure out what blocks were affected and start from
-     there, but this is enormously complicated by commit_edge_insertions,
-     which would screw up any indices we'd collected, and also need to
-     be involved in the update.  Bail and recompute global life info for
-     everything.  */
-
-  allocate_reg_life_data ();
-  update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
-                   (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
-                    | PROP_SCAN_DEAD_CODE | PROP_REG_INFO));
+  max_regno = max_reg_num ();
+  allocate_reg_info (max_regno, FALSE, FALSE);
+  update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+                                   (PROP_DEATH_NOTES | PROP_KILL_DEAD_CODE
+                                    | PROP_SCAN_DEAD_CODE));
 
   return 1;
 }
index 6039c4d..69f75b7 100644 (file)
@@ -392,6 +392,17 @@ apply_change_group ()
 
   if (i == num_changes)
     {
+      basic_block bb;
+
+      for (i = 0; i < num_changes; i++)
+       if (changes[i].object
+           && INSN_P (changes[i].object)
+           && basic_block_for_insn
+           && ((unsigned int)INSN_UID (changes[i].object)
+               < basic_block_for_insn->num_elements)
+           && (bb = BLOCK_FOR_INSN (changes[i].object)))
+        bb->flags |= BB_DIRTY;
+
       num_changes = 0;
       return 1;
     }
index 9676dcd..7cf0c96 100644 (file)
@@ -240,13 +240,14 @@ enum dump_file_index
   DFI_ssa_ccp,
   DFI_ssa_dce,
   DFI_ussa,
+  DFI_null,
   DFI_cse,
   DFI_addressof,
   DFI_gcse,
   DFI_loop,
-  DFI_cse2,
   DFI_cfg,
   DFI_bp,
+  DFI_cse2,
   DFI_life,
   DFI_combine,
   DFI_ce,
@@ -272,7 +273,7 @@ enum dump_file_index
 
    Remaining -d letters:
 
-       "              o q   u     "
+       "              o q         "
        "       H JK   OPQ  TUV  YZ"
 */
 
@@ -286,13 +287,14 @@ static struct dump_file_info dump_file[DFI_MAX] =
   { "ssaccp",  'W', 1, 0, 0 },
   { "ssadce",  'X', 1, 0, 0 },
   { "ussa",    'e', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
+  { "null",    'u', 0, 0, 0 },
   { "cse",     's', 0, 0, 0 },
   { "addressof", 'F', 0, 0, 0 },
   { "gcse",    'G', 1, 0, 0 },
   { "loop",    'L', 1, 0, 0 },
-  { "cse2",    't', 1, 0, 0 },
   { "cfg",     'f', 1, 0, 0 },
   { "bp",      'b', 1, 0, 0 },
+  { "cse2",    't', 1, 0, 0 },
   { "life",    'f', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
   { "combine", 'c', 1, 0, 0 },
   { "ce",      'C', 1, 0, 0 },
@@ -2608,6 +2610,8 @@ rest_of_compilation (decl)
   reg_scan (insns, max_reg_num (), 0);
   rebuild_jump_labels (insns);
   find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+  if (rtl_dump_file)
+    dump_flow_info (rtl_dump_file);
   cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | CLEANUP_PRE_LOOP);
 
   /* CFG is no longer maintained up-to-date.  */
@@ -2616,11 +2620,11 @@ rest_of_compilation (decl)
   purge_line_number_notes (insns);
 
   timevar_pop (TV_JUMP);
+  close_dump_file (DFI_jump, print_rtl, insns);
 
   /* Now is when we stop if -fsyntax-only and -Wreturn-type.  */
   if (rtl_dump_and_exit || flag_syntax_only || DECL_DEFER_OUTPUT (decl))
     {
-      close_dump_file (DFI_jump, print_rtl, insns);
       goto exit_rest_of_compilation;
     }
 
@@ -2697,23 +2701,22 @@ rest_of_compilation (decl)
 
   if (optimize > 0)
     {
+      open_dump_file (DFI_null, decl);
       find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+      if (rtl_dump_file)
+       dump_flow_info (rtl_dump_file);
       cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
                   | (flag_thread_jumps ? CLEANUP_THREADING : 0));
 
-      /* ??? Run if-conversion before delete_null_pointer_checks,
-         since the later does not preserve the CFG.  This should
-        be changed -- no since converting if's that are going to
-        be deleted.  */
-      timevar_push (TV_IFCVT);
-      if_convert (0);
-      timevar_pop (TV_IFCVT);
-
-      /* CFG is no longer maintained up-to-date.  */
-      free_bb_for_insn ();
       /* Try to identify useless null pointer tests and delete them.  */
       if (flag_delete_null_pointer_checks)
        delete_null_pointer_checks (insns);
+
+      timevar_push (TV_IFCVT);
+      if_convert (0);
+      timevar_pop (TV_IFCVT);
+      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
+      close_dump_file (DFI_null, print_rtl_with_bb, insns);
     }
 
   /* Jump optimization, and the removal of NULL pointer checks, may
@@ -2722,9 +2725,11 @@ rest_of_compilation (decl)
      maximum instruction UID, so if we can reduce the maximum UID
      we'll save big on memory.  */
   renumber_insns (rtl_dump_file);
+  if (optimize)
+    compute_bb_for_insn (get_max_uid ());
   timevar_pop (TV_JUMP);
 
-  close_dump_file (DFI_jump, print_rtl, insns);
+  close_dump_file (DFI_jump, print_rtl_with_bb, insns);
 
   ggc_collect ();
 
@@ -2736,36 +2741,32 @@ rest_of_compilation (decl)
   if (optimize > 0)
     {
       open_dump_file (DFI_cse, decl);
+      if (rtl_dump_file)
+       dump_flow_info (rtl_dump_file);
       timevar_push (TV_CSE);
 
       reg_scan (insns, max_reg_num (), 1);
 
       tem = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+      if (tem)
+       rebuild_jump_labels (insns);
+      purge_all_dead_edges (0);
 
       /* If we are not running more CSE passes, then we are no longer
         expecting CSE to be run.  But always rerun it in a cheap mode.  */
       cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
 
       if (tem || optimize > 1)
-       {
-         timevar_push (TV_JUMP);
-         rebuild_jump_labels (insns);
-         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-         cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
-         timevar_pop (TV_JUMP);
-         /* CFG is no longer maintained up-to-date.  */
-         free_bb_for_insn ();
-       }
+       cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
 
       /* Run this after jump optmizations remove all the unreachable code
         so that unreachable code will not keep values live.  */
-      delete_trivially_dead_insns (insns, max_reg_num (), 0);
+      delete_trivially_dead_insns (insns, max_reg_num (), 1);
 
       /* Try to identify useless null pointer tests and delete them.  */
       if (flag_delete_null_pointer_checks || flag_thread_jumps)
        {
          timevar_push (TV_JUMP);
-         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
 
          cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP
                       | (flag_thread_jumps ? CLEANUP_THREADING : 0));
@@ -2773,21 +2774,23 @@ rest_of_compilation (decl)
          if (flag_delete_null_pointer_checks)
            delete_null_pointer_checks (insns);
          /* CFG is no longer maintained up-to-date.  */
-         free_bb_for_insn ();
          timevar_pop (TV_JUMP);
        }
 
       /* The second pass of jump optimization is likely to have
          removed a bunch more instructions.  */
       renumber_insns (rtl_dump_file);
+      compute_bb_for_insn (get_max_uid ());
 
       timevar_pop (TV_CSE);
-      close_dump_file (DFI_cse, print_rtl, insns);
+      close_dump_file (DFI_cse, print_rtl_with_bb, insns);
     }
 
   open_dump_file (DFI_addressof, decl);
 
   purge_addressof (insns);
+  if (optimize)
+    purge_all_dead_edges (0);
   reg_scan (insns, max_reg_num (), 1);
 
   close_dump_file (DFI_addressof, print_rtl, insns);
@@ -2804,7 +2807,6 @@ rest_of_compilation (decl)
       timevar_push (TV_GCSE);
       open_dump_file (DFI_gcse, decl);
 
-      find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
       cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
       tem = gcse_main (insns, rtl_dump_file);
       rebuild_jump_labels (insns);
@@ -2813,8 +2815,6 @@ rest_of_compilation (decl)
       save_cfj = flag_cse_follow_jumps;
       flag_cse_skip_blocks = flag_cse_follow_jumps = 0;
 
-      /* CFG is no longer maintained up-to-date.  */
-      free_bb_for_insn ();
       /* If -fexpensive-optimizations, re-run CSE to clean up things done
         by gcse.  */
       if (flag_expensive_optimizations)
@@ -2822,6 +2822,7 @@ rest_of_compilation (decl)
          timevar_push (TV_CSE);
          reg_scan (insns, max_reg_num (), 1);
          tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+         purge_all_dead_edges (0);
          timevar_pop (TV_CSE);
          cse_not_expected = !flag_rerun_cse_after_loop;
        }
@@ -2833,11 +2834,8 @@ rest_of_compilation (decl)
          tem = tem2 = 0;
          timevar_push (TV_JUMP);
          rebuild_jump_labels (insns);
-         delete_trivially_dead_insns (insns, max_reg_num (), 0);
-         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+         delete_trivially_dead_insns (insns, max_reg_num (), 1);
          cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_PRE_LOOP);
-         /* CFG is no longer maintained up-to-date.  */
-         free_bb_for_insn ();
          timevar_pop (TV_JUMP);
 
          if (flag_expensive_optimizations)
@@ -2845,16 +2843,20 @@ rest_of_compilation (decl)
              timevar_push (TV_CSE);
              reg_scan (insns, max_reg_num (), 1);
              tem2 = cse_main (insns, max_reg_num (), 0, rtl_dump_file);
+             purge_all_dead_edges (0);
              timevar_pop (TV_CSE);
            }
        }
 
-      close_dump_file (DFI_gcse, print_rtl, insns);
+      close_dump_file (DFI_gcse, print_rtl_with_bb, insns);
       timevar_pop (TV_GCSE);
 
       ggc_collect ();
       flag_cse_skip_blocks = save_csb;
       flag_cse_follow_jumps = save_cfj;
+#ifdef ENABLE_CHECKING
+      verify_flow_info ();
+#endif
     }
 
   /* Move constant computations out of loops.  */
@@ -2863,6 +2865,7 @@ rest_of_compilation (decl)
     {
       timevar_push (TV_LOOP);
       open_dump_file (DFI_loop, decl);
+      /* CFG is no longer maintained up-to-date.  */
       free_bb_for_insn ();
 
       if (flag_rerun_loop_opt)
@@ -2888,62 +2891,98 @@ rest_of_compilation (decl)
                     (flag_unroll_loops ? LOOP_UNROLL : 0) | LOOP_BCT
                     | (flag_prefetch_loop_arrays ? LOOP_PREFETCH : 0));
 
+      /* Loop can create trivially dead instructions.  */
+      delete_trivially_dead_insns (insns, max_reg_num (), 0);
       close_dump_file (DFI_loop, print_rtl, insns);
       timevar_pop (TV_LOOP);
 
       ggc_collect ();
     }
 
+  /* Do control and data flow analysis; wrote some of the results to
+     the dump file.  */
+
+  timevar_push (TV_FLOW);
+  open_dump_file (DFI_cfg, decl);
+
+  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+  if (rtl_dump_file)
+    dump_flow_info (rtl_dump_file);
+  cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
+              | (flag_thread_jumps ? CLEANUP_THREADING : 0));
+
+  /* It may make more sense to mark constant functions after dead code is
+     eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs
+     may insert code making function non-constant, but we still must consider
+     it as constant, otherwise -fbranch-probabilities will not read data back.
+
+     life_analyzis rarely eliminates modification of external memory.
+   */
+  mark_constant_function ();
+
+  close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
+
+  /* Do branch profiling and static profile estimation passes.  */
+  if (optimize > 0 || profile_arc_flag || flag_test_coverage
+      || flag_branch_probabilities)
+    {
+      struct loops loops;
+
+      timevar_push (TV_BRANCH_PROB);
+      open_dump_file (DFI_bp, decl);
+      if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
+       branch_prob ();
+
+      /* Discover and record the loop depth at the head of each basic
+        block.  The loop infrastructure does the real job for us.  */
+      flow_loops_find (&loops, LOOP_TREE);
+
+      /* Estimate using heuristics if no profiling info is available.  */
+      if (flag_guess_branch_prob)
+       estimate_probability (&loops);
+
+      if (rtl_dump_file)
+       flow_loops_dump (&loops, rtl_dump_file, NULL, 0);
+
+      flow_loops_free (&loops);
+      close_dump_file (DFI_bp, print_rtl_with_bb, insns);
+      timevar_pop (TV_BRANCH_PROB);
+    }
+
   if (optimize > 0)
     {
       timevar_push (TV_CSE2);
       open_dump_file (DFI_cse2, decl);
+      if (rtl_dump_file)
+       dump_flow_info (rtl_dump_file);
 
       if (flag_rerun_cse_after_loop)
        {
-         /* Running another jump optimization pass before the second
-            cse pass sometimes simplifies the RTL enough to allow
-            the second CSE pass to do a better job.  Jump_optimize can change
-            max_reg_num so we must rerun reg_scan afterwards.
-            ??? Rework to not call reg_scan so often.  */
          timevar_push (TV_JUMP);
 
-         /* The previous call to loop_optimize makes some instructions
-            trivially dead.  We delete those instructions now in the
-            hope that doing so will make the heuristics in jump work
-            better and possibly speed up compilation.  */
-         delete_trivially_dead_insns (insns, max_reg_num (), 0);
-
          reg_scan (insns, max_reg_num (), 0);
 
          timevar_push (TV_IFCVT);
-
-         find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
          cleanup_cfg (CLEANUP_EXPENSIVE);
          if_convert (0);
-
          timevar_pop(TV_IFCVT);
 
          timevar_pop (TV_JUMP);
-
          /* CFG is no longer maintained up-to-date.  */
-         free_bb_for_insn ();
          reg_scan (insns, max_reg_num (), 0);
          tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
+         purge_all_dead_edges (0);
 
          if (tem)
            {
              timevar_push (TV_JUMP);
              rebuild_jump_labels (insns);
-             find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
              cleanup_cfg (CLEANUP_EXPENSIVE);
-             /* CFG is no longer maintained up-to-date.  */
-             free_bb_for_insn ();
              timevar_pop (TV_JUMP);
            }
        }
 
-      close_dump_file (DFI_cse2, print_rtl, insns);
+      close_dump_file (DFI_cse2, print_rtl_with_bb, insns);
       timevar_pop (TV_CSE2);
 
       ggc_collect ();
@@ -2951,60 +2990,17 @@ rest_of_compilation (decl)
 
   cse_not_expected = 1;
 
+  close_dump_file (DFI_life, print_rtl_with_bb, insns);
   regclass_init ();
 
-  /* Do control and data flow analysis; wrote some of the results to
-     the dump file.  */
-
-  timevar_push (TV_FLOW);
-  open_dump_file (DFI_cfg, decl);
-
-  find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
-  cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
-              | (flag_thread_jumps ? CLEANUP_THREADING : 0));
   check_function_return_warnings ();
 
-  /* It may make more sense to mark constant functions after dead code is
-     eliminated by life_analyzis, but we need to do it early, as -fprofile-arcs
-     may insert code making function non-constant, but we still must consider
-     it as constant, otherwise -fbranch-probabilities will not read data back.
-
-     life_analyzis rarely eliminates modification of external memory.
-   */
-  mark_constant_function ();
-
-  close_dump_file (DFI_cfg, print_rtl_with_bb, insns);
-
-  if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities)
-    {
-      timevar_push (TV_BRANCH_PROB);
-      open_dump_file (DFI_bp, decl);
-
-      branch_prob ();
-
-      close_dump_file (DFI_bp, print_rtl_with_bb, insns);
-      timevar_pop (TV_BRANCH_PROB);
-    }
-
-  open_dump_file (DFI_life, decl);
-  if (optimize)
-    {
-      struct loops loops;
-
-      /* Discover and record the loop depth at the head of each basic
-        block.  The loop infrastructure does the real job for us.  */
-      flow_loops_find (&loops, LOOP_TREE);
-
-      /* Estimate using heuristics if no profiling info is available.  */
-      if (flag_guess_branch_prob)
-       estimate_probability (&loops);
-
-      if (rtl_dump_file)
-       flow_loops_dump (&loops, rtl_dump_file, NULL, 0);
-
-      flow_loops_free (&loops);
-    }
+#ifdef ENABLE_CHECKING
+  verify_flow_info ();
+#endif
   life_analysis (insns, rtl_dump_file, PROP_FINAL);
+  if (optimize)
+    cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
   timevar_pop (TV_FLOW);
 
   no_new_pseudos = 1;
@@ -3018,12 +3014,14 @@ rest_of_compilation (decl)
 
   if (optimize)
     {
+      clear_bb_flags ();
       if (initialize_uninitialized_subregs ())
        {
          /* Insns were inserted, so things might look a bit different.  */
          insns = get_insns ();
-         life_analysis (insns, rtl_dump_file, 
-                        (PROP_LOG_LINKS | PROP_REG_INFO | PROP_DEATH_NOTES));
+         update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+                                           PROP_LOG_LINKS | PROP_REG_INFO
+                                           | PROP_DEATH_NOTES);
        }
     }
 
@@ -3089,6 +3087,7 @@ rest_of_compilation (decl)
 
       regmove_optimize (insns, max_reg_num (), rtl_dump_file);
 
+      cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_UPDATE_LIFE);
       close_dump_file (DFI_regmove, print_rtl_with_bb, insns);
       timevar_pop (TV_REGMOVE);
 
@@ -3107,13 +3106,7 @@ rest_of_compilation (decl)
   timevar_push (TV_MODE_SWITCH);
 
   no_new_pseudos = 0;
-  if (optimize_mode_switching (NULL))
-    {
-      /* We did work, and so had to regenerate global life information.
-        Take advantage of this and don't re-recompute register life
-        information below.  */
-      register_life_up_to_date = 1;
-    }
+  optimize_mode_switching (NULL);
   no_new_pseudos = 1;
 
   timevar_pop (TV_MODE_SWITCH);