OSDN Git Service

contrib:
[pf3gnuchains/gcc-fork.git] / gcc / cfgrtl.c
index cfeca97..a42063b 100644 (file)
@@ -1,6 +1,6 @@
 /* Control flow graph manipulation code for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -187,6 +187,7 @@ delete_insn (rtx insn)
 }
 
 /* Like delete_insn but also purge dead edges from BB.  */
+
 rtx
 delete_insn_and_edges (rtx insn)
 {
@@ -231,6 +232,22 @@ delete_insn_chain (rtx start, rtx finish, bool clear_bb)
       start = next;
     }
 }
+
+/* Like delete_insn_chain but also purge dead edges from BB.  */
+
+void
+delete_insn_chain_and_edges (rtx first, rtx last)
+{
+  bool purge = false;
+
+  if (INSN_P (last)
+      && BLOCK_FOR_INSN (last)
+      && BB_END (BLOCK_FOR_INSN (last)) == last)
+    purge = true;
+  delete_insn_chain (first, last, false);
+  if (purge)
+    purge_dead_edges (BLOCK_FOR_INSN (last));
+}
 \f
 /* Create a new basic block consisting of the instructions between HEAD and END
    inclusive.  This function is designed to allow fast BB construction - reuses
@@ -410,8 +427,10 @@ free_bb_for_insn (void)
   return 0;
 }
 
-struct tree_opt_pass pass_free_cfg =
+struct rtl_opt_pass pass_free_cfg =
 {
+ {
+  RTL_PASS,
   NULL,                                 /* name */
   NULL,                                 /* gate */
   free_bb_for_insn,                     /* execute */
@@ -424,7 +443,7 @@ struct tree_opt_pass pass_free_cfg =
   PROP_cfg,                             /* properties_destroyed */
   0,                                    /* todo_flags_start */
   0,                                    /* todo_flags_finish */
-  0                                     /* letter */
+ }
 };
 
 /* Return RTX to emit after when we want to emit code on the entry of function.  */
@@ -448,24 +467,31 @@ emit_insn_at_entry (rtx insn)
   commit_edge_insertions ();
 }
 
-/* Update insns block within BB.  */
+/* Update BLOCK_FOR_INSN of insns between BEGIN and END
+   (or BARRIER if found) and notify df of the bb change. 
+   The insn chain range is inclusive
+   (i.e. both BEGIN and END will be updated. */
 
-void
-update_bb_for_insn (basic_block bb)
+static void
+update_bb_for_insn_chain (rtx begin, rtx end, basic_block bb)
 {
   rtx insn;
 
-  for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
-    {
-      if (!BARRIER_P (insn))
-       {
-         set_block_for_insn (insn, bb);
-         df_insn_change_bb (insn);
-       }
-      if (insn == BB_END (bb))
-       break;
-    }
+  end = NEXT_INSN (end);
+  for (insn = begin; insn != end; insn = NEXT_INSN (insn))
+    if (!BARRIER_P (insn))
+      df_insn_change_bb (insn, bb);
 }
+
+/* Update BLOCK_FOR_INSN of insns in BB to BB,
+   and notify df of the change.  */
+
+void
+update_bb_for_insn (basic_block bb)
+{
+  update_bb_for_insn_chain (BB_HEAD (bb), BB_END (bb), bb);
+}
+
 \f
 /* Return the INSN immediately following the NOTE_INSN_BASIC_BLOCK
    note associated with the BLOCK.  */
@@ -612,16 +638,7 @@ rtl_merge_blocks (basic_block a, basic_block b)
   /* Reassociate the insns of B with A.  */
   if (!b_empty)
     {
-      rtx x;
-
-      for (x = a_end; x != b_end; x = NEXT_INSN (x))
-       {
-         set_block_for_insn (x, a);
-         df_insn_change_bb (x);
-       }
-
-      set_block_for_insn (b_end, a);
-      df_insn_change_bb (b_end);
+      update_bb_for_insn_chain (a_end, b_end, a);
 
       a_end = b_end;
     }
@@ -826,14 +843,9 @@ try_redirect_by_replacing_jump (edge e, basic_block target, bool in_cfglayout)
                 which originally were or were created before jump table are
                 inside the basic block.  */
              rtx new_insn = BB_END (src);
-             rtx tmp;
 
-             for (tmp = NEXT_INSN (BB_END (src)); tmp != barrier;
-                  tmp = NEXT_INSN (tmp))
-               {
-                 set_block_for_insn (tmp, src);
-                 df_insn_change_bb (tmp);
-               }
+             update_bb_for_insn_chain (NEXT_INSN (BB_END (src)),
+                                       PREV_INSN (barrier), src);
 
              NEXT_INSN (PREV_INSN (new_insn)) = NEXT_INSN (new_insn);
              PREV_INSN (NEXT_INSN (new_insn)) = PREV_INSN (new_insn);
@@ -2620,6 +2632,13 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
        first = NEXT_INSN (first);
       gcc_assert (NOTE_INSN_BASIC_BLOCK_P (first));
       BB_HEAD (b) = NULL;
+
+      /* emit_insn_after_noloc doesn't call df_insn_change_bb.
+         We need to explicitly call. */
+      update_bb_for_insn_chain (NEXT_INSN (first),
+                               BB_END (b),
+                               a);
+
       delete_insn (first);
     }
   /* Otherwise just re-associate the instructions.  */
@@ -2627,13 +2646,7 @@ cfg_layout_merge_blocks (basic_block a, basic_block b)
     {
       rtx insn;
 
-      for (insn = BB_HEAD (b);
-          insn != NEXT_INSN (BB_END (b));
-          insn = NEXT_INSN (insn))
-       {
-         set_block_for_insn (insn, a);
-         df_insn_change_bb (insn);
-       }
+      update_bb_for_insn_chain (BB_HEAD (b), BB_END (b), a);
 
       insn = BB_HEAD (b);
       /* Skip possible DELETED_LABEL insn.  */
@@ -2679,6 +2692,10 @@ cfg_layout_split_edge (edge e)
                        ? NEXT_INSN (BB_END (e->src)) : get_insns (),
                        NULL_RTX, e->src);
 
+  if (e->dest == EXIT_BLOCK_PTR)
+    BB_COPY_PARTITION (new_bb, e->src);
+  else
+    BB_COPY_PARTITION (new_bb, e->dest);
   make_edge (new_bb, e->dest, EDGE_FALLTHRU);
   redirect_edge_and_branch_force (e, new_bb);