diff gcc/cfgbuild.c @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents a06113de4d67
children b7f97abdc517
line wrap: on
line diff
--- a/gcc/cfgbuild.c	Sun Feb 07 18:28:00 2010 +0900
+++ b/gcc/cfgbuild.c	Fri Feb 12 23:39:51 2010 +0900
@@ -19,16 +19,6 @@
 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
-   basic_block_info array; the CFG exists in the edge structures
-   referenced by the blocks.
-
-   find_basic_blocks also finds any unreachable loops and deletes them.
-
-   Available functionality:
-     - CFG construction
-	 find_basic_blocks  */
 
 #include "config.h"
 #include "system.h"
@@ -43,11 +33,10 @@
 #include "output.h"
 #include "function.h"
 #include "except.h"
+#include "expr.h"
 #include "toplev.h"
 #include "timevar.h"
 
-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 find_bb_boundaries (basic_block);
@@ -74,6 +63,7 @@
 
     case CALL_INSN:
     case INSN:
+    case DEBUG_INSN:
       return true;
 
     case BARRIER:
@@ -91,12 +81,11 @@
 bool
 control_flow_insn_p (const_rtx insn)
 {
-  rtx note;
-
   switch (GET_CODE (insn))
     {
     case NOTE:
     case CODE_LABEL:
+    case DEBUG_INSN:
       return false;
 
     case JUMP_INSN:
@@ -111,21 +100,20 @@
 	   || 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,
-					       NULL_RTX))
-		   || INTVAL (XEXP (note, 0)) >= 0))
-	      /* Or may trap.  */
-	      || can_throw_internal (insn));
+      if (can_nonlocal_goto (insn))
+	return true;
+      break;
 
     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));
+      if (!flag_non_call_exceptions)
+	return false;
+      break;
 
     case BARRIER:
       /* It is nonsense to reach barrier when looking for the
@@ -136,47 +124,10 @@
     default:
       gcc_unreachable ();
     }
+
+  return can_throw_internal (insn);
 }
 
-/* Count the basic blocks of the function.  */
-
-static int
-count_basic_blocks (const_rtx f)
-{
-  int count = NUM_FIXED_BLOCKS;
-  bool saw_insn = false;
-  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.  */
-      if ((LABEL_P (insn) || BARRIER_P (insn))
-	  && saw_insn)
-	count++, saw_insn = false;
-
-      /* Start basic block if needed.  */
-      if (!saw_insn && inside_basic_block_p (insn))
-	saw_insn = true;
-
-      /* Control flow insn causes current basic block to be terminated.  */
-      if (saw_insn && control_flow_insn_p (insn))
-	count++, saw_insn = false;
-    }
-
-  if (saw_insn)
-    count++;
-
-  /* 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 == NUM_FIXED_BLOCKS)
-    {
-      emit_use (const0_rtx);
-      count = NUM_FIXED_BLOCKS + 1;
-    }
-
-  return count;
-}
 
 /* Create an edge between two basic blocks.  FLAGS are auxiliary information
    about the edge that is accumulated between calls.  */
@@ -204,16 +155,23 @@
 void
 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;
+  eh_landing_pad lp = get_eh_landing_pad_from_rtx (insn);
 
-  handlers = reachable_handlers (insn);
+  if (lp)
+    {
+      rtx label = lp->landing_pad;
 
-  for (i = handlers; i; i = XEXP (i, 1))
-    make_label_edge (edge_cache, src, XEXP (i, 0),
-		     EDGE_ABNORMAL | EDGE_EH | is_call);
+      /* During initial rtl generation, use the post_landing_pad.  */
+      if (label == NULL)
+	{
+	  gcc_assert (lp->post_landing_pad);
+	  label = label_rtx (lp->post_landing_pad);
+	}
 
-  free_INSN_LIST_list (&handlers);
+      make_label_edge (edge_cache, src, label,
+		       EDGE_ABNORMAL | EDGE_EH
+		       | (CALL_P (insn) ? EDGE_ABNORMAL_CALL : 0));
+    }
 }
 
 /* States of basic block as seen by find_many_sub_basic_blocks.  */
@@ -302,13 +260,9 @@
 	{
 	  rtx tmp;
 
-	  /* Recognize exception handling placeholders.  */
-	  if (GET_CODE (PATTERN (insn)) == RESX)
-	    rtl_make_eh_edge (edge_cache, bb, insn);
-
 	  /* Recognize a non-local goto as a branch outside the
 	     current function.  */
-	  else if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
+	  if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
 	    ;
 
 	  /* Recognize a tablejump and do the right thing.  */
@@ -349,6 +303,15 @@
 	  else if (returnjump_p (insn))
 	    cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, 0);
 
+	  /* Recognize asm goto and do the right thing.  */
+	  else if ((tmp = extract_asm_operands (PATTERN (insn))) != NULL)
+	    {
+	      int i, n = ASM_OPERANDS_LABEL_LENGTH (tmp);
+	      for (i = 0; i < n; ++i)
+		make_label_edge (edge_cache, bb,
+				 XEXP (ASM_OPERANDS_LABEL (tmp, i), 0), 0);
+	    }
+
 	  /* Otherwise, we have a plain conditional or unconditional jump.  */
 	  else
 	    {
@@ -382,12 +345,7 @@
 		 gotos do not have their addresses taken, then only calls to
 		 those functions or to other nested functions that use them
 		 could possibly do nonlocal gotos.  */
-
-	      /* We do know that a REG_EH_REGION note with a value less
-		 than 0 is guaranteed not to perform a non-local goto.  */
-	      rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-
-	      if (!note || INTVAL (XEXP (note, 0)) >=  0)
+	      if (can_nonlocal_goto (insn))
 		for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
 		  make_label_edge (edge_cache, bb, XEXP (x, 0),
 				   EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
@@ -418,157 +376,6 @@
     sbitmap_vector_free (edge_cache);
 }
 
-/* Find all basic blocks of the function whose first insn is F.
-
-   Collect and return a list of labels whose addresses are taken.  This
-   will be used in make_edges for use with computed gotos.  */
-
-static void
-find_basic_blocks_1 (rtx f)
-{
-  rtx insn, next;
-  rtx bb_note = NULL_RTX;
-  rtx head = NULL_RTX;
-  rtx end = NULL_RTX;
-  basic_block prev = ENTRY_BLOCK_PTR;
-
-  /* We process the instructions in a slightly different way than we did
-     previously.  This is so that we see a NOTE_BASIC_BLOCK after we have
-     closed out the previous block, so that it gets attached at the proper
-     place.  Since this form should be equivalent to the previous,
-     count_basic_blocks continues to use the old form as a check.  */
-
-  for (insn = f; insn; insn = next)
-    {
-      enum rtx_code code = GET_CODE (insn);
-
-      next = NEXT_INSN (insn);
-
-      if ((LABEL_P (insn) || BARRIER_P (insn))
-	  && head)
-	{
-	  prev = create_basic_block_structure (head, end, bb_note, prev);
-	  head = end = NULL_RTX;
-	  bb_note = NULL_RTX;
-	}
-
-      if (inside_basic_block_p (insn))
-	{
-	  if (head == NULL_RTX)
-	    head = insn;
-	  end = insn;
-	}
-
-      if (head && control_flow_insn_p (insn))
-	{
-	  prev = create_basic_block_structure (head, end, bb_note, prev);
-	  head = end = NULL_RTX;
-	  bb_note = NULL_RTX;
-	}
-
-      switch (code)
-	{
-	case NOTE:
-	  /* 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:
-	case CALL_INSN:
-	case INSN:
-	case BARRIER:
-	  break;
-
-	default:
-	  gcc_unreachable ();
-	}
-    }
-
-  if (head != NULL_RTX)
-    create_basic_block_structure (head, end, bb_note, prev);
-  else if (bb_note)
-    delete_insn (bb_note);
-
-  gcc_assert (last_basic_block == n_basic_blocks);
-
-  clear_aux_for_blocks ();
-}
-
-
-/* Find basic blocks of the current function.
-   F is the first insn of the function.  */
-
-void
-find_basic_blocks (rtx f)
-{
-  basic_block bb;
-
-  timevar_push (TV_CFG);
-
-  /* Flush out existing data.  */
-  if (basic_block_info != NULL)
-    {
-      clear_edges ();
-
-      /* Clear bb->aux on all extant basic blocks.  We'll use this as a
-	 tag for reuse during create_basic_block, just in case some pass
-	 copies around basic block notes improperly.  */
-      FOR_EACH_BB (bb)
-	bb->aux = NULL;
-
-      basic_block_info = NULL;
-    }
-
-  n_basic_blocks = count_basic_blocks (f);
-  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.  */
-  /* ??? This whole issue would be much simpler if we called find_basic_blocks
-     exactly once, and thereafter we don't have a single long chain of
-     instructions at all until close to the end of compilation when we
-     actually lay them out.  */
-
-  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);
-
-  /* Do very simple cleanup now, for the benefit of code that runs between
-     here and cleanup_cfg, e.g. thread_prologue_and_epilogue_insns.  */
-  tidy_fallthru_edges ();
-
-#ifdef ENABLE_CHECKING
-  verify_flow_info ();
-#endif
-  timevar_pop (TV_CFG);
-}
-
 static void
 mark_tablejump_edge (rtx label)
 {
@@ -646,8 +453,10 @@
     {
       enum rtx_code code = GET_CODE (insn);
 
-      /* On code label, split current basic block.  */
-      if (code == CODE_LABEL)
+      /* In case we've previously seen an insn that effects a control
+	 flow transfer, split the block.  */
+      if ((flow_transfer_insn || code == CODE_LABEL)
+	  && inside_basic_block_p (insn))
 	{
 	  fallthru = split_block (bb, PREV_INSN (insn));
 	  if (flow_transfer_insn)
@@ -665,27 +474,16 @@
 	  bb = fallthru->dest;
 	  remove_edge (fallthru);
 	  flow_transfer_insn = NULL_RTX;
-	  if (LABEL_ALT_ENTRY_P (insn))
+	  if (code == CODE_LABEL && LABEL_ALT_ENTRY_P (insn))
 	    make_edge (ENTRY_BLOCK_PTR, bb, 0);
 	}
-
-      /* In case we've previously seen an insn that effects a control
-	 flow transfer, split the block.  */
-      if (flow_transfer_insn && inside_basic_block_p (insn))
+      else if (code == BARRIER)
 	{
-	  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;
+	  /* __builtin_unreachable () may cause a barrier to be emitted in
+	     the middle of a BB.  We need to split it in the same manner as
+	     if the barrier were preceded by a control_flow_insn_p insn.  */
+	  if (!flow_transfer_insn)
+	    flow_transfer_insn = prev_nonnote_insn_bb (insn);
 	}
 
       if (control_flow_insn_p (insn))