OSDN Git Service

PR c++/37877
[pf3gnuchains/gcc-fork.git] / gcc / cfgcleanup.c
index a95204c..190bde6 100644 (file)
@@ -1,6 +1,6 @@
 /* Control flow optimization 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.
@@ -418,8 +418,8 @@ try_forward_edges (int mode, basic_block b)
      and cold sections.
 
      Basic block partitioning may result in some jumps that appear to
-     be optimizable (or blocks that appear to be mergeable), but which really m
-     ust be left untouched (they are required to make it safely across
+     be optimizable (or blocks that appear to be mergeable), but which really
+     must be left untouched (they are required to make it safely across
      partition boundaries).  See the comments at the top of
      bb-reorder.c:partition_hot_cold_basic_blocks for complete details.  */
 
@@ -429,7 +429,7 @@ try_forward_edges (int mode, basic_block b)
   for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); )
     {
       basic_block target, first;
-      int counter;
+      int counter, goto_locus;
       bool threaded = false;
       int nthreaded_edges = 0;
       bool may_thread = first_pass | df_get_bb_dirty (b);
@@ -447,6 +447,7 @@ try_forward_edges (int mode, basic_block b)
 
       target = first = e->dest;
       counter = NUM_FIXED_BLOCKS;
+      goto_locus = e->goto_locus;
 
       /* If we are partitioning hot/cold basic_blocks, we don't want to mess
         up jumps that cross between hot/cold sections.
@@ -476,6 +477,28 @@ try_forward_edges (int mode, basic_block b)
              new_target = single_succ (target);
              if (target == new_target)
                counter = n_basic_blocks;
+             else if (!optimize)
+               {
+                 /* When not optimizing, ensure that edges or forwarder
+                    blocks with different locus are not optimized out.  */
+                 int locus = single_succ_edge (target)->goto_locus;
+
+                 if (locus && goto_locus && !locator_eq (locus, goto_locus))
+                   counter = n_basic_blocks;
+                 else if (locus)
+                   goto_locus = locus;
+
+                 if (INSN_P (BB_END (target)))
+                   {
+                     locus = INSN_LOCATOR (BB_END (target));
+
+                     if (locus && goto_locus
+                         && !locator_eq (locus, goto_locus))
+                       counter = n_basic_blocks;
+                     else if (locus)
+                       goto_locus = locus;
+                   }
+               }
            }
 
          /* Allow to thread only over one edge at time to simplify updating
@@ -539,6 +562,8 @@ try_forward_edges (int mode, basic_block b)
          int edge_frequency;
          int n = 0;
 
+         e->goto_locus = goto_locus;
+
          /* Don't force if target is exit block.  */
          if (threaded && target != EXIT_BLOCK_PTR)
            {
@@ -1235,9 +1260,8 @@ outgoing_edges_match (int mode, basic_block bb1, basic_block bb2)
         we require the existing branches to have probabilities that are
         roughly similar.  */
       if (match
-         && !optimize_size
-         && maybe_hot_bb_p (bb1)
-         && maybe_hot_bb_p (bb2))
+         && optimize_bb_for_speed_p (bb1)
+         && optimize_bb_for_speed_p (bb2))
        {
          int prob2;
 
@@ -1684,7 +1708,7 @@ try_crossjump_bb (int mode, basic_block bb)
 
   /* Don't crossjump if this block ends in a computed jump,
      unless we are optimizing for size.  */
-  if (!optimize_size
+  if (optimize_bb_for_size_p (bb)
       && bb != EXIT_BLOCK_PTR
       && computed_jump_p (BB_END (bb)))
     return false;
@@ -2176,13 +2200,15 @@ rest_of_handle_jump (void)
 {
   delete_unreachable_blocks ();
 
-  if (cfun->tail_call_emit)
+  if (crtl->tail_call_emit)
     fixup_tail_calls ();
   return 0;
 }
 
-struct tree_opt_pass pass_jump =
+struct rtl_opt_pass pass_jump =
 {
+ {
+  RTL_PASS,
   "sibling",                            /* name */
   NULL,                                 /* gate */
   rest_of_handle_jump,                 /* execute */
@@ -2195,7 +2221,7 @@ struct tree_opt_pass pass_jump =
   0,                                    /* properties_destroyed */
   TODO_ggc_collect,                     /* todo_flags_start */
   TODO_verify_flow,                     /* todo_flags_finish */
-  'i'                                   /* letter */
+ }
 };
 
 
@@ -2211,8 +2237,10 @@ rest_of_handle_jump2 (void)
 }
 
 
-struct tree_opt_pass pass_jump2 =
+struct rtl_opt_pass pass_jump2 =
 {
+ {
+  RTL_PASS,
   "jump",                               /* name */
   NULL,                                 /* gate */
   rest_of_handle_jump2,                        /* execute */
@@ -2225,7 +2253,7 @@ struct tree_opt_pass pass_jump2 =
   0,                                    /* properties_destroyed */
   TODO_ggc_collect,                     /* todo_flags_start */
   TODO_dump_func | TODO_verify_rtl_sharing,/* todo_flags_finish */
-  'j'                                   /* letter */
+ }
 };