OSDN Git Service

* cfgcleanup.c (try_crossjump_to_edge): Only skip past
[pf3gnuchains/gcc-fork.git] / gcc / cfglayout.c
index be1188d..d93b845 100644 (file)
@@ -1,5 +1,5 @@
 /* Basic block reordering routines for the GNU compiler.
-   Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -363,9 +363,9 @@ struct rtl_opt_pass pass_into_cfg_layout_mode =
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  0,                                    /* tv_id */
+  TV_NONE,                              /* tv_id */
   0,                                    /* properties_required */
-  0,                                    /* properties_provided */
+  PROP_cfglayout,                       /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_dump_func,                       /* todo_flags_finish */
@@ -382,10 +382,10 @@ struct rtl_opt_pass pass_outof_cfg_layout_mode =
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  0,                                    /* tv_id */
+  TV_NONE,                              /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
-  0,                                    /* properties_destroyed */
+  PROP_cfglayout,                       /* properties_destroyed */
   0,                                    /* todo_flags_start */
   TODO_dump_func,                       /* todo_flags_finish */
  }
@@ -448,13 +448,12 @@ change_scope (rtx orig_insn, tree s1, tree s2)
     }
 }
 
-/* Return lexical scope block insn belong to.  */
+/* Return lexical scope block locator belongs to.  */
 static tree
-insn_scope (const_rtx insn)
+locator_scope (int loc)
 {
   int max = VEC_length (int, block_locators_locs);
   int min = 0;
-  int loc = INSN_LOCATOR (insn);
 
   /* When block_locators_locs was initialized, the pro- and epilogue
      insns didn't exist yet and can therefore not be found this way.
@@ -488,8 +487,15 @@ insn_scope (const_rtx insn)
   return VEC_index (tree, block_locators_blocks, min);
 }
 
+/* Return lexical scope block insn belongs to.  */
+static tree
+insn_scope (const_rtx insn)
+{
+  return locator_scope (INSN_LOCATOR (insn));
+}
+
 /* Return line number of the statement specified by the locator.  */
-static location_t
+location_t
 locator_location (int loc)
 {
   int max = VEC_length (int, locations_locators_locs);
@@ -551,6 +557,17 @@ insn_file (const_rtx insn)
   return locator_file (INSN_LOCATOR (insn));
 }
 
+/* Return true if LOC1 and LOC2 locators have the same location and scope.  */
+bool
+locator_eq (int loc1, int loc2)
+{
+  if (loc1 == loc2)
+    return true;
+  if (locator_location (loc1) != locator_location (loc2))
+    return false;
+  return locator_scope (loc1) == locator_scope (loc2);
+}
+
 /* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based
    on the scope tree and the newly reordered instructions.  */
 
@@ -900,24 +917,30 @@ fixup_reorder_chain (void)
          if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
            {
              basic_block nb;
-
-             if (simplejump_p (BB_END (e->src)))
+             rtx end;
+
+             insn = BB_END (e->src);
+             end = PREV_INSN (BB_HEAD (e->src));
+             while (insn != end
+                    && (!INSN_P (insn) || INSN_LOCATOR (insn) == 0))
+               insn = PREV_INSN (insn);
+             if (insn != end
+                 && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
+               continue;
+             if (simplejump_p (BB_END (e->src))
+                 && INSN_LOCATOR (BB_END (e->src)) == 0)
                {
-                 if (INSN_LOCATOR (BB_END (e->src)) == (int) e->goto_locus)
-                   continue;
-                 if (INSN_LOCATOR (BB_END (e->src)) == 0)
-                   {
-                     INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
-                     continue;
-                   }
+                 INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
+                 continue;
                }
              if (e->dest != EXIT_BLOCK_PTR)
                {
                  insn = BB_HEAD (e->dest);
-                 if (!INSN_P (insn))
-                   insn = next_insn (insn);
-                 if (insn && INSN_P (insn)
-                     && INSN_LOCATOR (insn) == (int) e->goto_locus)
+                 end = NEXT_INSN (BB_END (e->dest));
+                 while (insn != end && !INSN_P (insn))
+                   insn = NEXT_INSN (insn);
+                 if (insn != end && INSN_LOCATOR (insn)
+                     && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
                    continue;
                }
              nb = split_edge (e);
@@ -1089,7 +1112,7 @@ cfg_layout_can_duplicate_bb_p (const_basic_block bb)
 rtx
 duplicate_insn_chain (rtx from, rtx to)
 {
-  rtx insn, last;
+  rtx insn, last, copy;
 
   /* Avoid updating of boundaries of previous basic block.  The
      note will get removed from insn stream in fixup.  */
@@ -1110,7 +1133,8 @@ duplicate_insn_chain (rtx from, rtx to)
          if (GET_CODE (PATTERN (insn)) == ADDR_VEC
              || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
            break;
-         emit_copy_of_insn_after (insn, get_last_insn ());
+         copy = emit_copy_of_insn_after (insn, get_last_insn ());
+          maybe_copy_epilogue_insn (insn, copy);
          break;
 
        case CODE_LABEL:
@@ -1130,23 +1154,18 @@ duplicate_insn_chain (rtx from, rtx to)
            case NOTE_INSN_DELETED:
            case NOTE_INSN_DELETED_LABEL:
              /* No problem to strip these.  */
-           case NOTE_INSN_EPILOGUE_BEG:
-             /* Debug code expect these notes to exist just once.
-                Keep them in the master copy.
-                ??? It probably makes more sense to duplicate them for each
-                epilogue copy.  */
            case NOTE_INSN_FUNCTION_BEG:
              /* There is always just single entry to function.  */
            case NOTE_INSN_BASIC_BLOCK:
              break;
 
+           case NOTE_INSN_EPILOGUE_BEG:
            case NOTE_INSN_SWITCH_TEXT_SECTIONS:
              emit_note_copy (insn);
              break;
 
            default:
-             /* All other notes should have already been eliminated.
-              */
+             /* All other notes should have already been eliminated.  */
              gcc_unreachable ();
            }
          break;