diff gcc/reload.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 3bfb6c00c1e0
children b7f97abdc517
line wrap: on
line diff
--- a/gcc/reload.c	Sun Feb 07 18:28:00 2010 +0900
+++ b/gcc/reload.c	Fri Feb 12 23:39:51 2010 +0900
@@ -112,6 +112,7 @@
 #include "params.h"
 #include "target.h"
 #include "df.h"
+#include "ira.h"
 
 /* True if X is a constant that can be forced into the constant pool.  */
 #define CONST_POOL_OK_P(X)			\
@@ -267,7 +268,8 @@
 static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx,
 				int *);
 static rtx make_memloc (rtx, int);
-static int maybe_memory_address_p (enum machine_mode, rtx, rtx *);
+static int maybe_memory_address_addr_space_p (enum machine_mode, rtx,
+					      addr_space_t, rtx *);
 static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *,
 				 int, enum reload_type, int, rtx);
 static rtx subst_reg_equivs (rtx, rtx);
@@ -363,7 +365,7 @@
   sri.icode = CODE_FOR_nothing;
   sri.prev_sri = prev_sri;
   rclass = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
-  icode = sri.icode;
+  icode = (enum insn_code) sri.icode;
 
   /* If we don't need any secondary registers, done.  */
   if (rclass == NO_REGS && icode == CODE_FOR_nothing)
@@ -525,7 +527,7 @@
   sri.icode = CODE_FOR_nothing;
   sri.prev_sri = NULL;
   rclass = targetm.secondary_reload (in_p, x, rclass, mode, &sri);
-  icode = sri.icode;
+  icode = (enum insn_code) sri.icode;
 
   /* If there are no secondary reloads at all, we return NO_REGS.
      If an intermediate register is needed, we return its class.  */
@@ -611,7 +613,8 @@
      didn't give us a new MEM, make a new one if it isn't valid.  */
 
   loc = eliminate_regs (secondary_memlocs[(int) mode], VOIDmode, NULL_RTX);
-  mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));
+  mem_valid = strict_memory_address_addr_space_p (mode, XEXP (loc, 0),
+						  MEM_ADDR_SPACE (loc));
 
   if (! mem_valid && loc == secondary_memlocs[(int) mode])
     loc = copy_rtx (loc);
@@ -685,15 +688,16 @@
 
       if (bad || !good)
 	continue;
-      cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
+      cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass, dest_class);
 
       if ((reg_class_size[rclass] > best_size
 	   && (best_cost < 0 || best_cost >= cost))
 	  || best_cost > cost)
 	{
-	  best_class = rclass;
+	  best_class = (enum reg_class) rclass;
 	  best_size = reg_class_size[rclass];
-	  best_cost = REGISTER_MOVE_COST (outer, rclass, dest_class);
+	  best_cost = REGISTER_MOVE_COST (outer, (enum reg_class) rclass,
+					  dest_class);
 	}
     }
 
@@ -1282,7 +1286,7 @@
 	     Returning zero here ought to be safe as we take care in
 	     find_reloads to not process the reloads when instruction was
 	     replaced by USE.  */
-	    
+
 	  return 0;
 	}
     }
@@ -1516,7 +1520,7 @@
 	 value for the incoming operand (same as outgoing one).  */
       if (rld[i].reg_rtx == out
 	  && (REG_P (in) || CONSTANT_P (in))
-	  && 0 != find_equiv_reg (in, this_insn, 0, REGNO (out),
+	  && 0 != find_equiv_reg (in, this_insn, NO_REGS, REGNO (out),
 				  static_reload_reg_p, i, inmode))
 	rld[i].in = out;
     }
@@ -2127,18 +2131,24 @@
   return 0;
 }
 
-/* Return 1 if ADDR is a valid memory address for mode MODE,
-   and check that each pseudo reg has the proper kind of
-   hard reg.  */
+/* Return 1 if ADDR is a valid memory address for mode MODE
+   in address space AS, and check that each pseudo reg has the
+   proper kind of hard reg.  */
 
 int
-strict_memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
+strict_memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+				    rtx addr, addr_space_t as)
 {
+#ifdef GO_IF_LEGITIMATE_ADDRESS
+  gcc_assert (ADDR_SPACE_GENERIC_P (as));
   GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
   return 0;
 
  win:
   return 1;
+#else
+  return targetm.addr_space.legitimate_address_p (mode, addr, 1, as);
+#endif
 }
 
 /* Like rtx_equal_p except that it allows a REG and a SUBREG to match
@@ -2241,6 +2251,10 @@
   if (GET_MODE (x) != GET_MODE (y))
     return 0;
 
+  /* MEMs refering to different address space are not equivalent.  */
+  if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
+    return 0;
+
   switch (code)
     {
     case CONST_INT:
@@ -2335,7 +2349,7 @@
       {
 	rtx base = NULL_RTX, offset = 0;
 	rtx addr = XEXP (x, 0);
-	
+
 	if (GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
 	    || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
 	  {
@@ -2345,7 +2359,7 @@
 	    val.safe = REGNO (val.base) == STACK_POINTER_REGNUM;
 	    return val;
 	  }
-	
+
 	if (GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
 	  {
 	    if (GET_CODE (XEXP (addr, 1)) == PLUS
@@ -2359,7 +2373,7 @@
 		return val;
 	      }
 	  }
-	
+
 	if (GET_CODE (addr) == CONST)
 	  {
 	    addr = XEXP (addr, 0);
@@ -2378,7 +2392,7 @@
 		offset = XEXP (addr, 1);
 	      }
 	  }
-	
+
 	if (offset == 0)
 	  {
 	    base = addr;
@@ -2388,12 +2402,12 @@
 	  offset = XEXP (offset, 0);
 	if (GET_CODE (offset) == PLUS)
 	  {
-	    if (GET_CODE (XEXP (offset, 0)) == CONST_INT)
+	    if (CONST_INT_P (XEXP (offset, 0)))
 	      {
 		base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 1));
 		offset = XEXP (offset, 0);
 	      }
-	    else if (GET_CODE (XEXP (offset, 1)) == CONST_INT)
+	    else if (CONST_INT_P (XEXP (offset, 1)))
 	      {
 		base = gen_rtx_PLUS (GET_MODE (base), base, XEXP (offset, 0));
 		offset = XEXP (offset, 1);
@@ -2404,23 +2418,23 @@
 		offset = const0_rtx;
 	      }
 	  }
-	else if (GET_CODE (offset) != CONST_INT)
+	else if (!CONST_INT_P (offset))
 	  {
 	    base = gen_rtx_PLUS (GET_MODE (base), base, offset);
 	    offset = const0_rtx;
 	  }
-	
+
 	if (all_const && GET_CODE (base) == PLUS)
 	  base = gen_rtx_CONST (GET_MODE (base), base);
-	
-	gcc_assert (GET_CODE (offset) == CONST_INT);
-	
+
+	gcc_assert (CONST_INT_P (offset));
+
 	val.start = INTVAL (offset);
 	val.end = val.start + GET_MODE_SIZE (GET_MODE (x));
 	val.base = base;
       }
       break;
-      
+
     case REG:
       val.reg_flag = 1;
       val.start = true_regnum (x);
@@ -2551,7 +2565,7 @@
      a register.  */
   enum reg_class preferred_class[MAX_RECOG_OPERANDS];
   char pref_or_nothing[MAX_RECOG_OPERANDS];
-  /* Nonzero for a MEM operand whose entire address needs a reload. 
+  /* Nonzero for a MEM operand whose entire address needs a reload.
      May be -1 to indicate the entire address may or may not need a reload.  */
   int address_reloaded[MAX_RECOG_OPERANDS];
   /* Nonzero for an address operand that needs to be completely reloaded.
@@ -2565,7 +2579,7 @@
   enum reload_usage { RELOAD_READ, RELOAD_READ_WRITE, RELOAD_WRITE } modified[MAX_RECOG_OPERANDS];
   int no_input_reloads = 0, no_output_reloads = 0;
   int n_alternatives;
-  int this_alternative[MAX_RECOG_OPERANDS];
+  enum reg_class this_alternative[MAX_RECOG_OPERANDS];
   char this_alternative_match_win[MAX_RECOG_OPERANDS];
   char this_alternative_win[MAX_RECOG_OPERANDS];
   char this_alternative_offmemok[MAX_RECOG_OPERANDS];
@@ -2584,6 +2598,7 @@
   char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS];
   int goal_alternative_swapped;
   int best;
+  int best_small_class_operands_num;
   int commutative;
   char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
   rtx substed_operand[MAX_RECOG_OPERANDS];
@@ -2909,6 +2924,7 @@
      all the operands together against the register constraints.  */
 
   best = MAX_RECOG_OPERANDS * 2 + 600;
+  best_small_class_operands_num = 0;
 
   swapped = 0;
   goal_alternative_swapped = 0;
@@ -3059,7 +3075,7 @@
 		force_reload = 1;
 	    }
 
-	  this_alternative[i] = (int) NO_REGS;
+	  this_alternative[i] = NO_REGS;
 	  this_alternative_win[i] = 0;
 	  this_alternative_match_win[i] = 0;
 	  this_alternative_offmemok[i] = 0;
@@ -3146,7 +3162,7 @@
 		       this combination, because we can't reload it.  */
 		    if (this_alternative_offmemok[m]
 			&& MEM_P (recog_data.operand[m])
-			&& this_alternative[m] == (int) NO_REGS
+			&& this_alternative[m] == NO_REGS
 			&& ! this_alternative_win[m])
 		      bad = 1;
 
@@ -3162,7 +3178,7 @@
 		    if (this_alternative_win[m])
 		      losers++;
 		    this_alternative_win[m] = 0;
-		    if (this_alternative[m] == (int) NO_REGS)
+		    if (this_alternative[m] == NO_REGS)
 		      bad = 1;
 		    /* But count the pair only once in the total badness of
 		       this alternative, if the pair can be a dummy reload.
@@ -3211,8 +3227,8 @@
 	      case 'p':
 		/* All necessary reloads for an address_operand
 		   were handled in find_reloads_address.  */
-		this_alternative[i]
-		  = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
+		this_alternative[i] = base_reg_class (VOIDmode, ADDRESS,
+						      SCRATCH);
 		win = 1;
 		badop = 0;
 		break;
@@ -3317,7 +3333,7 @@
 		break;
 
 	      case 's':
-		if (GET_CODE (operand) == CONST_INT
+		if (CONST_INT_P (operand)
 		    || (GET_CODE (operand) == CONST_DOUBLE
 			&& GET_MODE (operand) == VOIDmode))
 		  break;
@@ -3328,7 +3344,7 @@
 		break;
 
 	      case 'n':
-		if (GET_CODE (operand) == CONST_INT
+		if (CONST_INT_P (operand)
 		    || (GET_CODE (operand) == CONST_DOUBLE
 			&& GET_MODE (operand) == VOIDmode))
 		  win = 1;
@@ -3342,7 +3358,7 @@
 	      case 'N':
 	      case 'O':
 	      case 'P':
-		if (GET_CODE (operand) == CONST_INT
+		if (CONST_INT_P (operand)
 		    && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
 		  win = 1;
 		break;
@@ -3371,7 +3387,7 @@
 
 	      case 'r':
 		this_alternative[i]
-		  = (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
+		  = reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
 		goto reg;
 
 	      default:
@@ -3417,8 +3433,9 @@
 
 			/* If we didn't already win, we can reload
 			   the address into a base register.  */
-			this_alternative[i]
-			  = (int) base_reg_class (VOIDmode, ADDRESS, SCRATCH);
+			this_alternative[i] = base_reg_class (VOIDmode,
+							      ADDRESS,
+							      SCRATCH);
 			badop = 0;
 			break;
 		      }
@@ -3430,9 +3447,9 @@
 		  }
 
 		this_alternative[i]
-		  = (int) (reg_class_subunion
-			   [this_alternative[i]]
-			   [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
+		  = (reg_class_subunion
+		     [this_alternative[i]]
+		     [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
 	      reg:
 		if (GET_MODE (operand) == BLKmode)
 		  break;
@@ -3449,7 +3466,7 @@
 
 	  /* If this operand could be handled with a reg,
 	     and some reg is allowed, then this operand can be handled.  */
-	  if (winreg && this_alternative[i] != (int) NO_REGS)
+	  if (winreg && this_alternative[i] != NO_REGS)
 	    badop = 0;
 
 	  /* Record which operands fit this alternative.  */
@@ -3468,7 +3485,7 @@
 		bad = 1;
 	      /* Alternative loses if it has no regs for a reg operand.  */
 	      if (REG_P (operand)
-		  && this_alternative[i] == (int) NO_REGS
+		  && this_alternative[i] == NO_REGS
 		  && this_alternative_matches[i] < 0)
 		bad = 1;
 
@@ -3481,14 +3498,13 @@
 		 precisely the same as in the code below that calls
 		 force_const_mem.  */
 	      if (CONST_POOL_OK_P (operand)
-		  && ((PREFERRED_RELOAD_CLASS (operand,
-					       (enum reg_class) this_alternative[i])
+		  && ((PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
 		       == NO_REGS)
 		      || no_input_reloads)
 		  && operand_mode[i] != VOIDmode)
 		{
 		  const_to_mem = 1;
-		  if (this_alternative[i] != (int) NO_REGS)
+		  if (this_alternative[i] != NO_REGS)
 		    losers++;
 		}
 
@@ -3508,19 +3524,17 @@
 		 LIMIT_RELOAD_CLASS, but we don't check that
 		 here.  */
 
-	      if (! CONSTANT_P (operand)
-		  && (enum reg_class) this_alternative[i] != NO_REGS)
+	      if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS)
 		{
-		  if (PREFERRED_RELOAD_CLASS
-			(operand, (enum reg_class) this_alternative[i])
+		  if (PREFERRED_RELOAD_CLASS (operand, this_alternative[i])
 		      == NO_REGS)
 		    reject = 600;
 
 #ifdef PREFERRED_OUTPUT_RELOAD_CLASS
 		  if (operand_type[i] == RELOAD_FOR_OUTPUT
-		      && PREFERRED_OUTPUT_RELOAD_CLASS
-			   (operand, (enum reg_class) this_alternative[i])
-		         == NO_REGS)
+		      && (PREFERRED_OUTPUT_RELOAD_CLASS (operand,
+							this_alternative[i])
+			  == NO_REGS))
 		    reject = 600;
 #endif
 		}
@@ -3568,7 +3582,7 @@
 	     because we might otherwise exhaust the class.  */
 
 	  if (! win && ! did_match
-	      && this_alternative[i] != (int) NO_REGS
+	      && this_alternative[i] != NO_REGS
 	      && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
 	      && reg_class_size [(int) preferred_class[i]] > 0
 	      && ! SMALL_REGISTER_CLASS_P (preferred_class[i]))
@@ -3582,7 +3596,7 @@
 		     common case anyway.  */
 		  if (reg_class_subset_p (preferred_class[i],
 					  this_alternative[i]))
-		    this_alternative[i] = (int) preferred_class[i];
+		    this_alternative[i] = preferred_class[i];
 		  else
 		    reject += (2 + 2 * pref_or_nothing[i]);
 		}
@@ -3694,22 +3708,48 @@
       /* If this alternative can be made to work by reloading,
 	 and it needs less reloading than the others checked so far,
 	 record it as the chosen goal for reloading.  */
-      if (! bad && best > losers)
+      if (! bad)
 	{
-	  for (i = 0; i < noperands; i++)
+	  bool change_p = false;
+	  int small_class_operands_num = 0;
+
+	  if (best >= losers)
 	    {
-	      goal_alternative[i] = this_alternative[i];
-	      goal_alternative_win[i] = this_alternative_win[i];
-	      goal_alternative_match_win[i] = this_alternative_match_win[i];
-	      goal_alternative_offmemok[i] = this_alternative_offmemok[i];
-	      goal_alternative_matches[i] = this_alternative_matches[i];
-	      goal_alternative_earlyclobber[i]
-		= this_alternative_earlyclobber[i];
+	      for (i = 0; i < noperands; i++)
+		small_class_operands_num
+		  += SMALL_REGISTER_CLASS_P (this_alternative[i]) ? 1 : 0;
+	      if (best > losers
+		  || (best == losers
+		      /* If the cost of the reloads is the same,
+			 prefer alternative which requires minimal
+			 number of small register classes for the
+			 operands.  This improves chances of reloads
+			 for insn requiring small register
+			 classes.  */
+		      && (small_class_operands_num
+			  < best_small_class_operands_num)))
+		change_p = true;
 	    }
-	  goal_alternative_swapped = swapped;
-	  best = losers;
-	  goal_alternative_number = this_alternative_number;
-	  goal_earlyclobber = this_earlyclobber;
+	  if (change_p)
+	    {
+	      for (i = 0; i < noperands; i++)
+		{
+		  goal_alternative[i] = this_alternative[i];
+		  goal_alternative_win[i] = this_alternative_win[i];
+		  goal_alternative_match_win[i]
+		    = this_alternative_match_win[i];
+		  goal_alternative_offmemok[i]
+		    = this_alternative_offmemok[i];
+		  goal_alternative_matches[i] = this_alternative_matches[i];
+		  goal_alternative_earlyclobber[i]
+		    = this_alternative_earlyclobber[i];
+		}
+	      goal_alternative_swapped = swapped;
+	      best = losers;
+	      best_small_class_operands_num = small_class_operands_num;
+	      goal_alternative_number = this_alternative_number;
+	      goal_earlyclobber = this_earlyclobber;
+	    }
 	}
     }
 
@@ -3947,12 +3987,15 @@
 		 && MEM_P (recog_data.operand[i]))
 	  {
 	    /* If the address to be reloaded is a VOIDmode constant,
-	       use Pmode as mode of the reload register, as would have
-	       been done by find_reloads_address.  */
+	       use the default address mode as mode of the reload register,
+	       as would have been done by find_reloads_address.  */
 	    enum machine_mode address_mode;
 	    address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
 	    if (address_mode == VOIDmode)
-	      address_mode = Pmode;
+	      {
+		addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
+		address_mode = targetm.addr_space.address_mode (as);
+	      }
 
 	    operand_reloadnum[i]
 	      = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
@@ -4230,7 +4273,7 @@
   /* If we detected error and replaced asm instruction by USE, forget about the
      reloads.  */
   if (GET_CODE (PATTERN (insn)) == USE
-      && GET_CODE (XEXP (PATTERN (insn), 0)) == CONST_INT)
+      && CONST_INT_P (XEXP (PATTERN (insn), 0)))
     n_reloads = 0;
 
   /* Perhaps an output reload can be combined with another
@@ -4557,7 +4600,8 @@
    is null.  */
 
 static bool
-alternative_allows_const_pool_ref (rtx mem, const char *constraint, int altnum)
+alternative_allows_const_pool_ref (rtx mem ATTRIBUTE_UNUSED,
+				   const char *constraint, int altnum)
 {
   int c;
 
@@ -4727,8 +4771,9 @@
 #endif
 	       && (reg_equiv_address[regno] != 0
 		   || (reg_equiv_mem[regno] != 0
-		       && (! strict_memory_address_p (GET_MODE (x),
-						      XEXP (reg_equiv_mem[regno], 0))
+		       && (! strict_memory_address_addr_space_p
+			       (GET_MODE (x), XEXP (reg_equiv_mem[regno], 0),
+				MEM_ADDR_SPACE (reg_equiv_mem[regno]))
 			   || ! offsettable_memref_p (reg_equiv_mem[regno])
 			   || num_not_at_initial_offset))))
 	x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
@@ -4767,7 +4812,8 @@
   /* We must rerun eliminate_regs, in case the elimination
      offsets have changed.  */
   rtx tem
-    = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0, NULL_RTX), 0);
+    = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], VOIDmode, NULL_RTX),
+	    0);
 
   /* If TEM might contain a pseudo, we must copy it to avoid
      modifying it when we do the substitution for the reload.  */
@@ -4785,18 +4831,19 @@
 }
 
 /* Returns true if AD could be turned into a valid memory reference
-   to mode MODE by reloading the part pointed to by PART into a
-   register.  */
+   to mode MODE in address space AS by reloading the part pointed to
+   by PART into a register.  */
 
 static int
-maybe_memory_address_p (enum machine_mode mode, rtx ad, rtx *part)
+maybe_memory_address_addr_space_p (enum machine_mode mode, rtx ad,
+				   addr_space_t as, rtx *part)
 {
   int retv;
   rtx tem = *part;
   rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ());
 
   *part = reg;
-  retv = memory_address_p (mode, ad);
+  retv = memory_address_addr_space_p (mode, ad, as);
   *part = tem;
 
   return retv;
@@ -4832,6 +4879,8 @@
 		      rtx *loc, int opnum, enum reload_type type,
 		      int ind_levels, rtx insn)
 {
+  addr_space_t as = memrefloc? MEM_ADDR_SPACE (*memrefloc)
+			     : ADDR_SPACE_GENERIC;
   int regno;
   int removed_and = 0;
   int op_index;
@@ -4859,7 +4908,9 @@
 	  if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)
 	    {
 	      tem = make_memloc (ad, regno);
-	      if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
+	      if (! strict_memory_address_addr_space_p (GET_MODE (tem),
+							XEXP (tem, 0),
+							MEM_ADDR_SPACE (tem)))
 		{
 		  rtx orig = tem;
 
@@ -4875,7 +4926,7 @@
 		 address: only reg or reg+constant.  */
 
 	      if (ind_levels > 0
-		  && strict_memory_address_p (mode, tem)
+		  && strict_memory_address_addr_space_p (mode, tem, as)
 		  && (REG_P (XEXP (tem, 0))
 		      || (GET_CODE (XEXP (tem, 0)) == PLUS
 			  && REG_P (XEXP (XEXP (tem, 0), 0))
@@ -4919,7 +4970,7 @@
       return 1;
     }
 
-  if (strict_memory_address_p (mode, ad))
+  if (strict_memory_address_addr_space_p (mode, ad, as))
     {
       /* The address appears valid, so reloads are not needed.
 	 But the address may contain an eliminable register.
@@ -4930,7 +4981,7 @@
 
       /* But first quickly dispose of a common case.  */
       if (GET_CODE (ad) == PLUS
-	  && GET_CODE (XEXP (ad, 1)) == CONST_INT
+	  && CONST_INT_P (XEXP (ad, 1))
 	  && REG_P (XEXP (ad, 0))
 	  && reg_equiv_constant[REGNO (XEXP (ad, 0))] == 0)
 	return 0;
@@ -4942,14 +4993,14 @@
 	return 0;
 
       /* Check result for validity after substitution.  */
-      if (strict_memory_address_p (mode, ad))
+      if (strict_memory_address_addr_space_p (mode, ad, as))
 	return 0;
     }
 
 #ifdef LEGITIMIZE_RELOAD_ADDRESS
   do
     {
-      if (memrefloc)
+      if (memrefloc && ADDR_SPACE_GENERIC_P (as))
 	{
 	  LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
 				     ind_levels, win);
@@ -5010,7 +5061,7 @@
 	  || ! (REG_P (XEXP (tem, 0))
 		|| (GET_CODE (XEXP (tem, 0)) == PLUS
 		    && REG_P (XEXP (XEXP (tem, 0), 0))
-		    && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)))
+		    && CONST_INT_P (XEXP (XEXP (tem, 0), 1)))))
 	{
 	  /* Must use TEM here, not AD, since it is the one that will
 	     have any subexpressions reloaded, if needed.  */
@@ -5032,7 +5083,7 @@
   else if (GET_CODE (ad) == PLUS
 	   && REG_P (XEXP (ad, 0))
 	   && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
-	   && GET_CODE (XEXP (ad, 1)) == CONST_INT
+	   && CONST_INT_P (XEXP (ad, 1))
 	   && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
 				   CONST_INT))
 
@@ -5065,7 +5116,7 @@
 	     That will at least work.  */
 	  find_reloads_address_part (ad, loc,
 				     base_reg_class (mode, MEM, SCRATCH),
-				     Pmode, opnum, type, ind_levels);
+				     GET_MODE (ad), opnum, type, ind_levels);
 	}
       return ! removed_and;
     }
@@ -5105,8 +5156,8 @@
 	  continue;
 
       inner_code = GET_CODE (XEXP (ad, 0));
-      if (!(GET_CODE (ad) == PLUS 
-	    && GET_CODE (XEXP (ad, 1)) == CONST_INT
+      if (!(GET_CODE (ad) == PLUS
+	    && CONST_INT_P (XEXP (ad, 1))
 	    && (inner_code == PLUS || inner_code == LO_SUM)))
 	continue;
 
@@ -5126,8 +5177,8 @@
 	   || operand == arg_pointer_rtx
 #endif
 	   || operand == stack_pointer_rtx)
-	  && ! maybe_memory_address_p (mode, ad, 
-				       &XEXP (XEXP (ad, 0), 1 - op_index)))
+	  && ! maybe_memory_address_addr_space_p
+		(mode, ad, as, &XEXP (XEXP (ad, 0), 1 - op_index)))
 	{
 	  rtx offset_reg;
 	  enum reg_class cls;
@@ -5136,17 +5187,17 @@
 
 	  /* Form the adjusted address.  */
 	  if (GET_CODE (XEXP (ad, 0)) == PLUS)
-	    ad = gen_rtx_PLUS (GET_MODE (ad), 
-			       op_index == 0 ? offset_reg : addend, 
+	    ad = gen_rtx_PLUS (GET_MODE (ad),
+			       op_index == 0 ? offset_reg : addend,
 			       op_index == 0 ? addend : offset_reg);
 	  else
-	    ad = gen_rtx_LO_SUM (GET_MODE (ad), 
-				 op_index == 0 ? offset_reg : addend, 
+	    ad = gen_rtx_LO_SUM (GET_MODE (ad),
+				 op_index == 0 ? offset_reg : addend,
 				 op_index == 0 ? addend : offset_reg);
 	  *loc = ad;
 
 	  cls = base_reg_class (mode, MEM, GET_CODE (addend));
-	  find_reloads_address_part (XEXP (ad, op_index), 
+	  find_reloads_address_part (XEXP (ad, op_index),
 				     &XEXP (ad, op_index), cls,
 				     GET_MODE (ad), opnum, type, ind_levels);
 	  find_reloads_address_1 (mode,
@@ -5165,7 +5216,7 @@
   tem = ad;
   if (GET_CODE (ad) == PLUS)
     tem = subst_indexed_address (ad);
-  if (tem != ad && strict_memory_address_p (mode, tem))
+  if (tem != ad && strict_memory_address_addr_space_p (mode, tem, as))
     {
       /* Ok, we win that way.  Replace any additional eliminable
 	 registers.  */
@@ -5175,7 +5226,8 @@
 
       /* Make sure that didn't make the address invalid again.  */
 
-      if (! subst_reg_equivs_changed || strict_memory_address_p (mode, tem))
+      if (! subst_reg_equivs_changed
+	  || strict_memory_address_addr_space_p (mode, tem, as))
 	{
 	  *loc = tem;
 	  return 0;
@@ -5184,8 +5236,12 @@
 
   /* If constants aren't valid addresses, reload the constant address
      into a register.  */
-  if (CONSTANT_P (ad) && ! strict_memory_address_p (mode, ad))
+  if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as))
     {
+      enum machine_mode address_mode = GET_MODE (ad);
+      if (address_mode == VOIDmode)
+	address_mode = targetm.addr_space.address_mode (as);
+
       /* If AD is an address in the constant pool, the MEM rtx may be shared.
 	 Unshare it so we can safely alter it.  */
       if (memrefloc && GET_CODE (ad) == SYMBOL_REF
@@ -5198,7 +5254,7 @@
 	}
 
       find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
-				 Pmode, opnum, type, ind_levels);
+				 address_mode, opnum, type, ind_levels);
       return ! removed_and;
     }
 
@@ -5262,7 +5318,7 @@
     case PLUS:
       /* Quickly dispose of a common case.  */
       if (XEXP (ad, 0) == frame_pointer_rtx
-	  && GET_CODE (XEXP (ad, 1)) == CONST_INT)
+	  && CONST_INT_P (XEXP (ad, 1)))
 	return ad;
       break;
 
@@ -5285,31 +5341,27 @@
    This routine assumes both inputs are already in canonical form.  */
 
 rtx
-form_sum (rtx x, rtx y)
+form_sum (enum machine_mode mode, rtx x, rtx y)
 {
   rtx tem;
-  enum machine_mode mode = GET_MODE (x);
-
-  if (mode == VOIDmode)
-    mode = GET_MODE (y);
-
-  if (mode == VOIDmode)
-    mode = Pmode;
-
-  if (GET_CODE (x) == CONST_INT)
+
+  gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
+  gcc_assert (GET_MODE (y) == mode || GET_MODE (y) == VOIDmode);
+
+  if (CONST_INT_P (x))
     return plus_constant (y, INTVAL (x));
-  else if (GET_CODE (y) == CONST_INT)
+  else if (CONST_INT_P (y))
     return plus_constant (x, INTVAL (y));
   else if (CONSTANT_P (x))
     tem = x, x = y, y = tem;
 
   if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
-    return form_sum (XEXP (x, 0), form_sum (XEXP (x, 1), y));
+    return form_sum (mode, XEXP (x, 0), form_sum (mode, XEXP (x, 1), y));
 
   /* Note that if the operands of Y are specified in the opposite
      order in the recursive calls below, infinite recursion will occur.  */
   if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
-    return form_sum (form_sum (x, XEXP (y, 0)), XEXP (y, 1));
+    return form_sum (mode, form_sum (mode, x, XEXP (y, 0)), XEXP (y, 1));
 
   /* If both constant, encapsulate sum.  Otherwise, just form sum.  A
      constant will have been placed second.  */
@@ -5376,9 +5428,9 @@
 
       /* Compute the sum.  */
       if (op2 != 0)
-	op1 = form_sum (op1, op2);
+	op1 = form_sum (GET_MODE (addr), op1, op2);
       if (op1 != 0)
-	op0 = form_sum (op0, op1);
+	op0 = form_sum (GET_MODE (addr), op0, op1);
 
       return op0;
     }
@@ -5448,7 +5500,7 @@
 #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, OUTER, INDEX)		\
   ((CONTEXT) == 0							\
    ? regno_ok_for_base_p (REGNO, MODE, OUTER, INDEX)			\
-   : REGNO_OK_FOR_INDEX_P (REGNO))					
+   : REGNO_OK_FOR_INDEX_P (REGNO))
 
   enum reg_class context_reg_class;
   RTX_CODE code = GET_CODE (x);
@@ -5778,7 +5830,8 @@
 	      rtx equiv = (MEM_P (XEXP (x, 0))
 			   ? XEXP (x, 0)
 			   : reg_equiv_mem[regno]);
-	      int icode = (int) optab_handler (add_optab, Pmode)->insn_code;
+	      int icode
+		= (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
 	      if (insn && NONJUMP_INSN_P (insn) && equiv
 		  && memory_operand (equiv, GET_MODE (equiv))
 #ifdef HAVE_cc0
@@ -5786,9 +5839,9 @@
 #endif
 		  && ! (icode != CODE_FOR_nothing
 			&& ((*insn_data[icode].operand[0].predicate)
-			    (equiv, Pmode))
+			    (equiv, GET_MODE (x)))
 			&& ((*insn_data[icode].operand[1].predicate)
-			    (equiv, Pmode))))
+			    (equiv, GET_MODE (x)))))
 		{
 		  /* We use the original pseudo for loc, so that
 		     emit_reload_insns() knows which pseudo this
@@ -5954,7 +6007,7 @@
 	      if ((unsigned) CLASS_MAX_NREGS (rclass, GET_MODE (SUBREG_REG (x)))
 		  > reg_class_size[rclass])
 		{
-		  x = find_reloads_subreg_address (x, 0, opnum, 
+		  x = find_reloads_subreg_address (x, 0, opnum,
 						   ADDR_TYPE (type),
 						   ind_levels, insn);
 		  push_reload (x, NULL_RTX, loc, (rtx*) 0, rclass,
@@ -6110,7 +6163,7 @@
 		  base = XEXP (tem, 0);
 		  if (GET_CODE (base) == PLUS)
 		    {
-		      if (GET_CODE (XEXP (base, 1)) == CONST_INT
+		      if (CONST_INT_P (XEXP (base, 1))
 			  && INTVAL (XEXP (base, 1)) % outer_size != 0)
 			return x;
 		      base = XEXP (base, 0);
@@ -6131,18 +6184,27 @@
 	      /* For some processors an address may be valid in the
 		 original mode but not in a smaller mode.  For
 		 example, ARM accepts a scaled index register in
-		 SImode but not in HImode.  Similarly, the address may
-		 have been valid before the subreg offset was added,
-		 but not afterwards.  find_reloads_address
-		 assumes that we pass it a valid address, and doesn't
-		 force a reload.  This will probably be fine if
-		 find_reloads_address finds some reloads.  But if it
-		 doesn't find any, then we may have just converted a
-		 valid address into an invalid one.  Check for that
-		 here.  */
+		 SImode but not in HImode.  Note that this is only
+		 a problem if the address in reg_equiv_mem is already
+		 invalid in the new mode; other cases would be fixed
+		 by find_reloads_address as usual.
+
+		 ??? We attempt to handle such cases here by doing an
+		 additional reload of the full address after the
+		 usual processing by find_reloads_address.  Note that
+		 this may not work in the general case, but it seems
+		 to cover the cases where this situation currently
+		 occurs.  A more general fix might be to reload the
+		 *value* instead of the address, but this would not
+		 be expected by the callers of this routine as-is.
+
+		 If find_reloads_address already completed replaced
+		 the address, there is nothing further to do.  */
 	      if (reloaded == 0
-		  && !strict_memory_address_p (GET_MODE (tem),
-					       XEXP (tem, 0)))
+		  && reg_equiv_mem[regno] != 0
+		  && !strict_memory_address_addr_space_p
+			(GET_MODE (x), XEXP (reg_equiv_mem[regno], 0),
+			 MEM_ADDR_SPACE (reg_equiv_mem[regno])))
 		push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
 			     base_reg_class (GET_MODE (tem), MEM, SCRATCH),
 			     GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
@@ -6546,7 +6608,7 @@
   /* If either argument is a constant, then modifying X can not affect IN.  */
   if (CONSTANT_P (x) || CONSTANT_P (in))
     return 0;
-  else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM)
+  else if (GET_CODE (x) == SUBREG && MEM_P (SUBREG_REG (x)))
     return refers_to_mem_for_reload_p (in);
   else if (GET_CODE (x) == SUBREG)
     {
@@ -6585,7 +6647,7 @@
   else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
 	   || GET_CODE (x) == CC0)
     return reg_mentioned_p (x, in);
-  else 
+  else
     {
       gcc_assert (GET_CODE (x) == PLUS);
 
@@ -6726,6 +6788,8 @@
   while (1)
     {
       p = PREV_INSN (p);
+      if (p && DEBUG_INSN_P (p))
+	continue;
       num++;
       if (p == 0 || LABEL_P (p)
 	  || num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS))
@@ -6780,7 +6844,7 @@
 			  || (REG_P (SET_DEST (pat))
 			      && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
 			      && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
-			      && GET_CODE (goal) == CONST_INT
+			      && CONST_INT_P (goal)
 			      && 0 != (goaltry
 				       = operand_subword (XEXP (tem, 0), 0, 0,
 							  VOIDmode))
@@ -6794,7 +6858,7 @@
 		      && REG_P (SET_DEST (pat))
 		      && GET_CODE (XEXP (tem, 0)) == CONST_DOUBLE
 		      && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (tem, 0)))
-		      && GET_CODE (goal) == CONST_INT
+		      && CONST_INT_P (goal)
 		      && 0 != (goaltry = operand_subword (XEXP (tem, 0), 1, 0,
 							  VOIDmode))
 		      && rtx_equal_p (goal, goaltry)
@@ -7122,7 +7186,7 @@
 	       && GET_CODE (XEXP (addr, 1)) == PLUS
 	       && XEXP (addr, 0) == XEXP (XEXP (addr, 1), 0)
 	       && XEXP (addr, 0) == inced
-	       && GET_CODE (XEXP (XEXP (addr, 1), 1)) == CONST_INT)
+	       && CONST_INT_P (XEXP (XEXP (addr, 1), 1)))
 	{
 	  i = INTVAL (XEXP (XEXP (addr, 1), 1));
 	  return i < 0 ? -i : i;
@@ -7157,7 +7221,7 @@
    REG_INC note in insn INSN.  REGNO must refer to a hard register.  */
 
 #ifdef AUTO_INC_DEC
-static int 
+static int
 reg_inc_found_and_valid_p (unsigned int regno, unsigned int endregno,
 			   rtx insn)
 {
@@ -7167,13 +7231,13 @@
 
   if (! INSN_P (insn))
     return 0;
-    
+
   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
     if (REG_NOTE_KIND (link) == REG_INC)
       {
 	unsigned int test = (int) REGNO (XEXP (link, 0));
 	if (test >= regno && test < endregno)
-	  return 1; 
+	  return 1;
       }
   return 0;
 }
@@ -7181,7 +7245,7 @@
 
 #define reg_inc_found_and_valid_p(regno,endregno,insn) 0
 
-#endif 
+#endif
 
 /* Return 1 if register REGNO is the subject of a clobber in insn INSN.
    If SETS is 1, also consider SETs.  If SETS is 2, enable checking
@@ -7209,8 +7273,8 @@
     }
 
   if (sets == 2 && reg_inc_found_and_valid_p (regno, endregno, insn))
-    return 1; 
-  
+    return 1;
+
   if (GET_CODE (PATTERN (insn)) == PARALLEL)
     {
       int i = XVECLEN (PATTERN (insn), 0) - 1;
@@ -7229,7 +7293,7 @@
 	    }
 	  if (sets == 2
 	      && reg_inc_found_and_valid_p (regno, endregno, elt))
-	    return 1; 
+	    return 1;
 	}
     }