OSDN Git Service

* tree-pretty-print.c (dump_generic_node, case ARRAY_TYPE): Properly
[pf3gnuchains/gcc-fork.git] / gcc / cfgbuild.c
index cd662da..ac064cf 100644 (file)
@@ -1,6 +1,6 @@
 /* Control flow graph building code for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -50,10 +50,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 static int count_basic_blocks (rtx);
 static void find_basic_blocks_1 (rtx);
-static rtx find_label_refs (rtx, rtx);
-static void make_edges (rtx, basic_block, basic_block, int);
+static void make_edges (basic_block, basic_block, int);
 static void make_label_edge (sbitmap *, basic_block, rtx, int);
-static void make_eh_edge (sbitmap *, basic_block, rtx);
 static void find_bb_boundaries (basic_block);
 static void compute_outgoing_frequencies (basic_block);
 \f
@@ -109,6 +107,12 @@ control_flow_insn_p (rtx insn)
              && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
 
     case CALL_INSN:
+      /* Noreturn and sibling call instructions terminate the basic blocks
+        (but only if they happen unconditionally).  */
+      if ((SIBLING_CALL_P (insn)
+          || find_reg_note (insn, REG_NORETURN, 0))
+         && GET_CODE (PATTERN (insn)) != COND_EXEC)
+       return true;
       /* Call insn may return to the nonlocal goto handler.  */
       return ((nonlocal_goto_handler_labels
               && (0 == (note = find_reg_note (insn, REG_EH_REGION,
@@ -170,51 +174,6 @@ count_basic_blocks (rtx f)
 
   return count;
 }
-
-/* Scan a list of insns for labels referred to other than by jumps.
-   This is used to scan the alternatives of a call placeholder.  */
-
-static rtx
-find_label_refs (rtx f, rtx lvl)
-{
-  rtx insn;
-
-  for (insn = f; insn; insn = NEXT_INSN (insn))
-    if (INSN_P (insn) && GET_CODE (insn) != JUMP_INSN)
-      {
-       rtx note;
-
-       /* Make a list of all labels referred to other than by jumps
-          (which just don't have the REG_LABEL notes).
-
-          Make a special exception for labels followed by an ADDR*VEC,
-          as this would be a part of the tablejump setup code.
-
-          Make a special exception to registers loaded with label
-          values just before jump insns that use them.  */
-
-       for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-         if (REG_NOTE_KIND (note) == REG_LABEL)
-           {
-             rtx lab = XEXP (note, 0), next;
-
-             if ((next = next_nonnote_insn (lab)) != NULL
-                 && GET_CODE (next) == JUMP_INSN
-                 && (GET_CODE (PATTERN (next)) == ADDR_VEC
-                     || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
-               ;
-             else if (GET_CODE (lab) == NOTE)
-               ;
-             else if (GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
-                      && find_reg_note (NEXT_INSN (insn), REG_LABEL, lab))
-               ;
-             else
-               lvl = alloc_EXPR_LIST (0, XEXP (note, 0), lvl);
-           }
-      }
-
-  return lvl;
-}
 \f
 /* Create an edge between two basic blocks.  FLAGS are auxiliary information
    about the edge that is accumulated between calls.  */
@@ -240,8 +199,8 @@ make_label_edge (sbitmap *edge_cache, basic_block src, rtx label, int flags)
 
 /* Create the edges generated by INSN in REGION.  */
 
-static void
-make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
+void
+rtl_make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
 {
   int is_call = GET_CODE (insn) == CALL_INSN ? EDGE_ABNORMAL_CALL : 0;
   rtx handlers, i;
@@ -264,7 +223,7 @@ make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
    the list of exception regions active at the end of the basic block.  */
 
 static void
-make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p)
+make_edges (basic_block min, basic_block max, int update_p)
 {
   basic_block bb;
   sbitmap *edge_cache = NULL;
@@ -272,10 +231,16 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
   /* 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.  */
+
+  if (flag_reorder_blocks_and_partition)
+    current_function_has_computed_jump = 1;
+
   /* 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 || label_value_list || cfun->max_jumptable_ents > 100)
+  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);
@@ -302,14 +267,16 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
       rtx insn, x;
       enum rtx_code code;
       int force_fallthru = 0;
+      edge e;
 
-      if (GET_CODE (bb->head) == CODE_LABEL && LABEL_ALT_ENTRY_P (bb->head))
+      if (GET_CODE (BB_HEAD (bb)) == CODE_LABEL
+         && LABEL_ALT_ENTRY_P (BB_HEAD (bb)))
        cached_make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0);
 
       /* Examine the last instruction of the block, and discover the
         ways we can leave the block.  */
 
-      insn = bb->end;
+      insn = BB_END (bb);
       code = GET_CODE (insn);
 
       /* A branch.  */
@@ -319,7 +286,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
 
          /* Recognize exception handling placeholders.  */
          if (GET_CODE (PATTERN (insn)) == RESX)
-           make_eh_edge (edge_cache, bb, insn);
+           rtl_make_eh_edge (edge_cache, bb, insn);
 
          /* Recognize a non-local goto as a branch outside the
             current function.  */
@@ -359,14 +326,11 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
            }
 
          /* If this is a computed jump, then mark it as reaching
-            everything on the label_value_list and forced_labels list.  */
+            everything on the forced_labels list.  */
          else if (computed_jump_p (insn))
            {
              current_function_has_computed_jump = 1;
 
-             for (x = label_value_list; x; x = XEXP (x, 1))
-               make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
-
              for (x = forced_labels; x; x = XEXP (x, 1))
                make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
            }
@@ -399,7 +363,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
       else if (code == CALL_INSN || flag_non_call_exceptions)
        {
          /* Add any appropriate EH edges.  */
-         make_eh_edge (edge_cache, bb, insn);
+         rtl_make_eh_edge (edge_cache, bb, insn);
 
          if (code == CALL_INSN && nonlocal_goto_handler_labels)
            {
@@ -423,6 +387,12 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
 
       /* Find out if we can drop through to the next block.  */
       insn = NEXT_INSN (insn);
+      for (e = bb->succ; e; e = e->succ_next)
+       if (e->dest == EXIT_BLOCK_PTR && e->flags & EDGE_FALLTHRU)
+         {
+           insn = 0;
+           break;
+         }
       while (insn
             && GET_CODE (insn) == NOTE
             && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
@@ -432,7 +402,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
        cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
       else if (bb->next_bb != EXIT_BLOCK_PTR)
        {
-         if (force_fallthru || insn == bb->next_bb->head)
+         if (force_fallthru || insn == BB_HEAD (bb->next_bb))
            cached_make_edge (edge_cache, bb, bb->next_bb, EDGE_FALLTHRU);
        }
     }
@@ -451,8 +421,6 @@ find_basic_blocks_1 (rtx f)
 {
   rtx insn, next;
   rtx bb_note = NULL_RTX;
-  rtx lvl = NULL_RTX;
-  rtx trll = NULL_RTX;
   rtx head = NULL_RTX;
   rtx end = NULL_RTX;
   basic_block prev = ENTRY_BLOCK_PTR;
@@ -513,58 +481,14 @@ find_basic_blocks_1 (rtx f)
 
        case CODE_LABEL:
        case JUMP_INSN:
+       case CALL_INSN:
        case INSN:
        case BARRIER:
          break;
 
-       case CALL_INSN:
-         if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
-           {
-             /* Scan each of the alternatives for label refs.  */
-             lvl = find_label_refs (XEXP (PATTERN (insn), 0), lvl);
-             lvl = find_label_refs (XEXP (PATTERN (insn), 1), lvl);
-             lvl = find_label_refs (XEXP (PATTERN (insn), 2), lvl);
-             /* Record its tail recursion label, if any.  */
-             if (XEXP (PATTERN (insn), 3) != NULL_RTX)
-               trll = alloc_EXPR_LIST (0, XEXP (PATTERN (insn), 3), trll);
-           }
-         break;
-
        default:
          abort ();
        }
-
-      if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
-       {
-         rtx note;
-
-         /* Make a list of all labels referred to other than by jumps.
-
-            Make a special exception for labels followed by an ADDR*VEC,
-            as this would be a part of the tablejump setup code.
-
-            Make a special exception to registers loaded with label
-            values just before jump insns that use them.  */
-
-         for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-           if (REG_NOTE_KIND (note) == REG_LABEL)
-             {
-               rtx lab = XEXP (note, 0), next;
-
-               if ((next = next_nonnote_insn (lab)) != NULL
-                        && GET_CODE (next) == JUMP_INSN
-                        && (GET_CODE (PATTERN (next)) == ADDR_VEC
-                            || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
-                 ;
-               else if (GET_CODE (lab) == NOTE)
-                 ;
-               else if (GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
-                        && find_reg_note (NEXT_INSN (insn), REG_LABEL, lab))
-                 ;
-               else
-                 lvl = alloc_EXPR_LIST (0, XEXP (note, 0), lvl);
-             }
-       }
     }
 
   if (head != NULL_RTX)
@@ -575,8 +499,6 @@ find_basic_blocks_1 (rtx f)
   if (last_basic_block != n_basic_blocks)
     abort ();
 
-  label_value_list = lvl;
-  tail_recursion_label_list = trll;
   clear_aux_for_blocks ();
 }
 
@@ -604,7 +526,7 @@ find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
       FOR_EACH_BB (bb)
        bb->aux = NULL;
 
-      VARRAY_FREE (basic_block_info);
+      basic_block_info = NULL;
     }
 
   n_basic_blocks = count_basic_blocks (f);
@@ -625,7 +547,7 @@ find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
   find_basic_blocks_1 (f);
 
   /* Discover the edges of our cfg.  */
-  make_edges (label_value_list, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, 0);
+  make_edges (ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, 0);
 
   /* Do very simple cleanup now, for the benefit of code that runs between
      here and cleanup_cfg, e.g. thread_prologue_and_epilogue_insns.  */
@@ -649,12 +571,12 @@ enum state {BLOCK_NEW = 0, BLOCK_ORIGINAL, BLOCK_TO_SPLIT};
 static void
 find_bb_boundaries (basic_block bb)
 {
-  rtx insn = bb->head;
-  rtx end = bb->end;
+  rtx insn = BB_HEAD (bb);
+  rtx end = BB_END (bb);
   rtx flow_transfer_insn = NULL_RTX;
   edge fallthru = NULL;
 
-  if (insn == bb->end)
+  if (insn == BB_END (bb))
     return;
 
   if (GET_CODE (insn) == CODE_LABEL)
@@ -670,7 +592,7 @@ find_bb_boundaries (basic_block bb)
        {
          fallthru = split_block (bb, PREV_INSN (insn));
          if (flow_transfer_insn)
-           bb->end = flow_transfer_insn;
+           BB_END (bb) = flow_transfer_insn;
 
          bb = fallthru->dest;
          remove_edge (fallthru);
@@ -684,7 +606,7 @@ find_bb_boundaries (basic_block bb)
       if (flow_transfer_insn && inside_basic_block_p (insn))
        {
          fallthru = split_block (bb, PREV_INSN (insn));
-         bb->end = flow_transfer_insn;
+         BB_END (bb) = flow_transfer_insn;
          bb = fallthru->dest;
          remove_edge (fallthru);
          flow_transfer_insn = NULL_RTX;
@@ -701,7 +623,7 @@ 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 = flow_transfer_insn;
+    BB_END (bb) = flow_transfer_insn;
 
   /* We've possibly replaced the conditional jump by conditional jump
      followed by cleanup at fallthru edge, so the outgoing edges may
@@ -719,15 +641,13 @@ compute_outgoing_frequencies (basic_block b)
 
   if (b->succ && b->succ->succ_next && !b->succ->succ_next->succ_next)
     {
-      rtx note = find_reg_note (b->end, REG_BR_PROB, NULL);
+      rtx note = find_reg_note (BB_END (b), REG_BR_PROB, NULL);
       int probability;
 
       if (!note)
        return;
 
-      probability = INTVAL (XEXP (find_reg_note (b->end,
-                                                REG_BR_PROB, NULL),
-                                 0));
+      probability = INTVAL (XEXP (note, 0));
       e = BRANCH_EDGE (b);
       e->probability = probability;
       e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
@@ -772,7 +692,7 @@ find_many_sub_basic_blocks (sbitmap blocks)
 
   /* Now re-scan and wire in all edges.  This expect simple (conditional)
      jumps at the end of each new basic blocks.  */
-  make_edges (NULL, min, max, 1);
+  make_edges (min, max, 1);
 
   /* Update branch probabilities.  Expect only (un)conditional jumps
      to be created with only the forward edges.  */
@@ -814,7 +734,7 @@ find_sub_basic_blocks (basic_block bb)
 
   /* Now re-scan and wire in all edges.  This expect simple (conditional)
      jumps at the end of each new basic blocks.  */
-  make_edges (NULL, min, max, 1);
+  make_edges (min, max, 1);
 
   /* Update branch probabilities.  Expect only (un)conditional jumps
      to be created with only the forward edges.  */