OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / cfglayout.c
index 8a0d35c..22d3d87 100644 (file)
@@ -1,6 +1,6 @@
 /* Basic block reordering routines for the GNU compiler.
-   Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfglayout.h"
 #include "cfgloop.h"
 #include "target.h"
+#include "common/common-target.h"
 #include "ggc.h"
 #include "alloc-pool.h"
 #include "flags.h"
@@ -54,7 +55,6 @@ static void change_scope (rtx, tree, tree);
 
 void verify_insn_chain (void);
 static void fixup_fallthru_exit_predecessor (void);
-static tree insn_scope (const_rtx);
 \f
 rtx
 unlink_insn_chain (rtx first, rtx last)
@@ -149,6 +149,7 @@ skip_insns_after_block (basic_block bb)
            break;
          case NOTE_INSN_DELETED:
          case NOTE_INSN_DELETED_LABEL:
+         case NOTE_INSN_DELETED_DEBUG_LABEL:
            continue;
          default:
            reorder_insns (insn, insn, last_insn);
@@ -254,8 +255,8 @@ insn_locators_alloc (void)
   locations_locators_locs = VEC_alloc (int, heap, 32);
   locations_locators_vals = VEC_alloc (location_t, heap, 32);
 
-  last_location = -1;
-  curr_location = -1;
+  curr_location = UNKNOWN_LOCATION;
+  last_location = UNKNOWN_LOCATION;
   curr_block = NULL;
   last_block = NULL;
   curr_rtl_loc = 0;
@@ -324,7 +325,7 @@ get_curr_insn_block (void)
 int
 curr_insn_locator (void)
 {
-  if (curr_rtl_loc == -1)
+  if (curr_rtl_loc == -1 || curr_location == UNKNOWN_LOCATION)
     return 0;
   if (last_block != curr_block)
     {
@@ -374,12 +375,12 @@ struct rtl_opt_pass pass_into_cfg_layout_mode =
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  TV_NONE,                              /* tv_id */
+  TV_CFG,                               /* tv_id */
   0,                                    /* properties_required */
   PROP_cfglayout,                       /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
+  0                                     /* todo_flags_finish */
  }
 };
 
@@ -393,12 +394,12 @@ struct rtl_opt_pass pass_outof_cfg_layout_mode =
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  TV_NONE,                              /* tv_id */
+  TV_CFG,                               /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   PROP_cfglayout,                       /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  TODO_dump_func,                       /* todo_flags_finish */
+  0                                     /* todo_flags_finish */
  }
 };
 \f
@@ -499,7 +500,7 @@ locator_scope (int loc)
 }
 
 /* Return lexical scope block insn belongs to.  */
-static tree
+tree
 insn_scope (const_rtx insn)
 {
   return locator_scope (INSN_LOCATOR (insn));
@@ -767,7 +768,8 @@ fixup_reorder_chain (void)
     {
       edge e_fall, e_taken, e;
       rtx bb_end_insn;
-      basic_block nb;
+      rtx ret_label = NULL_RTX;
+      basic_block nb, src_bb;
       edge_iterator ei;
 
       if (EDGE_COUNT (bb->succs) == 0)
@@ -786,6 +788,7 @@ fixup_reorder_chain (void)
       bb_end_insn = BB_END (bb);
       if (JUMP_P (bb_end_insn))
        {
+         ret_label = JUMP_LABEL (bb_end_insn);
          if (any_condjump_p (bb_end_insn))
            {
              /* This might happen if the conditional jump has side
@@ -895,8 +898,11 @@ fixup_reorder_chain (void)
            continue;
        }
 
-      /* We got here if we need to add a new jump insn.  */
-      nb = force_nonfallthru (e_fall);
+      /* We got here if we need to add a new jump insn. 
+        Note force_nonfallthru can delete E_FALL and thus we have to
+        save E_FALL->src prior to the call to force_nonfallthru.  */
+      src_bb = e_fall->src;
+      nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
       if (nb)
        {
          nb->il.rtl->visited = 1;
@@ -906,11 +912,11 @@ fixup_reorder_chain (void)
          bb = nb;
 
          /* Make sure new bb is tagged for correct section (same as
-            fall-thru source, since you cannot fall-throu across
+            fall-thru source, since you cannot fall-thru across
             section boundaries).  */
-         BB_COPY_PARTITION (e_fall->src, single_pred (bb));
+         BB_COPY_PARTITION (src_bb, single_pred (bb));
          if (flag_reorder_blocks_and_partition
-             && targetm.have_named_sections
+             && targetm_common.have_named_sections
              && JUMP_P (BB_END (bb))
              && !any_condjump_p (BB_END (bb))
              && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING))
@@ -940,7 +946,9 @@ fixup_reorder_chain (void)
         FOR_EACH_EDGE (e, ei, bb->succs)
          if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
            {
-             basic_block nb;
+             edge e2;
+             edge_iterator ei2;
+             basic_block dest, nb;
              rtx end;
 
              insn = BB_END (e->src);
@@ -957,10 +965,17 @@ fixup_reorder_chain (void)
                  INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
                  continue;
                }
-             if (e->dest != EXIT_BLOCK_PTR)
+             dest = e->dest;
+             if (dest == EXIT_BLOCK_PTR)
+               {
+                 /* Non-fallthru edges to the exit block cannot be split.  */
+                 if (!(e->flags & EDGE_FALLTHRU))
+                   continue;
+               }
+             else
                {
-                 insn = BB_HEAD (e->dest);
-                 end = NEXT_INSN (BB_END (e->dest));
+                 insn = BB_HEAD (dest);
+                 end = NEXT_INSN (BB_END (dest));
                  while (insn != end && !NONDEBUG_INSN_P (insn))
                    insn = NEXT_INSN (insn);
                  if (insn != end && INSN_LOCATOR (insn)
@@ -972,6 +987,18 @@ fixup_reorder_chain (void)
                BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
                                                     nb);
              INSN_LOCATOR (BB_END (nb)) = e->goto_locus;
+
+             /* If there are other incoming edges to the destination block
+                with the same goto locus, redirect them to the new block as
+                well, this can prevent other such blocks from being created
+                in subsequent iterations of the loop.  */
+             for (ei2 = ei_start (dest->preds); (e2 = ei_safe_edge (ei2)); )
+               if (e2->goto_locus
+                   && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
+                   && locator_eq (e->goto_locus, e2->goto_locus))
+                 redirect_edge_and_branch (e2, nb);
+               else
+                 ei_next (&ei2);
            }
       }
 }
@@ -1148,6 +1175,10 @@ duplicate_insn_chain (rtx from, rtx to)
       switch (GET_CODE (insn))
        {
        case DEBUG_INSN:
+         /* Don't duplicate label debug insns.  */
+         if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL)
+           break;
+         /* FALLTHRU */
        case INSN:
        case CALL_INSN:
        case JUMP_INSN:
@@ -1156,9 +1187,25 @@ duplicate_insn_chain (rtx from, rtx to)
             moved far from original jump.  */
          if (GET_CODE (PATTERN (insn)) == ADDR_VEC
              || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
-           break;
+           {
+             /* Avoid copying following barrier as well if any
+                (and debug insns in between).  */
+             rtx next;
+
+             for (next = NEXT_INSN (insn);
+                  next != NEXT_INSN (to);
+                  next = NEXT_INSN (next))
+               if (!DEBUG_INSN_P (next))
+                 break;
+             if (next != NEXT_INSN (to) && BARRIER_P (next))
+               insn = next;
+             break;
+           }
          copy = emit_copy_of_insn_after (insn, get_last_insn ());
-          maybe_copy_epilogue_insn (insn, copy);
+         if (JUMP_P (insn) && JUMP_LABEL (insn) != NULL_RTX
+             && ANY_RETURN_P (JUMP_LABEL (insn)))
+           JUMP_LABEL (copy) = JUMP_LABEL (insn);
+          maybe_copy_prologue_epilogue_insn (insn, copy);
          break;
 
        case CODE_LABEL:
@@ -1177,6 +1224,7 @@ duplicate_insn_chain (rtx from, rtx to)
 
            case NOTE_INSN_DELETED:
            case NOTE_INSN_DELETED_LABEL:
+           case NOTE_INSN_DELETED_DEBUG_LABEL:
              /* No problem to strip these.  */
            case NOTE_INSN_FUNCTION_BEG:
              /* There is always just single entry to function.  */