diff gcc/cfgrtl.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 58ad6c70ea60
children b7f97abdc517
line wrap: on
line diff
--- a/gcc/cfgrtl.c	Sun Feb 07 18:28:00 2010 +0900
+++ b/gcc/cfgrtl.c	Fri Feb 12 23:39:51 2010 +0900
@@ -1,6 +1,6 @@
 /* Control flow graph manipulation code for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -65,7 +65,6 @@
 
 static int can_delete_note_p (const_rtx);
 static int can_delete_label_p (const_rtx);
-static void commit_one_edge_insertion (edge);
 static basic_block rtl_split_edge (edge);
 static bool rtl_move_block_after (basic_block, basic_block);
 static int rtl_verify_flow_info (void);
@@ -87,8 +86,16 @@
 static int
 can_delete_note_p (const_rtx note)
 {
-  return (NOTE_KIND (note) == NOTE_INSN_DELETED
-	  || NOTE_KIND (note) == NOTE_INSN_BASIC_BLOCK);
+  switch (NOTE_KIND (note))
+    {
+    case NOTE_INSN_DELETED:
+    case NOTE_INSN_BASIC_BLOCK:
+    case NOTE_INSN_EPILOGUE_BEG:
+      return true;
+
+    default:
+      return false;
+    }
 }
 
 /* True if a given label can be deleted.  */
@@ -163,9 +170,7 @@
       remove_note (insn, note);
     }
 
-  if (JUMP_P (insn)
-      && (GET_CODE (PATTERN (insn)) == ADDR_VEC
-	  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
+  if (JUMP_TABLE_DATA_P (insn))
     {
       rtx pat = PATTERN (insn);
       int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
@@ -233,22 +238,6 @@
       start = next;
     }
 }
-
-/* Like delete_insn_chain but also purge dead edges from BB.  */
-
-void
-delete_insn_chain_and_edges (rtx first, rtx last)
-{
-  bool purge = false;
-
-  if (INSN_P (last)
-      && BLOCK_FOR_INSN (last)
-      && BB_END (BLOCK_FOR_INSN (last)) == last)
-    purge = true;
-  delete_insn_chain (first, last, false);
-  if (purge)
-    purge_dead_edges (BLOCK_FOR_INSN (last));
-}
 
 /* Create a new basic block consisting of the instructions between HEAD and END
    inclusive.  This function is designed to allow fast BB construction - reuses
@@ -380,8 +369,6 @@
      label for an exception handler which can't be reached.  We need
      to remove the label from the exception_handler_label list.  */
   insn = BB_HEAD (b);
-  if (LABEL_P (insn))
-    maybe_remove_eh_handler (insn);
 
   end = get_last_bb_insn (b);
 
@@ -446,13 +433,13 @@
 {
  {
   RTL_PASS,
-  NULL,                                 /* name */
+  "*free_cfg",                          /* name */
   NULL,                                 /* gate */
   rest_of_pass_free_cfg,                /* execute */
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  0,                                    /* tv_id */
+  TV_NONE,                              /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   PROP_cfg,                             /* properties_destroyed */
@@ -483,7 +470,7 @@
 }
 
 /* Update BLOCK_FOR_INSN of insns between BEGIN and END
-   (or BARRIER if found) and notify df of the bb change. 
+   (or BARRIER if found) and notify df of the bb change.
    The insn chain range is inclusive
    (i.e. both BEGIN and END will be updated. */
 
@@ -544,7 +531,26 @@
       insn = first_insn_after_basic_block_note (bb);
 
       if (insn)
-	insn = PREV_INSN (insn);
+	{
+	  rtx next = insn;
+
+	  insn = PREV_INSN (insn);
+
+	  /* If the block contains only debug insns, insn would have
+	     been NULL in a non-debug compilation, and then we'd end
+	     up emitting a DELETED note.  For -fcompare-debug
+	     stability, emit the note too.  */
+	  if (insn != BB_END (bb)
+	      && DEBUG_INSN_P (next)
+	      && DEBUG_INSN_P (BB_END (bb)))
+	    {
+	      while (next != BB_END (bb) && DEBUG_INSN_P (next))
+		next = NEXT_INSN (next);
+
+	      if (next == BB_END (bb))
+		emit_note_after (NOTE_INSN_DELETED, next);
+	    }
+	}
       else
 	insn = get_last_insn ();
     }
@@ -579,18 +585,18 @@
 {
   rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a);
   rtx del_first = NULL_RTX, del_last = NULL_RTX;
+  rtx b_debug_start = b_end, b_debug_end = b_end;
   int b_empty = 0;
 
   if (dump_file)
     fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index);
 
+  while (DEBUG_INSN_P (b_end))
+    b_end = PREV_INSN (b_debug_start = b_end);
+
   /* If there was a CODE_LABEL beginning B, delete it.  */
   if (LABEL_P (b_head))
     {
-      /* This might have been an EH label that no longer has incoming
-	 EH edges.  Update data structures to match.  */
-      maybe_remove_eh_handler (b_head);
-
       /* Detect basic blocks with nothing but a label.  This can happen
 	 in particular at the end of a function.  */
       if (b_head == b_end)
@@ -653,9 +659,21 @@
   /* Reassociate the insns of B with A.  */
   if (!b_empty)
     {
-      update_bb_for_insn_chain (a_end, b_end, a);
-
-      a_end = b_end;
+      update_bb_for_insn_chain (a_end, b_debug_end, a);
+
+      a_end = b_debug_end;
+    }
+  else if (b_end != b_debug_end)
+    {
+      /* Move any deleted labels and other notes between the end of A
+	 and the debug insns that make up B after the debug insns,
+	 bringing the debug insns into A while keeping the notes after
+	 the end of A.  */
+      if (NEXT_INSN (a_end) != b_debug_start)
+	reorder_insns_nobb (NEXT_INSN (a_end), PREV_INSN (b_debug_start),
+			    b_debug_end);
+      update_bb_for_insn_chain (b_debug_start, b_debug_end, a);
+      a_end = b_debug_end;
     }
 
   df_bb_delete (b->index);
@@ -893,31 +911,25 @@
   return e;
 }
 
-/* Redirect edge representing branch of (un)conditional jump or tablejump,
-   NULL on failure  */
-static edge
-redirect_branch_edge (edge e, basic_block target)
+/* Subroutine of redirect_branch_edge that tries to patch the jump
+   instruction INSN so that it reaches block NEW.  Do this
+   only when it originally reached block OLD.  Return true if this
+   worked or the original target wasn't OLD, return false if redirection
+   doesn't work.  */
+
+static bool
+patch_jump_insn (rtx insn, rtx old_label, basic_block new_bb)
 {
   rtx tmp;
-  rtx old_label = BB_HEAD (e->dest);
-  basic_block src = e->src;
-  rtx insn = BB_END (src);
-
-  /* We can only redirect non-fallthru edges of jump insn.  */
-  if (e->flags & EDGE_FALLTHRU)
-    return NULL;
-  else if (!JUMP_P (insn))
-    return NULL;
-
   /* Recognize a tablejump and adjust all matching cases.  */
   if (tablejump_p (insn, NULL, &tmp))
     {
       rtvec vec;
       int j;
-      rtx new_label = block_label (target);
-
-      if (target == EXIT_BLOCK_PTR)
-	return NULL;
+      rtx new_label = block_label (new_bb);
+
+      if (new_bb == EXIT_BLOCK_PTR)
+	return false;
       if (GET_CODE (PATTERN (tmp)) == ADDR_VEC)
 	vec = XVEC (PATTERN (tmp), 0);
       else
@@ -944,6 +956,45 @@
 	  ++LABEL_NUSES (new_label);
 	}
     }
+  else if ((tmp = extract_asm_operands (PATTERN (insn))) != NULL)
+    {
+      int i, n = ASM_OPERANDS_LABEL_LENGTH (tmp);
+      rtx new_label, note;
+
+      if (new_bb == EXIT_BLOCK_PTR)
+	return false;
+      new_label = block_label (new_bb);
+
+      for (i = 0; i < n; ++i)
+	{
+	  rtx old_ref = ASM_OPERANDS_LABEL (tmp, i);
+	  gcc_assert (GET_CODE (old_ref) == LABEL_REF);
+	  if (XEXP (old_ref, 0) == old_label)
+	    {
+	      ASM_OPERANDS_LABEL (tmp, i)
+		= gen_rtx_LABEL_REF (Pmode, new_label);
+	      --LABEL_NUSES (old_label);
+	      ++LABEL_NUSES (new_label);
+	    }
+	}
+
+      if (JUMP_LABEL (insn) == old_label)
+	{
+	  JUMP_LABEL (insn) = new_label;
+	  note = find_reg_note (insn, REG_LABEL_TARGET, new_label);
+	  if (note)
+	    remove_note (insn, note);
+	}
+      else
+	{
+	  note = find_reg_note (insn, REG_LABEL_TARGET, old_label);
+	  if (note)
+	    remove_note (insn, note);
+	  if (JUMP_LABEL (insn) != new_label
+	      && !find_reg_note (insn, REG_LABEL_TARGET, new_label))
+	    add_reg_note (insn, REG_LABEL_TARGET, new_label);
+	}
+    }
   else
     {
       /* ?? We may play the games with moving the named labels from
@@ -952,20 +1003,55 @@
       if (computed_jump_p (insn)
 	  /* A return instruction can't be redirected.  */
 	  || returnjump_p (insn))
-	return NULL;
-
-      /* If the insn doesn't go where we think, we're confused.  */
-      gcc_assert (JUMP_LABEL (insn) == old_label);
-
-      /* If the substitution doesn't succeed, die.  This can happen
-	 if the back end emitted unrecognizable instructions or if
-	 target is exit block on some arches.  */
-      if (!redirect_jump (insn, block_label (target), 0))
+	return false;
+
+      if (!currently_expanding_to_rtl || JUMP_LABEL (insn) == old_label)
 	{
-	  gcc_assert (target == EXIT_BLOCK_PTR);
-	  return NULL;
+	  /* If the insn doesn't go where we think, we're confused.  */
+	  gcc_assert (JUMP_LABEL (insn) == old_label);
+
+	  /* If the substitution doesn't succeed, die.  This can happen
+	     if the back end emitted unrecognizable instructions or if
+	     target is exit block on some arches.  */
+	  if (!redirect_jump (insn, block_label (new_bb), 0))
+	    {
+	      gcc_assert (new_bb == EXIT_BLOCK_PTR);
+	      return false;
+	    }
 	}
     }
+  return true;
+}
+
+
+/* Redirect edge representing branch of (un)conditional jump or tablejump,
+   NULL on failure  */
+static edge
+redirect_branch_edge (edge e, basic_block target)
+{
+  rtx old_label = BB_HEAD (e->dest);
+  basic_block src = e->src;
+  rtx insn = BB_END (src);
+
+  /* We can only redirect non-fallthru edges of jump insn.  */
+  if (e->flags & EDGE_FALLTHRU)
+    return NULL;
+  else if (!JUMP_P (insn) && !currently_expanding_to_rtl)
+    return NULL;
+
+  if (!currently_expanding_to_rtl)
+    {
+      if (!patch_jump_insn (insn, old_label, target))
+	return NULL;
+    }
+  else
+    /* When expanding this BB might actually contain multiple
+       jumps (i.e. not yet split by find_many_sub_basic_blocks).
+       Redirect all of those that match our label.  */
+    for (insn = BB_HEAD (src); insn != NEXT_INSN (BB_END (src));
+	 insn = NEXT_INSN (insn))
+      if (JUMP_P (insn) && !patch_jump_insn (insn, old_label, target))
+	return NULL;
 
   if (dump_file)
     fprintf (dump_file, "Edge %i->%i redirected to %i\n",
@@ -1170,7 +1256,7 @@
   if (abnormal_edge_flags)
     make_edge (src, target, abnormal_edge_flags);
 
-  df_mark_solutions_dirty (); 
+  df_mark_solutions_dirty ();
   return new_bb;
 }
 
@@ -1350,7 +1436,7 @@
 
 /* Update the CFG for the instructions queued on edge E.  */
 
-static void
+void
 commit_one_edge_insertion (edge e)
 {
   rtx before = NULL_RTX, after = NULL_RTX, insns, tmp, last;
@@ -1418,24 +1504,11 @@
 	      && targetm.have_named_sections
 	      && e->src != ENTRY_BLOCK_PTR
 	      && BB_PARTITION (e->src) == BB_COLD_PARTITION
-	      && !(e->flags & EDGE_CROSSING))
-	    {
-	      rtx bb_note, cur_insn;
-
-	      bb_note = NULL_RTX;
-	      for (cur_insn = BB_HEAD (bb); cur_insn != NEXT_INSN (BB_END (bb));
-		   cur_insn = NEXT_INSN (cur_insn))
-		if (NOTE_INSN_BASIC_BLOCK_P (cur_insn))
-		  {
-		    bb_note = cur_insn;
-		    break;
-		  }
-
-	      if (JUMP_P (BB_END (bb))
-		  && !any_condjump_p (BB_END (bb))
-		  && (single_succ_edge (bb)->flags & EDGE_CROSSING))
-		add_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX);
-	    }
+	      && !(e->flags & EDGE_CROSSING)
+	      && JUMP_P (after)
+	      && !any_condjump_p (after)
+	      && (single_succ_edge (bb)->flags & EDGE_CROSSING))
+	    add_reg_note (after, REG_CROSSING_JUMP, NULL_RTX);
 	}
     }
 
@@ -1539,7 +1612,7 @@
   s_indent = (char *) alloca ((size_t) indent + 1);
   memset (s_indent, ' ', (size_t) indent);
   s_indent[indent] = '\0';
-  
+
   if (df)
     {
       df_dump_top (bb, outf);
@@ -1606,7 +1679,7 @@
 	    {
 	      edge e;
 	      edge_iterator ei;
-	      
+
 	      fprintf (outf, ";; Start of basic block (");
 	      FOR_EACH_EDGE (e, ei, bb->preds)
 		fprintf (outf, " %d", e->src->index);
@@ -1700,11 +1773,11 @@
     end = tmp;
 
   /* Include any barriers that may follow the basic block.  */
-  tmp = next_nonnote_insn (end);
+  tmp = next_nonnote_insn_bb (end);
   while (tmp && BARRIER_P (tmp))
     {
       end = tmp;
-      tmp = next_nonnote_insn (end);
+      tmp = next_nonnote_insn_bb (end);
     }
 
   return end;
@@ -1826,12 +1899,16 @@
 	    n_abnormal++;
 	}
 
-      if (n_eh && GET_CODE (PATTERN (BB_END (bb))) != RESX
-	  && !find_reg_note (BB_END (bb), REG_EH_REGION, NULL_RTX))
+      if (n_eh && !find_reg_note (BB_END (bb), REG_EH_REGION, NULL_RTX))
 	{
 	  error ("missing REG_EH_REGION note in the end of bb %i", bb->index);
 	  err = 1;
 	}
+      if (n_eh > 1)
+	{
+	  error ("too many eh edges %i", bb->index);
+	  err = 1;
+	}
       if (n_branch
 	  && (!JUMP_P (BB_END (bb))
 	      || (n_branch > 1 && (any_uncondjump_p (BB_END (bb))
@@ -1847,7 +1924,8 @@
 	}
       if (n_branch != 1 && any_uncondjump_p (BB_END (bb)))
 	{
-	  error ("wrong amount of branch edges after unconditional jump %i", bb->index);
+	  error ("wrong number of branch edges after unconditional jump %i",
+		 bb->index);
 	  err = 1;
 	}
       if (n_branch != 1 && any_condjump_p (BB_END (bb))
@@ -2032,15 +2110,17 @@
 	  rtx insn;
 
 	  /* Ensure existence of barrier in BB with no fallthru edges.  */
-	  for (insn = BB_END (bb); !insn || !BARRIER_P (insn);
-	       insn = NEXT_INSN (insn))
-	    if (!insn
-		|| NOTE_INSN_BASIC_BLOCK_P (insn))
+	  for (insn = NEXT_INSN (BB_END (bb)); ; insn = NEXT_INSN (insn))
+	    {
+	      if (!insn || NOTE_INSN_BASIC_BLOCK_P (insn))
 		{
 		  error ("missing barrier after block %i", bb->index);
 		  err = 1;
 		  break;
 		}
+	      if (BARRIER_P (insn))
+		break;
+	    }
 	}
       else if (e->src != ENTRY_BLOCK_PTR
 	       && e->dest != EXIT_BLOCK_PTR)
@@ -2108,9 +2188,7 @@
 	    case CODE_LABEL:
 	      /* An addr_vec is placed outside any basic block.  */
 	      if (NEXT_INSN (x)
-		  && JUMP_P (NEXT_INSN (x))
-		  && (GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_DIFF_VEC
-		      || GET_CODE (PATTERN (NEXT_INSN (x))) == ADDR_VEC))
+		  && JUMP_TABLE_DATA_P (NEXT_INSN (x)))
 		x = NEXT_INSN (x);
 
 	      /* But in any case, non-deletable labels can appear anywhere.  */
@@ -2150,6 +2228,11 @@
   bool found;
   edge_iterator ei;
 
+  if (DEBUG_INSN_P (insn) && insn != BB_HEAD (bb))
+    do
+      insn = PREV_INSN (insn);
+    while ((DEBUG_INSN_P (insn) || NOTE_P (insn)) && insn != BB_HEAD (bb));
+
   /* If this instruction cannot trap, remove REG_EH_REGION notes.  */
   if (NONJUMP_INSN_P (insn)
       && (note = find_reg_note (insn, REG_EH_REGION, NULL)))
@@ -2165,39 +2248,33 @@
   /* Cleanup abnormal edges caused by exceptions or non-local gotos.  */
   for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
     {
+      bool remove = false;
+
       /* There are three types of edges we need to handle correctly here: EH
 	 edges, abnormal call EH edges, and abnormal call non-EH edges.  The
 	 latter can appear when nonlocal gotos are used.  */
-      if (e->flags & EDGE_EH)
+      if (e->flags & EDGE_ABNORMAL_CALL)
 	{
-	  if (can_throw_internal (BB_END (bb))
-	      /* If this is a call edge, verify that this is a call insn.  */
-	      && (! (e->flags & EDGE_ABNORMAL_CALL)
-		  || CALL_P (BB_END (bb))))
-	    {
-	      ei_next (&ei);
-	      continue;
-	    }
+	  if (!CALL_P (insn))
+	    remove = true;
+	  else if (can_nonlocal_goto (insn))
+	    ;
+	  else if ((e->flags & EDGE_EH) && can_throw_internal (insn))
+	    ;
+	  else
+	    remove = true;
 	}
-      else if (e->flags & EDGE_ABNORMAL_CALL)
+      else if (e->flags & EDGE_EH)
+	remove = !can_throw_internal (insn);
+
+      if (remove)
 	{
-	  if (CALL_P (BB_END (bb))
-	      && (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
-		  || INTVAL (XEXP (note, 0)) >= 0))
-	    {
-	      ei_next (&ei);
-	      continue;
-	    }
+	  remove_edge (e);
+	  df_set_bb_dirty (bb);
+	  purged = true;
 	}
       else
-	{
-	  ei_next (&ei);
-	  continue;
-	}
-
-      remove_edge (e);
-      df_set_bb_dirty (bb);
-      purged = true;
+	ei_next (&ei);
     }
 
   if (JUMP_P (insn))
@@ -2613,10 +2690,6 @@
   /* If there was a CODE_LABEL beginning B, delete it.  */
   if (LABEL_P (BB_HEAD (b)))
     {
-      /* This might have been an EH label that no longer has incoming
-	 EH edges.  Update data structures to match.  */
-      maybe_remove_eh_handler (BB_HEAD (b));
-
       delete_insn (BB_HEAD (b));
     }
 
@@ -2763,7 +2836,8 @@
   while (!CALL_P (insn)
 	 && insn != BB_HEAD (bb)
 	 && (keep_with_call_p (insn)
-	     || NOTE_P (insn)))
+	     || NOTE_P (insn)
+	     || DEBUG_INSN_P (insn)))
     insn = PREV_INSN (insn);
   return (CALL_P (insn));
 }