OSDN Git Service

2008-05-06 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/gcc-fork.git] / gcc / cfgbuild.c
index fdfbcca..b4e3baa 100644 (file)
@@ -1,12 +1,12 @@
 /* Control flow graph building code for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +15,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* find_basic_blocks divides the current function's rtl into basic
    blocks and constructs the CFG.  The blocks are recorded in the
@@ -28,9 +27,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
    Available functionality:
      - CFG construction
-         find_basic_blocks
-     - Local CFG construction
-         find_sub_basic_blocks          */
+        find_basic_blocks  */
 \f
 #include "config.h"
 #include "system.h"
@@ -48,10 +45,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "toplev.h"
 #include "timevar.h"
 
-static int count_basic_blocks (rtx);
+static int count_basic_blocks (const_rtx);
 static void find_basic_blocks_1 (rtx);
 static void make_edges (basic_block, basic_block, int);
-static void make_label_edge (sbitmap *, basic_block, rtx, int);
+static void make_label_edge (sbitmap, basic_block, rtx, int);
 static void find_bb_boundaries (basic_block);
 static void compute_outgoing_frequencies (basic_block);
 \f
@@ -59,7 +56,7 @@ static void compute_outgoing_frequencies (basic_block);
    block.  */
 
 bool
-inside_basic_block_p (rtx insn)
+inside_basic_block_p (const_rtx insn)
 {
   switch (GET_CODE (insn))
     {
@@ -91,7 +88,7 @@ inside_basic_block_p (rtx insn)
    the basic block.  */
 
 bool
-control_flow_insn_p (rtx insn)
+control_flow_insn_p (const_rtx insn)
 {
   rtx note;
 
@@ -122,12 +119,17 @@ control_flow_insn_p (rtx insn)
              || can_throw_internal (insn));
 
     case INSN:
+      /* Treat trap instructions like noreturn calls (same provision).  */
+      if (GET_CODE (PATTERN (insn)) == TRAP_IF
+         && XEXP (PATTERN (insn), 0) == const1_rtx)
+       return true;
+
       return (flag_non_call_exceptions && can_throw_internal (insn));
 
     case BARRIER:
       /* It is nonsense to reach barrier when looking for the
-         end of basic block, but before dead code is eliminated
-         this may happen.  */
+        end of basic block, but before dead code is eliminated
+        this may happen.  */
       return false;
 
     default:
@@ -138,16 +140,16 @@ control_flow_insn_p (rtx insn)
 /* Count the basic blocks of the function.  */
 
 static int
-count_basic_blocks (rtx f)
+count_basic_blocks (const_rtx f)
 {
-  int count = 0;
+  int count = NUM_FIXED_BLOCKS;
   bool saw_insn = false;
-  rtx insn;
+  const_rtx insn;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
     {
       /* Code labels and barriers causes current basic block to be
-         terminated at previous real insn.  */
+        terminated at previous real insn.  */
       if ((LABEL_P (insn) || BARRIER_P (insn))
          && saw_insn)
        count++, saw_insn = false;
@@ -166,10 +168,10 @@ count_basic_blocks (rtx f)
 
   /* The rest of the compiler works a bit smoother when we don't have to
      check for the edge case of do-nothing functions with no basic blocks.  */
-  if (count == 0)
+  if (count == NUM_FIXED_BLOCKS)
     {
       emit_insn (gen_rtx_USE (VOIDmode, const0_rtx));
-      count = 1;
+      count = NUM_FIXED_BLOCKS + 1;
     }
 
   return count;
@@ -181,7 +183,7 @@ count_basic_blocks (rtx f)
 /* Create an edge from a basic block to a label.  */
 
 static void
-make_label_edge (sbitmap *edge_cache, basic_block src, rtx label, int flags)
+make_label_edge (sbitmap edge_cache, basic_block src, rtx label, int flags)
 {
   gcc_assert (LABEL_P (label));
 
@@ -199,7 +201,7 @@ make_label_edge (sbitmap *edge_cache, basic_block src, rtx label, int flags)
 /* Create the edges generated by INSN in REGION.  */
 
 void
-rtl_make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
+rtl_make_eh_edge (sbitmap edge_cache, basic_block src, rtx insn)
 {
   int is_call = CALL_P (insn) ? EDGE_ABNORMAL_CALL : 0;
   rtx handlers, i;
@@ -213,63 +215,76 @@ rtl_make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
   free_INSN_LIST_list (&handlers);
 }
 
-/* Identify the edges between basic blocks MIN to MAX.
+/* States of basic block as seen by find_many_sub_basic_blocks.  */
+enum state {
+  /* Basic blocks created via split_block belong to this state.
+     make_edges will examine these basic blocks to see if we need to
+     create edges going out of them.  */
+  BLOCK_NEW = 0,
+
+  /* Basic blocks that do not need examining belong to this state.
+     These blocks will be left intact.  In particular, make_edges will
+     not create edges going out of these basic blocks.  */
+  BLOCK_ORIGINAL,
+
+  /* Basic blocks that may need splitting (due to a label appearing in
+     the middle, etc) belong to this state.  After splitting them,
+     make_edges will create edges going out of them as needed.  */
+  BLOCK_TO_SPLIT
+};
+
+#define STATE(BB) (enum state) ((size_t) (BB)->aux)
+#define SET_STATE(BB, STATE) ((BB)->aux = (void *) (size_t) (STATE))
+
+/* Used internally by purge_dead_tablejump_edges, ORed into state.  */
+#define BLOCK_USED_BY_TABLEJUMP                32
+#define FULL_STATE(BB) ((size_t) (BB)->aux)
 
-   NONLOCAL_LABEL_LIST is a list of non-local labels in the function.  Blocks
-   that are otherwise unreachable may be reachable with a non-local goto.
+/* Identify the edges going out of basic blocks between MIN and MAX,
+   inclusive, that have their states set to BLOCK_NEW or
+   BLOCK_TO_SPLIT.
 
-   BB_EH_END is an array indexed by basic block number in which we record
-   the list of exception regions active at the end of the basic block.  */
+   UPDATE_P should be nonzero if we are updating CFG and zero if we
+   are building CFG from scratch.  */
 
 static void
 make_edges (basic_block min, basic_block max, int update_p)
 {
   basic_block bb;
-  sbitmap *edge_cache = NULL;
-
-  /* Assume no computed jump; revise as we create edges.  */
-  current_function_has_computed_jump = 0;
-
-  /* If we are partitioning hot and cold basic blocks into separate
-     sections, we cannot assume there is no computed jump (partitioning
-     sometimes requires the use of indirect jumps; see comments about
-     partitioning at the top of bb-reorder.c:partition_hot_cold_basic_blocks 
-     for complete details).  */
-
-  if (flag_reorder_blocks_and_partition)
-    current_function_has_computed_jump = 1;
+  sbitmap edge_cache = NULL;
 
   /* Heavy use of computed goto in machine-generated code can lead to
      nearly fully-connected CFGs.  In that case we spend a significant
      amount of time searching the edge lists for duplicates.  */
-  if (forced_labels || cfun->max_jumptable_ents > 100)
-    {
-      edge_cache = sbitmap_vector_alloc (last_basic_block, last_basic_block);
-      sbitmap_vector_zero (edge_cache, last_basic_block);
-
-      if (update_p)
-        FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
-         {
-           edge e;
-           edge_iterator ei;
-
-           FOR_EACH_EDGE (e, ei, bb->succs)
-             if (e->dest != EXIT_BLOCK_PTR)
-               SET_BIT (edge_cache[bb->index], e->dest->index);
-         }
-    }
+  if (forced_labels || cfun->cfg->max_jumptable_ents > 100)
+    edge_cache = sbitmap_alloc (last_basic_block);
 
   /* By nature of the way these get numbered, ENTRY_BLOCK_PTR->next_bb block
      is always the entry.  */
   if (min == ENTRY_BLOCK_PTR->next_bb)
-    cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, min,
-                     EDGE_FALLTHRU);
+    make_edge (ENTRY_BLOCK_PTR, min, EDGE_FALLTHRU);
 
   FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
     {
       rtx insn, x;
       enum rtx_code code;
       edge e;
+      edge_iterator ei;
+
+      if (STATE (bb) == BLOCK_ORIGINAL)
+       continue;
+
+      /* If we have an edge cache, cache edges going out of BB.  */
+      if (edge_cache)
+       {
+         sbitmap_zero (edge_cache);
+         if (update_p)
+           {
+             FOR_EACH_EDGE (e, ei, bb->succs)
+               if (e->dest != EXIT_BLOCK_PTR)
+                 SET_BIT (edge_cache, e->dest->index);
+           }
+       }
 
       if (LABEL_P (BB_HEAD (bb))
          && LABEL_ALT_ENTRY_P (BB_HEAD (bb)))
@@ -325,8 +340,6 @@ make_edges (basic_block min, basic_block max, int update_p)
             everything on the forced_labels list.  */
          else if (computed_jump_p (insn))
            {
-             current_function_has_computed_jump = 1;
-
              for (x = forced_labels; x; x = XEXP (x, 1))
                make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
            }
@@ -388,7 +401,7 @@ make_edges (basic_block min, basic_block max, int update_p)
 
       while (insn
             && NOTE_P (insn)
-            && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
+            && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK)
        insn = NEXT_INSN (insn);
 
       if (!insn)
@@ -455,22 +468,18 @@ find_basic_blocks_1 (rtx f)
       switch (code)
        {
        case NOTE:
-         {
-           int kind = NOTE_LINE_NUMBER (insn);
-
-           /* Look for basic block notes with which to keep the
-              basic_block_info pointers stable.  Unthread the note now;
-              we'll put it back at the right place in create_basic_block.
-              Or not at all if we've already found a note in this block.  */
-           if (kind == NOTE_INSN_BASIC_BLOCK)
-             {
-               if (bb_note == NULL_RTX)
-                 bb_note = insn;
-               else
-                 next = delete_insn (insn);
-             }
-           break;
-         }
+         /* Look for basic block notes with which to keep the
+            basic_block_info pointers stable.  Unthread the note now;
+            we'll put it back at the right place in create_basic_block.
+            Or not at all if we've already found a note in this block.  */
+         if (NOTE_INSN_BASIC_BLOCK_P (insn))
+           {
+             if (bb_note == NULL_RTX)
+               bb_note = insn;
+             else
+               next = delete_insn (insn);
+           }
+         break;
 
        case CODE_LABEL:
        case JUMP_INSN:
@@ -496,12 +505,10 @@ find_basic_blocks_1 (rtx f)
 
 
 /* Find basic blocks of the current function.
-   F is the first insn of the function and NREGS the number of register
-   numbers in use.  */
+   F is the first insn of the function.  */
 
 void
-find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
-                  FILE *file ATTRIBUTE_UNUSED)
+find_basic_blocks (rtx f)
 {
   basic_block bb;
 
@@ -522,10 +529,11 @@ find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
     }
 
   n_basic_blocks = count_basic_blocks (f);
-  last_basic_block = 0;
+  last_basic_block = NUM_FIXED_BLOCKS;
   ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
   EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
 
+
   /* Size the basic block table.  The actual structures will be allocated
      by find_basic_blocks_1, since we want to keep the structure pointers
      stable across calls to find_basic_blocks.  */
@@ -534,12 +542,19 @@ find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
      instructions at all until close to the end of compilation when we
      actually lay them out.  */
 
-  VARRAY_BB_INIT (basic_block_info, n_basic_blocks, "basic_block_info");
+  basic_block_info = VEC_alloc (basic_block, gc, n_basic_blocks);
+  VEC_safe_grow_cleared (basic_block, gc, basic_block_info, n_basic_blocks);
+  SET_BASIC_BLOCK (ENTRY_BLOCK, ENTRY_BLOCK_PTR);
+  SET_BASIC_BLOCK (EXIT_BLOCK, EXIT_BLOCK_PTR);
 
   find_basic_blocks_1 (f);
 
   profile_status = PROFILE_ABSENT;
 
+  /* Tell make_edges to examine every block for out-going edges.  */
+  FOR_EACH_BB (bb)
+    SET_STATE (bb, BLOCK_NEW);
+
   /* Discover the edges of our cfg.  */
   make_edges (ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, 0);
 
@@ -553,16 +568,6 @@ find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
   timevar_pop (TV_CFG);
 }
 \f
-/* State of basic block as seen by find_sub_basic_blocks.  */
-enum state {BLOCK_NEW = 0, BLOCK_ORIGINAL, BLOCK_TO_SPLIT};
-
-#define STATE(BB) (enum state) ((size_t) (BB)->aux)
-#define SET_STATE(BB, STATE) ((BB)->aux = (void *) (size_t) (STATE))
-
-/* Used internally by purge_dead_tablejump_edges, ORed into state.  */
-#define BLOCK_USED_BY_TABLEJUMP                32
-#define FULL_STATE(BB) ((size_t) (BB)->aux)
-
 static void
 mark_tablejump_edge (rtx label)
 {
@@ -605,13 +610,13 @@ purge_dead_tablejump_edges (basic_block bb, rtx table)
   for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
     {
       if (FULL_STATE (e->dest) & BLOCK_USED_BY_TABLEJUMP)
-        SET_STATE (e->dest, FULL_STATE (e->dest)
-                            & ~(size_t) BLOCK_USED_BY_TABLEJUMP);
+       SET_STATE (e->dest, FULL_STATE (e->dest)
+                           & ~(size_t) BLOCK_USED_BY_TABLEJUMP);
       else if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
-        {
-          remove_edge (e);
-          continue;
-        }
+       {
+         remove_edge (e);
+         continue;
+       }
       ei_next (&ei);
     }
 }
@@ -624,7 +629,7 @@ find_bb_boundaries (basic_block bb)
 {
   basic_block orig_bb = bb;
   rtx insn = BB_HEAD (bb);
-  rtx end = BB_END (bb);
+  rtx end = BB_END (bb), x;
   rtx table;
   rtx flow_transfer_insn = NULL_RTX;
   edge fallthru = NULL;
@@ -645,7 +650,16 @@ find_bb_boundaries (basic_block bb)
        {
          fallthru = split_block (bb, PREV_INSN (insn));
          if (flow_transfer_insn)
-           BB_END (bb) = flow_transfer_insn;
+           {
+             BB_END (bb) = flow_transfer_insn;
+
+             /* Clean up the bb field for the insns between the blocks.  */
+             for (x = NEXT_INSN (flow_transfer_insn);
+                  x != BB_HEAD (fallthru->dest);
+                  x = NEXT_INSN (x))
+               if (!BARRIER_P (x))
+                 set_block_for_insn (x, NULL);
+           }
 
          bb = fallthru->dest;
          remove_edge (fallthru);
@@ -660,6 +674,14 @@ find_bb_boundaries (basic_block bb)
        {
          fallthru = split_block (bb, PREV_INSN (insn));
          BB_END (bb) = flow_transfer_insn;
+
+         /* Clean up the bb field for the insns between the blocks.  */
+         for (x = NEXT_INSN (flow_transfer_insn);
+              x != BB_HEAD (fallthru->dest);
+              x = NEXT_INSN (x))
+           if (!BARRIER_P (x))
+             set_block_for_insn (x, NULL);
+
          bb = fallthru->dest;
          remove_edge (fallthru);
          flow_transfer_insn = NULL_RTX;
@@ -676,7 +698,18 @@ find_bb_boundaries (basic_block bb)
      return and barrier, or possibly other sequence not behaving like
      ordinary jump, we need to take care and move basic block boundary.  */
   if (flow_transfer_insn)
-    BB_END (bb) = flow_transfer_insn;
+    {
+      BB_END (bb) = flow_transfer_insn;
+
+      /* Clean up the bb field for the insns that do not belong to BB.  */
+      x = flow_transfer_insn;
+      while (x != end)
+       {
+         x = NEXT_INSN (x);
+         if (!BARRIER_P (x))
+           set_block_for_insn (x, NULL);
+       }
+    }
 
   /* We've possibly replaced the conditional jump by conditional jump
      followed by cleanup at fallthru edge, so the outgoing edges may
@@ -717,9 +750,9 @@ compute_outgoing_frequencies (basic_block b)
        }
     }
 
-  if (EDGE_COUNT (b->succs) == 1)
+  if (single_succ_p (b))
     {
-      e = EDGE_SUCC (b, 0);
+      e = single_succ_edge (b);
       e->probability = REG_BR_PROB_BASE;
       e->count = b->count;
       return;
@@ -731,8 +764,9 @@ compute_outgoing_frequencies (basic_block b)
                  / REG_BR_PROB_BASE);
 }
 
-/* Assume that someone emitted code with control flow instructions to the
-   basic block.  Update the data structure.  */
+/* Assume that some pass has inserted labels or control flow
+   instructions within a basic block.  Split basic blocks as needed
+   and create edges.  */
 
 void
 find_many_sub_basic_blocks (sbitmap blocks)
@@ -787,41 +821,3 @@ find_many_sub_basic_blocks (sbitmap blocks)
   FOR_EACH_BB (bb)
     SET_STATE (bb, 0);
 }
-
-/* Like above but for single basic block only.  */
-
-void
-find_sub_basic_blocks (basic_block bb)
-{
-  basic_block min, max, b;
-  basic_block next = bb->next_bb;
-
-  min = bb;
-  find_bb_boundaries (bb);
-  max = next->prev_bb;
-
-  /* Now re-scan and wire in all edges.  This expect simple (conditional)
-     jumps at the end of each new basic blocks.  */
-  make_edges (min, max, 1);
-
-  /* Update branch probabilities.  Expect only (un)conditional jumps
-     to be created with only the forward edges.  */
-  FOR_BB_BETWEEN (b, min, max->next_bb, next_bb)
-    {
-      edge e;
-      edge_iterator ei;
-
-      if (b != min)
-       {
-         b->count = 0;
-         b->frequency = 0;
-         FOR_EACH_EDGE (e, ei, b->preds)
-           {
-             b->count += e->count;
-             b->frequency += EDGE_FREQUENCY (e);
-           }
-       }
-
-      compute_outgoing_frequencies (b);
-    }
-}