public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
@ 2011-08-04 13:43 Georg-Johann Lay
  2011-08-04 16:20 ` Ulrich Weigand
  0 siblings, 1 reply; 21+ messages in thread
From: Georg-Johann Lay @ 2011-08-04 13:43 UTC (permalink / raw)
  To: gcc

Trying to make named address space support work for target AVR,
I am facing the following problem:

For generic AS, there are three valid base pointer registers
X , Y and Z.

For the new __pgm AS, only Z is available without offset.

The problem is now that addresses.h:base_reg_class() does not
pass down AS information, i.e. addr_space_t down to target hook
MODE_CODE_BASE_REG_CLASS.

Likewise for REGNO_MODE_CODE_OK_FOR_BASE_P.

The MODE argument that both of these get describe the mode of
the MEM but not the mode associated with the AS.

Thus, it is not possible to provide proper implementations of
these hooks.  IRA/reload choses the wrong hard register so
that in postreload no constraints match, i.e.
TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P returns wrong for that
hard register (which is right) so that postreload busts.

I'd just like to reassure me that I didn't do something fundamentally
wrong and named address space support if not yet smoothly supported
in GCC.

FYI, the C source is

int read_from_pgm_2 (int * const __pgm * const addr)
{
    return **addr;
}

===== Prior to reload: PHI is attached to __pgm, i.e. AS1, looks fine:

(insn 2 4 3 2 (set (reg/v/f:PHI 45 [ addr ])
        (reg:PHI 24 r24 [ addr ])) pgm.c:42 8 {*movphi}
     (nil))

(note 3 2 6 2 NOTE_INSN_FUNCTION_BEG)

(insn 6 3 7 2 (set (reg/f:HI 47 [ *addr_1(D) ])
        (mem/f:HI (reg/v/f:PHI 45 [ addr ]) [2 *addr_1(D)+0 S2 A8 AS1])) pgm.c:43 7 {*movhi}
     (expr_list:REG_DEAD (reg/v/f:PHI 45 [ addr ])
        (nil)))

(note 7 6 12 2 NOTE_INSN_DELETED)

(insn 12 7 15 2 (set (reg/i:HI 24 r24)
        (mem:HI (reg/f:HI 47 [ *addr_1(D) ]) [3 *D.1949_2+0 S2 A8])) pgm.c:44 7 {*movhi}
     (expr_list:REG_DEAD (reg/f:HI 47 [ *addr_1(D) ])
        (nil)))

(insn 15 12 0 2 (use (reg/i:HI 24 r24)) pgm.c:44 -1
     (nil))


===== After reload

(insn 20 3 6 2 (set (reg:PHI 26 r26)
        (reg/v/f:PHI 24 r24 [orig:45 addr ] [45])) pgm.c:43 8 {*movphi}
     (nil))

(insn 6 20 7 2 (set (reg/f:HI 30 r30 [orig:47 *addr_1(D) ] [47])
        (mem/f:HI (reg:PHI 26 r26) [2 *addr_1(D)+0 S2 A8 AS1])) pgm.c:43 7 {*movhi}
     (nil))

(note 7 6 12 2 NOTE_INSN_DELETED)

(insn 12 7 15 2 (set (reg/i:HI 24 r24)
        (mem:HI (reg/f:HI 30 r30 [orig:47 *addr_1(D) ] [47]) [3 *D.1949_2+0 S2 A8])) pgm.c:44 7 {*movhi}
     (nil))

(insn 15 12 18 2 (use (reg/i:HI 24 r24)) pgm.c:44 -1
     (nil))

The register names are (X=r26, invalid to load from AS1 in insn 6).

Johann

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-04 13:43 [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands Georg-Johann Lay
@ 2011-08-04 16:20 ` Ulrich Weigand
  2011-08-04 16:26   ` DJ Delorie
  2011-08-04 17:28   ` Georg-Johann Lay
  0 siblings, 2 replies; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-04 16:20 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

Georg-Johann Lay wrote:

> Trying to make named address space support work for target AVR,
> I am facing the following problem:
> 
> For generic AS, there are three valid base pointer registers
> X , Y and Z.
> 
> For the new __pgm AS, only Z is available without offset.
> 
> The problem is now that addresses.h:base_reg_class() does not
> pass down AS information, i.e. addr_space_t down to target hook
> MODE_CODE_BASE_REG_CLASS.
> 
> Likewise for REGNO_MODE_CODE_OK_FOR_BASE_P.
> 
> The MODE argument that both of these get describe the mode of
> the MEM but not the mode associated with the AS.
> 
> Thus, it is not possible to provide proper implementations of
> these hooks.  IRA/reload choses the wrong hard register so
> that in postreload no constraints match, i.e.
> TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P returns wrong for that
> hard register (which is right) so that postreload busts.
> 
> I'd just like to reassure me that I didn't do something fundamentally
> wrong and named address space support if not yet smoothly supported
> in GCC.

No, you're correct.  The only target supporting named address spaces
today is spu-elf, and here we're eliminating any reference to the
non-default space during expand, so that reload never sees any.

This means that problems like the one you're seeing have been hidden
so far.  I've started looking into fixing this, but since I don't
have a target where this is needed, this effort never really went
anywhere.  I'll append below a patch I did a year or so ago; just
as something to look at, it probably will not even apply to the
current sources any more.

I'd be happy to bring this up to date if you're willing to work with
me to get this tested on a target that needs this support ...

Bye,
Ulrich



ChangeLog:

	* doc/tm.texi (MODE_CODE_BASE_REG_CLASS): Add address space
	argument.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.

	* config/cris/cris.h (MODE_CODE_BASE_REG_CLASS): Add address
	space argument.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
	* config/bfin/bfin.h (MODE_CODE_BASE_REG_CLASS): Likewise.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.

	* addresses.h (base_reg_class): Add address space argument.
	Pass to MODE_CODE_BASE_REG_CLASS.
	(ok_for_base_p_1): Add address space argument.  Pass to
	REGNO_MODE_CODE_OK_FOR_BASE_P.
	(regno_ok_for_base_p): Add address space argument.  Pass to
	ok_for_base_p_1.

	* regrename.c (scan_rtx_address): Add address space argument.
	Pass address space to regno_ok_for_base_p and base_reg_class.
	Update recursive calls.
	(scan_rtx): Pass address space to scan_rtx_address.
	(build_def_use): Likewise.
	* regcprop.c (replace_oldest_value_addr): Add address space
	argument.  Pass to regno_ok_for_base_p and base_reg_class.
	Update recursive calls.
	(replace_oldest_value_mem): Pass address space to
	replace_oldest_value_addr.
	(copyprop_hardreg_forward_1): Likewise.

	* reload.c (find_reloads_address_1): Add address space argument.
	Pass address space to base_reg_class and regno_ok_for_base_p.
	Update recursive calls.
	(find_reloads_address): Pass address space to base_reg_class,
	regno_ok_for_base_p, and find_reloads_address_1.
	(find_reloads): Pass address space to base_reg_class.
	(find_reloads_subreg_address): Likewise.

	* ira-costs.c (record_reg_classes): Update calls to base_reg_class.
	(ok_for_base_p_nonstrict): Add address space argument.  Pass to
	ok_for_base_p_1.
	(record_address_regs): Add address space argument.  Pass to
	base_reg_class and ok_for_base_p_nonstrict.  Update recursive calls.
	(record_operand_costs): Pass address space to record_address_regs.
	(scan_one_insn): Likewise.

	* caller-save.c (init_caller_save): Update call to base_reg_class.
	* ira-conflicts.c (ira_build_conflicts): Likewise.
	* reload1.c (maybe_fix_stack_asms): Likewise.


Index: gcc/regrename.c
===================================================================
*** gcc/regrename.c	(revision 153564)
--- gcc/regrename.c	(working copy)
*************** static void do_replace (struct du_chain 
*** 83,89 ****
  static void scan_rtx_reg (rtx, rtx *, enum reg_class,
  			  enum scan_actions, enum op_type, int);
  static void scan_rtx_address (rtx, rtx *, enum reg_class,
! 			      enum scan_actions, enum machine_mode);
  static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
  		      enum op_type, int);
  static struct du_chain *build_def_use (basic_block);
--- 83,90 ----
  static void scan_rtx_reg (rtx, rtx *, enum reg_class,
  			  enum scan_actions, enum op_type, int);
  static void scan_rtx_address (rtx, rtx *, enum reg_class,
! 			      enum scan_actions, enum machine_mode,
! 			      addr_space_t);
  static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
  		      enum op_type, int);
  static struct du_chain *build_def_use (basic_block);
*************** scan_rtx_reg (rtx insn, rtx *loc, enum r
*** 527,533 ****
  
  static void
  scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl,
! 		  enum scan_actions action, enum machine_mode mode)
  {
    rtx x = *loc;
    RTX_CODE code = GET_CODE (x);
--- 528,535 ----
  
  static void
  scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl,
! 		  enum scan_actions action, enum machine_mode mode,
! 		  addr_space_t as)
  {
    rtx x = *loc;
    RTX_CODE code = GET_CODE (x);
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 595,609 ****
  	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
  	    if (REGNO_OK_FOR_INDEX_P (regno1)
! 		&& regno_ok_for_base_p (regno0, mode, PLUS, REG))
  	      index_op = 1;
  	    else if (REGNO_OK_FOR_INDEX_P (regno0)
! 		     && regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG)
  		     || REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
  	    else
  	      index_op = 1;
--- 597,611 ----
  	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
  	    if (REGNO_OK_FOR_INDEX_P (regno1)
! 		&& regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
  	      index_op = 1;
  	    else if (REGNO_OK_FOR_INDEX_P (regno0)
! 		     && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
  		     || REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
  	      index_op = 0;
  	    else
  	      index_op = 1;
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 626,635 ****
  	  }
  
  	if (locI)
! 	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode);
  	if (locB)
! 	  scan_rtx_address (insn, locB, base_reg_class (mode, PLUS, index_code),
! 			    action, mode);
  
  	return;
        }
--- 628,638 ----
  	  }
  
  	if (locI)
! 	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode, as);
  	if (locB)
! 	  scan_rtx_address (insn, locB,
! 			    base_reg_class (mode, as, PLUS, index_code),
! 			    action, mode, as);
  
  	return;
        }
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 649,656 ****
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
! 			GET_MODE (x));
        return;
  
      case REG:
--- 652,660 ----
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x),
! 					MEM, SCRATCH),
! 			action, GET_MODE (x), MEM_ADDR_SPACE (x));
        return;
  
      case REG:
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 665,674 ****
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      {
        if (fmt[i] == 'e')
! 	scan_rtx_address (insn, &XEXP (x, i), cl, action, mode);
        else if (fmt[i] == 'E')
  	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
! 	  scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode);
      }
  }
  
--- 669,678 ----
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      {
        if (fmt[i] == 'e')
! 	scan_rtx_address (insn, &XEXP (x, i), cl, action, mode, as);
        else if (fmt[i] == 'E')
  	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
! 	  scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode, as);
      }
  }
  
*************** scan_rtx (rtx insn, rtx *loc, enum reg_c
*** 701,708 ****
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
! 			GET_MODE (x));
        return;
  
      case SET:
--- 705,713 ----
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x),
! 					MEM, SCRATCH),
! 			action, GET_MODE (x), MEM_ADDR_SPACE (x));
        return;
  
      case SET:
*************** build_def_use (basic_block bb)
*** 891,897 ****
  		continue;
  
  	      if (recog_op_alt[opn][alt].is_address)
! 		scan_rtx_address (insn, loc, cl, mark_read, VOIDmode);
  	      else
  		scan_rtx (insn, loc, cl, mark_read, type, 0);
  	    }
--- 896,903 ----
  		continue;
  
  	      if (recog_op_alt[opn][alt].is_address)
! 		scan_rtx_address (insn, loc, cl, mark_read,
! 				  VOIDmode, ADDR_SPACE_GENERIC);
  	      else
  		scan_rtx (insn, loc, cl, mark_read, type, 0);
  	    }
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi	(revision 153571)
--- gcc/doc/tm.texi	(working copy)
*************** register address.  You should define thi
*** 2495,2506 ****
  addresses have different requirements than other base register uses.
  @end defmac
  
! @defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{outer_code}, @var{index_code})
  A C expression whose value is the register class to which a valid
! base register must belong.  @var{outer_code} and @var{index_code} define the
! context in which the base register occurs.  @var{outer_code} is the code of
! the immediately enclosing expression (@code{MEM} for the top level of an
! address, @code{ADDRESS} for something that occurs in an
  @code{address_operand}).  @var{index_code} is the code of the corresponding
  index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise.
  @end defmac
--- 2495,2507 ----
  addresses have different requirements than other base register uses.
  @end defmac
  
! @defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
  A C expression whose value is the register class to which a valid
! base register for a memory reference in mode @var{mode} to address
! space @var{address_space} must belong.  @var{outer_code} and @var{index_code}
! define the context in which the base register occurs.  @var{outer_code} is
! the code of the immediately enclosing expression (@code{MEM} for the top level
! of an address, @code{ADDRESS} for something that occurs in an
  @code{address_operand}).  @var{index_code} is the code of the corresponding
  index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise.
  @end defmac
*************** Use of this macro is deprecated; please 
*** 2555,2562 ****
  This macro also has strict and non-strict variants.
  @end defmac
  
! @defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{outer_code}, @var{index_code})
! A C expression that is just like @code{REGNO_MODE_OK_FOR_BASE_P}, except
  that that expression may examine the context in which the register
  appears in the memory reference.  @var{outer_code} is the code of the
  immediately enclosing expression (@code{MEM} if at the top level of the
--- 2556,2566 ----
  This macro also has strict and non-strict variants.
  @end defmac
  
! @defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
! A C expression which is nonzero if register number @var{num} is
! suitable for use as a base register in operand addresses, accessing
! memory in mode @var{mode} in address space @var{address_space}.
! This is similar to @code{REGNO_MODE_OK_FOR_BASE_P}, except
  that that expression may examine the context in which the register
  appears in the memory reference.  @var{outer_code} is the code of the
  immediately enclosing expression (@code{MEM} if at the top level of the
Index: gcc/ira-conflicts.c
===================================================================
*** gcc/ira-conflicts.c	(revision 153564)
--- gcc/ira-conflicts.c	(working copy)
*************** ira_debug_conflicts (bool reg_p)
*** 761,766 ****
--- 761,767 ----
  void
  ira_build_conflicts (void)
  {
+   enum reg_class base;
    ira_allocno_t a;
    ira_allocno_iterator ai;
    HARD_REG_SET temp_hard_reg_set;
*************** ira_build_conflicts (void)
*** 787,798 ****
  	  ira_free (conflicts);
  	}
      }
!   if (! CLASS_LIKELY_SPILLED_P (base_reg_class (VOIDmode, ADDRESS, SCRATCH)))
      CLEAR_HARD_REG_SET (temp_hard_reg_set);
    else
      {
!       COPY_HARD_REG_SET (temp_hard_reg_set,
! 			 reg_class_contents[base_reg_class (VOIDmode, ADDRESS, SCRATCH)]);
        AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs);
        AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set);
      }
--- 788,800 ----
  	  ira_free (conflicts);
  	}
      }
! 
!   base = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH);
!   if (! CLASS_LIKELY_SPILLED_P (base))
      CLEAR_HARD_REG_SET (temp_hard_reg_set);
    else
      {
!       COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[base]);
        AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs);
        AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set);
      }
Index: gcc/reload.c
===================================================================
*** gcc/reload.c	(revision 153564)
--- gcc/reload.c	(working copy)
*************** static int find_reloads_address (enum ma
*** 275,281 ****
  static rtx subst_reg_equivs (rtx, rtx);
  static rtx subst_indexed_address (rtx);
  static void update_auto_inc_notes (rtx, int, int);
! static int find_reloads_address_1 (enum machine_mode, rtx, int,
  				   enum rtx_code, enum rtx_code, rtx *,
  				   int, enum reload_type,int, rtx);
  static void find_reloads_address_part (rtx, rtx *, enum reg_class,
--- 275,281 ----
  static rtx subst_reg_equivs (rtx, rtx);
  static rtx subst_indexed_address (rtx);
  static void update_auto_inc_notes (rtx, int, int);
! static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int,
  				   enum rtx_code, enum rtx_code, rtx *,
  				   int, enum reload_type,int, rtx);
  static void find_reloads_address_part (rtx, rtx *, enum reg_class,
*************** find_reloads (rtx insn, int replace, int
*** 3227,3234 ****
  	      case 'p':
  		/* All necessary reloads for an address_operand
  		   were handled in find_reloads_address.  */
! 		this_alternative[i] = base_reg_class (VOIDmode, ADDRESS,
! 						      SCRATCH);
  		win = 1;
  		badop = 0;
  		break;
--- 3227,3235 ----
  	      case 'p':
  		/* All necessary reloads for an address_operand
  		   were handled in find_reloads_address.  */
! 		this_alternative[i]
! 		  = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 				    ADDRESS, SCRATCH);
  		win = 1;
  		badop = 0;
  		break;
*************** find_reloads (rtx insn, int replace, int
*** 3433,3441 ****
  
  			/* If we didn't already win, we can reload
  			   the address into a base register.  */
! 			this_alternative[i] = base_reg_class (VOIDmode,
! 							      ADDRESS,
! 							      SCRATCH);
  			badop = 0;
  			break;
  		      }
--- 3434,3442 ----
  
  			/* If we didn't already win, we can reload
  			   the address into a base register.  */
! 			this_alternative[i]
! 			  = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					    ADDRESS, SCRATCH);
  			badop = 0;
  			break;
  		      }
*************** find_reloads (rtx insn, int replace, int
*** 3989,4006 ****
  	    /* If the address to be reloaded is a VOIDmode constant,
  	       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)
! 	      {
! 		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,
  			     &XEXP (recog_data.operand[i], 0), (rtx*) 0,
! 			     base_reg_class (VOIDmode, MEM, SCRATCH),
  			     address_mode,
  			     VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
  	    rld[operand_reloadnum[i]].inc
--- 3990,4005 ----
  	    /* If the address to be reloaded is a VOIDmode constant,
  	       use the default address mode as mode of the reload register,
  	       as would have been done by find_reloads_address.  */
+ 	    addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
  	    enum machine_mode address_mode;
  	    address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
  	    if (address_mode == VOIDmode)
! 	      address_mode = targetm.addr_space.address_mode (as);
  
  	    operand_reloadnum[i]
  	      = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
  			     &XEXP (recog_data.operand[i], 0), (rtx*) 0,
! 			     base_reg_class (VOIDmode, as, MEM, SCRATCH),
  			     address_mode,
  			     VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
  	    rld[operand_reloadnum[i]].inc
*************** find_reloads_address (enum machine_mode 
*** 4897,4903 ****
        if (reg_equiv_constant[regno] != 0)
  	{
  	  find_reloads_address_part (reg_equiv_constant[regno], loc,
! 				     base_reg_class (mode, MEM, SCRATCH),
  				     GET_MODE (ad), opnum, type, ind_levels);
  	  return 1;
  	}
--- 4896,4902 ----
        if (reg_equiv_constant[regno] != 0)
  	{
  	  find_reloads_address_part (reg_equiv_constant[regno], loc,
! 				     base_reg_class (mode, as, MEM, SCRATCH),
  				     GET_MODE (ad), opnum, type, ind_levels);
  	  return 1;
  	}
*************** find_reloads_address (enum machine_mode 
*** 4960,4971 ****
  	 subject of a CLOBBER in this insn.  */
  
        else if (regno < FIRST_PSEUDO_REGISTER
! 	       && regno_ok_for_base_p (regno, mode, MEM, SCRATCH)
  	       && ! regno_clobbered_p (regno, this_insn, mode, 0))
  	return 0;
  
        /* If we do not have one of the cases above, we must do the reload.  */
!       push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH),
  		   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
        return 1;
      }
--- 4959,4971 ----
  	 subject of a CLOBBER in this insn.  */
  
        else if (regno < FIRST_PSEUDO_REGISTER
! 	       && regno_ok_for_base_p (regno, mode, as, MEM, SCRATCH)
  	       && ! regno_clobbered_p (regno, this_insn, mode, 0))
  	return 0;
  
        /* If we do not have one of the cases above, we must do the reload.  */
!       push_reload (ad, NULL_RTX, loc, (rtx*) 0,
! 		   base_reg_class (mode, as, MEM, SCRATCH),
  		   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
        return 1;
      }
*************** find_reloads_address (enum machine_mode 
*** 5066,5072 ****
  	  /* Must use TEM here, not AD, since it is the one that will
  	     have any subexpressions reloaded, if needed.  */
  	  push_reload (tem, NULL_RTX, loc, (rtx*) 0,
! 		       base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem),
  		       VOIDmode, 0,
  		       0, opnum, type);
  	  return ! removed_and;
--- 5066,5072 ----
  	  /* Must use TEM here, not AD, since it is the one that will
  	     have any subexpressions reloaded, if needed.  */
  	  push_reload (tem, NULL_RTX, loc, (rtx*) 0,
! 		       base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (tem),
  		       VOIDmode, 0,
  		       0, opnum, type);
  	  return ! removed_and;
*************** find_reloads_address (enum machine_mode 
*** 5084,5090 ****
  	   && REG_P (XEXP (ad, 0))
  	   && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
  	   && CONST_INT_P (XEXP (ad, 1))
! 	   && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
  				   CONST_INT))
  
      {
--- 5084,5090 ----
  	   && REG_P (XEXP (ad, 0))
  	   && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
  	   && CONST_INT_P (XEXP (ad, 1))
! 	   && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as, PLUS,
  				   CONST_INT))
  
      {
*************** find_reloads_address (enum machine_mode 
*** 5115,5121 ****
  	     reload the sum into a base reg.
  	     That will at least work.  */
  	  find_reloads_address_part (ad, loc,
! 				     base_reg_class (mode, MEM, SCRATCH),
  				     GET_MODE (ad), opnum, type, ind_levels);
  	}
        return ! removed_and;
--- 5115,5121 ----
  	     reload the sum into a base reg.
  	     That will at least work.  */
  	  find_reloads_address_part (ad, loc,
! 				     base_reg_class (mode, as, MEM, SCRATCH),
  				     GET_MODE (ad), opnum, type, ind_levels);
  	}
        return ! removed_and;
*************** find_reloads_address (enum machine_mode 
*** 5167,5173 ****
  
        addend = XEXP (XEXP (ad, 0), 1 - op_index);
  
!       if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code,
  				GET_CODE (addend))
  	   || operand == frame_pointer_rtx
  #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
--- 5167,5173 ----
  
        addend = XEXP (XEXP (ad, 0), 1 - op_index);
  
!       if ((regno_ok_for_base_p (REGNO (operand), mode, as, inner_code,
  				GET_CODE (addend))
  	   || operand == frame_pointer_rtx
  #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
*************** find_reloads_address (enum machine_mode 
*** 5196,5206 ****
  				 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), 
  				     &XEXP (ad, op_index), cls,
  				     GET_MODE (ad), opnum, type, ind_levels);
! 	  find_reloads_address_1 (mode,
  				  XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
  				  GET_CODE (XEXP (ad, op_index)),
  				  &XEXP (ad, 1 - op_index), opnum,
--- 5196,5206 ----
  				 op_index == 0 ? addend : offset_reg);
  	  *loc = ad;
  
! 	  cls = base_reg_class (mode, as, MEM, GET_CODE (addend));
  	  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, as,
  				  XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
  				  GET_CODE (XEXP (ad, op_index)),
  				  &XEXP (ad, 1 - op_index), opnum,
*************** find_reloads_address (enum machine_mode 
*** 5253,5265 ****
  	    loc = &XEXP (*loc, 0);
  	}
  
!       find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
  				 address_mode, opnum, type, ind_levels);
        return ! removed_and;
      }
  
!   return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type,
! 				 ind_levels, insn);
  }
  \f
  /* Find all pseudo regs appearing in AD
--- 5253,5266 ----
  	    loc = &XEXP (*loc, 0);
  	}
  
!       find_reloads_address_part (ad, loc,
! 				 base_reg_class (mode, as, MEM, SCRATCH),
  				 address_mode, opnum, type, ind_levels);
        return ! removed_and;
      }
  
!   return find_reloads_address_1 (mode, as, ad, 0, MEM, SCRATCH, loc,
! 				 opnum, type, ind_levels, insn);
  }
  \f
  /* Find all pseudo regs appearing in AD
*************** update_auto_inc_notes (rtx insn ATTRIBUT
*** 5492,5505 ****
     handles those cases gracefully.  */
  
  static int
! find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
  			enum rtx_code outer_code, enum rtx_code index_code,
  			rtx *loc, int opnum, enum reload_type type,
  			int ind_levels, rtx insn)
  {
! #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))					
  
    enum reg_class context_reg_class;
--- 5493,5507 ----
     handles those cases gracefully.  */
  
  static int
! find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
! 			rtx x, int context,
  			enum rtx_code outer_code, enum rtx_code index_code,
  			rtx *loc, int opnum, enum reload_type type,
  			int ind_levels, rtx insn)
  {
! #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, AS, OUTER, INDEX)	\
    ((CONTEXT) == 0							\
!    ? regno_ok_for_base_p (REGNO, MODE, AS, OUTER, INDEX)		\
     : REGNO_OK_FOR_INDEX_P (REGNO))					
  
    enum reg_class context_reg_class;
*************** find_reloads_address_1 (enum machine_mod
*** 5508,5514 ****
    if (context == 1)
      context_reg_class = INDEX_REG_CLASS;
    else
!     context_reg_class = base_reg_class (mode, outer_code, index_code);
  
    switch (code)
      {
--- 5510,5516 ----
    if (context == 1)
      context_reg_class = INDEX_REG_CLASS;
    else
!     context_reg_class = base_reg_class (mode, as, outer_code, index_code);
  
    switch (code)
      {
*************** find_reloads_address_1 (enum machine_mod
*** 5565,5574 ****
  	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
  	    || code0 == ZERO_EXTEND || code1 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
--- 5567,5576 ----
  	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
  	    || code0 == ZERO_EXTEND || code1 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
*************** find_reloads_address_1 (enum machine_mod
*** 5576,5631 ****
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
  
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
  				  &XEXP (x, 1), opnum, type, ind_levels,
  				  insn);
  
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
  				  &XEXP (x, 0), opnum, type, ind_levels,
  				  insn);
  
  	else if (code0 == REG && code1 == REG)
  	  {
  	    if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
! 		&& regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
  	      return 0;
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
! 		     && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
  	      return 0;
! 	    else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
! 	      find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
  				      &XEXP (x, 1), opnum, type, ind_levels,
  				      insn);
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
! 	      find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
  				      &XEXP (x, 0), opnum, type, ind_levels,
  				      insn);
! 	    else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
! 	      find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
  				      &XEXP (x, 0), opnum, type, ind_levels,
  				      insn);
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
! 	      find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
  				      &XEXP (x, 1), opnum, type, ind_levels,
  				      insn);
  	    else
  	      {
! 		find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
  					&XEXP (x, 0), opnum, type, ind_levels,
  					insn);
! 		find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
  					&XEXP (x, 1), opnum, type, ind_levels,
  					insn);
  	      }
--- 5578,5633 ----
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
  
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0,
  				  &XEXP (x, 1), opnum, type, ind_levels,
  				  insn);
  
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1,
  				  &XEXP (x, 0), opnum, type, ind_levels,
  				  insn);
  
  	else if (code0 == REG && code1 == REG)
  	  {
  	    if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
! 		&& regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
  	      return 0;
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
! 		     && regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
  	      return 0;
! 	    else if (regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
! 	      find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
  				      &XEXP (x, 1), opnum, type, ind_levels,
  				      insn);
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
! 	      find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
  				      &XEXP (x, 0), opnum, type, ind_levels,
  				      insn);
! 	    else if (regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
! 	      find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
  				      &XEXP (x, 0), opnum, type, ind_levels,
  				      insn);
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
! 	      find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG,
  				      &XEXP (x, 1), opnum, type, ind_levels,
  				      insn);
  	    else
  	      {
! 		find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
  					&XEXP (x, 0), opnum, type, ind_levels,
  					insn);
! 		find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
  					&XEXP (x, 1), opnum, type, ind_levels,
  					insn);
  	      }
*************** find_reloads_address_1 (enum machine_mod
*** 5633,5652 ****
  
  	else if (code0 == REG)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
  
  	else if (code1 == REG)
  	  {
! 	    find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
  	  }
--- 5635,5654 ----
  
  	else if (code0 == REG)
  	  {
! 	    find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
  
  	else if (code1 == REG)
  	  {
! 	    find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
  	  }
*************** find_reloads_address_1 (enum machine_mod
*** 5688,5694 ****
  	if ((REG_P (XEXP (op1, 1))
  	     && !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
  	    || GET_CODE (XEXP (op1, 1)) == PLUS)
! 	  find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
  				  &XEXP (op1, 1), opnum, RELOAD_OTHER,
  				  ind_levels, insn);
  
--- 5690,5696 ----
  	if ((REG_P (XEXP (op1, 1))
  	     && !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
  	    || GET_CODE (XEXP (op1, 1)) == PLUS)
! 	  find_reloads_address_1 (mode, as, XEXP (op1, 1), 1, code, SCRATCH,
  				  &XEXP (op1, 1), opnum, RELOAD_OTHER,
  				  ind_levels, insn);
  
*************** find_reloads_address_1 (enum machine_mod
*** 5730,5737 ****
  		   register.  */
  		reloadnum = push_reload (tem, tem, &XEXP (x, 0),
  					 &XEXP (op1, 0),
! 					 base_reg_class (mode, code,
! 							 index_code),
  					 GET_MODE (x), GET_MODE (x), 0,
  					 0, opnum, RELOAD_OTHER);
  
--- 5732,5739 ----
  		   register.  */
  		reloadnum = push_reload (tem, tem, &XEXP (x, 0),
  					 &XEXP (op1, 0),
! 					 base_reg_class (mode, as,
! 							 code, index_code),
  					 GET_MODE (x), GET_MODE (x), 0,
  					 0, opnum, RELOAD_OTHER);
  
*************** find_reloads_address_1 (enum machine_mod
*** 5744,5754 ****
  	  regno = reg_renumber[regno];
  
  	/* We require a base register here...  */
! 	if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code))
  	  {
  	    reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
  				     &XEXP (op1, 0), &XEXP (x, 0),
! 				     base_reg_class (mode, code, index_code),
  				     GET_MODE (x), GET_MODE (x), 0, 0,
  				     opnum, RELOAD_OTHER);
  
--- 5746,5757 ----
  	  regno = reg_renumber[regno];
  
  	/* We require a base register here...  */
! 	if (!regno_ok_for_base_p (regno, GET_MODE (x), as, code, index_code))
  	  {
  	    reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
  				     &XEXP (op1, 0), &XEXP (x, 0),
! 				     base_reg_class (mode, as,
! 						     code, index_code),
  				     GET_MODE (x), GET_MODE (x), 0, 0,
  				     opnum, RELOAD_OTHER);
  
*************** find_reloads_address_1 (enum machine_mod
*** 5814,5820 ****
  	  if (reg_renumber[regno] >= 0)
  	    regno = reg_renumber[regno];
  	  if (regno >= FIRST_PSEUDO_REGISTER
! 	      || !REG_OK_FOR_CONTEXT (context, regno, mode, code,
  				      index_code))
  	    {
  	      int reloadnum;
--- 5817,5823 ----
  	  if (reg_renumber[regno] >= 0)
  	    regno = reg_renumber[regno];
  	  if (regno >= FIRST_PSEUDO_REGISTER
! 	      || !REG_OK_FOR_CONTEXT (context, regno, mode, as, code,
  				      index_code))
  	    {
  	      int reloadnum;
*************** find_reloads_address_1 (enum machine_mod
*** 5886,5892 ****
  	 reloaded.  Targets that are better off reloading just either part
  	 (or perhaps even a different part of an outer expression), should
  	 define LEGITIMIZE_RELOAD_ADDRESS.  */
!       find_reloads_address_1 (GET_MODE (XEXP (x, 0)), XEXP (x, 0),
  			      context, code, SCRATCH, &XEXP (x, 0), opnum,
  			      type, ind_levels, insn);
        push_reload (x, NULL_RTX, loc, (rtx*) 0,
--- 5889,5895 ----
  	 reloaded.  Targets that are better off reloading just either part
  	 (or perhaps even a different part of an outer expression), should
  	 define LEGITIMIZE_RELOAD_ADDRESS.  */
!       find_reloads_address_1 (GET_MODE (XEXP (x, 0)), as, XEXP (x, 0),
  			      context, code, SCRATCH, &XEXP (x, 0), opnum,
  			      type, ind_levels, insn);
        push_reload (x, NULL_RTX, loc, (rtx*) 0,
*************** find_reloads_address_1 (enum machine_mod
*** 5957,5963 ****
  	  regno = reg_renumber[regno];
  
  	if (regno >= FIRST_PSEUDO_REGISTER
! 	    || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
  				    index_code))
  	  {
  	    push_reload (x, NULL_RTX, loc, (rtx*) 0,
--- 5960,5966 ----
  	  regno = reg_renumber[regno];
  
  	if (regno >= FIRST_PSEUDO_REGISTER
! 	    || !REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
  				    index_code))
  	  {
  	    push_reload (x, NULL_RTX, loc, (rtx*) 0,
*************** find_reloads_address_1 (enum machine_mod
*** 5990,5996 ****
  	    {
  	      int regno ATTRIBUTE_UNUSED = subreg_regno (x);
  
! 	      if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
  				       index_code))
  		{
  		  push_reload (x, NULL_RTX, loc, (rtx*) 0,
--- 5993,5999 ----
  	    {
  	      int regno ATTRIBUTE_UNUSED = subreg_regno (x);
  
! 	      if (!REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
  				       index_code))
  		{
  		  push_reload (x, NULL_RTX, loc, (rtx*) 0,
*************** find_reloads_address_1 (enum machine_mod
*** 6031,6038 ****
  	if (fmt[i] == 'e')
  	  /* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once
  	     we get here.  */
! 	  find_reloads_address_1 (mode, XEXP (x, i), context, code, SCRATCH,
! 				  &XEXP (x, i), opnum, type, ind_levels, insn);
        }
    }
  
--- 6034,6042 ----
  	if (fmt[i] == 'e')
  	  /* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once
  	     we get here.  */
! 	  find_reloads_address_1 (mode, as, XEXP (x, i), context,
! 				  code, SCRATCH, &XEXP (x, i),
! 				  opnum, type, ind_levels, insn);
        }
    }
  
*************** find_reloads_subreg_address (rtx x, int 
*** 6203,6209 ****
  			(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,
  			     opnum, type);
  
--- 6207,6215 ----
  			(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_ADDR_SPACE (tem),
! 					     MEM, SCRATCH),
  			     GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
  			     opnum, type);
  
Index: gcc/caller-save.c
===================================================================
*** gcc/caller-save.c	(revision 153564)
--- gcc/caller-save.c	(working copy)
*************** init_caller_save (void)
*** 246,252 ****
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      if (TEST_HARD_REG_BIT
  	(reg_class_contents
! 	 [(int) base_reg_class (regno_save_mode[i][1], PLUS, CONST_INT)], i))
        break;
  
    gcc_assert (i < FIRST_PSEUDO_REGISTER);
--- 246,253 ----
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      if (TEST_HARD_REG_BIT
  	(reg_class_contents
! 	 [(int) base_reg_class (regno_save_mode[i][1], ADDR_SPACE_GENERIC,
! 				PLUS, CONST_INT)], i))
        break;
  
    gcc_assert (i < FIRST_PSEUDO_REGISTER);
Index: gcc/recog.c
===================================================================
*** gcc/recog.c	(revision 153564)
--- gcc/recog.c	(working copy)
*************** preprocess_constraints (void)
*** 2243,2249 ****
  		case 'p':
  		  op_alt[j].is_address = 1;
  		  op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
! 		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
--- 2243,2250 ----
  		case 'p':
  		  op_alt[j].is_address = 1;
  		  op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
! 		      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					     ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
*************** preprocess_constraints (void)
*** 2264,2271 ****
  		      op_alt[j].cl
  			= (reg_class_subunion
  			   [(int) op_alt[j].cl]
! 			   [(int) base_reg_class (VOIDmode, ADDRESS,
! 						  SCRATCH)]);
  		      break;
  		    }
  
--- 2265,2272 ----
  		      op_alt[j].cl
  			= (reg_class_subunion
  			   [(int) op_alt[j].cl]
! 			   [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 						  ADDRESS, SCRATCH)]);
  		      break;
  		    }
  
Index: gcc/ira-costs.c
===================================================================
*** gcc/ira-costs.c	(revision 153564)
--- gcc/ira-costs.c	(working copy)
*************** record_reg_classes (int n_alts, int n_op
*** 398,404 ****
  		     base of an address, i.e. BASE_REG_CLASS.  */
  		  classes[i]
  		    = ira_reg_class_union[classes[i]]
! 		      [base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  break;
  
  		case 'm':  case 'o':  case 'V':
--- 398,405 ----
  		     base of an address, i.e. BASE_REG_CLASS.  */
  		  classes[i]
  		    = ira_reg_class_union[classes[i]]
! 		      [base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 				       ADDRESS, SCRATCH)];
  		  break;
  
  		case 'm':  case 'o':  case 'V':
*************** record_reg_classes (int n_alts, int n_op
*** 513,519 ****
  			 i.e. BASE_REG_CLASS.  */
  		      classes[i]
  			= ira_reg_class_union[classes[i]]
! 			  [base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		    }
  #endif
  		  break;
--- 514,521 ----
  			 i.e. BASE_REG_CLASS.  */
  		      classes[i]
  			= ira_reg_class_union[classes[i]]
! 			  [base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					   ADDRESS, SCRATCH)];
  		    }
  #endif
  		  break;
*************** ok_for_index_p_nonstrict (rtx reg)
*** 727,740 ****
     pseudo-registers should count as OK.  Arguments as for
     regno_ok_for_base_p.  */
  static inline bool
! ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode,
  			 enum rtx_code outer_code, enum rtx_code index_code)
  {
    unsigned regno = REGNO (reg);
  
    if (regno >= FIRST_PSEUDO_REGISTER)
      return true;
!   return ok_for_base_p_1 (regno, mode, outer_code, index_code);
  }
  
  /* Record the pseudo registers we must reload into hard registers in a
--- 729,742 ----
     pseudo-registers should count as OK.  Arguments as for
     regno_ok_for_base_p.  */
  static inline bool
! ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode, addr_space_t as,
  			 enum rtx_code outer_code, enum rtx_code index_code)
  {
    unsigned regno = REGNO (reg);
  
    if (regno >= FIRST_PSEUDO_REGISTER)
      return true;
!   return ok_for_base_p_1 (regno, mode, as, outer_code, index_code);
  }
  
  /* Record the pseudo registers we must reload into hard registers in a
*************** ok_for_base_p_nonstrict (rtx reg, enum m
*** 743,758 ****
     If CONTEXT is 0, we are looking at the base part of an address,
     otherwise we are looking at the index part.
  
!    MODE is the mode of the memory reference; OUTER_CODE and INDEX_CODE
!    give the context that the rtx appears in.  These three arguments
!    are passed down to base_reg_class.
  
     SCALE is twice the amount to multiply the cost by (it is twice so
     we can represent half-cost adjustments).  */
  static void
! record_address_regs (enum machine_mode mode, rtx x, int context,
! 		     enum rtx_code outer_code, enum rtx_code index_code,
! 		     int scale)
  {
    enum rtx_code code = GET_CODE (x);
    enum reg_class rclass;
--- 745,760 ----
     If CONTEXT is 0, we are looking at the base part of an address,
     otherwise we are looking at the index part.
  
!    MODE and AS are the mode and address space of the memory reference;
!    OUTER_CODE and INDEX_CODE give the context that the rtx appears in.
!    These four arguments are passed down to base_reg_class.
  
     SCALE is twice the amount to multiply the cost by (it is twice so
     we can represent half-cost adjustments).  */
  static void
! record_address_regs (enum machine_mode mode, addr_space_t as, rtx x,
! 		     int context, enum rtx_code outer_code,
! 		     enum rtx_code index_code, int scale)
  {
    enum rtx_code code = GET_CODE (x);
    enum reg_class rclass;
*************** record_address_regs (enum machine_mode m
*** 760,766 ****
    if (context == 1)
      rclass = INDEX_REG_CLASS;
    else
!     rclass = base_reg_class (mode, outer_code, index_code);
  
    switch (code)
      {
--- 762,768 ----
    if (context == 1)
      rclass = INDEX_REG_CLASS;
    else
!     rclass = base_reg_class (mode, as, outer_code, index_code);
  
    switch (code)
      {
*************** record_address_regs (enum machine_mode m
*** 799,865 ****
  	/* If this machine only allows one register per address, it
  	   must be in the first operand.  */
  	if (MAX_REGS_PER_ADDRESS == 1)
! 	  record_address_regs (mode, arg0, 0, PLUS, code1, scale);
  
  	/* If index and base registers are the same on this machine,
  	   just record registers in any non-constant operands.  We
  	   assume here, as well as in the tests below, that all
  	   addresses are in canonical form.  */
! 	else if (INDEX_REG_CLASS == base_reg_class (VOIDmode, PLUS, SCRATCH))
  	  {
! 	    record_address_regs (mode, arg0, context, PLUS, code1, scale);
  	    if (! CONSTANT_P (arg1))
! 	      record_address_regs (mode, arg1, context, PLUS, code0, scale);
  	  }
  
  	/* If the second operand is a constant integer, it doesn't
  	   change what class the first operand must be.  */
  	else if (code1 == CONST_INT || code1 == CONST_DOUBLE)
! 	  record_address_regs (mode, arg0, context, PLUS, code1, scale);
  	/* If the second operand is a symbolic constant, the first
  	   operand must be an index register.  */
  	else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF)
! 	  record_address_regs (mode, arg0, 1, PLUS, code1, scale);
  	/* If both operands are registers but one is already a hard
  	   register of index or reg-base class, give the other the
  	   class that the hard register is not.  */
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg0) < FIRST_PSEUDO_REGISTER
! 		 && (ok_for_base_p_nonstrict (arg0, mode, PLUS, REG)
  		     || ok_for_index_p_nonstrict (arg0)))
! 	  record_address_regs (mode, arg1,
! 			       ok_for_base_p_nonstrict (arg0, mode, PLUS, REG)
! 			       ? 1 : 0,
  			       PLUS, REG, scale);
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg1) < FIRST_PSEUDO_REGISTER
! 		 && (ok_for_base_p_nonstrict (arg1, mode, PLUS, REG)
  		     || ok_for_index_p_nonstrict (arg1)))
! 	  record_address_regs (mode, arg0,
! 			       ok_for_base_p_nonstrict (arg1, mode, PLUS, REG)
! 			       ? 1 : 0,
  			       PLUS, REG, scale);
  	/* If one operand is known to be a pointer, it must be the
  	   base with the other operand the index.  Likewise if the
  	   other operand is a MULT.  */
  	else if ((code0 == REG && REG_POINTER (arg0)) || code1 == MULT)
  	  {
! 	    record_address_regs (mode, arg0, 0, PLUS, code1, scale);
! 	    record_address_regs (mode, arg1, 1, PLUS, code0, scale);
  	  }
  	else if ((code1 == REG && REG_POINTER (arg1)) || code0 == MULT)
  	  {
! 	    record_address_regs (mode, arg0, 1, PLUS, code1, scale);
! 	    record_address_regs (mode, arg1, 0, PLUS, code0, scale);
  	  }
  	/* Otherwise, count equal chances that each might be a base or
  	   index register.  This case should be rare.  */
  	else
  	  {
! 	    record_address_regs (mode, arg0, 0, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, arg0, 1, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, arg1, 0, PLUS, code0, scale / 2);
! 	    record_address_regs (mode, arg1, 1, PLUS, code0, scale / 2);
  	  }
        }
        break;
--- 801,868 ----
  	/* If this machine only allows one register per address, it
  	   must be in the first operand.  */
  	if (MAX_REGS_PER_ADDRESS == 1)
! 	  record_address_regs (mode, as, arg0, 0, PLUS, code1, scale);
  
  	/* If index and base registers are the same on this machine,
  	   just record registers in any non-constant operands.  We
  	   assume here, as well as in the tests below, that all
  	   addresses are in canonical form.  */
! 	else if (INDEX_REG_CLASS
! 		 == base_reg_class (VOIDmode, as, PLUS, SCRATCH))
  	  {
! 	    record_address_regs (mode, as, arg0, context, PLUS, code1, scale);
  	    if (! CONSTANT_P (arg1))
! 	      record_address_regs (mode, as, arg1, context, PLUS, code0, scale);
  	  }
  
  	/* If the second operand is a constant integer, it doesn't
  	   change what class the first operand must be.  */
  	else if (code1 == CONST_INT || code1 == CONST_DOUBLE)
! 	  record_address_regs (mode, as, arg0, context, PLUS, code1, scale);
  	/* If the second operand is a symbolic constant, the first
  	   operand must be an index register.  */
  	else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF)
! 	  record_address_regs (mode, as, arg0, 1, PLUS, code1, scale);
  	/* If both operands are registers but one is already a hard
  	   register of index or reg-base class, give the other the
  	   class that the hard register is not.  */
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg0) < FIRST_PSEUDO_REGISTER
! 		 && (ok_for_base_p_nonstrict (arg0, mode, as, PLUS, REG)
  		     || ok_for_index_p_nonstrict (arg0)))
! 	  record_address_regs (mode, as, arg1,
! 			       ok_for_base_p_nonstrict (arg0, mode, as,
! 							PLUS, REG) ? 1 : 0,
  			       PLUS, REG, scale);
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg1) < FIRST_PSEUDO_REGISTER
! 		 && (ok_for_base_p_nonstrict (arg1, mode, as, PLUS, REG)
  		     || ok_for_index_p_nonstrict (arg1)))
! 	  record_address_regs (mode, as, arg0,
! 			       ok_for_base_p_nonstrict (arg1, mode, as,
! 							PLUS, REG) ? 1 : 0,
  			       PLUS, REG, scale);
  	/* If one operand is known to be a pointer, it must be the
  	   base with the other operand the index.  Likewise if the
  	   other operand is a MULT.  */
  	else if ((code0 == REG && REG_POINTER (arg0)) || code1 == MULT)
  	  {
! 	    record_address_regs (mode, as, arg0, 0, PLUS, code1, scale);
! 	    record_address_regs (mode, as, arg1, 1, PLUS, code0, scale);
  	  }
  	else if ((code1 == REG && REG_POINTER (arg1)) || code0 == MULT)
  	  {
! 	    record_address_regs (mode, as, arg0, 1, PLUS, code1, scale);
! 	    record_address_regs (mode, as, arg1, 0, PLUS, code0, scale);
  	  }
  	/* Otherwise, count equal chances that each might be a base or
  	   index register.  This case should be rare.  */
  	else
  	  {
! 	    record_address_regs (mode, as, arg0, 0, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, as, arg0, 1, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, as, arg1, 0, PLUS, code0, scale / 2);
! 	    record_address_regs (mode, as, arg1, 1, PLUS, code0, scale / 2);
  	  }
        }
        break;
*************** record_address_regs (enum machine_mode m
*** 869,878 ****
  	 up in the wrong place.  */
      case POST_MODIFY:
      case PRE_MODIFY:
!       record_address_regs (mode, XEXP (x, 0), 0, code,
  			   GET_CODE (XEXP (XEXP (x, 1), 1)), 2 * scale);
        if (REG_P (XEXP (XEXP (x, 1), 1)))
! 	record_address_regs (mode, XEXP (XEXP (x, 1), 1), 1, code, REG,
  			     2 * scale);
        break;
  
--- 872,881 ----
  	 up in the wrong place.  */
      case POST_MODIFY:
      case PRE_MODIFY:
!       record_address_regs (mode, as, XEXP (x, 0), 0, code,
  			   GET_CODE (XEXP (XEXP (x, 1), 1)), 2 * scale);
        if (REG_P (XEXP (XEXP (x, 1), 1)))
! 	record_address_regs (mode, as, XEXP (XEXP (x, 1), 1), 1, code, REG,
  			     2 * scale);
        break;
  
*************** record_address_regs (enum machine_mode m
*** 889,895 ****
  	  && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
  	in_inc_dec[COST_INDEX (REGNO (XEXP (x, 0)))] = true;
  #endif
!       record_address_regs (mode, XEXP (x, 0), 0, code, SCRATCH, 2 * scale);
        break;
  
      case REG:
--- 892,898 ----
  	  && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
  	in_inc_dec[COST_INDEX (REGNO (XEXP (x, 0)))] = true;
  #endif
!       record_address_regs (mode, as, XEXP (x, 0), 0, code, SCRATCH, 2 * scale);
        break;
  
      case REG:
*************** record_address_regs (enum machine_mode m
*** 920,926 ****
  	int i;
  	for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  	  if (fmt[i] == 'e')
! 	    record_address_regs (mode, XEXP (x, i), context, code, SCRATCH,
  				 scale);
        }
      }
--- 923,929 ----
  	int i;
  	for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  	  if (fmt[i] == 'e')
! 	    record_address_regs (mode, as, XEXP (x, i), context, code, SCRATCH,
  				 scale);
        }
      }
*************** record_operand_costs (rtx insn, struct c
*** 956,968 ****
  
        if (MEM_P (recog_data.operand[i]))
  	record_address_regs (GET_MODE (recog_data.operand[i]),
  			     XEXP (recog_data.operand[i], 0),
  			     0, MEM, SCRATCH, frequency * 2);
        else if (constraints[i][0] == 'p'
  	       || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0],
  					    constraints[i]))
! 	record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS,
! 			     SCRATCH, frequency * 2);
      }
  
    /* Check for commutative in a separate loop so everything will have
--- 959,973 ----
  
        if (MEM_P (recog_data.operand[i]))
  	record_address_regs (GET_MODE (recog_data.operand[i]),
+ 			     MEM_ADDR_SPACE (recog_data.operand[i]),
  			     XEXP (recog_data.operand[i], 0),
  			     0, MEM, SCRATCH, frequency * 2);
        else if (constraints[i][0] == 'p'
  	       || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0],
  					    constraints[i]))
! 	record_address_regs (VOIDmode, ADDR_SPACE_GENERIC,
! 			     recog_data.operand[i], 0, ADDRESS, SCRATCH,
! 			     frequency * 2);
      }
  
    /* Check for commutative in a separate loop so everything will have
*************** scan_one_insn (rtx insn)
*** 1028,1035 ****
  	cl = pref[num];
        COSTS (costs, num)->mem_cost
  	-= ira_memory_move_cost[GET_MODE (reg)][cl][1] * frequency;
!       record_address_regs (GET_MODE (SET_SRC (set)), XEXP (SET_SRC (set), 0),
! 			   0, MEM, SCRATCH, frequency * 2);
      }
  
    record_operand_costs (insn, op_costs, pref);
--- 1033,1042 ----
  	cl = pref[num];
        COSTS (costs, num)->mem_cost
  	-= ira_memory_move_cost[GET_MODE (reg)][cl][1] * frequency;
!       record_address_regs (GET_MODE (SET_SRC (set)),
! 			   MEM_ADDR_SPACE (SET_SRC (set)),
! 			   XEXP (SET_SRC (set), 0), 0, MEM, SCRATCH,
! 			   frequency * 2);
      }
  
    record_operand_costs (insn, op_costs, pref);
Index: gcc/addresses.h
===================================================================
*** gcc/addresses.h	(revision 153564)
--- gcc/addresses.h	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 23,33 ****
  
  static inline enum reg_class
  base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
  		enum rtx_code outer_code ATTRIBUTE_UNUSED,
  		enum rtx_code index_code ATTRIBUTE_UNUSED)
  {
  #ifdef MODE_CODE_BASE_REG_CLASS
!   return MODE_CODE_BASE_REG_CLASS (mode, outer_code, index_code);
  #else
  #ifdef MODE_BASE_REG_REG_CLASS
    if (index_code == REG)
--- 23,34 ----
  
  static inline enum reg_class
  base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
+ 		addr_space_t as ATTRIBUTE_UNUSED,
  		enum rtx_code outer_code ATTRIBUTE_UNUSED,
  		enum rtx_code index_code ATTRIBUTE_UNUSED)
  {
  #ifdef MODE_CODE_BASE_REG_CLASS
!   return MODE_CODE_BASE_REG_CLASS (mode, as, outer_code, index_code);
  #else
  #ifdef MODE_BASE_REG_REG_CLASS
    if (index_code == REG)
*************** base_reg_class (enum machine_mode mode A
*** 48,58 ****
  
  static inline bool
  ok_for_base_p_1 (unsigned regno, enum machine_mode mode ATTRIBUTE_UNUSED,
  		 enum rtx_code outer_code ATTRIBUTE_UNUSED,
  		 enum rtx_code index_code ATTRIBUTE_UNUSED)
  {
  #ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
!   return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, mode, outer_code, index_code);
  #else
  #ifdef REGNO_MODE_OK_FOR_REG_BASE_P
    if (index_code == REG)
--- 49,61 ----
  
  static inline bool
  ok_for_base_p_1 (unsigned regno, enum machine_mode mode ATTRIBUTE_UNUSED,
+ 		 addr_space_t as ATTRIBUTE_UNUSED,
  		 enum rtx_code outer_code ATTRIBUTE_UNUSED,
  		 enum rtx_code index_code ATTRIBUTE_UNUSED)
  {
  #ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
!   return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, mode, as,
! 					outer_code, index_code);
  #else
  #ifdef REGNO_MODE_OK_FOR_REG_BASE_P
    if (index_code == REG)
*************** ok_for_base_p_1 (unsigned regno, enum ma
*** 70,80 ****
     complete.  Arguments as for the called function.  */
  
  static inline bool
! regno_ok_for_base_p (unsigned regno, enum machine_mode mode,
  		     enum rtx_code outer_code, enum rtx_code index_code)
  {
    if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
      regno = reg_renumber[regno];
  
!   return ok_for_base_p_1 (regno, mode, outer_code, index_code);
  }
--- 73,83 ----
     complete.  Arguments as for the called function.  */
  
  static inline bool
! regno_ok_for_base_p (unsigned regno, enum machine_mode mode, addr_space_t as,
  		     enum rtx_code outer_code, enum rtx_code index_code)
  {
    if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
      regno = reg_renumber[regno];
  
!   return ok_for_base_p_1 (regno, mode, as, outer_code, index_code);
  }
Index: gcc/config/cris/cris.h
===================================================================
*** gcc/config/cris/cris.h	(revision 153564)
--- gcc/config/cris/cris.h	(working copy)
*************** enum reg_class
*** 578,584 ****
  
  #define BASE_REG_CLASS GENERAL_REGS
  
! #define MODE_CODE_BASE_REG_CLASS(MODE, OCODE, ICODE)	\
    ((OCODE) != POST_INC ? BASE_REG_CLASS : GENNONACR_REGS)
  
  #define INDEX_REG_CLASS GENERAL_REGS
--- 578,584 ----
  
  #define BASE_REG_CLASS GENERAL_REGS
  
! #define MODE_CODE_BASE_REG_CLASS(MODE, AS, OCODE, ICODE)	\
    ((OCODE) != POST_INC ? BASE_REG_CLASS : GENNONACR_REGS)
  
  #define INDEX_REG_CLASS GENERAL_REGS
*************** enum reg_class
*** 605,611 ****
  
  /* REGNO_OK_FOR_BASE_P seems to be obsolete wrt. this one, but not yet
     documented as such.  */
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(REGNO, MODE, OCODE, ICODE)	\
   (REGNO_OK_FOR_BASE_P (REGNO)						\
    && ((OCODE) != POST_INC						\
        || !((REGNO) == CRIS_ACR_REGNUM					\
--- 605,611 ----
  
  /* REGNO_OK_FOR_BASE_P seems to be obsolete wrt. this one, but not yet
     documented as such.  */
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(REGNO, MODE, AS, OCODE, ICODE)	\
   (REGNO_OK_FOR_BASE_P (REGNO)						\
    && ((OCODE) != POST_INC						\
        || !((REGNO) == CRIS_ACR_REGNUM					\
Index: gcc/config/bfin/bfin.h
===================================================================
*** gcc/config/bfin/bfin.h	(revision 153564)
--- gcc/config/bfin/bfin.h	(working copy)
*************** enum reg_class
*** 690,696 ****
     || (OUTER) == POST_DEC || (OUTER) == PRE_DEC		     \
     || (OUTER) == MEM || (OUTER) == ADDRESS)
  
! #define MODE_CODE_BASE_REG_CLASS(MODE, OUTER, INDEX)			\
    ((MODE) == HImode && IREG_POSSIBLE_P (OUTER) ? IPREGS : PREGS)
  
  #define INDEX_REG_CLASS         PREGS
--- 690,696 ----
     || (OUTER) == POST_DEC || (OUTER) == PRE_DEC		     \
     || (OUTER) == MEM || (OUTER) == ADDRESS)
  
! #define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX)	\
    ((MODE) == HImode && IREG_POSSIBLE_P (OUTER) ? IPREGS : PREGS)
  
  #define INDEX_REG_CLASS         PREGS
*************** enum reg_class
*** 705,714 ****
     || REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX))
  
  #ifdef REG_OK_STRICT
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, OUTER, INDEX) \
    REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX)
  #else
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, OUTER, INDEX) \
    REGNO_OK_FOR_BASE_NONSTRICT_P (X, MODE, OUTER, INDEX)
  #endif
  
--- 705,714 ----
     || REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX))
  
  #ifdef REG_OK_STRICT
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, AS, OUTER, INDEX) \
    REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX)
  #else
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, AS, OUTER, INDEX) \
    REGNO_OK_FOR_BASE_NONSTRICT_P (X, MODE, OUTER, INDEX)
  #endif
  
Index: gcc/regcprop.c
===================================================================
*** gcc/regcprop.c	(revision 153564)
--- gcc/regcprop.c	(working copy)
*************** static rtx find_oldest_value_reg (enum r
*** 82,88 ****
  static bool replace_oldest_value_reg (rtx *, enum reg_class, rtx,
  				      struct value_data *);
  static bool replace_oldest_value_addr (rtx *, enum reg_class,
! 				       enum machine_mode, rtx,
  				       struct value_data *);
  static bool replace_oldest_value_mem (rtx, rtx, struct value_data *);
  static bool copyprop_hardreg_forward_1 (basic_block, struct value_data *);
--- 82,88 ----
  static bool replace_oldest_value_reg (rtx *, enum reg_class, rtx,
  				      struct value_data *);
  static bool replace_oldest_value_addr (rtx *, enum reg_class,
! 				       enum machine_mode, addr_space_t, rtx,
  				       struct value_data *);
  static bool replace_oldest_value_mem (rtx, rtx, struct value_data *);
  static bool copyprop_hardreg_forward_1 (basic_block, struct value_data *);
*************** replace_oldest_value_reg (rtx *loc, enum
*** 462,469 ****
  
  static bool
  replace_oldest_value_addr (rtx *loc, enum reg_class cl,
! 			   enum machine_mode mode, rtx insn,
! 			   struct value_data *vd)
  {
    rtx x = *loc;
    RTX_CODE code = GET_CODE (x);
--- 462,469 ----
  
  static bool
  replace_oldest_value_addr (rtx *loc, enum reg_class cl,
! 			   enum machine_mode mode, addr_space_t as,
! 			   rtx insn, struct value_data *vd)
  {
    rtx x = *loc;
    RTX_CODE code = GET_CODE (x);
*************** replace_oldest_value_addr (rtx *loc, enu
*** 532,546 ****
  	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
  	    if (REGNO_OK_FOR_INDEX_P (regno1)
! 		&& regno_ok_for_base_p (regno0, mode, PLUS, REG))
  	      index_op = 1;
  	    else if (REGNO_OK_FOR_INDEX_P (regno0)
! 		     && regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG)
  		     || REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
  	    else
  	      index_op = 1;
--- 532,546 ----
  	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
  	    if (REGNO_OK_FOR_INDEX_P (regno1)
! 		&& regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
  	      index_op = 1;
  	    else if (REGNO_OK_FOR_INDEX_P (regno0)
! 		     && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
  		     || REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
  	      index_op = 0;
  	    else
  	      index_op = 1;
*************** replace_oldest_value_addr (rtx *loc, enu
*** 563,575 ****
  	  }
  
  	if (locI)
! 	  changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS, mode,
! 						insn, vd);
  	if (locB)
  	  changed |= replace_oldest_value_addr (locB,
! 						base_reg_class (mode, PLUS,
  								index_code),
! 						mode, insn, vd);
  	return changed;
        }
  
--- 563,575 ----
  	  }
  
  	if (locI)
! 	  changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS,
! 						mode, as, insn, vd);
  	if (locB)
  	  changed |= replace_oldest_value_addr (locB,
! 						base_reg_class (mode, as, PLUS,
  								index_code),
! 						mode, as, insn, vd);
  	return changed;
        }
  
*************** replace_oldest_value_addr (rtx *loc, enu
*** 595,606 ****
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      {
        if (fmt[i] == 'e')
! 	changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode,
  					      insn, vd);
        else if (fmt[i] == 'E')
  	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
  	  changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), cl,
! 						mode, insn, vd);
      }
  
    return changed;
--- 595,606 ----
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      {
        if (fmt[i] == 'e')
! 	changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode, as,
  					      insn, vd);
        else if (fmt[i] == 'E')
  	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
  	  changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), cl,
! 						mode, as, insn, vd);
      }
  
    return changed;
*************** replace_oldest_value_mem (rtx x, rtx ins
*** 616,625 ****
    if (DEBUG_INSN_P (insn))
      cl = ALL_REGS;
    else
!     cl = base_reg_class (GET_MODE (x), MEM, SCRATCH);
  
    return replace_oldest_value_addr (&XEXP (x, 0), cl,
! 				    GET_MODE (x), insn, vd);
  }
  
  /* Perform the forward copy propagation on basic block BB.  */
--- 616,626 ----
    if (DEBUG_INSN_P (insn))
      cl = ALL_REGS;
    else
!     cl = base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x), MEM, SCRATCH);
  
    return replace_oldest_value_addr (&XEXP (x, 0), cl,
! 				    GET_MODE (x), MEM_ADDR_SPACE (x),
! 				    insn, vd);
  }
  
  /* Perform the forward copy propagation on basic block BB.  */
*************** copyprop_hardreg_forward_1 (basic_block 
*** 646,652 ****
  	      if (!VAR_LOC_UNKNOWN_P (loc)
  		  && replace_oldest_value_addr (&INSN_VAR_LOCATION_LOC (insn),
  						ALL_REGS, GET_MODE (loc),
! 						insn, vd))
  		{
  		  changed = apply_change_group ();
  		  gcc_assert (changed);
--- 647,653 ----
  	      if (!VAR_LOC_UNKNOWN_P (loc)
  		  && replace_oldest_value_addr (&INSN_VAR_LOCATION_LOC (insn),
  						ALL_REGS, GET_MODE (loc),
! 						ADDR_SPACE_GENERIC, insn, vd))
  		{
  		  changed = apply_change_group ();
  		  gcc_assert (changed);
*************** copyprop_hardreg_forward_1 (basic_block 
*** 790,796 ****
  		replaced[i]
  		  = replace_oldest_value_addr (recog_data.operand_loc[i],
  					       recog_op_alt[i][alt].cl,
! 					       VOIDmode, insn, vd);
  	      else if (REG_P (recog_data.operand[i]))
  		replaced[i]
  		  = replace_oldest_value_reg (recog_data.operand_loc[i],
--- 791,798 ----
  		replaced[i]
  		  = replace_oldest_value_addr (recog_data.operand_loc[i],
  					       recog_op_alt[i][alt].cl,
! 					       VOIDmode, ADDR_SPACE_GENERIC,
! 					       insn, vd);
  	      else if (REG_P (recog_data.operand[i]))
  		replaced[i]
  		  = replace_oldest_value_reg (recog_data.operand_loc[i],
Index: gcc/reload1.c
===================================================================
*** gcc/reload1.c	(revision 153564)
--- gcc/reload1.c	(working copy)
*************** maybe_fix_stack_asms (void)
*** 1535,1541 ****
  
  		case 'p':
  		  cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
--- 1535,1542 ----
  
  		case 'p':
  		  cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					     ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
*************** maybe_fix_stack_asms (void)
*** 1546,1552 ****
  		default:
  		  if (EXTRA_ADDRESS_CONSTRAINT (c, p))
  		    cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  else
  		    cls = (int) reg_class_subunion[cls]
  		      [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
--- 1547,1554 ----
  		default:
  		  if (EXTRA_ADDRESS_CONSTRAINT (c, p))
  		    cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					     ADDRESS, SCRATCH)];
  		  else
  		    cls = (int) reg_class_subunion[cls]
  		      [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-04 16:20 ` Ulrich Weigand
@ 2011-08-04 16:26   ` DJ Delorie
  2011-08-04 16:33     ` Ulrich Weigand
  2011-08-04 17:28   ` Georg-Johann Lay
  1 sibling, 1 reply; 21+ messages in thread
From: DJ Delorie @ 2011-08-04 16:26 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: avr, gcc


> The only target supporting named address spaces today is spu-elf,

m32c-elf does too.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-04 16:26   ` DJ Delorie
@ 2011-08-04 16:33     ` Ulrich Weigand
  0 siblings, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-04 16:33 UTC (permalink / raw)
  To: DJ Delorie; +Cc: avr, gcc

DJ Delorie wrote:
> > The only target supporting named address spaces today is spu-elf,
> 
> m32c-elf does too.

Huh, I totally missed that, sorry ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-04 16:20 ` Ulrich Weigand
  2011-08-04 16:26   ` DJ Delorie
@ 2011-08-04 17:28   ` Georg-Johann Lay
  2011-08-05 10:19     ` Ulrich Weigand
  2011-08-05 20:43     ` Ulrich Weigand
  1 sibling, 2 replies; 21+ messages in thread
From: Georg-Johann Lay @ 2011-08-04 17:28 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc

Ulrich Weigand wrote:
> Georg-Johann Lay wrote:
> 
>> Trying to make named address space support work for target AVR,
>> I am facing the following problem:
>>
>> For generic AS, there are three valid base pointer registers
>> X , Y and Z.
>>
>> For the new __pgm AS, only Z is available without offset.
>>
>> The problem is now that addresses.h:base_reg_class() does not
>> pass down AS information, i.e. addr_space_t down to target hook
>> MODE_CODE_BASE_REG_CLASS.
>>
>> Likewise for REGNO_MODE_CODE_OK_FOR_BASE_P.
>>
>> The MODE argument that both of these get describe the mode of
>> the MEM but not the mode associated with the AS.
>>
>> Thus, it is not possible to provide proper implementations of
>> these hooks.  IRA/reload choses the wrong hard register so
>> that in postreload no constraints match, i.e.
>> TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P returns wrong for that
>> hard register (which is right) so that postreload busts.
>>
>> I'd just like to reassure me that I didn't do something fundamentally
>> wrong and named address space support if not yet smoothly supported
>> in GCC.
> 
> No, you're correct.  The only target supporting named address spaces
> today is spu-elf, and here we're eliminating any reference to the
> non-default space during expand, so that reload never sees any.

So a solution for me would be to expand as inline asm instead of as
proper insns.  Yes, it's hack.  But before AS support I tried it via
builtin that expanded as unspec and IRA created horribly bloated code.

The annoyance is that only POST_INC addresses for one single hard reg
is supported by the device.  Greetings from spill fails...


> This means that problems like the one you're seeing have been hidden
> so far.  I've started looking into fixing this, but since I don't
> have a target where this is needed, this effort never really went
> anywhere.  I'll append below a patch I did a year or so ago; just
> as something to look at, it probably will not even apply to the
> current sources any more.

Sounds great that you tried to fix it!  Much work below... wow.

> I'd be happy to bring this up to date if you're willing to work with
> me to get this tested on a target that needs this support ...

Just attached a patch to bugzilla because an AVR user wanted to play
with the AS support and asked me to supply my changes. It's still in
a mess but you could get a more reasonable base than on a target where
all named addresses vanish at expand.

The patch is fresh and attached to the enhancement PR49868, just BE stuff.
There is also some sample code.

http://gcc.gnu.org/PR49868

Johann


> Bye,
> Ulrich
> 
> 
> 
> ChangeLog:
> 
> 	* doc/tm.texi (MODE_CODE_BASE_REG_CLASS): Add address space
> 	argument.
> 	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
> 
> 	* config/cris/cris.h (MODE_CODE_BASE_REG_CLASS): Add address
> 	space argument.
> 	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
> 	* config/bfin/bfin.h (MODE_CODE_BASE_REG_CLASS): Likewise.
> 	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
> 
> 	* addresses.h (base_reg_class): Add address space argument.
> 	Pass to MODE_CODE_BASE_REG_CLASS.
> 	(ok_for_base_p_1): Add address space argument.  Pass to
> 	REGNO_MODE_CODE_OK_FOR_BASE_P.
> 	(regno_ok_for_base_p): Add address space argument.  Pass to
> 	ok_for_base_p_1.
> 
> 	* regrename.c (scan_rtx_address): Add address space argument.
> 	Pass address space to regno_ok_for_base_p and base_reg_class.
> 	Update recursive calls.
> 	(scan_rtx): Pass address space to scan_rtx_address.
> 	(build_def_use): Likewise.
> 	* regcprop.c (replace_oldest_value_addr): Add address space
> 	argument.  Pass to regno_ok_for_base_p and base_reg_class.
> 	Update recursive calls.
> 	(replace_oldest_value_mem): Pass address space to
> 	replace_oldest_value_addr.
> 	(copyprop_hardreg_forward_1): Likewise.
> 
> 	* reload.c (find_reloads_address_1): Add address space argument.
> 	Pass address space to base_reg_class and regno_ok_for_base_p.
> 	Update recursive calls.
> 	(find_reloads_address): Pass address space to base_reg_class,
> 	regno_ok_for_base_p, and find_reloads_address_1.
> 	(find_reloads): Pass address space to base_reg_class.
> 	(find_reloads_subreg_address): Likewise.
> 
> 	* ira-costs.c (record_reg_classes): Update calls to base_reg_class.
> 	(ok_for_base_p_nonstrict): Add address space argument.  Pass to
> 	ok_for_base_p_1.
> 	(record_address_regs): Add address space argument.  Pass to
> 	base_reg_class and ok_for_base_p_nonstrict.  Update recursive calls.
> 	(record_operand_costs): Pass address space to record_address_regs.
> 	(scan_one_insn): Likewise.
> 
> 	* caller-save.c (init_caller_save): Update call to base_reg_class.
> 	* ira-conflicts.c (ira_build_conflicts): Likewise.
> 	* reload1.c (maybe_fix_stack_asms): Likewise.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-04 17:28   ` Georg-Johann Lay
@ 2011-08-05 10:19     ` Ulrich Weigand
  2011-08-05 12:47       ` Georg-Johann Lay
  2011-08-05 20:43     ` Ulrich Weigand
  1 sibling, 1 reply; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-05 10:19 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

Georg-Johann Lay wrote:
> Ulrich Weigand wrote:
> > I'd be happy to bring this up to date if you're willing to work with
> > me to get this tested on a target that needs this support ...
> 
> Just attached a patch to bugzilla because an AVR user wanted to play
> with the AS support and asked me to supply my changes. It's still in
> a mess but you could get a more reasonable base than on a target where
> all named addresses vanish at expand.
> 
> The patch is fresh and attached to the enhancement PR49868, just BE stuff.
> There is also some sample code.

OK, I'll have a look.

Looking at your definition of the routines avr_addr_space_subset_p and
avr_addr_space_convert, they appear to imply that any generic address
can be used without conversion as a __pgm address and vice versa.

That is: avr_addr_space_subset_p says that __pgm is both a superset
and a subset of the generic address space, so they must be co-extensive.
avr_addr_space_convert then says that the addresses can be converted
between the two without changing their value.

Is this really true?  If so, why have a distinct __pgm address space
in the first place?

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-05 10:19     ` Ulrich Weigand
@ 2011-08-05 12:47       ` Georg-Johann Lay
  2011-08-05 13:24         ` Ulrich Weigand
  0 siblings, 1 reply; 21+ messages in thread
From: Georg-Johann Lay @ 2011-08-05 12:47 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc

Ulrich Weigand schrieb:
> Georg-Johann Lay wrote:
> 
>>Ulrich Weigand wrote:
>>
>>>I'd be happy to bring this up to date if you're willing to work with
>>>me to get this tested on a target that needs this support ...
>>
>>Just attached a patch to bugzilla because an AVR user wanted to play
>>with the AS support and asked me to supply my changes. It's still in
>>a mess but you could get a more reasonable base than on a target where
>>all named addresses vanish at expand.
>>
>>The patch is fresh and attached to the enhancement PR49868, just BE stuff.
>>There is also some sample code.
> 
> OK, I'll have a look.
> 
> Looking at your definition of the routines avr_addr_space_subset_p and
> avr_addr_space_convert, they appear to imply that any generic address
> can be used without conversion as a __pgm address and vice versa.

There is a conversion HI (pmode) <-> PHI (__pgm)

These two modes resp. insns have the same arithmetic but differ in the
instructions they emit and in reloading.

> That is: avr_addr_space_subset_p says that __pgm is both a superset
> and a subset of the generic address space, so they must be co-extensive.
> avr_addr_space_convert then says that the addresses can be converted
> between the two without changing their value.
> 
> Is this really true?  If so, why have a distinct __pgm address space
> in the first place?
> 
> Bye,
> Ulrich

AVR hardware has basically three address spaces:

Memoy     Physical       Mode      Instruction  Holds
----------------------------------------------------------------------
RAM       0, 1, 2, ...   HI=Pmode  LD*, ST*     .data, .rodata, .bss
Flash     0, 1, 2, ...   PHI       LPM          .text, .progmem.data
EEPROM    0, 1, 2, ...   --        via SFR      .eeprom

Devices have just some KB of RAM and constants are put into
.progmem.data via attribute progmem and read via inline asm.

AVR has three address registers X, Y and Z that can access memory.
SP is fixed and can just do push/pop on RAM.

Adressing capabilities follow. Only accessing byte is supported by HW:

RAM:
Constant address
*X, *--X, *X++
*Y, *--Y, *Y++, *(Y+offset)  is Frame pointer
*Z, *--Z, *Z++, *(Z+offset)

Offset in [0, 63]

Flash:
*Z, *Z++

Of course, RAM and Flash are no subsets of each other when regarded as
physical memory, but they are subsets when regarded as numbers. This
lead to my mistake to define RAM and Flash being no subsets of each other:
   http://gcc.gnu.org/ml/gcc/2010-11/msg00170.html

In a typical AVR program the user knows at compile time how to access a
variable and use an appropriate pointer like int* or const __pgm int*.
In a current program he uses inline asm for the second case.

However, there are situations like the following where you like to take
the decision at runtime:

char cast_3 (char in_pgm, void * p)
{
     return in_pgm ? (*((char __pgm *) p)) : (*((char *) p));
}

The numeric value of p will stay exactly the same; just the mode and 
thus the access instruction changes like

  if (in_pgm)
    r = LPM Z (PHI:Z)
  else
    r = LD Z (HI:Z or LD X+ or whatever)

Linearizing the address space at compiler level is not wanted because 
that lead to bulky, slow code and reduced the effective address space
available for Flash which might be up to 64kWords.

An address in X, Y, Z is 16 bits wide, these regs occupy 2 hard regs.

Johann

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-05 12:47       ` Georg-Johann Lay
@ 2011-08-05 13:24         ` Ulrich Weigand
  2011-08-05 14:09           ` Michael Matz
  0 siblings, 1 reply; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-05 13:24 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

Georg-Johann Lay wrote:

> AVR hardware has basically three address spaces:
[snip]

OK, thanks for the information!

> Of course, RAM and Flash are no subsets of each other when regarded as
> physical memory, but they are subsets when regarded as numbers. This
> lead to my mistake to define RAM and Flash being no subsets of each other:
>    http://gcc.gnu.org/ml/gcc/2010-11/msg00170.html

Right, in your situation those are *not* subsets according to the AS rules,
so your avr_addr_space_subset_p routine needs to always return false
(which of course implies you don't need a avr_addr_space_convert routine).

Getting back to the discussion in the other thread, this also means that
pointer conversions during initialization cannot happen either, so this
discussion is basically moot.

> However, there are situations like the following where you like to take
> the decision at runtime:
> 
> char cast_3 (char in_pgm, void * p)
> {
>      return in_pgm ? (*((char __pgm *) p)) : (*((char *) p));
> }

That's really an abuse of "void *" ... if you have an address in the
Flash space, you should never assign it to a "void *".

Instead, if you just have a address and you don't know ahead of time
whether it refers to Flash or RAM space, you ought to hold that number
in an "int" (or "short" or whatever integer type is most appropriate),
and then convert from that integer type to either a "char *" or a
"char __pgm *".

> Linearizing the address space at compiler level is not wanted because 
> that lead to bulky, slow code and reduced the effective address space
> available for Flash which might be up to 64kWords.

I guess to simplify things like the above, you might have a third
address space (e.g. "__far") that is a superset of both the default
address space and the __pgm address space.  Pointers in the __far
address space might be e.g. 3 bytes wide, with the low 2 bytes
holding the address and the high byte identifying whether the address
is in Flash or RAM.

Then a plain dereference of a __far pointer would do the equivalent
of your cast_3 routine above.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-05 13:24         ` Ulrich Weigand
@ 2011-08-05 14:09           ` Michael Matz
  2011-08-05 14:29             ` Ulrich Weigand
  0 siblings, 1 reply; 21+ messages in thread
From: Michael Matz @ 2011-08-05 14:09 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Georg-Johann Lay, gcc

Hi,

On Fri, 5 Aug 2011, Ulrich Weigand wrote:

> > However, there are situations like the following where you like to take
> > the decision at runtime:
> > 
> > char cast_3 (char in_pgm, void * p)
> > {
> >      return in_pgm ? (*((char __pgm *) p)) : (*((char *) p));
> > }
> 
> That's really an abuse of "void *" ... if you have an address in the
> Flash space, you should never assign it to a "void *".
> 
> Instead, if you just have a address and you don't know ahead of time
> whether it refers to Flash or RAM space, you ought to hold that number
> in an "int" (or "short" or whatever integer type is most appropriate),
> and then convert from that integer type to either a "char *" or a
> "char __pgm *".

That would leave standard C.  You aren't allowed to construct pointers out 
of random integers.  I'd rather choose to abuse "void*" to be able to 
point into a yet-unspecified address spaces, which becomes specified once 
the void* pointer is converted into a non-void pointer (which it must be 
because you can't dereference a void pointer, hence it does no harm to 
leave its address space unspecified).

That would point to a third address space, call it "undef" :)  It would be 
superset of default and pgm, conversions between undef to {default,pgm} 
are allowed freely (and value preserving, i.e. trivial).  Conversion into 
undef could be rejected.  If they are allowed too, then also conversions 
between default and pgm are possible (via an intermediate step over 
undef), at which point the whole excercise seems a bit pointless and one 
could just as well allow conversions between default and pgm.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-05 14:09           ` Michael Matz
@ 2011-08-05 14:29             ` Ulrich Weigand
  0 siblings, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-05 14:29 UTC (permalink / raw)
  To: Michael Matz; +Cc: Georg-Johann Lay, gcc

Michael Matz wrote:
> On Fri, 5 Aug 2011, Ulrich Weigand wrote:
> > Instead, if you just have a address and you don't know ahead of time
> > whether it refers to Flash or RAM space, you ought to hold that number
> > in an "int" (or "short" or whatever integer type is most appropriate),
> > and then convert from that integer type to either a "char *" or a
> > "char __pgm *".
> 
> That would leave standard C.  You aren't allowed to construct pointers out 
> of random integers.

C leaves integer-to-pointer conversion *implementation-defined*,
not undefined, and GCC has always chosen to implement this by
(usually) keeping the value unchanged:
http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Arrays-and-pointers-implementation.html
This works both for default and non-default address spaces.

Of course, my suggested implementation would therefore rely on
implementation-defined behaviour (but by simply using the __pgm
address space, it does so anyway).

> That would point to a third address space, call it "undef" :)  It would be 
> superset of default and pgm, conversions between undef to {default,pgm} 
> are allowed freely (and value preserving, i.e. trivial).

That would probably violate the named AS specification, since two different
entities in the undef space would share the same pointer value ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-04 17:28   ` Georg-Johann Lay
  2011-08-05 10:19     ` Ulrich Weigand
@ 2011-08-05 20:43     ` Ulrich Weigand
  2011-08-05 20:47       ` DJ Delorie
  2011-08-08 11:38       ` Georg-Johann Lay
  1 sibling, 2 replies; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-05 20:43 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

Georg-Johann Lay wrote:
> Ulrich Weigand wrote:
> > This means that problems like the one you're seeing have been hidden
> > so far.  I've started looking into fixing this, but since I don't
> > have a target where this is needed, this effort never really went
> > anywhere.  I'll append below a patch I did a year or so ago; just
> > as something to look at, it probably will not even apply to the
> > current sources any more.
> 
> Sounds great that you tried to fix it!  Much work below... wow.
> 
> > I'd be happy to bring this up to date if you're willing to work with
> > me to get this tested on a target that needs this support ...

Here's an updated version of the patch that build with current GCC
mainline and passes the SPU test suite with no regressions.

Let me know if this works for you ...

Bye,
Ulrich


ChangeLog:

	* doc/tm.texi.in (MODE_CODE_BASE_REG_CLASS): Add address space
	argument.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
	* doc/tm.texi: Regenerate.

	* config/cris/cris.h (MODE_CODE_BASE_REG_CLASS): Add address
	space argument.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
	* config/bfin/bfin.h (MODE_CODE_BASE_REG_CLASS): Likewise.
	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.

	* addresses.h (base_reg_class): Add address space argument.
	Pass to MODE_CODE_BASE_REG_CLASS.
	(ok_for_base_p_1): Add address space argument.  Pass to
	REGNO_MODE_CODE_OK_FOR_BASE_P.
	(regno_ok_for_base_p): Add address space argument.  Pass to
	ok_for_base_p_1.

	* regrename.c (scan_rtx_address): Add address space argument.
	Pass address space to regno_ok_for_base_p and base_reg_class.
	Update recursive calls.
	(scan_rtx): Pass address space to scan_rtx_address.
	(build_def_use): Likewise.
	* regcprop.c (replace_oldest_value_addr): Add address space
	argument.  Pass to regno_ok_for_base_p and base_reg_class.
	Update recursive calls.
	(replace_oldest_value_mem): Pass address space to
	replace_oldest_value_addr.
	(copyprop_hardreg_forward_1): Likewise.

	* reload.c (find_reloads_address_1): Add address space argument.
	Pass address space to base_reg_class and regno_ok_for_base_p.
	Update recursive calls.
	(find_reloads_address): Pass address space to base_reg_class,
	regno_ok_for_base_p, and find_reloads_address_1.
	(find_reloads): Pass address space to base_reg_class.
	(find_reloads_subreg_address): Likewise.

	* ira-costs.c (record_reg_classes): Update calls to base_reg_class.
	(ok_for_base_p_nonstrict): Add address space argument.  Pass to
	ok_for_base_p_1.
	(record_address_regs): Add address space argument.  Pass to
	base_reg_class and ok_for_base_p_nonstrict.  Update recursive calls.
	(record_operand_costs): Pass address space to record_address_regs.
	(scan_one_insn): Likewise.

	* caller-save.c (init_caller_save): Update call to base_reg_class.
	* ira-conflicts.c (ira_build_conflicts): Likewise.
	* reload1.c (maybe_fix_stack_asms): Likewise.


Index: gcc/regrename.c
===================================================================
*** gcc/regrename.c	(revision 177409)
--- gcc/regrename.c	(working copy)
*************** static void do_replace (struct du_head *
*** 138,144 ****
  static void scan_rtx_reg (rtx, rtx *, enum reg_class,
  			  enum scan_actions, enum op_type);
  static void scan_rtx_address (rtx, rtx *, enum reg_class,
! 			      enum scan_actions, enum machine_mode);
  static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
  		      enum op_type);
  static struct du_head *build_def_use (basic_block);
--- 138,145 ----
  static void scan_rtx_reg (rtx, rtx *, enum reg_class,
  			  enum scan_actions, enum op_type);
  static void scan_rtx_address (rtx, rtx *, enum reg_class,
! 			      enum scan_actions, enum machine_mode,
! 			      addr_space_t);
  static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
  		      enum op_type);
  static struct du_head *build_def_use (basic_block);
*************** scan_rtx_reg (rtx insn, rtx *loc, enum r
*** 778,784 ****
  
  static void
  scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl,
! 		  enum scan_actions action, enum machine_mode mode)
  {
    rtx x = *loc;
    RTX_CODE code = GET_CODE (x);
--- 779,786 ----
  
  static void
  scan_rtx_address (rtx insn, rtx *loc, enum reg_class cl,
! 		  enum scan_actions action, enum machine_mode mode,
! 		  addr_space_t as)
  {
    rtx x = *loc;
    RTX_CODE code = GET_CODE (x);
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 846,860 ****
  	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
  	    if (REGNO_OK_FOR_INDEX_P (regno1)
! 		&& regno_ok_for_base_p (regno0, mode, PLUS, REG))
  	      index_op = 1;
  	    else if (REGNO_OK_FOR_INDEX_P (regno0)
! 		     && regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG)
  		     || REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
  	    else
  	      index_op = 1;
--- 848,862 ----
  	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
  	    if (REGNO_OK_FOR_INDEX_P (regno1)
! 		&& regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
  	      index_op = 1;
  	    else if (REGNO_OK_FOR_INDEX_P (regno0)
! 		     && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
  		     || REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
  	      index_op = 0;
  	    else
  	      index_op = 1;
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 877,886 ****
  	  }
  
  	if (locI)
! 	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode);
  	if (locB)
! 	  scan_rtx_address (insn, locB, base_reg_class (mode, PLUS, index_code),
! 			    action, mode);
  
  	return;
        }
--- 879,889 ----
  	  }
  
  	if (locI)
! 	  scan_rtx_address (insn, locI, INDEX_REG_CLASS, action, mode, as);
  	if (locB)
! 	  scan_rtx_address (insn, locB,
! 			    base_reg_class (mode, as, PLUS, index_code),
! 			    action, mode, as);
  
  	return;
        }
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 900,907 ****
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
! 			GET_MODE (x));
        return;
  
      case REG:
--- 903,911 ----
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x),
! 					MEM, SCRATCH),
! 			action, GET_MODE (x), MEM_ADDR_SPACE (x));
        return;
  
      case REG:
*************** scan_rtx_address (rtx insn, rtx *loc, en
*** 916,925 ****
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      {
        if (fmt[i] == 'e')
! 	scan_rtx_address (insn, &XEXP (x, i), cl, action, mode);
        else if (fmt[i] == 'E')
  	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
! 	  scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode);
      }
  }
  
--- 920,929 ----
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      {
        if (fmt[i] == 'e')
! 	scan_rtx_address (insn, &XEXP (x, i), cl, action, mode, as);
        else if (fmt[i] == 'E')
  	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
! 	  scan_rtx_address (insn, &XVECEXP (x, i, j), cl, action, mode, as);
      }
  }
  
*************** scan_rtx (rtx insn, rtx *loc, enum reg_c
*** 952,959 ****
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM, SCRATCH), action,
! 			GET_MODE (x));
        return;
  
      case SET:
--- 956,964 ----
  
      case MEM:
        scan_rtx_address (insn, &XEXP (x, 0),
! 			base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x),
! 					MEM, SCRATCH),
! 			action, GET_MODE (x), MEM_ADDR_SPACE (x));
        return;
  
      case SET:
*************** build_def_use (basic_block bb)
*** 1290,1296 ****
  		continue;
  
  	      if (recog_op_alt[opn][alt].is_address)
! 		scan_rtx_address (insn, loc, cl, mark_read, VOIDmode);
  	      else
  		scan_rtx (insn, loc, cl, mark_read, type);
  	    }
--- 1295,1302 ----
  		continue;
  
  	      if (recog_op_alt[opn][alt].is_address)
! 		scan_rtx_address (insn, loc, cl, mark_read,
! 				  VOIDmode, ADDR_SPACE_GENERIC);
  	      else
  		scan_rtx (insn, loc, cl, mark_read, type);
  	    }
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi	(revision 177409)
--- gcc/doc/tm.texi	(working copy)
*************** register address.  You should define thi
*** 2453,2464 ****
  addresses have different requirements than other base register uses.
  @end defmac
  
! @defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{outer_code}, @var{index_code})
  A C expression whose value is the register class to which a valid
! base register must belong.  @var{outer_code} and @var{index_code} define the
! context in which the base register occurs.  @var{outer_code} is the code of
! the immediately enclosing expression (@code{MEM} for the top level of an
! address, @code{ADDRESS} for something that occurs in an
  @code{address_operand}).  @var{index_code} is the code of the corresponding
  index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise.
  @end defmac
--- 2453,2465 ----
  addresses have different requirements than other base register uses.
  @end defmac
  
! @defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
  A C expression whose value is the register class to which a valid
! base register for a memory reference in mode @var{mode} to address
! space @var{address_space} must belong.  @var{outer_code} and @var{index_code}
! define the context in which the base register occurs.  @var{outer_code} is
! the code of the immediately enclosing expression (@code{MEM} for the top level
! of an address, @code{ADDRESS} for something that occurs in an
  @code{address_operand}).  @var{index_code} is the code of the corresponding
  index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise.
  @end defmac
*************** Use of this macro is deprecated; please 
*** 2498,2505 ****
  @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
  @end defmac
  
! @defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{outer_code}, @var{index_code})
! A C expression that is just like @code{REGNO_MODE_OK_FOR_BASE_P}, except
  that that expression may examine the context in which the register
  appears in the memory reference.  @var{outer_code} is the code of the
  immediately enclosing expression (@code{MEM} if at the top level of the
--- 2499,2509 ----
  @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
  @end defmac
  
! @defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
! A C expression which is nonzero if register number @var{num} is
! suitable for use as a base register in operand addresses, accessing
! memory in mode @var{mode} in address space @var{address_space}.
! This is similar to @code{REGNO_MODE_OK_FOR_BASE_P}, except
  that that expression may examine the context in which the register
  appears in the memory reference.  @var{outer_code} is the code of the
  immediately enclosing expression (@code{MEM} if at the top level of the
Index: gcc/doc/tm.texi.in
===================================================================
*** gcc/doc/tm.texi.in	(revision 177409)
--- gcc/doc/tm.texi.in	(working copy)
*************** register address.  You should define thi
*** 2441,2452 ****
  addresses have different requirements than other base register uses.
  @end defmac
  
! @defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{outer_code}, @var{index_code})
  A C expression whose value is the register class to which a valid
! base register must belong.  @var{outer_code} and @var{index_code} define the
! context in which the base register occurs.  @var{outer_code} is the code of
! the immediately enclosing expression (@code{MEM} for the top level of an
! address, @code{ADDRESS} for something that occurs in an
  @code{address_operand}).  @var{index_code} is the code of the corresponding
  index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise.
  @end defmac
--- 2441,2453 ----
  addresses have different requirements than other base register uses.
  @end defmac
  
! @defmac MODE_CODE_BASE_REG_CLASS (@var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
  A C expression whose value is the register class to which a valid
! base register for a memory reference in mode @var{mode} to address
! space @var{address_space} must belong.  @var{outer_code} and @var{index_code}
! define the context in which the base register occurs.  @var{outer_code} is
! the code of the immediately enclosing expression (@code{MEM} for the top level
! of an address, @code{ADDRESS} for something that occurs in an
  @code{address_operand}).  @var{index_code} is the code of the corresponding
  index expression if @var{outer_code} is @code{PLUS}; @code{SCRATCH} otherwise.
  @end defmac
*************** Use of this macro is deprecated; please 
*** 2486,2493 ****
  @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
  @end defmac
  
! @defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{outer_code}, @var{index_code})
! A C expression that is just like @code{REGNO_MODE_OK_FOR_BASE_P}, except
  that that expression may examine the context in which the register
  appears in the memory reference.  @var{outer_code} is the code of the
  immediately enclosing expression (@code{MEM} if at the top level of the
--- 2487,2497 ----
  @code{REGNO_MODE_CODE_OK_FOR_BASE_P}.
  @end defmac
  
! @defmac REGNO_MODE_CODE_OK_FOR_BASE_P (@var{num}, @var{mode}, @var{address_space}, @var{outer_code}, @var{index_code})
! A C expression which is nonzero if register number @var{num} is
! suitable for use as a base register in operand addresses, accessing
! memory in mode @var{mode} in address space @var{address_space}.
! This is similar to @code{REGNO_MODE_OK_FOR_BASE_P}, except
  that that expression may examine the context in which the register
  appears in the memory reference.  @var{outer_code} is the code of the
  immediately enclosing expression (@code{MEM} if at the top level of the
Index: gcc/ira-conflicts.c
===================================================================
*** gcc/ira-conflicts.c	(revision 177409)
--- gcc/ira-conflicts.c	(working copy)
*************** ira_debug_conflicts (bool reg_p)
*** 845,850 ****
--- 845,851 ----
  void
  ira_build_conflicts (void)
  {
+   enum reg_class base;
    ira_allocno_t a;
    ira_allocno_iterator ai;
    HARD_REG_SET temp_hard_reg_set;
*************** ira_build_conflicts (void)
*** 874,886 ****
  	  ira_free (conflicts);
  	}
      }
!   if (! targetm.class_likely_spilled_p (base_reg_class (VOIDmode, ADDRESS,
! 							SCRATCH)))
      CLEAR_HARD_REG_SET (temp_hard_reg_set);
    else
      {
!       COPY_HARD_REG_SET (temp_hard_reg_set,
! 			 reg_class_contents[base_reg_class (VOIDmode, ADDRESS, SCRATCH)]);
        AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs);
        AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set);
      }
--- 875,886 ----
  	  ira_free (conflicts);
  	}
      }
!   base = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, ADDRESS, SCRATCH);
!   if (! targetm.class_likely_spilled_p (base))
      CLEAR_HARD_REG_SET (temp_hard_reg_set);
    else
      {
!       COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[base]);
        AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs);
        AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set);
      }
Index: gcc/reload.c
===================================================================
*** gcc/reload.c	(revision 177409)
--- gcc/reload.c	(working copy)
*************** static int find_reloads_address (enum ma
*** 278,284 ****
  static rtx subst_reg_equivs (rtx, rtx);
  static rtx subst_indexed_address (rtx);
  static void update_auto_inc_notes (rtx, int, int);
! static int find_reloads_address_1 (enum machine_mode, rtx, int,
  				   enum rtx_code, enum rtx_code, rtx *,
  				   int, enum reload_type,int, rtx);
  static void find_reloads_address_part (rtx, rtx *, enum reg_class,
--- 278,284 ----
  static rtx subst_reg_equivs (rtx, rtx);
  static rtx subst_indexed_address (rtx);
  static void update_auto_inc_notes (rtx, int, int);
! static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int,
  				   enum rtx_code, enum rtx_code, rtx *,
  				   int, enum reload_type,int, rtx);
  static void find_reloads_address_part (rtx, rtx *, enum reg_class,
*************** find_reloads (rtx insn, int replace, int
*** 3235,3242 ****
  	      case 'p':
  		/* All necessary reloads for an address_operand
  		   were handled in find_reloads_address.  */
! 		this_alternative[i] = base_reg_class (VOIDmode, ADDRESS,
! 						      SCRATCH);
  		win = 1;
  		badop = 0;
  		break;
--- 3235,3243 ----
  	      case 'p':
  		/* All necessary reloads for an address_operand
  		   were handled in find_reloads_address.  */
! 		this_alternative[i]
! 		  = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 				    ADDRESS, SCRATCH);
  		win = 1;
  		badop = 0;
  		break;
*************** find_reloads (rtx insn, int replace, int
*** 3441,3449 ****
  
  			/* If we didn't already win, we can reload
  			   the address into a base register.  */
! 			this_alternative[i] = base_reg_class (VOIDmode,
! 							      ADDRESS,
! 							      SCRATCH);
  			badop = 0;
  			break;
  		      }
--- 3442,3450 ----
  
  			/* If we didn't already win, we can reload
  			   the address into a base register.  */
! 			this_alternative[i]
! 			  = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					    ADDRESS, SCRATCH);
  			badop = 0;
  			break;
  		      }
*************** find_reloads (rtx insn, int replace, int
*** 3973,3990 ****
  	    /* If the address to be reloaded is a VOIDmode constant,
  	       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)
! 	      {
! 		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,
  			     &XEXP (recog_data.operand[i], 0), (rtx*) 0,
! 			     base_reg_class (VOIDmode, MEM, SCRATCH),
  			     address_mode,
  			     VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
  	    rld[operand_reloadnum[i]].inc
--- 3974,3989 ----
  	    /* If the address to be reloaded is a VOIDmode constant,
  	       use the default address mode as mode of the reload register,
  	       as would have been done by find_reloads_address.  */
+ 	    addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
  	    enum machine_mode address_mode;
  	    address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
  	    if (address_mode == VOIDmode)
! 	      address_mode = targetm.addr_space.address_mode (as);
  
  	    operand_reloadnum[i]
  	      = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
  			     &XEXP (recog_data.operand[i], 0), (rtx*) 0,
! 			     base_reg_class (VOIDmode, as, MEM, SCRATCH),
  			     address_mode,
  			     VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
  	    rld[operand_reloadnum[i]].inc
*************** find_reloads_address (enum machine_mode 
*** 4881,4887 ****
        if (reg_equiv_constant (regno) != 0)
  	{
  	  find_reloads_address_part (reg_equiv_constant (regno), loc,
! 				     base_reg_class (mode, MEM, SCRATCH),
  				     GET_MODE (ad), opnum, type, ind_levels);
  	  return 1;
  	}
--- 4880,4886 ----
        if (reg_equiv_constant (regno) != 0)
  	{
  	  find_reloads_address_part (reg_equiv_constant (regno), loc,
! 				     base_reg_class (mode, as, MEM, SCRATCH),
  				     GET_MODE (ad), opnum, type, ind_levels);
  	  return 1;
  	}
*************** find_reloads_address (enum machine_mode 
*** 4944,4955 ****
  	 subject of a CLOBBER in this insn.  */
  
        else if (regno < FIRST_PSEUDO_REGISTER
! 	       && regno_ok_for_base_p (regno, mode, MEM, SCRATCH)
  	       && ! regno_clobbered_p (regno, this_insn, mode, 0))
  	return 0;
  
        /* If we do not have one of the cases above, we must do the reload.  */
!       push_reload (ad, NULL_RTX, loc, (rtx*) 0, base_reg_class (mode, MEM, SCRATCH),
  		   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
        return 1;
      }
--- 4943,4955 ----
  	 subject of a CLOBBER in this insn.  */
  
        else if (regno < FIRST_PSEUDO_REGISTER
! 	       && regno_ok_for_base_p (regno, mode, as, MEM, SCRATCH)
  	       && ! regno_clobbered_p (regno, this_insn, mode, 0))
  	return 0;
  
        /* If we do not have one of the cases above, we must do the reload.  */
!       push_reload (ad, NULL_RTX, loc, (rtx*) 0,
! 		   base_reg_class (mode, as, MEM, SCRATCH),
  		   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
        return 1;
      }
*************** find_reloads_address (enum machine_mode 
*** 5050,5056 ****
  	  /* Must use TEM here, not AD, since it is the one that will
  	     have any subexpressions reloaded, if needed.  */
  	  push_reload (tem, NULL_RTX, loc, (rtx*) 0,
! 		       base_reg_class (mode, MEM, SCRATCH), GET_MODE (tem),
  		       VOIDmode, 0,
  		       0, opnum, type);
  	  return ! removed_and;
--- 5050,5056 ----
  	  /* Must use TEM here, not AD, since it is the one that will
  	     have any subexpressions reloaded, if needed.  */
  	  push_reload (tem, NULL_RTX, loc, (rtx*) 0,
! 		       base_reg_class (mode, as, MEM, SCRATCH), GET_MODE (tem),
  		       VOIDmode, 0,
  		       0, opnum, type);
  	  return ! removed_and;
*************** find_reloads_address (enum machine_mode 
*** 5068,5074 ****
  	   && REG_P (XEXP (ad, 0))
  	   && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
  	   && CONST_INT_P (XEXP (ad, 1))
! 	   && (regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, PLUS,
  				    CONST_INT)
  	       /* Similarly, if we were to reload the base register and the
  		  mem+offset address is still invalid, then we want to reload
--- 5068,5074 ----
  	   && REG_P (XEXP (ad, 0))
  	   && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
  	   && CONST_INT_P (XEXP (ad, 1))
! 	   && (regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as, PLUS,
  				    CONST_INT)
  	       /* Similarly, if we were to reload the base register and the
  		  mem+offset address is still invalid, then we want to reload
*************** find_reloads_address (enum machine_mode 
*** 5087,5093 ****
  	}
  
        if (double_reg_address_ok
! 	  && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode,
  				  PLUS, CONST_INT))
  	{
  	  /* Unshare the sum as well.  */
--- 5087,5093 ----
  	}
  
        if (double_reg_address_ok
! 	  && regno_ok_for_base_p (REGNO (XEXP (ad, 0)), mode, as,
  				  PLUS, CONST_INT))
  	{
  	  /* Unshare the sum as well.  */
*************** find_reloads_address (enum machine_mode 
*** 5106,5112 ****
  	     reload the sum into a base reg.
  	     That will at least work.  */
  	  find_reloads_address_part (ad, loc,
! 				     base_reg_class (mode, MEM, SCRATCH),
  				     GET_MODE (ad), opnum, type, ind_levels);
  	}
        return ! removed_and;
--- 5106,5112 ----
  	     reload the sum into a base reg.
  	     That will at least work.  */
  	  find_reloads_address_part (ad, loc,
! 				     base_reg_class (mode, as, MEM, SCRATCH),
  				     GET_MODE (ad), opnum, type, ind_levels);
  	}
        return ! removed_and;
*************** find_reloads_address (enum machine_mode 
*** 5158,5164 ****
  
        addend = XEXP (XEXP (ad, 0), 1 - op_index);
  
!       if ((regno_ok_for_base_p (REGNO (operand), mode, inner_code,
  				GET_CODE (addend))
  	   || operand == frame_pointer_rtx
  #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
--- 5158,5164 ----
  
        addend = XEXP (XEXP (ad, 0), 1 - op_index);
  
!       if ((regno_ok_for_base_p (REGNO (operand), mode, as, inner_code,
  				GET_CODE (addend))
  	   || operand == frame_pointer_rtx
  #if !HARD_FRAME_POINTER_IS_FRAME_POINTER
*************** find_reloads_address (enum machine_mode 
*** 5187,5197 ****
  				 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),
  				     &XEXP (ad, op_index), cls,
  				     GET_MODE (ad), opnum, type, ind_levels);
! 	  find_reloads_address_1 (mode,
  				  XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
  				  GET_CODE (XEXP (ad, op_index)),
  				  &XEXP (ad, 1 - op_index), opnum,
--- 5187,5197 ----
  				 op_index == 0 ? addend : offset_reg);
  	  *loc = ad;
  
! 	  cls = base_reg_class (mode, as, MEM, GET_CODE (addend));
  	  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, as,
  				  XEXP (ad, 1 - op_index), 1, GET_CODE (ad),
  				  GET_CODE (XEXP (ad, op_index)),
  				  &XEXP (ad, 1 - op_index), opnum,
*************** find_reloads_address (enum machine_mode 
*** 5244,5256 ****
  	    loc = &XEXP (*loc, 0);
  	}
  
!       find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
  				 address_mode, opnum, type, ind_levels);
        return ! removed_and;
      }
  
!   return find_reloads_address_1 (mode, ad, 0, MEM, SCRATCH, loc, opnum, type,
! 				 ind_levels, insn);
  }
  \f
  /* Find all pseudo regs appearing in AD
--- 5244,5257 ----
  	    loc = &XEXP (*loc, 0);
  	}
  
!       find_reloads_address_part (ad, loc,
! 				 base_reg_class (mode, as, MEM, SCRATCH),
  				 address_mode, opnum, type, ind_levels);
        return ! removed_and;
      }
  
!   return find_reloads_address_1 (mode, as, ad, 0, MEM, SCRATCH, loc,
! 				 opnum, type, ind_levels, insn);
  }
  \f
  /* Find all pseudo regs appearing in AD
*************** update_auto_inc_notes (rtx insn ATTRIBUT
*** 5483,5496 ****
     handles those cases gracefully.  */
  
  static int
! find_reloads_address_1 (enum machine_mode mode, rtx x, int context,
  			enum rtx_code outer_code, enum rtx_code index_code,
  			rtx *loc, int opnum, enum reload_type type,
  			int ind_levels, rtx insn)
  {
! #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))
  
    enum reg_class context_reg_class;
--- 5484,5498 ----
     handles those cases gracefully.  */
  
  static int
! find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
! 			rtx x, int context,
  			enum rtx_code outer_code, enum rtx_code index_code,
  			rtx *loc, int opnum, enum reload_type type,
  			int ind_levels, rtx insn)
  {
! #define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, AS, OUTER, INDEX)	\
    ((CONTEXT) == 0							\
!    ? regno_ok_for_base_p (REGNO, MODE, AS, OUTER, INDEX)		\
     : REGNO_OK_FOR_INDEX_P (REGNO))
  
    enum reg_class context_reg_class;
*************** find_reloads_address_1 (enum machine_mod
*** 5499,5505 ****
    if (context == 1)
      context_reg_class = INDEX_REG_CLASS;
    else
!     context_reg_class = base_reg_class (mode, outer_code, index_code);
  
    switch (code)
      {
--- 5501,5507 ----
    if (context == 1)
      context_reg_class = INDEX_REG_CLASS;
    else
!     context_reg_class = base_reg_class (mode, as, outer_code, index_code);
  
    switch (code)
      {
*************** find_reloads_address_1 (enum machine_mod
*** 5556,5565 ****
  	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
  	    || code0 == ZERO_EXTEND || code1 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
--- 5558,5567 ----
  	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
  	    || code0 == ZERO_EXTEND || code1 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
*************** find_reloads_address_1 (enum machine_mod
*** 5567,5622 ****
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
  
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  find_reloads_address_1 (mode, orig_op1, 0, PLUS, code0,
  				  &XEXP (x, 1), opnum, type, ind_levels,
  				  insn);
  
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  find_reloads_address_1 (mode, orig_op0, 0, PLUS, code1,
  				  &XEXP (x, 0), opnum, type, ind_levels,
  				  insn);
  
  	else if (code0 == REG && code1 == REG)
  	  {
  	    if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
! 		&& regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
  	      return 0;
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
! 		     && regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
  	      return 0;
! 	    else if (regno_ok_for_base_p (REGNO (op0), mode, PLUS, REG))
! 	      find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
  				      &XEXP (x, 1), opnum, type, ind_levels,
  				      insn);
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
! 	      find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
  				      &XEXP (x, 0), opnum, type, ind_levels,
  				      insn);
! 	    else if (regno_ok_for_base_p (REGNO (op1), mode, PLUS, REG))
! 	      find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
  				      &XEXP (x, 0), opnum, type, ind_levels,
  				      insn);
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
! 	      find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
  				      &XEXP (x, 1), opnum, type, ind_levels,
  				      insn);
  	    else
  	      {
! 		find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
  					&XEXP (x, 0), opnum, type, ind_levels,
  					insn);
! 		find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
  					&XEXP (x, 1), opnum, type, ind_levels,
  					insn);
  	      }
--- 5569,5624 ----
  	else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
  		 || code1 == ZERO_EXTEND || code0 == MEM)
  	  {
! 	    find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
  
  	else if (code0 == CONST_INT || code0 == CONST
  		 || code0 == SYMBOL_REF || code0 == LABEL_REF)
! 	  find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, code0,
  				  &XEXP (x, 1), opnum, type, ind_levels,
  				  insn);
  
  	else if (code1 == CONST_INT || code1 == CONST
  		 || code1 == SYMBOL_REF || code1 == LABEL_REF)
! 	  find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, code1,
  				  &XEXP (x, 0), opnum, type, ind_levels,
  				  insn);
  
  	else if (code0 == REG && code1 == REG)
  	  {
  	    if (REGNO_OK_FOR_INDEX_P (REGNO (op1))
! 		&& regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
  	      return 0;
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0))
! 		     && regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
  	      return 0;
! 	    else if (regno_ok_for_base_p (REGNO (op0), mode, as, PLUS, REG))
! 	      find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
  				      &XEXP (x, 1), opnum, type, ind_levels,
  				      insn);
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op1)))
! 	      find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
  				      &XEXP (x, 0), opnum, type, ind_levels,
  				      insn);
! 	    else if (regno_ok_for_base_p (REGNO (op1), mode, as, PLUS, REG))
! 	      find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
  				      &XEXP (x, 0), opnum, type, ind_levels,
  				      insn);
  	    else if (REGNO_OK_FOR_INDEX_P (REGNO (op0)))
! 	      find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG,
  				      &XEXP (x, 1), opnum, type, ind_levels,
  				      insn);
  	    else
  	      {
! 		find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
  					&XEXP (x, 0), opnum, type, ind_levels,
  					insn);
! 		find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
  					&XEXP (x, 1), opnum, type, ind_levels,
  					insn);
  	      }
*************** find_reloads_address_1 (enum machine_mod
*** 5624,5643 ****
  
  	else if (code0 == REG)
  	  {
! 	    find_reloads_address_1 (mode, orig_op0, 1, PLUS, SCRATCH,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, orig_op1, 0, PLUS, REG,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
  
  	else if (code1 == REG)
  	  {
! 	    find_reloads_address_1 (mode, orig_op1, 1, PLUS, SCRATCH,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, orig_op0, 0, PLUS, REG,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
  	  }
--- 5626,5645 ----
  
  	else if (code0 == REG)
  	  {
! 	    find_reloads_address_1 (mode, as, orig_op0, 1, PLUS, SCRATCH,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, as, orig_op1, 0, PLUS, REG,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
  	  }
  
  	else if (code1 == REG)
  	  {
! 	    find_reloads_address_1 (mode, as, orig_op1, 1, PLUS, SCRATCH,
  				    &XEXP (x, 1), opnum, type, ind_levels,
  				    insn);
! 	    find_reloads_address_1 (mode, as, orig_op0, 0, PLUS, REG,
  				    &XEXP (x, 0), opnum, type, ind_levels,
  				    insn);
  	  }
*************** find_reloads_address_1 (enum machine_mod
*** 5679,5685 ****
  	if ((REG_P (XEXP (op1, 1))
  	     && !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
  	    || GET_CODE (XEXP (op1, 1)) == PLUS)
! 	  find_reloads_address_1 (mode, XEXP (op1, 1), 1, code, SCRATCH,
  				  &XEXP (op1, 1), opnum, RELOAD_OTHER,
  				  ind_levels, insn);
  
--- 5681,5687 ----
  	if ((REG_P (XEXP (op1, 1))
  	     && !REGNO_OK_FOR_INDEX_P (REGNO (XEXP (op1, 1))))
  	    || GET_CODE (XEXP (op1, 1)) == PLUS)
! 	  find_reloads_address_1 (mode, as, XEXP (op1, 1), 1, code, SCRATCH,
  				  &XEXP (op1, 1), opnum, RELOAD_OTHER,
  				  ind_levels, insn);
  
*************** find_reloads_address_1 (enum machine_mod
*** 5721,5728 ****
  		   register.  */
  		reloadnum = push_reload (tem, tem, &XEXP (x, 0),
  					 &XEXP (op1, 0),
! 					 base_reg_class (mode, code,
! 							 index_code),
  					 GET_MODE (x), GET_MODE (x), 0,
  					 0, opnum, RELOAD_OTHER);
  
--- 5723,5730 ----
  		   register.  */
  		reloadnum = push_reload (tem, tem, &XEXP (x, 0),
  					 &XEXP (op1, 0),
! 					 base_reg_class (mode, as,
! 							 code, index_code),
  					 GET_MODE (x), GET_MODE (x), 0,
  					 0, opnum, RELOAD_OTHER);
  
*************** find_reloads_address_1 (enum machine_mod
*** 5735,5745 ****
  	  regno = reg_renumber[regno];
  
  	/* We require a base register here...  */
! 	if (!regno_ok_for_base_p (regno, GET_MODE (x), code, index_code))
  	  {
  	    reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
  				     &XEXP (op1, 0), &XEXP (x, 0),
! 				     base_reg_class (mode, code, index_code),
  				     GET_MODE (x), GET_MODE (x), 0, 0,
  				     opnum, RELOAD_OTHER);
  
--- 5737,5748 ----
  	  regno = reg_renumber[regno];
  
  	/* We require a base register here...  */
! 	if (!regno_ok_for_base_p (regno, GET_MODE (x), as, code, index_code))
  	  {
  	    reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
  				     &XEXP (op1, 0), &XEXP (x, 0),
! 				     base_reg_class (mode, as,
! 						     code, index_code),
  				     GET_MODE (x), GET_MODE (x), 0, 0,
  				     opnum, RELOAD_OTHER);
  
*************** find_reloads_address_1 (enum machine_mod
*** 5805,5811 ****
  	  if (reg_renumber[regno] >= 0)
  	    regno = reg_renumber[regno];
  	  if (regno >= FIRST_PSEUDO_REGISTER
! 	      || !REG_OK_FOR_CONTEXT (context, regno, mode, code,
  				      index_code))
  	    {
  	      int reloadnum;
--- 5808,5814 ----
  	  if (reg_renumber[regno] >= 0)
  	    regno = reg_renumber[regno];
  	  if (regno >= FIRST_PSEUDO_REGISTER
! 	      || !REG_OK_FOR_CONTEXT (context, regno, mode, as, code,
  				      index_code))
  	    {
  	      int reloadnum;
*************** find_reloads_address_1 (enum machine_mod
*** 5874,5880 ****
  	 reloaded.  Targets that are better off reloading just either part
  	 (or perhaps even a different part of an outer expression), should
  	 define LEGITIMIZE_RELOAD_ADDRESS.  */
!       find_reloads_address_1 (GET_MODE (XEXP (x, 0)), XEXP (x, 0),
  			      context, code, SCRATCH, &XEXP (x, 0), opnum,
  			      type, ind_levels, insn);
        push_reload (x, NULL_RTX, loc, (rtx*) 0,
--- 5877,5883 ----
  	 reloaded.  Targets that are better off reloading just either part
  	 (or perhaps even a different part of an outer expression), should
  	 define LEGITIMIZE_RELOAD_ADDRESS.  */
!       find_reloads_address_1 (GET_MODE (XEXP (x, 0)), as, XEXP (x, 0),
  			      context, code, SCRATCH, &XEXP (x, 0), opnum,
  			      type, ind_levels, insn);
        push_reload (x, NULL_RTX, loc, (rtx*) 0,
*************** find_reloads_address_1 (enum machine_mod
*** 5945,5951 ****
  	  regno = reg_renumber[regno];
  
  	if (regno >= FIRST_PSEUDO_REGISTER
! 	    || !REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
  				    index_code))
  	  {
  	    push_reload (x, NULL_RTX, loc, (rtx*) 0,
--- 5948,5954 ----
  	  regno = reg_renumber[regno];
  
  	if (regno >= FIRST_PSEUDO_REGISTER
! 	    || !REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
  				    index_code))
  	  {
  	    push_reload (x, NULL_RTX, loc, (rtx*) 0,
*************** find_reloads_address_1 (enum machine_mod
*** 5978,5984 ****
  	    {
  	      int regno ATTRIBUTE_UNUSED = subreg_regno (x);
  
! 	      if (!REG_OK_FOR_CONTEXT (context, regno, mode, outer_code,
  				       index_code))
  		{
  		  push_reload (x, NULL_RTX, loc, (rtx*) 0,
--- 5981,5987 ----
  	    {
  	      int regno ATTRIBUTE_UNUSED = subreg_regno (x);
  
! 	      if (!REG_OK_FOR_CONTEXT (context, regno, mode, as, outer_code,
  				       index_code))
  		{
  		  push_reload (x, NULL_RTX, loc, (rtx*) 0,
*************** find_reloads_address_1 (enum machine_mod
*** 6019,6026 ****
  	if (fmt[i] == 'e')
  	  /* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once
  	     we get here.  */
! 	  find_reloads_address_1 (mode, XEXP (x, i), context, code, SCRATCH,
! 				  &XEXP (x, i), opnum, type, ind_levels, insn);
        }
    }
  
--- 6022,6030 ----
  	if (fmt[i] == 'e')
  	  /* Pass SCRATCH for INDEX_CODE, since CODE can never be a PLUS once
  	     we get here.  */
! 	  find_reloads_address_1 (mode, as, XEXP (x, i), context,
! 				  code, SCRATCH, &XEXP (x, i),
! 				  opnum, type, ind_levels, insn);
        }
    }
  
*************** find_reloads_subreg_address (rtx x, int 
*** 6197,6203 ****
  			 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,
  			       opnum, type);
  		  reloaded = 1;
--- 6201,6209 ----
  			 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_ADDR_SPACE (tem),
! 					       MEM, SCRATCH),
  			       GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
  			       opnum, type);
  		  reloaded = 1;
Index: gcc/caller-save.c
===================================================================
*** gcc/caller-save.c	(revision 177409)
--- gcc/caller-save.c	(working copy)
*************** init_caller_save (void)
*** 231,237 ****
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      if (TEST_HARD_REG_BIT
  	(reg_class_contents
! 	 [(int) base_reg_class (regno_save_mode[i][1], PLUS, CONST_INT)], i))
        break;
  
    gcc_assert (i < FIRST_PSEUDO_REGISTER);
--- 231,238 ----
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      if (TEST_HARD_REG_BIT
  	(reg_class_contents
! 	 [(int) base_reg_class (regno_save_mode[i][1], ADDR_SPACE_GENERIC,
! 				PLUS, CONST_INT)], i))
        break;
  
    gcc_assert (i < FIRST_PSEUDO_REGISTER);
Index: gcc/recog.c
===================================================================
*** gcc/recog.c	(revision 177409)
--- gcc/recog.c	(working copy)
*************** preprocess_constraints (void)
*** 2259,2265 ****
  		case 'p':
  		  op_alt[j].is_address = 1;
  		  op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
! 		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
--- 2259,2266 ----
  		case 'p':
  		  op_alt[j].is_address = 1;
  		  op_alt[j].cl = reg_class_subunion[(int) op_alt[j].cl]
! 		      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					     ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
*************** preprocess_constraints (void)
*** 2280,2287 ****
  		      op_alt[j].cl
  			= (reg_class_subunion
  			   [(int) op_alt[j].cl]
! 			   [(int) base_reg_class (VOIDmode, ADDRESS,
! 						  SCRATCH)]);
  		      break;
  		    }
  
--- 2281,2288 ----
  		      op_alt[j].cl
  			= (reg_class_subunion
  			   [(int) op_alt[j].cl]
! 			   [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 						  ADDRESS, SCRATCH)]);
  		      break;
  		    }
  
Index: gcc/ira-costs.c
===================================================================
*** gcc/ira-costs.c	(revision 177409)
--- gcc/ira-costs.c	(working copy)
*************** record_reg_classes (int n_alts, int n_op
*** 615,621 ****
  		     base of an address, i.e. BASE_REG_CLASS.  */
  		  classes[i]
  		    = ira_reg_class_subunion[classes[i]]
! 		      [base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  break;
  
  		case 'm':  case 'o':  case 'V':
--- 615,622 ----
  		     base of an address, i.e. BASE_REG_CLASS.  */
  		  classes[i]
  		    = ira_reg_class_subunion[classes[i]]
! 		      [base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 				       ADDRESS, SCRATCH)];
  		  break;
  
  		case 'm':  case 'o':  case 'V':
*************** record_reg_classes (int n_alts, int n_op
*** 730,736 ****
  			 i.e. BASE_REG_CLASS.  */
  		      classes[i]
  			= ira_reg_class_subunion[classes[i]]
! 			  [base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		    }
  #endif
  		  break;
--- 731,738 ----
  			 i.e. BASE_REG_CLASS.  */
  		      classes[i]
  			= ira_reg_class_subunion[classes[i]]
! 			  [base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					   ADDRESS, SCRATCH)];
  		    }
  #endif
  		  break;
*************** ok_for_index_p_nonstrict (rtx reg)
*** 974,987 ****
     pseudo-registers should count as OK.  Arguments as for
     regno_ok_for_base_p.  */
  static inline bool
! ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode,
  			 enum rtx_code outer_code, enum rtx_code index_code)
  {
    unsigned regno = REGNO (reg);
  
    if (regno >= FIRST_PSEUDO_REGISTER)
      return true;
!   return ok_for_base_p_1 (regno, mode, outer_code, index_code);
  }
  
  /* Record the pseudo registers we must reload into hard registers in a
--- 976,989 ----
     pseudo-registers should count as OK.  Arguments as for
     regno_ok_for_base_p.  */
  static inline bool
! ok_for_base_p_nonstrict (rtx reg, enum machine_mode mode, addr_space_t as,
  			 enum rtx_code outer_code, enum rtx_code index_code)
  {
    unsigned regno = REGNO (reg);
  
    if (regno >= FIRST_PSEUDO_REGISTER)
      return true;
!   return ok_for_base_p_1 (regno, mode, as, outer_code, index_code);
  }
  
  /* Record the pseudo registers we must reload into hard registers in a
*************** ok_for_base_p_nonstrict (rtx reg, enum m
*** 990,1005 ****
     If CONTEXT is 0, we are looking at the base part of an address,
     otherwise we are looking at the index part.
  
!    MODE is the mode of the memory reference; OUTER_CODE and INDEX_CODE
!    give the context that the rtx appears in.  These three arguments
!    are passed down to base_reg_class.
  
     SCALE is twice the amount to multiply the cost by (it is twice so
     we can represent half-cost adjustments).  */
  static void
! record_address_regs (enum machine_mode mode, rtx x, int context,
! 		     enum rtx_code outer_code, enum rtx_code index_code,
! 		     int scale)
  {
    enum rtx_code code = GET_CODE (x);
    enum reg_class rclass;
--- 992,1007 ----
     If CONTEXT is 0, we are looking at the base part of an address,
     otherwise we are looking at the index part.
  
!    MODE and AS are the mode and address space of the memory reference;
!    OUTER_CODE and INDEX_CODE give the context that the rtx appears in.
!    These four arguments are passed down to base_reg_class.
  
     SCALE is twice the amount to multiply the cost by (it is twice so
     we can represent half-cost adjustments).  */
  static void
! record_address_regs (enum machine_mode mode, addr_space_t as, rtx x,
! 		     int context, enum rtx_code outer_code,
! 		     enum rtx_code index_code, int scale)
  {
    enum rtx_code code = GET_CODE (x);
    enum reg_class rclass;
*************** record_address_regs (enum machine_mode m
*** 1007,1013 ****
    if (context == 1)
      rclass = INDEX_REG_CLASS;
    else
!     rclass = base_reg_class (mode, outer_code, index_code);
  
    switch (code)
      {
--- 1009,1015 ----
    if (context == 1)
      rclass = INDEX_REG_CLASS;
    else
!     rclass = base_reg_class (mode, as, outer_code, index_code);
  
    switch (code)
      {
*************** record_address_regs (enum machine_mode m
*** 1046,1112 ****
  	/* If this machine only allows one register per address, it
  	   must be in the first operand.  */
  	if (MAX_REGS_PER_ADDRESS == 1)
! 	  record_address_regs (mode, arg0, 0, PLUS, code1, scale);
  
  	/* If index and base registers are the same on this machine,
  	   just record registers in any non-constant operands.  We
  	   assume here, as well as in the tests below, that all
  	   addresses are in canonical form.  */
! 	else if (INDEX_REG_CLASS == base_reg_class (VOIDmode, PLUS, SCRATCH))
  	  {
! 	    record_address_regs (mode, arg0, context, PLUS, code1, scale);
  	    if (! CONSTANT_P (arg1))
! 	      record_address_regs (mode, arg1, context, PLUS, code0, scale);
  	  }
  
  	/* If the second operand is a constant integer, it doesn't
  	   change what class the first operand must be.  */
  	else if (code1 == CONST_INT || code1 == CONST_DOUBLE)
! 	  record_address_regs (mode, arg0, context, PLUS, code1, scale);
  	/* If the second operand is a symbolic constant, the first
  	   operand must be an index register.  */
  	else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF)
! 	  record_address_regs (mode, arg0, 1, PLUS, code1, scale);
  	/* If both operands are registers but one is already a hard
  	   register of index or reg-base class, give the other the
  	   class that the hard register is not.  */
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg0) < FIRST_PSEUDO_REGISTER
! 		 && (ok_for_base_p_nonstrict (arg0, mode, PLUS, REG)
  		     || ok_for_index_p_nonstrict (arg0)))
! 	  record_address_regs (mode, arg1,
! 			       ok_for_base_p_nonstrict (arg0, mode, PLUS, REG)
! 			       ? 1 : 0,
  			       PLUS, REG, scale);
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg1) < FIRST_PSEUDO_REGISTER
! 		 && (ok_for_base_p_nonstrict (arg1, mode, PLUS, REG)
  		     || ok_for_index_p_nonstrict (arg1)))
! 	  record_address_regs (mode, arg0,
! 			       ok_for_base_p_nonstrict (arg1, mode, PLUS, REG)
! 			       ? 1 : 0,
  			       PLUS, REG, scale);
  	/* If one operand is known to be a pointer, it must be the
  	   base with the other operand the index.  Likewise if the
  	   other operand is a MULT.  */
  	else if ((code0 == REG && REG_POINTER (arg0)) || code1 == MULT)
  	  {
! 	    record_address_regs (mode, arg0, 0, PLUS, code1, scale);
! 	    record_address_regs (mode, arg1, 1, PLUS, code0, scale);
  	  }
  	else if ((code1 == REG && REG_POINTER (arg1)) || code0 == MULT)
  	  {
! 	    record_address_regs (mode, arg0, 1, PLUS, code1, scale);
! 	    record_address_regs (mode, arg1, 0, PLUS, code0, scale);
  	  }
  	/* Otherwise, count equal chances that each might be a base or
  	   index register.  This case should be rare.  */
  	else
  	  {
! 	    record_address_regs (mode, arg0, 0, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, arg0, 1, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, arg1, 0, PLUS, code0, scale / 2);
! 	    record_address_regs (mode, arg1, 1, PLUS, code0, scale / 2);
  	  }
        }
        break;
--- 1048,1115 ----
  	/* If this machine only allows one register per address, it
  	   must be in the first operand.  */
  	if (MAX_REGS_PER_ADDRESS == 1)
! 	  record_address_regs (mode, as, arg0, 0, PLUS, code1, scale);
  
  	/* If index and base registers are the same on this machine,
  	   just record registers in any non-constant operands.  We
  	   assume here, as well as in the tests below, that all
  	   addresses are in canonical form.  */
! 	else if (INDEX_REG_CLASS
! 		 == base_reg_class (VOIDmode, as, PLUS, SCRATCH))
  	  {
! 	    record_address_regs (mode, as, arg0, context, PLUS, code1, scale);
  	    if (! CONSTANT_P (arg1))
! 	      record_address_regs (mode, as, arg1, context, PLUS, code0, scale);
  	  }
  
  	/* If the second operand is a constant integer, it doesn't
  	   change what class the first operand must be.  */
  	else if (code1 == CONST_INT || code1 == CONST_DOUBLE)
! 	  record_address_regs (mode, as, arg0, context, PLUS, code1, scale);
  	/* If the second operand is a symbolic constant, the first
  	   operand must be an index register.  */
  	else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF)
! 	  record_address_regs (mode, as, arg0, 1, PLUS, code1, scale);
  	/* If both operands are registers but one is already a hard
  	   register of index or reg-base class, give the other the
  	   class that the hard register is not.  */
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg0) < FIRST_PSEUDO_REGISTER
! 		 && (ok_for_base_p_nonstrict (arg0, mode, as, PLUS, REG)
  		     || ok_for_index_p_nonstrict (arg0)))
! 	  record_address_regs (mode, as, arg1,
! 			       ok_for_base_p_nonstrict (arg0, mode, as,
! 							PLUS, REG) ? 1 : 0,
  			       PLUS, REG, scale);
  	else if (code0 == REG && code1 == REG
  		 && REGNO (arg1) < FIRST_PSEUDO_REGISTER
! 		 && (ok_for_base_p_nonstrict (arg1, mode, as, PLUS, REG)
  		     || ok_for_index_p_nonstrict (arg1)))
! 	  record_address_regs (mode, as, arg0,
! 			       ok_for_base_p_nonstrict (arg1, mode, as,
! 							PLUS, REG) ? 1 : 0,
  			       PLUS, REG, scale);
  	/* If one operand is known to be a pointer, it must be the
  	   base with the other operand the index.  Likewise if the
  	   other operand is a MULT.  */
  	else if ((code0 == REG && REG_POINTER (arg0)) || code1 == MULT)
  	  {
! 	    record_address_regs (mode, as, arg0, 0, PLUS, code1, scale);
! 	    record_address_regs (mode, as, arg1, 1, PLUS, code0, scale);
  	  }
  	else if ((code1 == REG && REG_POINTER (arg1)) || code0 == MULT)
  	  {
! 	    record_address_regs (mode, as, arg0, 1, PLUS, code1, scale);
! 	    record_address_regs (mode, as, arg1, 0, PLUS, code0, scale);
  	  }
  	/* Otherwise, count equal chances that each might be a base or
  	   index register.  This case should be rare.  */
  	else
  	  {
! 	    record_address_regs (mode, as, arg0, 0, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, as, arg0, 1, PLUS, code1, scale / 2);
! 	    record_address_regs (mode, as, arg1, 0, PLUS, code0, scale / 2);
! 	    record_address_regs (mode, as, arg1, 1, PLUS, code0, scale / 2);
  	  }
        }
        break;
*************** record_address_regs (enum machine_mode m
*** 1116,1125 ****
  	 up in the wrong place.  */
      case POST_MODIFY:
      case PRE_MODIFY:
!       record_address_regs (mode, XEXP (x, 0), 0, code,
  			   GET_CODE (XEXP (XEXP (x, 1), 1)), 2 * scale);
        if (REG_P (XEXP (XEXP (x, 1), 1)))
! 	record_address_regs (mode, XEXP (XEXP (x, 1), 1), 1, code, REG,
  			     2 * scale);
        break;
  
--- 1119,1128 ----
  	 up in the wrong place.  */
      case POST_MODIFY:
      case PRE_MODIFY:
!       record_address_regs (mode, as, XEXP (x, 0), 0, code,
  			   GET_CODE (XEXP (XEXP (x, 1), 1)), 2 * scale);
        if (REG_P (XEXP (XEXP (x, 1), 1)))
! 	record_address_regs (mode, as, XEXP (XEXP (x, 1), 1), 1, code, REG,
  			     2 * scale);
        break;
  
*************** record_address_regs (enum machine_mode m
*** 1130,1136 ****
        /* Double the importance of an allocno that is incremented or
  	 decremented, since it would take two extra insns if it ends
  	 up in the wrong place.  */
!       record_address_regs (mode, XEXP (x, 0), 0, code, SCRATCH, 2 * scale);
        break;
  
      case REG:
--- 1133,1139 ----
        /* Double the importance of an allocno that is incremented or
  	 decremented, since it would take two extra insns if it ends
  	 up in the wrong place.  */
!       record_address_regs (mode, as, XEXP (x, 0), 0, code, SCRATCH, 2 * scale);
        break;
  
      case REG:
*************** record_address_regs (enum machine_mode m
*** 1178,1184 ****
  	int i;
  	for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  	  if (fmt[i] == 'e')
! 	    record_address_regs (mode, XEXP (x, i), context, code, SCRATCH,
  				 scale);
        }
      }
--- 1181,1187 ----
  	int i;
  	for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  	  if (fmt[i] == 'e')
! 	    record_address_regs (mode, as, XEXP (x, i), context, code, SCRATCH,
  				 scale);
        }
      }
*************** record_operand_costs (rtx insn, enum reg
*** 1214,1226 ****
  
        if (MEM_P (recog_data.operand[i]))
  	record_address_regs (GET_MODE (recog_data.operand[i]),
  			     XEXP (recog_data.operand[i], 0),
  			     0, MEM, SCRATCH, frequency * 2);
        else if (constraints[i][0] == 'p'
  	       || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0],
  					    constraints[i]))
! 	record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS,
! 			     SCRATCH, frequency * 2);
      }
    
    /* Check for commutative in a separate loop so everything will have
--- 1217,1231 ----
  
        if (MEM_P (recog_data.operand[i]))
  	record_address_regs (GET_MODE (recog_data.operand[i]),
+ 			     MEM_ADDR_SPACE (recog_data.operand[i]),
  			     XEXP (recog_data.operand[i], 0),
  			     0, MEM, SCRATCH, frequency * 2);
        else if (constraints[i][0] == 'p'
  	       || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0],
  					    constraints[i]))
! 	record_address_regs (VOIDmode, ADDR_SPACE_GENERIC,
! 			     recog_data.operand[i], 0, ADDRESS, SCRATCH,
! 			     frequency * 2);
      }
    
    /* Check for commutative in a separate loop so everything will have
*************** scan_one_insn (rtx insn)
*** 1294,1301 ****
  
        COSTS (costs, num)->mem_cost
  	-= ira_memory_move_cost[GET_MODE (reg)][cl][1] * frequency;
!       record_address_regs (GET_MODE (SET_SRC (set)), XEXP (SET_SRC (set), 0),
! 			   0, MEM, SCRATCH, frequency * 2);
        counted_mem = true;
      }
  
--- 1299,1308 ----
  
        COSTS (costs, num)->mem_cost
  	-= ira_memory_move_cost[GET_MODE (reg)][cl][1] * frequency;
!       record_address_regs (GET_MODE (SET_SRC (set)),
! 			   MEM_ADDR_SPACE (SET_SRC (set)),
! 			   XEXP (SET_SRC (set), 0), 0, MEM, SCRATCH,
! 			   frequency * 2);
        counted_mem = true;
      }
  
Index: gcc/addresses.h
===================================================================
*** gcc/addresses.h	(revision 177409)
--- gcc/addresses.h	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 23,33 ****
  
  static inline enum reg_class
  base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
  		enum rtx_code outer_code ATTRIBUTE_UNUSED,
  		enum rtx_code index_code ATTRIBUTE_UNUSED)
  {
  #ifdef MODE_CODE_BASE_REG_CLASS
!   return MODE_CODE_BASE_REG_CLASS (mode, outer_code, index_code);
  #else
  #ifdef MODE_BASE_REG_REG_CLASS
    if (index_code == REG)
--- 23,34 ----
  
  static inline enum reg_class
  base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
+ 		addr_space_t as ATTRIBUTE_UNUSED,
  		enum rtx_code outer_code ATTRIBUTE_UNUSED,
  		enum rtx_code index_code ATTRIBUTE_UNUSED)
  {
  #ifdef MODE_CODE_BASE_REG_CLASS
!   return MODE_CODE_BASE_REG_CLASS (mode, as, outer_code, index_code);
  #else
  #ifdef MODE_BASE_REG_REG_CLASS
    if (index_code == REG)
*************** base_reg_class (enum machine_mode mode A
*** 49,59 ****
  static inline bool
  ok_for_base_p_1 (unsigned regno ATTRIBUTE_UNUSED,
  		 enum machine_mode mode ATTRIBUTE_UNUSED,
  		 enum rtx_code outer_code ATTRIBUTE_UNUSED,
  		 enum rtx_code index_code ATTRIBUTE_UNUSED)
  {
  #ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
!   return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, mode, outer_code, index_code);
  #else
  #ifdef REGNO_MODE_OK_FOR_REG_BASE_P
    if (index_code == REG)
--- 50,62 ----
  static inline bool
  ok_for_base_p_1 (unsigned regno ATTRIBUTE_UNUSED,
  		 enum machine_mode mode ATTRIBUTE_UNUSED,
+ 		 addr_space_t as ATTRIBUTE_UNUSED,
  		 enum rtx_code outer_code ATTRIBUTE_UNUSED,
  		 enum rtx_code index_code ATTRIBUTE_UNUSED)
  {
  #ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
!   return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, mode, as,
! 					outer_code, index_code);
  #else
  #ifdef REGNO_MODE_OK_FOR_REG_BASE_P
    if (index_code == REG)
*************** ok_for_base_p_1 (unsigned regno ATTRIBUT
*** 71,81 ****
     complete.  Arguments as for the called function.  */
  
  static inline bool
! regno_ok_for_base_p (unsigned regno, enum machine_mode mode,
  		     enum rtx_code outer_code, enum rtx_code index_code)
  {
    if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
      regno = reg_renumber[regno];
  
!   return ok_for_base_p_1 (regno, mode, outer_code, index_code);
  }
--- 74,84 ----
     complete.  Arguments as for the called function.  */
  
  static inline bool
! regno_ok_for_base_p (unsigned regno, enum machine_mode mode, addr_space_t as,
  		     enum rtx_code outer_code, enum rtx_code index_code)
  {
    if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
      regno = reg_renumber[regno];
  
!   return ok_for_base_p_1 (regno, mode, as, outer_code, index_code);
  }
Index: gcc/config/cris/cris.h
===================================================================
*** gcc/config/cris/cris.h	(revision 177409)
--- gcc/config/cris/cris.h	(working copy)
*************** enum reg_class
*** 549,555 ****
  
  #define BASE_REG_CLASS GENERAL_REGS
  
! #define MODE_CODE_BASE_REG_CLASS(MODE, OCODE, ICODE)	\
    ((OCODE) != POST_INC ? BASE_REG_CLASS : GENNONACR_REGS)
  
  #define INDEX_REG_CLASS GENERAL_REGS
--- 549,555 ----
  
  #define BASE_REG_CLASS GENERAL_REGS
  
! #define MODE_CODE_BASE_REG_CLASS(MODE, AS, OCODE, ICODE)	\
    ((OCODE) != POST_INC ? BASE_REG_CLASS : GENNONACR_REGS)
  
  #define INDEX_REG_CLASS GENERAL_REGS
*************** enum reg_class
*** 574,580 ****
  
  /* REGNO_OK_FOR_BASE_P seems to be obsolete wrt. this one, but not yet
     documented as such.  */
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(REGNO, MODE, OCODE, ICODE)	\
   (REGNO_OK_FOR_BASE_P (REGNO)						\
    && ((OCODE) != POST_INC						\
        || !((REGNO) == CRIS_ACR_REGNUM					\
--- 574,580 ----
  
  /* REGNO_OK_FOR_BASE_P seems to be obsolete wrt. this one, but not yet
     documented as such.  */
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(REGNO, MODE, AS, OCODE, ICODE)	\
   (REGNO_OK_FOR_BASE_P (REGNO)						\
    && ((OCODE) != POST_INC						\
        || !((REGNO) == CRIS_ACR_REGNUM					\
Index: gcc/config/bfin/bfin.h
===================================================================
*** gcc/config/bfin/bfin.h	(revision 177409)
--- gcc/config/bfin/bfin.h	(working copy)
*************** enum reg_class
*** 612,618 ****
     || (OUTER) == POST_DEC || (OUTER) == PRE_DEC		     \
     || (OUTER) == MEM || (OUTER) == ADDRESS)
  
! #define MODE_CODE_BASE_REG_CLASS(MODE, OUTER, INDEX)			\
    ((MODE) == HImode && IREG_POSSIBLE_P (OUTER) ? IPREGS : PREGS)
  
  #define INDEX_REG_CLASS         PREGS
--- 612,618 ----
     || (OUTER) == POST_DEC || (OUTER) == PRE_DEC		     \
     || (OUTER) == MEM || (OUTER) == ADDRESS)
  
! #define MODE_CODE_BASE_REG_CLASS(MODE, AS, OUTER, INDEX)	\
    ((MODE) == HImode && IREG_POSSIBLE_P (OUTER) ? IPREGS : PREGS)
  
  #define INDEX_REG_CLASS         PREGS
*************** enum reg_class
*** 627,636 ****
     || REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX))
  
  #ifdef REG_OK_STRICT
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, OUTER, INDEX) \
    REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX)
  #else
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, OUTER, INDEX) \
    REGNO_OK_FOR_BASE_NONSTRICT_P (X, MODE, OUTER, INDEX)
  #endif
  
--- 627,636 ----
     || REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX))
  
  #ifdef REG_OK_STRICT
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, AS, OUTER, INDEX) \
    REGNO_OK_FOR_BASE_STRICT_P (X, MODE, OUTER, INDEX)
  #else
! #define REGNO_MODE_CODE_OK_FOR_BASE_P(X, MODE, AS, OUTER, INDEX) \
    REGNO_OK_FOR_BASE_NONSTRICT_P (X, MODE, OUTER, INDEX)
  #endif
  
Index: gcc/regcprop.c
===================================================================
*** gcc/regcprop.c	(revision 177409)
--- gcc/regcprop.c	(working copy)
*************** static rtx find_oldest_value_reg (enum r
*** 98,104 ****
  static bool replace_oldest_value_reg (rtx *, enum reg_class, rtx,
  				      struct value_data *);
  static bool replace_oldest_value_addr (rtx *, enum reg_class,
! 				       enum machine_mode, rtx,
  				       struct value_data *);
  static bool replace_oldest_value_mem (rtx, rtx, struct value_data *);
  static bool copyprop_hardreg_forward_1 (basic_block, struct value_data *);
--- 98,104 ----
  static bool replace_oldest_value_reg (rtx *, enum reg_class, rtx,
  				      struct value_data *);
  static bool replace_oldest_value_addr (rtx *, enum reg_class,
! 				       enum machine_mode, addr_space_t, rtx,
  				       struct value_data *);
  static bool replace_oldest_value_mem (rtx, rtx, struct value_data *);
  static bool copyprop_hardreg_forward_1 (basic_block, struct value_data *);
*************** replace_oldest_value_reg (rtx *loc, enum
*** 515,522 ****
  
  static bool
  replace_oldest_value_addr (rtx *loc, enum reg_class cl,
! 			   enum machine_mode mode, rtx insn,
! 			   struct value_data *vd)
  {
    rtx x = *loc;
    RTX_CODE code = GET_CODE (x);
--- 515,522 ----
  
  static bool
  replace_oldest_value_addr (rtx *loc, enum reg_class cl,
! 			   enum machine_mode mode, addr_space_t as,
! 			   rtx insn, struct value_data *vd)
  {
    rtx x = *loc;
    RTX_CODE code = GET_CODE (x);
*************** replace_oldest_value_addr (rtx *loc, enu
*** 585,599 ****
  	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
  	    if (REGNO_OK_FOR_INDEX_P (regno1)
! 		&& regno_ok_for_base_p (regno0, mode, PLUS, REG))
  	      index_op = 1;
  	    else if (REGNO_OK_FOR_INDEX_P (regno0)
! 		     && regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, PLUS, REG)
  		     || REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, PLUS, REG))
  	      index_op = 0;
  	    else
  	      index_op = 1;
--- 585,599 ----
  	    unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
  
  	    if (REGNO_OK_FOR_INDEX_P (regno1)
! 		&& regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
  	      index_op = 1;
  	    else if (REGNO_OK_FOR_INDEX_P (regno0)
! 		     && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
  	      index_op = 0;
! 	    else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
  		     || REGNO_OK_FOR_INDEX_P (regno1))
  	      index_op = 1;
! 	    else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
  	      index_op = 0;
  	    else
  	      index_op = 1;
*************** replace_oldest_value_addr (rtx *loc, enu
*** 616,628 ****
  	  }
  
  	if (locI)
! 	  changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS, mode,
! 						insn, vd);
  	if (locB)
  	  changed |= replace_oldest_value_addr (locB,
! 						base_reg_class (mode, PLUS,
  								index_code),
! 						mode, insn, vd);
  	return changed;
        }
  
--- 616,628 ----
  	  }
  
  	if (locI)
! 	  changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS,
! 						mode, as, insn, vd);
  	if (locB)
  	  changed |= replace_oldest_value_addr (locB,
! 						base_reg_class (mode, as, PLUS,
  								index_code),
! 						mode, as, insn, vd);
  	return changed;
        }
  
*************** replace_oldest_value_addr (rtx *loc, enu
*** 648,659 ****
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      {
        if (fmt[i] == 'e')
! 	changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode,
  					      insn, vd);
        else if (fmt[i] == 'E')
  	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
  	  changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), cl,
! 						mode, insn, vd);
      }
  
    return changed;
--- 648,659 ----
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
      {
        if (fmt[i] == 'e')
! 	changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode, as,
  					      insn, vd);
        else if (fmt[i] == 'E')
  	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
  	  changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), cl,
! 						mode, as, insn, vd);
      }
  
    return changed;
*************** replace_oldest_value_mem (rtx x, rtx ins
*** 669,678 ****
    if (DEBUG_INSN_P (insn))
      cl = ALL_REGS;
    else
!     cl = base_reg_class (GET_MODE (x), MEM, SCRATCH);
  
    return replace_oldest_value_addr (&XEXP (x, 0), cl,
! 				    GET_MODE (x), insn, vd);
  }
  
  /* Apply all queued updates for DEBUG_INSNs that change some reg to
--- 669,679 ----
    if (DEBUG_INSN_P (insn))
      cl = ALL_REGS;
    else
!     cl = base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x), MEM, SCRATCH);
  
    return replace_oldest_value_addr (&XEXP (x, 0), cl,
! 				    GET_MODE (x), MEM_ADDR_SPACE (x),
! 				    insn, vd);
  }
  
  /* Apply all queued updates for DEBUG_INSNs that change some reg to
*************** copyprop_hardreg_forward_1 (basic_block 
*** 751,757 ****
  	      if (!VAR_LOC_UNKNOWN_P (loc))
  		replace_oldest_value_addr (&INSN_VAR_LOCATION_LOC (insn),
  					   ALL_REGS, GET_MODE (loc),
! 					   insn, vd);
  	    }
  
  	  if (insn == BB_END (bb))
--- 752,758 ----
  	      if (!VAR_LOC_UNKNOWN_P (loc))
  		replace_oldest_value_addr (&INSN_VAR_LOCATION_LOC (insn),
  					   ALL_REGS, GET_MODE (loc),
! 					   ADDR_SPACE_GENERIC, insn, vd);
  	    }
  
  	  if (insn == BB_END (bb))
*************** copyprop_hardreg_forward_1 (basic_block 
*** 893,899 ****
  		replaced[i]
  		  = replace_oldest_value_addr (recog_data.operand_loc[i],
  					       recog_op_alt[i][alt].cl,
! 					       VOIDmode, insn, vd);
  	      else if (REG_P (recog_data.operand[i]))
  		replaced[i]
  		  = replace_oldest_value_reg (recog_data.operand_loc[i],
--- 894,901 ----
  		replaced[i]
  		  = replace_oldest_value_addr (recog_data.operand_loc[i],
  					       recog_op_alt[i][alt].cl,
! 					       VOIDmode, ADDR_SPACE_GENERIC,
! 					       insn, vd);
  	      else if (REG_P (recog_data.operand[i]))
  		replaced[i]
  		  = replace_oldest_value_reg (recog_data.operand_loc[i],
Index: gcc/reload1.c
===================================================================
*** gcc/reload1.c	(revision 177409)
--- gcc/reload1.c	(working copy)
*************** maybe_fix_stack_asms (void)
*** 1423,1429 ****
  
  		case 'p':
  		  cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
--- 1423,1430 ----
  
  		case 'p':
  		  cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					     ADDRESS, SCRATCH)];
  		  break;
  
  		case 'g':
*************** maybe_fix_stack_asms (void)
*** 1434,1440 ****
  		default:
  		  if (EXTRA_ADDRESS_CONSTRAINT (c, p))
  		    cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
  		  else
  		    cls = (int) reg_class_subunion[cls]
  		      [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
--- 1435,1442 ----
  		default:
  		  if (EXTRA_ADDRESS_CONSTRAINT (c, p))
  		    cls = (int) reg_class_subunion[cls]
! 		      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
! 					     ADDRESS, SCRATCH)];
  		  else
  		    cls = (int) reg_class_subunion[cls]
  		      [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];


-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-05 20:43     ` Ulrich Weigand
@ 2011-08-05 20:47       ` DJ Delorie
  2011-08-05 21:01         ` Ulrich Weigand
  2011-08-08 11:38       ` Georg-Johann Lay
  1 sibling, 1 reply; 21+ messages in thread
From: DJ Delorie @ 2011-08-05 20:47 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: avr, gcc


Was this reproducible for m32c also?  I can test it if so...

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-05 20:47       ` DJ Delorie
@ 2011-08-05 21:01         ` Ulrich Weigand
  2011-08-05 21:08           ` DJ Delorie
  0 siblings, 1 reply; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-05 21:01 UTC (permalink / raw)
  To: DJ Delorie; +Cc: avr, gcc

DJ Delorie wrote:

> Was this reproducible for m32c also?  I can test it if so...

The patch simply passes the destination address space through
to MODE_CODE_BASE_REG_CLASS and REGNO_MODE_CODE_OK_FOR_BASE_P,
to allow targets to make register allocation decisions based
on address space.

As long as m32c doesn't implement those, just applying the
patch wouldn't change anything.  But if that capability
*would* be helpful on your target, it would certainly be
good if you could try it out ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-05 21:01         ` Ulrich Weigand
@ 2011-08-05 21:08           ` DJ Delorie
  0 siblings, 0 replies; 21+ messages in thread
From: DJ Delorie @ 2011-08-05 21:08 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: avr, gcc


Nope, I don't use those :-)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-05 20:43     ` Ulrich Weigand
  2011-08-05 20:47       ` DJ Delorie
@ 2011-08-08 11:38       ` Georg-Johann Lay
  2011-08-09 17:16         ` Ulrich Weigand
  1 sibling, 1 reply; 21+ messages in thread
From: Georg-Johann Lay @ 2011-08-08 11:38 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc

Ulrich Weigand wrote:
> Georg-Johann Lay wrote:
>> Ulrich Weigand wrote:
>>> This means that problems like the one you're seeing have been hidden
>>> so far.  I've started looking into fixing this, but since I don't
>>> have a target where this is needed, this effort never really went
>>> anywhere.  I'll append below a patch I did a year or so ago; just
>>> as something to look at, it probably will not even apply to the
>>> current sources any more.
>> Sounds great that you tried to fix it!  Much work below... wow.
>>
>>> I'd be happy to bring this up to date if you're willing to work with
>>> me to get this tested on a target that needs this support ...
> 
> Here's an updated version of the patch that build with current GCC
> mainline and passes the SPU test suite with no regressions.
> 
> Let me know if this works for you ...

Thanks, it works.

However, it results in bloated code. I guess it's an IRA issue.

int read_from_pgm_3 (const int __pgm * const __pgm * const addr)
{
    return **addr;
}

results in bloated (-Os -mmcu=atmega8)

Z = r30/r31
Y = r28/r29 is frame pointer

Even if the dead store insn 30 is eliminated a frame is generated.

read_from_pgm_3:
	push r28	 ;  31	pushqi1/1	[length = 1]
	push r29	 ;  32	pushqi1/1	[length = 1]
	rcall .	 ;  36	*addhi3_sp_R_pc2	[length = 1]
	in r28,__SP_L__	 ;  37	*movhi_sp/2	[length = 2]
	in r29,__SP_H__
/* prologue: function */
/* frame size = 2 */
/* stack size = 4 */
.L__stack_usage = 4
	movw r30,r24	 ;  28	*movphi/1	[length = 2]
	lpm __tmp_reg__,Z+	 ;  19	*movphi/2	[length = 6]
	lpm r31,Z
	mov r30,__tmp_reg__
	std Y+2,r31	 ;  30	*movphi/3	[length = 7]
	std Y+1,r30
	lpm r24,Z+	 ;  23	*movhi/2	[length = 2]
	lpm r25,Z+
/* epilogue start */
	pop __tmp_reg__	 ;  42	*addhi3_sp_R_pc2	[length = 2]
	pop __tmp_reg__
	pop r29	 ;  43	popqi	[length = 1]
	pop r28	 ;  44	popqi	[length = 1]
	ret	 ;  45	return_from_epilogue	[length = 1]


The code could be just


read_from_pgm_3:
/* prologue: function */
        ;; Z = r24
	movw r30,r24	 ;  28	*movphi/1	[length = 2]
        ;; Z = *Z
	lpm __tmp_reg__,Z+	 ;  19	*movphi/2	[length = 6]
	lpm r31,Z
	mov r30,__tmp_reg__
        ;; r24 = *Z++
	lpm r24,Z+	 ;  23	*movhi/2	[length = 2]
	lpm r25,Z+
/* epilogue start */
	ret	 ;  45	return_from_epilogue	[length = 1]


MODE_CODE_BASE_REG_CLASS no reads

reg_class_t
avr_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
                              addr_space_t address_space,
                              RTX_CODE outer_code ATTRIBUTE_UNUSED,
                              RTX_CODE index_code ATTRIBUTE_UNUSED)
{
  if (ADDR_SPACE_PGM == address_space)
    {
      return POINTER_Z_REGS;
    }

  return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
}

even though for __pgm no base+offset addressing is available.
Returning NO_REGS for __pgm results in ICE in push_relaod.

I frequently see IRA doing a very bad job for small register classes
like here.  Maybe it's better to take it completely away from IRA
and write the load as

(set (reg:HI)
     (unspec:HI (post_inc:PHI (reg:PHI Z))))

Loading from __pgm is actually an unspec, i.e. reading two times from
the same address will yield the same result.

IRA gets fancy about spilling:
Spilling for insn 19.
Using reg 30 for reload 0
      Try Assign 47(a0), cost=48000
changing reg in insn 19
changing reg in insn 25
changing reg in insn 22
      Assigning 47(freq=3000) a new slot 0
 Register 47 now on stack.

Spilling for insn 19.
Using reg 30 for reload 1
Using reg 30 for reload 0
Using reg 18 for reload 3
Spilling for insn 22.
Using reg 26 for reload 0
Spilling for insn 25.
Using reg 26 for reload 0
Spilling for insn 19.
Using reg 30 for reload 0
Using reg 18 for reload 1
Spilling for insn 25.
Spilling for insn 19.
Using reg 30 for reload 0
Using reg 18 for reload 1
Spilling for insn 25.

Johann


> Bye,
> Ulrich
> 
> 
> ChangeLog:
> 
> 	* doc/tm.texi.in (MODE_CODE_BASE_REG_CLASS): Add address space
> 	argument.
> 	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
> 	* doc/tm.texi: Regenerate.
> 
> 	* config/cris/cris.h (MODE_CODE_BASE_REG_CLASS): Add address
> 	space argument.
> 	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
> 	* config/bfin/bfin.h (MODE_CODE_BASE_REG_CLASS): Likewise.
> 	(REGNO_MODE_CODE_OK_FOR_BASE_P): Likewise.
> 
> 	* addresses.h (base_reg_class): Add address space argument.
> 	Pass to MODE_CODE_BASE_REG_CLASS.
> 	(ok_for_base_p_1): Add address space argument.  Pass to
> 	REGNO_MODE_CODE_OK_FOR_BASE_P.
> 	(regno_ok_for_base_p): Add address space argument.  Pass to
> 	ok_for_base_p_1.
> 
> 	* regrename.c (scan_rtx_address): Add address space argument.
> 	Pass address space to regno_ok_for_base_p and base_reg_class.
> 	Update recursive calls.
> 	(scan_rtx): Pass address space to scan_rtx_address.
> 	(build_def_use): Likewise.
> 	* regcprop.c (replace_oldest_value_addr): Add address space
> 	argument.  Pass to regno_ok_for_base_p and base_reg_class.
> 	Update recursive calls.
> 	(replace_oldest_value_mem): Pass address space to
> 	replace_oldest_value_addr.
> 	(copyprop_hardreg_forward_1): Likewise.
> 
> 	* reload.c (find_reloads_address_1): Add address space argument.
> 	Pass address space to base_reg_class and regno_ok_for_base_p.
> 	Update recursive calls.
> 	(find_reloads_address): Pass address space to base_reg_class,
> 	regno_ok_for_base_p, and find_reloads_address_1.
> 	(find_reloads): Pass address space to base_reg_class.
> 	(find_reloads_subreg_address): Likewise.
> 
> 	* ira-costs.c (record_reg_classes): Update calls to base_reg_class.
> 	(ok_for_base_p_nonstrict): Add address space argument.  Pass to
> 	ok_for_base_p_1.
> 	(record_address_regs): Add address space argument.  Pass to
> 	base_reg_class and ok_for_base_p_nonstrict.  Update recursive calls.
> 	(record_operand_costs): Pass address space to record_address_regs.
> 	(scan_one_insn): Likewise.
> 
> 	* caller-save.c (init_caller_save): Update call to base_reg_class.
> 	* ira-conflicts.c (ira_build_conflicts): Likewise.
> 	* reload1.c (maybe_fix_stack_asms): Likewise.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-08 11:38       ` Georg-Johann Lay
@ 2011-08-09 17:16         ` Ulrich Weigand
  2011-08-10 14:04           ` Georg-Johann Lay
  0 siblings, 1 reply; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-09 17:16 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

Georg-Johann Lay wrote:

> Thanks, it works.

OK, thanks for testing!

> 	std Y+2,r31	 ;  30	*movphi/3	[length = 7]
> 	std Y+1,r30

I'm actually not seeing those (maybe I'm using a different code
base than you were using ...)

But I still see that the frame is created.  The problem is that IRA
thinks it needs to allocate a pseudo on the stack, and creates a
stack slot for it.  But then reload goes and just reloads the
pseudo into a hard register anyway, and simply doesn't need the
stack slot ... but it was already allocated and accounted for
such that get_frame_size () no longer returns 0.

> I frequently see IRA doing a very bad job for small register classes
> like here.  Maybe it's better to take it completely away from IRA
> and write the load as
> 
> (set (reg:HI)
>      (unspec:HI (post_inc:PHI (reg:PHI Z))))
> 
> Loading from __pgm is actually an unspec, i.e. reading two times from
> the same address will yield the same result.

This really seems to be a problem in IRA somewhere, but I'd guess it
would be better to fix in there instead of working around it.  Maybe
you should open a bug an get in touch with the IRA maintainers ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-09 17:16         ` Ulrich Weigand
@ 2011-08-10 14:04           ` Georg-Johann Lay
  2011-08-17 17:44             ` Georg-Johann Lay
  0 siblings, 1 reply; 21+ messages in thread
From: Georg-Johann Lay @ 2011-08-10 14:04 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc

Ulrich Weigand wrote:
> Georg-Johann Lay wrote:
> 
>> Thanks, it works.
> 
> OK, thanks for testing!
> 
>> 	std Y+2,r31	 ;  30	*movphi/3	[length = 7]
>> 	std Y+1,r30
> 
> I'm actually not seeing those (maybe I'm using a different code
> base than you were using ...)
> 
> But I still see that the frame is created.  The problem is that IRA
> thinks it needs to allocate a pseudo on the stack, and creates a
> stack slot for it.  But then reload goes and just reloads the
> pseudo into a hard register anyway, and simply doesn't need the
> stack slot ... but it was already allocated and accounted for
> such that get_frame_size () no longer returns 0.

The stack slot is an IRA hog because there are plenty of hard regs.

>> I frequently see IRA doing a very bad job for small register classes
>> like here.  Maybe it's better to take it completely away from IRA
>> and write the load as
>>
>> (set (reg:HI)
>>      (unspec:HI (post_inc:PHI (reg:PHI Z))))
>>
>> Loading from __pgm is actually an unspec, i.e. reading two times from
>> the same address will yield the same result.
> 
> This really seems to be a problem in IRA somewhere, but I'd guess it
> would be better to fix in there instead of working around it.  Maybe
> you should open a bug an get in touch with the IRA maintainers ...

It surely is an IRA issue.  However, it's extremely unlikely that anyone
cares for SSA/RTL optimization flaws that just show up on AVR or are
reported against AVR.  And if a patch turns out to overcharge IRA
like, e.g. in
   http://gcc.gnu.org/ml/gcc-patches/2011-07/msg02655.html
the patch won't be integrated.

Moreover, this one is hard to reproduce because it needs you patch,
my patch and is for a "irrelevant" target.

Johann

> Bye,
> Ulrich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-10 14:04           ` Georg-Johann Lay
@ 2011-08-17 17:44             ` Georg-Johann Lay
  2011-08-18 14:38               ` Ulrich Weigand
  0 siblings, 1 reply; 21+ messages in thread
From: Georg-Johann Lay @ 2011-08-17 17:44 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: Ulrich Weigand, gcc

http://gcc.gnu.org/ml/gcc/2011-08/msg00131.html

Georg-Johann Lay a écrit:
> Ulrich Weigand wrote:
> 
>>Georg-Johann Lay wrote:
>>
>>>Thanks, it works.
>>
>>OK, thanks for testing!
> [...]
> 
>>Bye,
>>Ulrich

Are you going to install that patch? Or maybe you already installed it?

Then, I wonder how the following named AS code translates:

int a = *((__as int*) 1000);

As const_int don't have a machmode (yet), I guess the above line just 
reads from generic AS and reading from a specific address from named AS 
cannot work.

Moreover, INDEX_REG_CLASS, REGNO_OK_FOR_INDEX_P, HAVE_PRE_INCREMENT et 
al. and maybe others are AS-dependent.

Johann

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-17 17:44             ` Georg-Johann Lay
@ 2011-08-18 14:38               ` Ulrich Weigand
  2011-08-21 16:43                 ` Georg-Johann Lay
  0 siblings, 1 reply; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-18 14:38 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

Georg-Johann Lay wrote:

> http://gcc.gnu.org/ml/gcc/2011-08/msg00131.html
>
> Are you going to install that patch? Or maybe you already installed it?

No, it isn't approved yet (in fact, it isn't even posted for approval).
Usually, patches that add new target macros, or new arguments to target
macros, but do not actually add any *exploiter* of the new features,
are frowned upon ...

Thus, I'd prefer to wait until you have patch ready that exploits this
in the AVR backend, and then submit the whole series.

> Then, I wonder how the following named AS code translates:
> 
> int a = *((__as int*) 1000);
> 
> As const_int don't have a machmode (yet), I guess the above line just 
> reads from generic AS and reading from a specific address from named AS 
> cannot work.

This should work fine.  Address space processing doesn't really depend
on the machine mode; the address space is annotated to the MEM RTX
directly.  Code like the above ought to generate a MEM with either
an immediate CONST_INT operand or one with the immediate loaded into
a register, depending on what the target supports, but in either case
the MEM_ADDR_SPACE will be set correctly.  It's then up the target to
implement the access as appropriate.

> Moreover, INDEX_REG_CLASS, REGNO_OK_FOR_INDEX_P, HAVE_PRE_INCREMENT et 
> al. and maybe others are AS-dependent.

I agree for INDEX_REG_CLASS and REGNO_OK_FOR_INDEX_P.  In fact, I'd
suggest they should first be converted to look similar to base registers
(i.e. add MODE_CODE_INDEX_REG_CLASS and REGNO_MODE_CODE_OK_FOR_INDEX_P)
and then add address space support to those extended macros, so as to
avoid having to change lots of back-ends.   Do you need this for AVR?
I could add that to the patch I posted previously ...

Now for HAVE_PRE_INCREMENT, I don't think we need anything special.
This is used just as a short-cut to bypass pre-increment handling
completely on targets that don't support it at all.  On targets
that *do*, there will always be additional requirement on just
which memory accesses support pre-increment.  Therefore, the
middle-end will still always check the target's legitimate_address
callback to ensure any particular pre-incremented memory access
is actually valid.  This mechanism can already look at the address
space to make its decision ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-18 14:38               ` Ulrich Weigand
@ 2011-08-21 16:43                 ` Georg-Johann Lay
  2011-08-22 12:39                   ` Ulrich Weigand
  0 siblings, 1 reply; 21+ messages in thread
From: Georg-Johann Lay @ 2011-08-21 16:43 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc

Ulrich Weigand schrieb:
> Georg-Johann Lay wrote:
> 
>>http://gcc.gnu.org/ml/gcc/2011-08/msg00131.html
>>
>>Are you going to install that patch? Or maybe you already installed it?
> 
> No, it isn't approved yet (in fact, it isn't even posted for approval).
> Usually, patches that add new target macros, or new arguments to target
> macros, but do not actually add any *exploiter* of the new features,
> are frowned upon ...

I thought about implementing a "hidden" named AS first and not exposing 
it to user land, e.g. to be able to do optimizations like
    http://gcc.gnu.org/PR49857
    http://gcc.gnu.org/PR43745
which need named AS to express that some pointers/accesses are different.

The most prominent drawback of named AS at the moment is that AVR has 
few address registers and register allocation often regerates unpleasant 
code or even runs into spill fails.

The AS in question can only be accessed by means of post-increment 
addressing via one single hard register.

> Thus, I'd prefer to wait until you have patch ready that exploits this
> in the AVR backend, and then submit the whole series.
> 
>>Then, I wonder how the following named AS code translates:
>>
>>int a = *((__as int*) 1000);
>>
>>As const_int don't have a machmode (yet), I guess the above line just 
>>reads from generic AS and reading from a specific address from named AS 
>>cannot work.
> 
> This should work fine.  Address space processing doesn't really depend
> on the machine mode; the address space is annotated to the MEM RTX
> directly.  Code like the above ought to generate a MEM with either
> an immediate CONST_INT operand or one with the immediate loaded into
> a register, depending on what the target supports, but in either case
> the MEM_ADDR_SPACE will be set correctly.  It's then up the target to
> implement the access as appropriate.

Thanks for pointing this out. I just used the mmode in my implementation 
instead of MEM_ADDR_SPACE. My bad.

>>Moreover, INDEX_REG_CLASS, REGNO_OK_FOR_INDEX_P, HAVE_PRE_INCREMENT et 
>>al. and maybe others are AS-dependent.
> 
> I agree for INDEX_REG_CLASS and REGNO_OK_FOR_INDEX_P.  In fact, I'd
> suggest they should first be converted to look similar to base registers
> (i.e. add MODE_CODE_INDEX_REG_CLASS and REGNO_MODE_CODE_OK_FOR_INDEX_P)
> and then add address space support to those extended macros, so as to
> avoid having to change lots of back-ends.   Do you need this for AVR?
> I could add that to the patch I posted previously ...

No, that's not needed for AVR.  I just noticed it.

> Now for HAVE_PRE_INCREMENT, I don't think we need anything special.
> This is used just as a short-cut to bypass pre-increment handling
> completely on targets that don't support it at all.  On targets
> that *do*, there will always be additional requirement on just
> which memory accesses support pre-increment.  Therefore, the
> middle-end will still always check the target's legitimate_address
> callback to ensure any particular pre-incremented memory access
> is actually valid.  This mechanism can already look at the address
> space to make its decision ...

Thanks for all your explanations. Johann

> Bye,
> Ulrich


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands
  2011-08-21 16:43                 ` Georg-Johann Lay
@ 2011-08-22 12:39                   ` Ulrich Weigand
  0 siblings, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2011-08-22 12:39 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

Georg-Johann Lay wrote:
> Ulrich Weigand schrieb:
> > Georg-Johann Lay wrote:
> > 
> >>http://gcc.gnu.org/ml/gcc/2011-08/msg00131.html
> >>
> >>Are you going to install that patch? Or maybe you already installed it?
> > 
> > No, it isn't approved yet (in fact, it isn't even posted for approval).
> > Usually, patches that add new target macros, or new arguments to target
> > macros, but do not actually add any *exploiter* of the new features,
> > are frowned upon ...
> 
> I thought about implementing a "hidden" named AS first and not exposing 
> it to user land, e.g. to be able to do optimizations like
>     http://gcc.gnu.org/PR49857
>     http://gcc.gnu.org/PR43745
> which need named AS to express that some pointers/accesses are different.
> 
> The most prominent drawback of named AS at the moment is that AVR has 
> few address registers and register allocation often regerates unpleasant 
> code or even runs into spill fails.
> 
> The AS in question can only be accessed by means of post-increment 
> addressing via one single hard register.

Well, it doesn't really matter whether you want to expose the AS externally
or just use it internally.  Either way, I'll be happy to propose my patch
for inclusion once you have a patch ready that depends on it ...

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2011-08-22 12:39 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-04 13:43 [named address] ice-on-valid: in postreload.c:reload_cse_simplify_operands Georg-Johann Lay
2011-08-04 16:20 ` Ulrich Weigand
2011-08-04 16:26   ` DJ Delorie
2011-08-04 16:33     ` Ulrich Weigand
2011-08-04 17:28   ` Georg-Johann Lay
2011-08-05 10:19     ` Ulrich Weigand
2011-08-05 12:47       ` Georg-Johann Lay
2011-08-05 13:24         ` Ulrich Weigand
2011-08-05 14:09           ` Michael Matz
2011-08-05 14:29             ` Ulrich Weigand
2011-08-05 20:43     ` Ulrich Weigand
2011-08-05 20:47       ` DJ Delorie
2011-08-05 21:01         ` Ulrich Weigand
2011-08-05 21:08           ` DJ Delorie
2011-08-08 11:38       ` Georg-Johann Lay
2011-08-09 17:16         ` Ulrich Weigand
2011-08-10 14:04           ` Georg-Johann Lay
2011-08-17 17:44             ` Georg-Johann Lay
2011-08-18 14:38               ` Ulrich Weigand
2011-08-21 16:43                 ` Georg-Johann Lay
2011-08-22 12:39                   ` Ulrich Weigand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).