diff gcc/combine-stack-adj.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 f6334be47118
line wrap: on
line diff
--- a/gcc/combine-stack-adj.c	Sun Feb 07 18:28:00 2010 +0900
+++ b/gcc/combine-stack-adj.c	Fri Feb 12 23:39:51 2010 +0900
@@ -1,6 +1,6 @@
 /* Combine stack adjustments.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -71,25 +71,26 @@
 #define STACK_GROWS_DOWNWARD 0
 #endif
 
-/* This structure records stack memory references between stack adjusting
-   instructions.  */
+/* This structure records two kinds of stack references between stack
+   adjusting instructions: stack references in memory addresses for
+   regular insns and all stack references for debug insns.  */
 
-struct csa_memlist
+struct csa_reflist
 {
   HOST_WIDE_INT sp_offset;
-  rtx insn, *mem;
-  struct csa_memlist *next;
+  rtx insn, *ref;
+  struct csa_reflist *next;
 };
 
 static int stack_memref_p (rtx);
 static rtx single_set_for_csa (rtx);
-static void free_csa_memlist (struct csa_memlist *);
-static struct csa_memlist *record_one_stack_memref (rtx, rtx *,
-						    struct csa_memlist *);
-static int try_apply_stack_adjustment (rtx, struct csa_memlist *,
+static void free_csa_reflist (struct csa_reflist *);
+static struct csa_reflist *record_one_stack_ref (rtx, rtx *,
+						 struct csa_reflist *);
+static int try_apply_stack_adjustment (rtx, struct csa_reflist *,
 				       HOST_WIDE_INT, HOST_WIDE_INT);
 static void combine_stack_adjustments_for_block (basic_block);
-static int record_stack_memrefs (rtx *, void *);
+static int record_stack_refs (rtx *, void *);
 
 
 /* Main entry point for stack adjustment combination.  */
@@ -116,7 +117,7 @@
     return 1;
   if (GET_CODE (x) == PLUS
       && XEXP (x, 0) == stack_pointer_rtx
-      && GET_CODE (XEXP (x, 1)) == CONST_INT)
+      && CONST_INT_P (XEXP (x, 1)))
     return 1;
 
   return 0;
@@ -157,65 +158,80 @@
   return XVECEXP (tmp, 0, 0);
 }
 
-/* Free the list of csa_memlist nodes.  */
+/* Free the list of csa_reflist nodes.  */
 
 static void
-free_csa_memlist (struct csa_memlist *memlist)
+free_csa_reflist (struct csa_reflist *reflist)
 {
-  struct csa_memlist *next;
-  for (; memlist ; memlist = next)
+  struct csa_reflist *next;
+  for (; reflist ; reflist = next)
     {
-      next = memlist->next;
-      free (memlist);
+      next = reflist->next;
+      free (reflist);
     }
 }
 
-/* Create a new csa_memlist node from the given memory reference.
-   It is already known that the memory is stack_memref_p.  */
+/* Create a new csa_reflist node from the given stack reference.
+   It is already known that the reference is either a MEM satisfying the
+   predicate stack_memref_p or a REG representing the stack pointer.  */
 
-static struct csa_memlist *
-record_one_stack_memref (rtx insn, rtx *mem, struct csa_memlist *next_memlist)
+static struct csa_reflist *
+record_one_stack_ref (rtx insn, rtx *ref, struct csa_reflist *next_reflist)
 {
-  struct csa_memlist *ml;
+  struct csa_reflist *ml;
 
-  ml = XNEW (struct csa_memlist);
+  ml = XNEW (struct csa_reflist);
 
-  if (XEXP (*mem, 0) == stack_pointer_rtx)
+  if (REG_P (*ref) || XEXP (*ref, 0) == stack_pointer_rtx)
     ml->sp_offset = 0;
   else
-    ml->sp_offset = INTVAL (XEXP (XEXP (*mem, 0), 1));
+    ml->sp_offset = INTVAL (XEXP (XEXP (*ref, 0), 1));
 
   ml->insn = insn;
-  ml->mem = mem;
-  ml->next = next_memlist;
+  ml->ref = ref;
+  ml->next = next_reflist;
 
   return ml;
 }
 
 /* Attempt to apply ADJUST to the stack adjusting insn INSN, as well
-   as each of the memories in MEMLIST.  Return true on success.  */
+   as each of the memories and stack references in REFLIST.  Return true
+   on success.  */
 
 static int
-try_apply_stack_adjustment (rtx insn, struct csa_memlist *memlist, HOST_WIDE_INT new_adjust,
-			    HOST_WIDE_INT delta)
+try_apply_stack_adjustment (rtx insn, struct csa_reflist *reflist,
+			    HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta)
 {
-  struct csa_memlist *ml;
+  struct csa_reflist *ml;
   rtx set;
 
   set = single_set_for_csa (insn);
-  validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);
+  if (MEM_P (SET_DEST (set)))
+    validate_change (insn, &SET_DEST (set),
+		     replace_equiv_address (SET_DEST (set), stack_pointer_rtx),
+		     1);
+  else
+    validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1);
 
-  for (ml = memlist; ml ; ml = ml->next)
-    validate_change
-      (ml->insn, ml->mem,
-       replace_equiv_address_nv (*ml->mem,
-				 plus_constant (stack_pointer_rtx,
-						ml->sp_offset - delta)), 1);
+  for (ml = reflist; ml ; ml = ml->next)
+    {
+      rtx new_addr = plus_constant (stack_pointer_rtx, ml->sp_offset - delta);
+      rtx new_val;
+
+      if (MEM_P (*ml->ref))
+	new_val = replace_equiv_address_nv (*ml->ref, new_addr);
+      else if (GET_MODE (*ml->ref) == GET_MODE (stack_pointer_rtx))
+	new_val = new_addr;
+      else
+	new_val = lowpart_subreg (GET_MODE (*ml->ref), new_addr,
+				  GET_MODE (new_addr));
+      validate_change (ml->insn, ml->ref, new_val, 1);
+    }
 
   if (apply_change_group ())
     {
-      /* Succeeded.  Update our knowledge of the memory references.  */
-      for (ml = memlist; ml ; ml = ml->next)
+      /* Succeeded.  Update our knowledge of the stack references.  */
+      for (ml = reflist; ml ; ml = ml->next)
 	ml->sp_offset -= delta;
 
       return 1;
@@ -224,20 +240,20 @@
     return 0;
 }
 
-/* Called via for_each_rtx and used to record all stack memory references in
-   the insn and discard all other stack pointer references.  */
-struct record_stack_memrefs_data
+/* Called via for_each_rtx and used to record all stack memory and other
+   references in the insn and discard all other stack pointer references.  */
+struct record_stack_refs_data
 {
   rtx insn;
-  struct csa_memlist *memlist;
+  struct csa_reflist *reflist;
 };
 
 static int
-record_stack_memrefs (rtx *xp, void *data)
+record_stack_refs (rtx *xp, void *data)
 {
   rtx x = *xp;
-  struct record_stack_memrefs_data *d =
-    (struct record_stack_memrefs_data *) data;
+  struct record_stack_refs_data *d =
+    (struct record_stack_refs_data *) data;
   if (!x)
     return 0;
   switch (GET_CODE (x))
@@ -249,10 +265,11 @@
          stack pointer, so this check is necessary.  */
       if (stack_memref_p (x))
 	{
-	  d->memlist = record_one_stack_memref (d->insn, xp, d->memlist);
+	  d->reflist = record_one_stack_ref (d->insn, xp, d->reflist);
 	  return -1;
 	}
-      return 1;
+      /* Try harder for DEBUG_INSNs, handle e.g. (mem (mem (sp + 16) + 4).  */
+      return !DEBUG_INSN_P (d->insn);
     case REG:
       /* ??? We want be able to handle non-memory stack pointer
 	 references later.  For now just discard all insns referring to
@@ -262,9 +279,17 @@
 	 We can't just compare with STACK_POINTER_RTX because the
 	 reference to the stack pointer might be in some other mode.
 	 In particular, an explicit clobber in an asm statement will
-	 result in a QImode clobber.  */
+	 result in a QImode clobber.
+
+	 In DEBUG_INSNs, we want to replace all occurrences, otherwise
+	 they will cause -fcompare-debug failures.  */
       if (REGNO (x) == STACK_POINTER_REGNUM)
-	return 1;
+	{
+	  if (!DEBUG_INSN_P (d->insn))
+	    return 1;
+	  d->reflist = record_one_stack_ref (d->insn, xp, d->reflist);
+	  return -1;
+	}
       break;
     default:
       break;
@@ -298,7 +323,7 @@
 	  && SET_DEST (last) == stack_pointer_rtx
 	  && GET_CODE (SET_SRC (last)) == PLUS
 	  && XEXP (SET_SRC (last), 0) == stack_pointer_rtx
-	  && GET_CODE (XEXP (SET_SRC (last), 1)) == CONST_INT)
+	  && CONST_INT_P (XEXP (SET_SRC (last), 1)))
 	{
 	  XEXP (SET_SRC (last), 1)
 	    = GEN_INT (INTVAL (XEXP (SET_SRC (last), 1)) + this_adjust);
@@ -333,9 +358,7 @@
   if (note)
     XEXP (note, 0) = new_expr;
   else
-    REG_NOTES (last_sp_set)
-      = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, new_expr,
-			   REG_NOTES (last_sp_set));
+    add_reg_note (last_sp_set, REG_FRAME_RELATED_EXPR, new_expr);
 }
 
 /* Subroutine of combine_stack_adjustments, called for each basic block.  */
@@ -345,9 +368,9 @@
 {
   HOST_WIDE_INT last_sp_adjust = 0;
   rtx last_sp_set = NULL_RTX;
-  struct csa_memlist *memlist = NULL;
+  struct csa_reflist *reflist = NULL;
   rtx insn, next, set;
-  struct record_stack_memrefs_data data;
+  struct record_stack_refs_data data;
   bool end_of_block = false;
 
   for (insn = BB_HEAD (bb); !end_of_block ; insn = next)
@@ -368,7 +391,7 @@
 	  if (dest == stack_pointer_rtx
 	      && GET_CODE (src) == PLUS
 	      && XEXP (src, 0) == stack_pointer_rtx
-	      && GET_CODE (XEXP (src, 1)) == CONST_INT)
+	      && CONST_INT_P (XEXP (src, 1)))
 	    {
 	      HOST_WIDE_INT this_adjust = INTVAL (XEXP (src, 1));
 
@@ -381,7 +404,7 @@
 		  continue;
 		}
 
-	      /* If not all recorded memrefs can be adjusted, or the
+	      /* If not all recorded refs can be adjusted, or the
 		 adjustment is now too large for a constant addition,
 		 we cannot merge the two stack adjustments.
 
@@ -405,7 +428,7 @@
 	      /* Combine an allocation into the first instruction.  */
 	      if (STACK_GROWS_DOWNWARD ? this_adjust <= 0 : this_adjust >= 0)
 		{
-		  if (try_apply_stack_adjustment (last_sp_set, memlist,
+		  if (try_apply_stack_adjustment (last_sp_set, reflist,
 						  last_sp_adjust + this_adjust,
 						  this_adjust))
 		    {
@@ -424,7 +447,7 @@
 	      else if (STACK_GROWS_DOWNWARD
 		       ? last_sp_adjust >= 0 : last_sp_adjust <= 0)
 		{
-		  if (try_apply_stack_adjustment (insn, memlist,
+		  if (try_apply_stack_adjustment (insn, reflist,
 						  last_sp_adjust + this_adjust,
 						  -last_sp_adjust))
 		    {
@@ -432,8 +455,8 @@
 		      delete_insn (last_sp_set);
 		      last_sp_set = insn;
 		      last_sp_adjust += this_adjust;
-		      free_csa_memlist (memlist);
-		      memlist = NULL;
+		      free_csa_reflist (reflist);
+		      reflist = NULL;
 		      continue;
 		    }
 		}
@@ -443,39 +466,44 @@
 		 delete the old deallocation insn.  */
 	      if (last_sp_set && last_sp_adjust == 0)
 		delete_insn (last_sp_set);
-	      free_csa_memlist (memlist);
-	      memlist = NULL;
+	      free_csa_reflist (reflist);
+	      reflist = NULL;
 	      last_sp_set = insn;
 	      last_sp_adjust = this_adjust;
 	      continue;
 	    }
 
-	  /* Find a predecrement of exactly the previous adjustment and
-	     turn it into a direct store.  Obviously we can't do this if
-	     there were any intervening uses of the stack pointer.  */
-	  if (memlist == NULL
-	      && MEM_P (dest)
-	      && ((GET_CODE (XEXP (dest, 0)) == PRE_DEC
-		   && (last_sp_adjust
-		       == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest))))
-		  || (GET_CODE (XEXP (dest, 0)) == PRE_MODIFY
+	  /* Find a store with pre-(dec|inc)rement or pre-modify of exactly
+	     the previous adjustment and turn it into a simple store.  This
+	     is equivalent to anticipating the stack adjustment so this must
+	     be an allocation.  */
+	  if (MEM_P (dest)
+	      && ((STACK_GROWS_DOWNWARD
+		   ? (GET_CODE (XEXP (dest, 0)) == PRE_DEC
+		      && last_sp_adjust
+			 == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest)))
+		   : (GET_CODE (XEXP (dest, 0)) == PRE_INC
+		      && last_sp_adjust
+		         == -(HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest))))
+		  || ((STACK_GROWS_DOWNWARD
+		       ? last_sp_adjust >= 0 : last_sp_adjust <= 0)
+		      && GET_CODE (XEXP (dest, 0)) == PRE_MODIFY
 		      && GET_CODE (XEXP (XEXP (dest, 0), 1)) == PLUS
-		      && XEXP (XEXP (XEXP (dest, 0), 1), 0) == stack_pointer_rtx
-		      && (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1))
-		          == CONST_INT)
-		      && (INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1))
-		          == -last_sp_adjust)))
+		      && XEXP (XEXP (XEXP (dest, 0), 1), 0)
+			 == stack_pointer_rtx
+		      && GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1))
+		         == CONST_INT
+		      && INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1))
+		         == -last_sp_adjust))
 	      && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx
-	      && ! reg_mentioned_p (stack_pointer_rtx, src)
+	      && !reg_mentioned_p (stack_pointer_rtx, src)
 	      && memory_address_p (GET_MODE (dest), stack_pointer_rtx)
-	      && validate_change (insn, &SET_DEST (set),
-				  replace_equiv_address (dest,
-							 stack_pointer_rtx),
-				  0))
+	      && try_apply_stack_adjustment (insn, reflist, 0,
+					     -last_sp_adjust))
 	    {
 	      delete_insn (last_sp_set);
-	      free_csa_memlist (memlist);
-	      memlist = NULL;
+	      free_csa_reflist (reflist);
+	      reflist = NULL;
 	      last_sp_set = NULL_RTX;
 	      last_sp_adjust = 0;
 	      continue;
@@ -483,14 +511,14 @@
 	}
 
       data.insn = insn;
-      data.memlist = memlist;
+      data.reflist = reflist;
       if (!CALL_P (insn) && last_sp_set
-	  && !for_each_rtx (&PATTERN (insn), record_stack_memrefs, &data))
+	  && !for_each_rtx (&PATTERN (insn), record_stack_refs, &data))
 	{
-	   memlist = data.memlist;
+	   reflist = data.reflist;
 	   continue;
 	}
-      memlist = data.memlist;
+      reflist = data.reflist;
 
       /* Otherwise, we were not able to process the instruction.
 	 Do not continue collecting data across such a one.  */
@@ -500,8 +528,8 @@
 	{
 	  if (last_sp_set && last_sp_adjust == 0)
 	    delete_insn (last_sp_set);
-	  free_csa_memlist (memlist);
-	  memlist = NULL;
+	  free_csa_reflist (reflist);
+	  reflist = NULL;
 	  last_sp_set = NULL_RTX;
 	  last_sp_adjust = 0;
 	}
@@ -510,8 +538,8 @@
   if (last_sp_set && last_sp_adjust == 0)
     delete_insn (last_sp_set);
 
-  if (memlist)
-    free_csa_memlist (memlist);
+  if (reflist)
+    free_csa_reflist (reflist);
 }
 
 
@@ -551,7 +579,7 @@
   NULL,                                 /* sub */
   NULL,                                 /* next */
   0,                                    /* static_pass_number */
-  0,                                    /* tv_id */
+  TV_COMBINE_STACK_ADJUST,              /* tv_id */
   0,                                    /* properties_required */
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
@@ -561,4 +589,3 @@
   TODO_ggc_collect,                     /* todo_flags_finish */
  }
 };
-