This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[named-addr-spaces-branches] Some more fixes


Hello,

I've checked in the following patch implementing some further updates to
the named-addr-spaces-branch.  This is the result of a review of middle-end
code which turned up a number of places that ignored the possibility of
addresses from non-generic address spaces.  Most of these never actually
show up on SPU as we eliminate any non-generic address space MEM RTX 
early in expand.  However, on other platforms that keep such RTXs throughout
the back-end stages, this would make a difference.

There's one new target hook, TARGET_ADDR_SPACE_VALID_POINTER_MODE, which is
an address-space aware version of TARGET_VALID_POINTER_MODE.  This allows
the target to designate different modes as valid pointer modes depending
on the particular target address space.

Tested on spu-elf.

Bye,
Ulrich


ChangeLog:

	* doc/tm.texi (TARGET_ADDR_SPACE_VALID_POINTER_MODE): Document
	new target hook.
	* target.h (struct gcc_target): Add addr_space.valid_pointer_mode.
	* target-def.h (TARGET_ADDR_SPACE_VALID_POINTER_MODE): Define.
	(TARGET_ADDR_SPACE_HOOKS): Update.
	* targhooks.c (default_addr_space_valid_pointer_mode): New function.
	* targhooks.h (default_addr_space_valid_pointer_mode): Add prototype.
	* config/spu/spu.c (spu_valid_pointer_mode): Remove.
	(TARGET_VALID_POINTER_MODE): Do not define.

	* tree-flow.h (multiplier_allowed_in_address_p): Add address space
	argument.
	(addr_for_mem_ref): Likewise.
	* tree-ssa-address.h: Include "target.h".
	(templates): Replace by ...
	(mem_addr_template_list): ... this new vector.
	(TEMPL_IDX): Handle address space numbers.
	(gen_addr_rtx): Add address mode argument.
	(addr_for_mem_ref): Add address space argument.  Handle named
	address spaces.
	(valid_mem_ref_p): Likewise.
	(create_mem_ref_raw): Handle named address spaces.
	(most_expensive_mult_to_index): Update call to
	multiplier_allowed_in_address_p.
	* tree-ssa-loop-ivopts.c (produce_memory_decl_rtl): Handle named
	address spaces.
	(computation_cost): Likewise.
	(get_computation_cost_at): Likewise.
	(multiplier_allowed_in_address_p): Add address space argument.
	Handle named address spaces.
	(get_address_cost): Likewise.

	* reload.h (form_sum): Add MODE argument.
	* reload.c (maybe_memory_address_p): Rename to ...
	(maybe_memory_address_addr_space_p): ... this.  Handle named
	address spaces.
	(strict_memory_address_p): Rename to ...
	(strict_memory_address_addr_space_p): ... this.  Handle named
	address spaces.
	(get_secondary_mem): Handle named address spaces.
	(find_reloads): Likewise.
	(find_reloads_toplev): Likewise.
	(find_reloads_address): Likewise.
	(find_reloads_subreg_address): Likewise.
	(find_reloads_address_1): Do not refer to Pmode.
	(form_sum): Add MODE argument.  Use it instead of referring to Pmode.
	Update recursive calls.
	(subst_indexed_address): Update calls to form_sum.
	* reload1.c (reload): Handle named address spaces.
	(eliminate_regs_1): Update call to form_sum.

	* rtl.h (address_cost): Add address space argument.
	(convert_memory_address): Implement as macro.
	(convert_memory_address_addr_space): Add prototype.

	* rtlanal.c (address_cost): Add address space argument.  Handle named
	address spaces.
	(nonzero_bits1): Guard pointer size optimizations.
	(num_sign_bit_copies1): Likewise.
	* alias.c: Include "targhooks.h".
	(find_base_value): Guard pointer size optimizations.
	(find_base_term): Likewise.
	* simplify-rtx.c (simplify_unary_operation_1): Guard
	pointer size optimizations.
	* loop-invariant.c (create_new_invariant): Update call to
	address_cost.

	* explow.c (convert_memory_address): Rename to ...
	(convert_memory_address_addr_space): ... this.  Add address space
	argument.  Handle named address spaces.  Update recursive calls.
	(memory_address_addr_space): Use convert_memory_address_addr_space.

	* expr.c (move_by_pieces): Handle named address spaces.
	(emit_block_move_hints): Likewise.
	(emit_block_move_via_loop): Likewise.
	(store_by_pieces): Likewise.
	(store_by_pieces_1): Likewise.
	(clear_storage_hints): Likewise.
	(expand_assignment): Likewise.
	(store_expr): Likewise.
	(store_constructor): Likewise.
	(expand_expr_addr_expr_1): Add address space argument.
	Handle named address spaces.  Update recursive calls.
	(expand_expr_addr_expr): Update call.
	(expand_expr_real_1): Handle TARGET_MEM_REF in named
	address spaces.

	* recog.c (verify_changes): Handle named address spaces.
	(general_operand): Likewise.
	(memory_address_p): Inline into ...
	(memory_address_addr_space_p): ... this function.
	(offsettable_memref_p): Handle named address spaces.
	(offsettable_nonstrict_memref_p): Likewise.
	(offsettable_address_p): Rename to ...
	(offsettable_address_addr_space_p): ... this.  Add address space
	argument.  Handle named address spaces.
	(constrain_operands): Handle named address spaces.
	* recog.h (memory_address_p): Implement as macro.
	(strict_memory_address_p): Likewise.
	(offsettable_address_p): Likewise.
	(offsettable_address_addr_space_p): Add prototype.

	* auto-inc-dec.c (find_inc): Revert local change.

	* rtlhooks.c (gen_lowpart_if_possible): Handle named address spaces.

	* fwprop.c (should_replace_address): Add address space argument.
	Handle named address spaces.
	(propagate_rtx_1): Update call.

	* ifcvt.c (noce_try_cmove_arith): Handle named address spaces.

	* sched-deps.c: Include "target.h".
	(sched_analyze_1): Handle named address spaces.
	(sched_analyze_2): Likewise.

	* sel-sched-dump.c: Include "target.h".
	(debug_mem_addr_value): Handle named address spaces.

	* dse.c (replace_inc_dec): Do not refer to Pmode.
	(canon_address): Handle named address spaces.

	* regmove.c (try_auto_increment): Do not refer to Pmode.

	* regcprop.c (kill_autoinc_value): Do not refer to Pmode.

	* tree-vect-data-refs.c (vect_create_data_ref_ptr): Do not
	refer to ptr_mode.

	* expmed.c (make_tree): Handle named address spaces.

	* emit-rtl.c (operand_subword): Handle named address spaces.

	* cselib.c (cselib_record_sets): Handle named address spaces.

	* combine.c (find_split_point): Handle named address spaces.

	* c-common.c (handle_mode_attribute): Handle named address spaces.

	* varasm.c (initializer_constant_valid_p): Do not refer to
	POINTER_SIZE.
	(output_constant): Handle named address spaces.

	* Makefile.in (tree-ssa-address.o): Add dependency on $(TARGET_H).
	(sched-deps.o): Likewise.
	(alias.o): Add dependency on targhooks.h.


Index: gcc/fwprop.c
===================================================================
*** gcc/fwprop.c	(revision 150188)
--- gcc/fwprop.c	(working copy)
*************** canonicalize_address (rtx x)
*** 375,385 ****
  
  static bool
  should_replace_address (rtx old_rtx, rtx new_rtx, enum machine_mode mode,
! 			bool speed)
  {
    int gain;
  
!   if (rtx_equal_p (old_rtx, new_rtx) || !memory_address_p (mode, new_rtx))
      return false;
  
    /* Copy propagation is always ok.  */
--- 375,386 ----
  
  static bool
  should_replace_address (rtx old_rtx, rtx new_rtx, enum machine_mode mode,
! 			addr_space_t as, bool speed)
  {
    int gain;
  
!   if (rtx_equal_p (old_rtx, new_rtx)
!       || !memory_address_addr_space_p (mode, new_rtx, as))
      return false;
  
    /* Copy propagation is always ok.  */
*************** should_replace_address (rtx old_rtx, rtx
*** 387,393 ****
      return true;
  
    /* Prefer the new address if it is less expensive.  */
!   gain = address_cost (old_rtx, mode, speed) - address_cost (new_rtx, mode, speed);
  
    /* If the addresses have equivalent cost, prefer the new address
       if it has the highest `rtx_cost'.  That has the potential of
--- 388,395 ----
      return true;
  
    /* Prefer the new address if it is less expensive.  */
!   gain = (address_cost (old_rtx, mode, as, speed)
! 	  - address_cost (new_rtx, mode, as, speed));
  
    /* If the addresses have equivalent cost, prefer the new address
       if it has the highest `rtx_cost'.  That has the potential of
*************** propagate_rtx_1 (rtx *px, rtx old_rtx, r
*** 555,560 ****
--- 557,563 ----
  	  /* Copy propagations are always ok.  Otherwise check the costs.  */
  	  if (!(REG_P (old_rtx) && REG_P (new_rtx))
  	      && !should_replace_address (op0, new_op0, GET_MODE (x),
+ 					  MEM_ADDR_SPACE (x),
  	      			 	  flags & PR_OPTIMIZE_FOR_SPEED))
  	    return true;
  
Index: gcc/doc/tm.texi
===================================================================
*** gcc/doc/tm.texi	(revision 150758)
--- gcc/doc/tm.texi	(working copy)
*************** The default version of this hook returns
*** 9845,9850 ****
--- 9845,9860 ----
  generic address space only.
  @end deftypefn
  
+ @deftypefn {Target Hook} bool TARGET_ADDR_SPACE_VALID_POINTER_MODE (enum machine_mode @var{mode}, addr_space_t @var{as})
+ Define this to return nonzero if the port can handle pointers
+ with machine mode @var{mode} to address space @var{as}.  This target
+ hook is the same as the @code{TARGET_VALID_POINTER_MODE} target hook,
+ except that it includes explicit named address space support.  The default
+ version of this hook returns true for the modes returned by either the
+ @code{TARGET_ADDR_SPACE_POINTER_MODE} or @code{TARGET_ADDR_SPACE_ADDRESS_MODE}
+ target hooks for the given address space.
+ @end deftypefn
+ 
  @deftypefn {Target Hook} {bool} TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P (enum machine_mode @var{mode}, rtx @var{exp}, bool @var{strict}, addr_space_t @var{as})
  Define this to return true if @var{exp} is a valid address for mode
  @var{mode} in the named address space @var{as}.  The @var{strict}
Index: gcc/targhooks.c
===================================================================
*** gcc/targhooks.c	(revision 150758)
--- gcc/targhooks.c	(working copy)
*************** default_addr_space_address_mode (addr_sp
*** 770,775 ****
--- 770,787 ----
    return Pmode;
  }
  
+ /* Named address space version of valid_pointer_mode.  */
+ 
+ bool
+ default_addr_space_valid_pointer_mode (enum machine_mode mode, addr_space_t as)
+ {
+   if (as)
+     return (mode == targetm.addr_space.pointer_mode (as)
+ 	    || mode == targetm.addr_space.address_mode (as));
+ 
+   return targetm.valid_pointer_mode (mode);
+ }
+ 
  /* Named address space version of legitimate_address_p.  */
  
  bool
Index: gcc/targhooks.h
===================================================================
*** gcc/targhooks.h	(revision 150758)
--- gcc/targhooks.h	(working copy)
*************** extern bool default_target_can_inline_p 
*** 111,116 ****
--- 111,118 ----
  extern bool default_valid_pointer_mode (enum machine_mode);
  extern enum machine_mode default_addr_space_pointer_mode (addr_space_t);
  extern enum machine_mode default_addr_space_address_mode (addr_space_t);
+ extern bool default_addr_space_valid_pointer_mode (enum machine_mode,
+ 						   addr_space_t);
  extern bool default_addr_space_legitimate_address_p (enum machine_mode, rtx,
  						     bool, addr_space_t);
  extern rtx default_addr_space_legitimize_address (rtx, rtx, enum machine_mode,
Index: gcc/rtlhooks.c
===================================================================
*** gcc/rtlhooks.c	(revision 150188)
--- gcc/rtlhooks.c	(working copy)
*************** gen_lowpart_if_possible (enum machine_mo
*** 153,159 ****
  		   - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
  
        new_rtx = adjust_address_nv (x, mode, offset);
!       if (! memory_address_p (mode, XEXP (new_rtx, 0)))
  	return 0;
  
        return new_rtx;
--- 153,160 ----
  		   - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
  
        new_rtx = adjust_address_nv (x, mode, offset);
!       if (! memory_address_addr_space_p (mode, XEXP (new_rtx, 0),
! 					 MEM_ADDR_SPACE (x)))
  	return 0;
  
        return new_rtx;
Index: gcc/reload.c
===================================================================
*** gcc/reload.c	(revision 150758)
--- gcc/reload.c	(working copy)
*************** static bool alternative_allows_const_poo
*** 267,273 ****
  static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx,
  				int *);
  static rtx make_memloc (rtx, int);
! static int maybe_memory_address_p (enum machine_mode, rtx, rtx *);
  static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *,
  				 int, enum reload_type, int, rtx);
  static rtx subst_reg_equivs (rtx, rtx);
--- 267,274 ----
  static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx,
  				int *);
  static rtx make_memloc (rtx, int);
! static int maybe_memory_address_addr_space_p (enum machine_mode, rtx,
! 					      addr_space_t, rtx *);
  static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *,
  				 int, enum reload_type, int, rtx);
  static rtx subst_reg_equivs (rtx, rtx);
*************** get_secondary_mem (rtx x ATTRIBUTE_UNUSE
*** 611,617 ****
       didn't give us a new MEM, make a new one if it isn't valid.  */
  
    loc = eliminate_regs (secondary_memlocs[(int) mode], VOIDmode, NULL_RTX);
!   mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));
  
    if (! mem_valid && loc == secondary_memlocs[(int) mode])
      loc = copy_rtx (loc);
--- 612,619 ----
       didn't give us a new MEM, make a new one if it isn't valid.  */
  
    loc = eliminate_regs (secondary_memlocs[(int) mode], VOIDmode, NULL_RTX);
!   mem_valid = strict_memory_address_addr_space_p (mode, XEXP (loc, 0),
! 						  MEM_ADDR_SPACE (loc));
  
    if (! mem_valid && loc == secondary_memlocs[(int) mode])
      loc = copy_rtx (loc);
*************** hard_reg_set_here_p (unsigned int beg_re
*** 2128,2148 ****
    return 0;
  }
  
! /* Return 1 if ADDR is a valid memory address for mode MODE,
!    and check that each pseudo reg has the proper kind of
!    hard reg.  */
  
  int
! strict_memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
  {
  #ifdef GO_IF_LEGITIMATE_ADDRESS
    GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
    return 0;
  
   win:
    return 1;
  #else
!   return targetm.legitimate_address_p (mode, addr, 1);
  #endif
  }
  
--- 2130,2152 ----
    return 0;
  }
  
! /* Return 1 if ADDR is a valid memory address for mode MODE
!    in address space AS, and check that each pseudo reg has the
!    proper kind of hard reg.  */
  
  int
! strict_memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
! 				    rtx addr, addr_space_t as)
  {
  #ifdef GO_IF_LEGITIMATE_ADDRESS
+   gcc_assert (as == 0);
    GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
    return 0;
  
   win:
    return 1;
  #else
!   return targetm.addr_space.legitimate_address_p (mode, addr, 1, as);
  #endif
  }
  
*************** find_reloads (rtx insn, int replace, int
*** 3954,3965 ****
  		 && MEM_P (recog_data.operand[i]))
  	  {
  	    /* If the address to be reloaded is a VOIDmode constant,
! 	       use Pmode as mode of the reload register, as would have
! 	       been done by find_reloads_address.  */
  	    enum machine_mode address_mode;
  	    address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
  	    if (address_mode == VOIDmode)
! 	      address_mode = Pmode;
  
  	    operand_reloadnum[i]
  	      = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
--- 3958,3972 ----
  		 && MEM_P (recog_data.operand[i]))
  	  {
  	    /* 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,
*************** find_reloads_toplev (rtx x, int opnum, e
*** 4735,4742 ****
  #endif
  	       && (reg_equiv_address[regno] != 0
  		   || (reg_equiv_mem[regno] != 0
! 		       && (! strict_memory_address_p (GET_MODE (x),
! 						      XEXP (reg_equiv_mem[regno], 0))
  			   || ! offsettable_memref_p (reg_equiv_mem[regno])
  			   || num_not_at_initial_offset))))
  	x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
--- 4742,4750 ----
  #endif
  	       && (reg_equiv_address[regno] != 0
  		   || (reg_equiv_mem[regno] != 0
! 		       && (! strict_memory_address_addr_space_p
! 			       (GET_MODE (x), XEXP (reg_equiv_mem[regno], 0),
! 				MEM_ADDR_SPACE (reg_equiv_mem[regno]))
  			   || ! offsettable_memref_p (reg_equiv_mem[regno])
  			   || num_not_at_initial_offset))))
  	x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
*************** make_memloc (rtx ad, int regno)
*** 4794,4811 ****
  }
  
  /* Returns true if AD could be turned into a valid memory reference
!    to mode MODE by reloading the part pointed to by PART into a
!    register.  */
  
  static int
! maybe_memory_address_p (enum machine_mode mode, rtx ad, rtx *part)
  {
    int retv;
    rtx tem = *part;
    rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ());
  
    *part = reg;
!   retv = memory_address_p (mode, ad);
    *part = tem;
  
    return retv;
--- 4802,4820 ----
  }
  
  /* Returns true if AD could be turned into a valid memory reference
!    to mode MODE in address space AS by reloading the part pointed to
!    by PART into a register.  */
  
  static int
! maybe_memory_address_addr_space_p (enum machine_mode mode, rtx ad,
! 				   addr_space_t as, rtx *part)
  {
    int retv;
    rtx tem = *part;
    rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ());
  
    *part = reg;
!   retv = memory_address_addr_space_p (mode, ad, as);
    *part = tem;
  
    return retv;
*************** find_reloads_address (enum machine_mode 
*** 4841,4846 ****
--- 4850,4856 ----
  		      rtx *loc, int opnum, enum reload_type type,
  		      int ind_levels, rtx insn)
  {
+   addr_space_t as = memrefloc? MEM_ADDR_SPACE (*memrefloc) : 0;
    int regno;
    int removed_and = 0;
    int op_index;
*************** find_reloads_address (enum machine_mode 
*** 4868,4874 ****
  	  if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)
  	    {
  	      tem = make_memloc (ad, regno);
! 	      if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
  		{
  		  rtx orig = tem;
  
--- 4878,4886 ----
  	  if (reg_equiv_address[regno] != 0 || num_not_at_initial_offset)
  	    {
  	      tem = make_memloc (ad, regno);
! 	      if (! strict_memory_address_addr_space_p (GET_MODE (tem),
! 							XEXP (tem, 0),
! 							MEM_ADDR_SPACE (tem)))
  		{
  		  rtx orig = tem;
  
*************** find_reloads_address (enum machine_mode 
*** 4884,4890 ****
  		 address: only reg or reg+constant.  */
  
  	      if (ind_levels > 0
! 		  && strict_memory_address_p (mode, tem)
  		  && (REG_P (XEXP (tem, 0))
  		      || (GET_CODE (XEXP (tem, 0)) == PLUS
  			  && REG_P (XEXP (XEXP (tem, 0), 0))
--- 4896,4902 ----
  		 address: only reg or reg+constant.  */
  
  	      if (ind_levels > 0
! 		  && strict_memory_address_addr_space_p (mode, tem, as)
  		  && (REG_P (XEXP (tem, 0))
  		      || (GET_CODE (XEXP (tem, 0)) == PLUS
  			  && REG_P (XEXP (XEXP (tem, 0), 0))
*************** find_reloads_address (enum machine_mode 
*** 4928,4934 ****
        return 1;
      }
  
!   if (strict_memory_address_p (mode, ad))
      {
        /* The address appears valid, so reloads are not needed.
  	 But the address may contain an eliminable register.
--- 4940,4946 ----
        return 1;
      }
  
!   if (strict_memory_address_addr_space_p (mode, ad, as))
      {
        /* The address appears valid, so reloads are not needed.
  	 But the address may contain an eliminable register.
*************** find_reloads_address (enum machine_mode 
*** 4951,4964 ****
  	return 0;
  
        /* Check result for validity after substitution.  */
!       if (strict_memory_address_p (mode, ad))
  	return 0;
      }
  
  #ifdef LEGITIMIZE_RELOAD_ADDRESS
    do
      {
!       if (memrefloc)
  	{
  	  LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
  				     ind_levels, win);
--- 4963,4976 ----
  	return 0;
  
        /* Check result for validity after substitution.  */
!       if (strict_memory_address_addr_space_p (mode, ad, as))
  	return 0;
      }
  
  #ifdef LEGITIMIZE_RELOAD_ADDRESS
    do
      {
!       if (memrefloc && as == 0)
  	{
  	  LEGITIMIZE_RELOAD_ADDRESS (ad, GET_MODE (*memrefloc), opnum, type,
  				     ind_levels, win);
*************** find_reloads_address (enum machine_mode 
*** 5074,5080 ****
  	     That will at least work.  */
  	  find_reloads_address_part (ad, loc,
  				     base_reg_class (mode, MEM, SCRATCH),
! 				     Pmode, opnum, type, ind_levels);
  	}
        return ! removed_and;
      }
--- 5086,5092 ----
  	     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;
      }
*************** find_reloads_address (enum machine_mode 
*** 5135,5142 ****
  	   || operand == arg_pointer_rtx
  #endif
  	   || operand == stack_pointer_rtx)
! 	  && ! maybe_memory_address_p (mode, ad, 
! 				       &XEXP (XEXP (ad, 0), 1 - op_index)))
  	{
  	  rtx offset_reg;
  	  enum reg_class cls;
--- 5147,5154 ----
  	   || operand == arg_pointer_rtx
  #endif
  	   || operand == stack_pointer_rtx)
! 	  && ! maybe_memory_address_addr_space_p
! 		(mode, ad, as, &XEXP (XEXP (ad, 0), 1 - op_index)))
  	{
  	  rtx offset_reg;
  	  enum reg_class cls;
*************** find_reloads_address (enum machine_mode 
*** 5174,5180 ****
    tem = ad;
    if (GET_CODE (ad) == PLUS)
      tem = subst_indexed_address (ad);
!   if (tem != ad && strict_memory_address_p (mode, tem))
      {
        /* Ok, we win that way.  Replace any additional eliminable
  	 registers.  */
--- 5186,5192 ----
    tem = ad;
    if (GET_CODE (ad) == PLUS)
      tem = subst_indexed_address (ad);
!   if (tem != ad && strict_memory_address_addr_space_p (mode, tem, as))
      {
        /* Ok, we win that way.  Replace any additional eliminable
  	 registers.  */
*************** find_reloads_address (enum machine_mode 
*** 5184,5190 ****
  
        /* Make sure that didn't make the address invalid again.  */
  
!       if (! subst_reg_equivs_changed || strict_memory_address_p (mode, tem))
  	{
  	  *loc = tem;
  	  return 0;
--- 5196,5203 ----
  
        /* Make sure that didn't make the address invalid again.  */
  
!       if (! subst_reg_equivs_changed
! 	  || strict_memory_address_addr_space_p (mode, tem, as))
  	{
  	  *loc = tem;
  	  return 0;
*************** find_reloads_address (enum machine_mode 
*** 5193,5200 ****
  
    /* If constants aren't valid addresses, reload the constant address
       into a register.  */
!   if (CONSTANT_P (ad) && ! strict_memory_address_p (mode, ad))
      {
        /* If AD is an address in the constant pool, the MEM rtx may be shared.
  	 Unshare it so we can safely alter it.  */
        if (memrefloc && GET_CODE (ad) == SYMBOL_REF
--- 5206,5217 ----
  
    /* If constants aren't valid addresses, reload the constant address
       into a register.  */
!   if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as))
      {
+       enum machine_mode address_mode = GET_MODE (ad);
+       if (ad == VOIDmode)
+ 	address_mode = targetm.addr_space.address_mode (as);
+ 
        /* If AD is an address in the constant pool, the MEM rtx may be shared.
  	 Unshare it so we can safely alter it.  */
        if (memrefloc && GET_CODE (ad) == SYMBOL_REF
*************** find_reloads_address (enum machine_mode 
*** 5207,5213 ****
  	}
  
        find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
! 				 Pmode, opnum, type, ind_levels);
        return ! removed_and;
      }
  
--- 5224,5230 ----
  	}
  
        find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
! 				 address_mode, opnum, type, ind_levels);
        return ! removed_and;
      }
  
*************** subst_reg_equivs (rtx ad, rtx insn)
*** 5294,5309 ****
     This routine assumes both inputs are already in canonical form.  */
  
  rtx
! form_sum (rtx x, rtx y)
  {
    rtx tem;
-   enum machine_mode mode = GET_MODE (x);
- 
-   if (mode == VOIDmode)
-     mode = GET_MODE (y);
  
!   if (mode == VOIDmode)
!     mode = Pmode;
  
    if (CONST_INT_P (x))
      return plus_constant (y, INTVAL (x));
--- 5311,5322 ----
     This routine assumes both inputs are already in canonical form.  */
  
  rtx
! form_sum (enum machine_mode mode, rtx x, rtx y)
  {
    rtx tem;
  
!   gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
!   gcc_assert (GET_MODE (y) == mode || GET_MODE (y) == VOIDmode);
  
    if (CONST_INT_P (x))
      return plus_constant (y, INTVAL (x));
*************** form_sum (rtx x, rtx y)
*** 5313,5324 ****
      tem = x, x = y, y = tem;
  
    if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
!     return form_sum (XEXP (x, 0), form_sum (XEXP (x, 1), y));
  
    /* Note that if the operands of Y are specified in the opposite
       order in the recursive calls below, infinite recursion will occur.  */
    if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
!     return form_sum (form_sum (x, XEXP (y, 0)), XEXP (y, 1));
  
    /* If both constant, encapsulate sum.  Otherwise, just form sum.  A
       constant will have been placed second.  */
--- 5326,5337 ----
      tem = x, x = y, y = tem;
  
    if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
!     return form_sum (mode, XEXP (x, 0), form_sum (mode, XEXP (x, 1), y));
  
    /* Note that if the operands of Y are specified in the opposite
       order in the recursive calls below, infinite recursion will occur.  */
    if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
!     return form_sum (mode, form_sum (mode, x, XEXP (y, 0)), XEXP (y, 1));
  
    /* If both constant, encapsulate sum.  Otherwise, just form sum.  A
       constant will have been placed second.  */
*************** subst_indexed_address (rtx addr)
*** 5385,5393 ****
  
        /* Compute the sum.  */
        if (op2 != 0)
! 	op1 = form_sum (op1, op2);
        if (op1 != 0)
! 	op0 = form_sum (op0, op1);
  
        return op0;
      }
--- 5398,5406 ----
  
        /* Compute the sum.  */
        if (op2 != 0)
! 	op1 = form_sum (GET_MODE (addr), op1, op2);
        if (op1 != 0)
! 	op0 = form_sum (GET_MODE (addr), op0, op1);
  
        return op0;
      }
*************** find_reloads_address_1 (enum machine_mod
*** 5787,5793 ****
  	      rtx equiv = (MEM_P (XEXP (x, 0))
  			   ? XEXP (x, 0)
  			   : reg_equiv_mem[regno]);
! 	      int icode = (int) optab_handler (add_optab, Pmode)->insn_code;
  	      if (insn && NONJUMP_INSN_P (insn) && equiv
  		  && memory_operand (equiv, GET_MODE (equiv))
  #ifdef HAVE_cc0
--- 5800,5807 ----
  	      rtx equiv = (MEM_P (XEXP (x, 0))
  			   ? XEXP (x, 0)
  			   : reg_equiv_mem[regno]);
! 	      int icode
! 		= (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
  	      if (insn && NONJUMP_INSN_P (insn) && equiv
  		  && memory_operand (equiv, GET_MODE (equiv))
  #ifdef HAVE_cc0
*************** find_reloads_address_1 (enum machine_mod
*** 5795,5803 ****
  #endif
  		  && ! (icode != CODE_FOR_nothing
  			&& ((*insn_data[icode].operand[0].predicate)
! 			    (equiv, Pmode))
  			&& ((*insn_data[icode].operand[1].predicate)
! 			    (equiv, Pmode))))
  		{
  		  /* We use the original pseudo for loc, so that
  		     emit_reload_insns() knows which pseudo this
--- 5809,5817 ----
  #endif
  		  && ! (icode != CODE_FOR_nothing
  			&& ((*insn_data[icode].operand[0].predicate)
! 			    (equiv, GET_MODE (x)))
  			&& ((*insn_data[icode].operand[1].predicate)
! 			    (equiv, GET_MODE (x)))))
  		{
  		  /* We use the original pseudo for loc, so that
  		     emit_reload_insns() knows which pseudo this
*************** find_reloads_subreg_address (rtx x, int 
*** 6147,6154 ****
  		 valid address into an invalid one.  Check for that
  		 here.  */
  	      if (reloaded == 0
! 		  && !strict_memory_address_p (GET_MODE (tem),
! 					       XEXP (tem, 0)))
  		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,
--- 6161,6168 ----
  		 valid address into an invalid one.  Check for that
  		 here.  */
  	      if (reloaded == 0
! 		  && !strict_memory_address_addr_space_p
! 		       (GET_MODE (tem), XEXP (tem, 0), MEM_ADDR_SPACE (tem)))
  		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,
Index: gcc/reload.h
===================================================================
*** gcc/reload.h	(revision 150188)
--- gcc/reload.h	(working copy)
*************** extern int find_reloads (rtx, int, int, 
*** 289,295 ****
     address, namely: sum constant integers, surround the sum of two
     constants with a CONST, put the constant as the second operand, and
     group the constant on the outermost sum.  */
! extern rtx form_sum (rtx, rtx);
  
  /* Substitute into the current INSN the registers into which we have reloaded
     the things that need reloading.  */
--- 289,295 ----
     address, namely: sum constant integers, surround the sum of two
     constants with a CONST, put the constant as the second operand, and
     group the constant on the outermost sum.  */
! extern rtx form_sum (enum machine_mode, rtx, rtx);
  
  /* Substitute into the current INSN the registers into which we have reloaded
     the things that need reloading.  */
Index: gcc/target.h
===================================================================
*** gcc/target.h	(revision 150758)
--- gcc/target.h	(working copy)
*************** struct gcc_target
*** 688,693 ****
--- 688,697 ----
      /* MODE to use for an address in another address space.  */
      enum machine_mode (* address_mode) (addr_space_t);
  
+     /* True if MODE is valid for a pointer in __attribute__((mode("MODE")))
+        in another address space.  */
+     bool (* valid_pointer_mode) (enum machine_mode, addr_space_t);
+ 
      /* True if an addrress is a valid memory address to a given named address
         space for a given mode.  */
      bool (* legitimate_address_p) (enum machine_mode, rtx, bool, addr_space_t);
Index: gcc/rtlanal.c
===================================================================
*** gcc/rtlanal.c	(revision 150188)
--- gcc/rtlanal.c	(working copy)
*************** rtx_cost (rtx x, enum rtx_code outer_cod
*** 3602,3614 ****
     be returned.  */
  
  int
! address_cost (rtx x, enum machine_mode mode, bool speed)
  {
    /* We may be asked for cost of various unusual addresses, such as operands
       of push instruction.  It is not worthwhile to complicate writing
       of the target hook by such cases.  */
  
!   if (!memory_address_p (mode, x))
      return 1000;
  
    return targetm.address_cost (x, speed);
--- 3602,3614 ----
     be returned.  */
  
  int
! address_cost (rtx x, enum machine_mode mode, addr_space_t as, bool speed)
  {
    /* We may be asked for cost of various unusual addresses, such as operands
       of push instruction.  It is not worthwhile to complicate writing
       of the target hook by such cases.  */
  
!   if (!memory_address_addr_space_p (mode, x, as))
      return 1000;
  
    return targetm.address_cost (x, speed);
*************** nonzero_bits1 (const_rtx x, enum machine
*** 3747,3753 ****
  #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
        /* If pointers extend unsigned and this is a pointer in Pmode, say that
  	 all the bits above ptr_mode are known to be zero.  */
!       if (POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && REG_POINTER (x))
  	nonzero &= GET_MODE_MASK (ptr_mode);
  #endif
--- 3747,3758 ----
  #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
        /* If pointers extend unsigned and this is a pointer in Pmode, say that
  	 all the bits above ptr_mode are known to be zero.  */
!       /* As we do not know which address space the pointer is refering to,
! 	 we can do this only if the target does not support different pointer
! 	 or address modes depending on the address space.  */
!       if (targetm.addr_space.address_mode == default_addr_space_address_mode
! 	  && targetm.addr_space.pointer_mode == default_addr_space_pointer_mode
! 	  && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && REG_POINTER (x))
  	nonzero &= GET_MODE_MASK (ptr_mode);
  #endif
*************** nonzero_bits1 (const_rtx x, enum machine
*** 3984,3990 ****
  	/* If pointers extend unsigned and this is an addition or subtraction
  	   to a pointer in Pmode, all the bits above ptr_mode are known to be
  	   zero.  */
! 	if (POINTERS_EXTEND_UNSIGNED > 0 && GET_MODE (x) == Pmode
  	    && (code == PLUS || code == MINUS)
  	    && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
  	  nonzero &= GET_MODE_MASK (ptr_mode);
--- 3989,4001 ----
  	/* If pointers extend unsigned and this is an addition or subtraction
  	   to a pointer in Pmode, all the bits above ptr_mode are known to be
  	   zero.  */
! 	/* As we do not know which address space the pointer is refering to,
! 	   we can do this only if the target does not support different pointer
! 	   or address modes depending on the address space.  */
! 	if (targetm.addr_space.address_mode == default_addr_space_address_mode
! 	    && targetm.addr_space.pointer_mode
! 	       == default_addr_space_pointer_mode
! 	    && POINTERS_EXTEND_UNSIGNED > 0 && GET_MODE (x) == Pmode
  	    && (code == PLUS || code == MINUS)
  	    && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
  	  nonzero &= GET_MODE_MASK (ptr_mode);
*************** num_sign_bit_copies1 (const_rtx x, enum 
*** 4258,4265 ****
  #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
        /* If pointers extend signed and this is a pointer in Pmode, say that
  	 all the bits above ptr_mode are known to be sign bit copies.  */
!       if (! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode && mode == Pmode
! 	  && REG_POINTER (x))
  	return GET_MODE_BITSIZE (Pmode) - GET_MODE_BITSIZE (ptr_mode) + 1;
  #endif
  
--- 4269,4281 ----
  #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
        /* If pointers extend signed and this is a pointer in Pmode, say that
  	 all the bits above ptr_mode are known to be sign bit copies.  */
!       /* As we do not know which address space the pointer is refering to,
! 	 we can do this only if the target does not support different pointer
! 	 or address modes depending on the address space.  */
!       if (targetm.addr_space.address_mode == default_addr_space_address_mode
! 	  && targetm.addr_space.pointer_mode == default_addr_space_pointer_mode
! 	  && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
! 	  && mode == Pmode && REG_POINTER (x))
  	return GET_MODE_BITSIZE (Pmode) - GET_MODE_BITSIZE (ptr_mode) + 1;
  #endif
  
*************** num_sign_bit_copies1 (const_rtx x, enum 
*** 4455,4461 ****
        /* If pointers extend signed and this is an addition or subtraction
  	 to a pointer in Pmode, all the bits above ptr_mode are known to be
  	 sign bit copies.  */
!       if (! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && (code == PLUS || code == MINUS)
  	  && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
  	result = MAX ((int) (GET_MODE_BITSIZE (Pmode)
--- 4471,4482 ----
        /* If pointers extend signed and this is an addition or subtraction
  	 to a pointer in Pmode, all the bits above ptr_mode are known to be
  	 sign bit copies.  */
!       /* As we do not know which address space the pointer is refering to,
! 	 we can do this only if the target does not support different pointer
! 	 or address modes depending on the address space.  */
!       if (targetm.addr_space.address_mode == default_addr_space_address_mode
! 	  && targetm.addr_space.pointer_mode == default_addr_space_pointer_mode
! 	  && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && (code == PLUS || code == MINUS)
  	  && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
  	result = MAX ((int) (GET_MODE_BITSIZE (Pmode)
Index: gcc/auto-inc-dec.c
===================================================================
*** gcc/auto-inc-dec.c	(revision 150188)
--- gcc/auto-inc-dec.c	(working copy)
*************** find_inc (bool first_try)
*** 1091,1097 ****
  		     we are going to increment the result of the add insn.
  		     For this trick to be correct, the result reg of
  		     the inc must be a valid addressing reg.  */
! 		  if (targetm.valid_pointer_mode (GET_MODE (inc_insn.reg_res)))
  		    {
  		      if (dump_file)
  			fprintf (dump_file, "base reg mode failure.\n");
--- 1091,1099 ----
  		     we are going to increment the result of the add insn.
  		     For this trick to be correct, the result reg of
  		     the inc must be a valid addressing reg.  */
! 		  addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
! 		  if (GET_MODE (inc_insn.reg_res)
! 		      != targetm.addr_space.address_mode (as))
  		    {
  		      if (dump_file)
  			fprintf (dump_file, "base reg mode failure.\n");
*************** find_inc (bool first_try)
*** 1140,1146 ****
  	{
  	  /* For this trick to be correct, the result reg of the inc
  	     must be a valid addressing reg.  */
! 	  if (targetm.valid_pointer_mode (GET_MODE (inc_insn.reg_res)))
  	    {
  	      if (dump_file)
  		fprintf (dump_file, "base reg mode failure.\n");
--- 1142,1150 ----
  	{
  	  /* For this trick to be correct, the result reg of the inc
  	     must be a valid addressing reg.  */
! 	  addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
! 	  if (GET_MODE (inc_insn.reg_res)
! 	      != targetm.addr_space.address_mode (as))
  	    {
  	      if (dump_file)
  		fprintf (dump_file, "base reg mode failure.\n");
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
*** gcc/tree-ssa-loop-ivopts.c	(revision 150188)
--- gcc/tree-ssa-loop-ivopts.c	(working copy)
*************** seq_cost (rtx seq, bool speed)
*** 2587,2607 ****
  static rtx
  produce_memory_decl_rtl (tree obj, int *regno)
  {
    rtx x;
    
    gcc_assert (obj);
    if (TREE_STATIC (obj) || DECL_EXTERNAL (obj))
      {
        const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (obj));
!       x = gen_rtx_SYMBOL_REF (Pmode, name);
        SET_SYMBOL_REF_DECL (x, obj);
        x = gen_rtx_MEM (DECL_MODE (obj), x);
        targetm.encode_section_info (obj, x, true);
      }
    else
      {
!       x = gen_raw_REG (Pmode, (*regno)++);
        x = gen_rtx_MEM (DECL_MODE (obj), x);
      }
  
    return x;
--- 2587,2611 ----
  static rtx
  produce_memory_decl_rtl (tree obj, int *regno)
  {
+   addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (obj));
+   enum machine_mode address_mode = targetm.addr_space.address_mode (as);
    rtx x;
    
    gcc_assert (obj);
    if (TREE_STATIC (obj) || DECL_EXTERNAL (obj))
      {
        const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (obj));
!       x = gen_rtx_SYMBOL_REF (address_mode, name);
        SET_SYMBOL_REF_DECL (x, obj);
        x = gen_rtx_MEM (DECL_MODE (obj), x);
+       set_mem_addr_space (x, as);
        targetm.encode_section_info (obj, x, true);
      }
    else
      {
!       x = gen_raw_REG (address_mode, (*regno)++);
        x = gen_rtx_MEM (DECL_MODE (obj), x);
+       set_mem_addr_space (x, as);
      }
  
    return x;
*************** computation_cost (tree expr, bool speed)
*** 2689,2695 ****
  
    cost = seq_cost (seq, speed);
    if (MEM_P (rslt))
!     cost += address_cost (XEXP (rslt, 0), TYPE_MODE (type), speed);
  
    return cost;
  }
--- 2693,2700 ----
  
    cost = seq_cost (seq, speed);
    if (MEM_P (rslt))
!     cost += address_cost (XEXP (rslt, 0), TYPE_MODE (type),
! 			  TYPE_ADDR_SPACE (type), speed);
  
    return cost;
  }
*************** multiply_by_cost (HOST_WIDE_INT cst, enu
*** 2965,3088 ****
  }
  
  /* Returns true if multiplying by RATIO is allowed in an address.  Test the
!    validity for a memory reference accessing memory of mode MODE.  */
  
  bool
! multiplier_allowed_in_address_p (HOST_WIDE_INT ratio, enum machine_mode mode)
  {
  #define MAX_RATIO 128
!   static sbitmap valid_mult[MAX_MACHINE_MODE];
!   
!   if (!valid_mult[mode])
      {
!       rtx reg1 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
        rtx addr;
        HOST_WIDE_INT i;
  
!       valid_mult[mode] = sbitmap_alloc (2 * MAX_RATIO + 1);
!       sbitmap_zero (valid_mult[mode]);
!       addr = gen_rtx_fmt_ee (MULT, Pmode, reg1, NULL_RTX);
        for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
  	{
! 	  XEXP (addr, 1) = gen_int_mode (i, Pmode);
! 	  if (memory_address_p (mode, addr))
! 	    SET_BIT (valid_mult[mode], i + MAX_RATIO);
  	}
  
        if (dump_file && (dump_flags & TDF_DETAILS))
  	{
  	  fprintf (dump_file, "  allowed multipliers:");
  	  for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
! 	    if (TEST_BIT (valid_mult[mode], i + MAX_RATIO))
  	      fprintf (dump_file, " %d", (int) i);
  	  fprintf (dump_file, "\n");
  	  fprintf (dump_file, "\n");
  	}
      }
  
    if (ratio > MAX_RATIO || ratio < -MAX_RATIO)
      return false;
  
!   return TEST_BIT (valid_mult[mode], ratio + MAX_RATIO);
  }
  
  /* Returns cost of address in shape symbol + var + OFFSET + RATIO * index.
     If SYMBOL_PRESENT is false, symbol is omitted.  If VAR_PRESENT is false,
     variable is omitted.  Compute the cost for a memory reference that accesses
!    a memory location of mode MEM_MODE.
  
     TODO -- there must be some better way.  This all is quite crude.  */
  
  static comp_cost
  get_address_cost (bool symbol_present, bool var_present,
  		  unsigned HOST_WIDE_INT offset, HOST_WIDE_INT ratio,
! 		  enum machine_mode mem_mode,
  		  bool speed)
  {
!   static bool initialized[MAX_MACHINE_MODE];
!   static HOST_WIDE_INT rat[MAX_MACHINE_MODE], off[MAX_MACHINE_MODE];
!   static HOST_WIDE_INT min_offset[MAX_MACHINE_MODE], max_offset[MAX_MACHINE_MODE];
!   static unsigned costs[MAX_MACHINE_MODE][2][2][2][2];
    unsigned cost, acost, complexity;
    bool offset_p, ratio_p;
    HOST_WIDE_INT s_offset;
    unsigned HOST_WIDE_INT mask;
    unsigned bits;
  
!   if (!initialized[mem_mode])
      {
        HOST_WIDE_INT i;
        HOST_WIDE_INT start = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
        int old_cse_not_expected;
        unsigned sym_p, var_p, off_p, rat_p, add_c;
        rtx seq, addr, base;
        rtx reg0, reg1;
  
!       initialized[mem_mode] = true;
  
!       reg1 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
  
!       addr = gen_rtx_fmt_ee (PLUS, Pmode, reg1, NULL_RTX);
        for (i = start; i <= 1 << 20; i <<= 1)
  	{
! 	  XEXP (addr, 1) = gen_int_mode (i, Pmode);
! 	  if (!memory_address_p (mem_mode, addr))
  	    break;
  	}
!       max_offset[mem_mode] = i == start ? 0 : i >> 1;
!       off[mem_mode] = max_offset[mem_mode];
  
        for (i = start; i <= 1 << 20; i <<= 1)
  	{
! 	  XEXP (addr, 1) = gen_int_mode (-i, Pmode);
! 	  if (!memory_address_p (mem_mode, addr))
  	    break;
  	}
!       min_offset[mem_mode] = i == start ? 0 : -(i >> 1);
  
        if (dump_file && (dump_flags & TDF_DETAILS))
  	{
  	  fprintf (dump_file, "get_address_cost:\n");
  	  fprintf (dump_file, "  min offset %s %d\n",
  		   GET_MODE_NAME (mem_mode),
! 		   (int) min_offset[mem_mode]);
  	  fprintf (dump_file, "  max offset %s %d\n",
  		   GET_MODE_NAME (mem_mode),
! 		   (int) max_offset[mem_mode]);
  	}
  
!       rat[mem_mode] = 1;
        for (i = 2; i <= MAX_RATIO; i++)
! 	if (multiplier_allowed_in_address_p (i, mem_mode))
  	  {
! 	    rat[mem_mode] = i;
  	    break;
  	  }
  
        /* Compute the cost of various addressing modes.  */
        acost = 0;
!       reg0 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
!       reg1 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 2);
  
        for (i = 0; i < 16; i++)
  	{
--- 2970,3122 ----
  }
  
  /* Returns true if multiplying by RATIO is allowed in an address.  Test the
!    validity for a memory reference accessing memory of mode MODE in
!    address space AS.  */
! 
! DEF_VEC_P (sbitmap);
! DEF_VEC_ALLOC_P (sbitmap, heap);
  
  bool
! multiplier_allowed_in_address_p (HOST_WIDE_INT ratio, enum machine_mode mode,
! 				 addr_space_t as)
  {
  #define MAX_RATIO 128
!   unsigned int data_index = (int) as * MAX_MACHINE_MODE + (int) mode;
!   static VEC (sbitmap, heap) *valid_mult_list;
!   sbitmap valid_mult;
!  
!   if (data_index >= VEC_length (sbitmap, valid_mult_list))
!     VEC_safe_grow_cleared (sbitmap, heap, valid_mult_list, data_index + 1);
! 
!   valid_mult = VEC_index (sbitmap, valid_mult_list, data_index);
!   if (!valid_mult)
      {
!       enum machine_mode address_mode = targetm.addr_space.address_mode (as);
!       rtx reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
        rtx addr;
        HOST_WIDE_INT i;
  
!       valid_mult = sbitmap_alloc (2 * MAX_RATIO + 1);
!       sbitmap_zero (valid_mult);
!       addr = gen_rtx_fmt_ee (MULT, address_mode, reg1, NULL_RTX);
        for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
  	{
! 	  XEXP (addr, 1) = gen_int_mode (i, address_mode);
! 	  if (memory_address_addr_space_p (mode, addr, as))
! 	    SET_BIT (valid_mult, i + MAX_RATIO);
  	}
  
        if (dump_file && (dump_flags & TDF_DETAILS))
  	{
  	  fprintf (dump_file, "  allowed multipliers:");
  	  for (i = -MAX_RATIO; i <= MAX_RATIO; i++)
! 	    if (TEST_BIT (valid_mult, i + MAX_RATIO))
  	      fprintf (dump_file, " %d", (int) i);
  	  fprintf (dump_file, "\n");
  	  fprintf (dump_file, "\n");
  	}
+ 
+       VEC_replace (sbitmap, valid_mult_list, data_index, valid_mult);
      }
  
    if (ratio > MAX_RATIO || ratio < -MAX_RATIO)
      return false;
  
!   return TEST_BIT (valid_mult, ratio + MAX_RATIO);
  }
  
  /* Returns cost of address in shape symbol + var + OFFSET + RATIO * index.
     If SYMBOL_PRESENT is false, symbol is omitted.  If VAR_PRESENT is false,
     variable is omitted.  Compute the cost for a memory reference that accesses
!    a memory location of mode MEM_MODE in address space AS.
  
     TODO -- there must be some better way.  This all is quite crude.  */
  
+ typedef struct
+ {
+   HOST_WIDE_INT min_offset, max_offset;
+   unsigned costs[2][2][2][2];
+ } *address_cost_data;
+ 
+ DEF_VEC_P (address_cost_data);
+ DEF_VEC_ALLOC_P (address_cost_data, heap);
+ 
  static comp_cost
  get_address_cost (bool symbol_present, bool var_present,
  		  unsigned HOST_WIDE_INT offset, HOST_WIDE_INT ratio,
! 		  enum machine_mode mem_mode, addr_space_t as,
  		  bool speed)
  {
!   enum machine_mode address_mode = targetm.addr_space.address_mode (as);
!   static VEC(address_cost_data, heap) *address_cost_data_list;
!   unsigned int data_index = (int) as * MAX_MACHINE_MODE + (int) mem_mode;
!   address_cost_data data;
    unsigned cost, acost, complexity;
    bool offset_p, ratio_p;
    HOST_WIDE_INT s_offset;
    unsigned HOST_WIDE_INT mask;
    unsigned bits;
  
!   if (data_index >= VEC_length (address_cost_data, address_cost_data_list))
!     VEC_safe_grow_cleared (address_cost_data, heap, address_cost_data_list,
! 			   data_index + 1);
! 
!   data = VEC_index (address_cost_data, address_cost_data_list, data_index);
!   if (!data)
      {
        HOST_WIDE_INT i;
        HOST_WIDE_INT start = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
+       HOST_WIDE_INT rat, off;
        int old_cse_not_expected;
        unsigned sym_p, var_p, off_p, rat_p, add_c;
        rtx seq, addr, base;
        rtx reg0, reg1;
  
!       data = (address_cost_data) xcalloc (1, sizeof (*data));
  
!       reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
  
!       addr = gen_rtx_fmt_ee (PLUS, address_mode, reg1, NULL_RTX);
        for (i = start; i <= 1 << 20; i <<= 1)
  	{
! 	  XEXP (addr, 1) = gen_int_mode (i, address_mode);
! 	  if (!memory_address_addr_space_p (mem_mode, addr, as))
  	    break;
  	}
!       data->max_offset = i == start ? 0 : i >> 1;
!       off = data->max_offset;
  
        for (i = start; i <= 1 << 20; i <<= 1)
  	{
! 	  XEXP (addr, 1) = gen_int_mode (-i, address_mode);
! 	  if (!memory_address_addr_space_p (mem_mode, addr, as))
  	    break;
  	}
!       data->min_offset = i == start ? 0 : -(i >> 1);
  
        if (dump_file && (dump_flags & TDF_DETAILS))
  	{
  	  fprintf (dump_file, "get_address_cost:\n");
  	  fprintf (dump_file, "  min offset %s %d\n",
  		   GET_MODE_NAME (mem_mode),
! 		   (int) data->min_offset);
  	  fprintf (dump_file, "  max offset %s %d\n",
  		   GET_MODE_NAME (mem_mode),
! 		   (int) data->max_offset);
  	}
  
!       rat = 1;
        for (i = 2; i <= MAX_RATIO; i++)
! 	if (multiplier_allowed_in_address_p (i, mem_mode, as))
  	  {
! 	    rat = i;
  	    break;
  	  }
  
        /* Compute the cost of various addressing modes.  */
        acost = 0;
!       reg0 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
!       reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2);
  
        for (i = 0; i < 16; i++)
  	{
*************** get_address_cost (bool symbol_present, b
*** 3093,3107 ****
  
  	  addr = reg0;
  	  if (rat_p)
! 	    addr = gen_rtx_fmt_ee (MULT, Pmode, addr,
! 				   gen_int_mode (rat[mem_mode], Pmode));
  
  	  if (var_p)
! 	    addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, reg1);
  
  	  if (sym_p)
  	    {
! 	      base = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (""));
  	      /* ??? We can run into trouble with some backends by presenting
  		 it with symbols which haven't been properly passed through
  		 targetm.encode_section_info.  By setting the local bit, we
--- 3127,3141 ----
  
  	  addr = reg0;
  	  if (rat_p)
! 	    addr = gen_rtx_fmt_ee (MULT, address_mode, addr,
! 				   gen_int_mode (rat, address_mode));
  
  	  if (var_p)
! 	    addr = gen_rtx_fmt_ee (PLUS, address_mode, addr, reg1);
  
  	  if (sym_p)
  	    {
! 	      base = gen_rtx_SYMBOL_REF (address_mode, ggc_strdup (""));
  	      /* ??? We can run into trouble with some backends by presenting
  		 it with symbols which haven't been properly passed through
  		 targetm.encode_section_info.  By setting the local bit, we
*************** get_address_cost (bool symbol_present, b
*** 3109,3144 ****
  	      SYMBOL_REF_FLAGS (base) = SYMBOL_FLAG_LOCAL;
  
  	      if (off_p)
! 		base = gen_rtx_fmt_e (CONST, Pmode,
! 				      gen_rtx_fmt_ee (PLUS, Pmode,
! 						      base,
! 						      gen_int_mode (off[mem_mode],
! 								    Pmode)));
  	    }
  	  else if (off_p)
! 	    base = gen_int_mode (off[mem_mode], Pmode);
  	  else
  	    base = NULL_RTX;
      
  	  if (base)
! 	    addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, base);
    
  	  start_sequence ();
  	  /* To avoid splitting addressing modes, pretend that no cse will
  	     follow.  */
  	  old_cse_not_expected = cse_not_expected;
  	  cse_not_expected = true;
! 	  addr = memory_address (mem_mode, addr);
  	  cse_not_expected = old_cse_not_expected;
  	  seq = get_insns ();
  	  end_sequence ();
  
  	  acost = seq_cost (seq, speed);
! 	  acost += address_cost (addr, mem_mode, speed);
  
  	  if (!acost)
  	    acost = 1;
! 	  costs[mem_mode][sym_p][var_p][off_p][rat_p] = acost;
  	}
  
        /* On some targets, it is quite expensive to load symbol to a register,
--- 3143,3177 ----
  	      SYMBOL_REF_FLAGS (base) = SYMBOL_FLAG_LOCAL;
  
  	      if (off_p)
! 		base = gen_rtx_fmt_e (CONST, address_mode,
! 				      gen_rtx_fmt_ee
! 					(PLUS, address_mode, base,
! 					 gen_int_mode (off, address_mode)));
  	    }
  	  else if (off_p)
! 	    base = gen_int_mode (off, address_mode);
  	  else
  	    base = NULL_RTX;
      
  	  if (base)
! 	    addr = gen_rtx_fmt_ee (PLUS, address_mode, addr, base);
    
  	  start_sequence ();
  	  /* To avoid splitting addressing modes, pretend that no cse will
  	     follow.  */
  	  old_cse_not_expected = cse_not_expected;
  	  cse_not_expected = true;
! 	  addr = memory_address_addr_space (mem_mode, addr, as);
  	  cse_not_expected = old_cse_not_expected;
  	  seq = get_insns ();
  	  end_sequence ();
  
  	  acost = seq_cost (seq, speed);
! 	  acost += address_cost (addr, mem_mode, as, speed);
  
  	  if (!acost)
  	    acost = 1;
! 	  data->costs[sym_p][var_p][off_p][rat_p] = acost;
  	}
  
        /* On some targets, it is quite expensive to load symbol to a register,
*************** get_address_cost (bool symbol_present, b
*** 3153,3171 ****
  	 If VAR_PRESENT is true, try whether the mode with
  	 SYMBOL_PRESENT = false is cheaper even with cost of addition, and
  	 if this is the case, use it.  */
!       add_c = add_cost (Pmode, speed);
        for (i = 0; i < 8; i++)
  	{
  	  var_p = i & 1;
  	  off_p = (i >> 1) & 1;
  	  rat_p = (i >> 2) & 1;
  
! 	  acost = costs[mem_mode][0][1][off_p][rat_p] + 1;
  	  if (var_p)
  	    acost += add_c;
  
! 	  if (acost < costs[mem_mode][1][var_p][off_p][rat_p])
! 	    costs[mem_mode][1][var_p][off_p][rat_p] = acost;
  	}
    
        if (dump_file && (dump_flags & TDF_DETAILS))
--- 3186,3204 ----
  	 If VAR_PRESENT is true, try whether the mode with
  	 SYMBOL_PRESENT = false is cheaper even with cost of addition, and
  	 if this is the case, use it.  */
!       add_c = add_cost (address_mode, speed);
        for (i = 0; i < 8; i++)
  	{
  	  var_p = i & 1;
  	  off_p = (i >> 1) & 1;
  	  rat_p = (i >> 2) & 1;
  
! 	  acost = data->costs[0][1][off_p][rat_p] + 1;
  	  if (var_p)
  	    acost += add_c;
  
! 	  if (acost < data->costs[1][var_p][off_p][rat_p])
! 	    data->costs[1][var_p][off_p][rat_p] = acost;
  	}
    
        if (dump_file && (dump_flags & TDF_DETAILS))
*************** get_address_cost (bool symbol_present, b
*** 3189,3202 ****
  	      if (rat_p)
  		fprintf (dump_file, "rat * ");
  
! 	      acost = costs[mem_mode][sym_p][var_p][off_p][rat_p];
  	      fprintf (dump_file, "index costs %d\n", acost);
  	    }
  	  fprintf (dump_file, "\n");
  	}
      }
  
!   bits = GET_MODE_BITSIZE (Pmode);
    mask = ~(~(unsigned HOST_WIDE_INT) 0 << (bits - 1) << 1);
    offset &= mask;
    if ((offset >> (bits - 1) & 1))
--- 3222,3238 ----
  	      if (rat_p)
  		fprintf (dump_file, "rat * ");
  
! 	      acost = data->costs[sym_p][var_p][off_p][rat_p];
  	      fprintf (dump_file, "index costs %d\n", acost);
  	    }
  	  fprintf (dump_file, "\n");
  	}
+ 
+       VEC_replace (address_cost_data, address_cost_data_list,
+ 		   data_index, data);
      }
  
!   bits = GET_MODE_BITSIZE (address_mode);
    mask = ~(~(unsigned HOST_WIDE_INT) 0 << (bits - 1) << 1);
    offset &= mask;
    if ((offset >> (bits - 1) & 1))
*************** get_address_cost (bool symbol_present, b
*** 3205,3222 ****
  
    cost = 0;
    offset_p = (s_offset != 0
! 	      && min_offset[mem_mode] <= s_offset
! 	      && s_offset <= max_offset[mem_mode]);
    ratio_p = (ratio != 1
! 	     && multiplier_allowed_in_address_p (ratio, mem_mode));
  
    if (ratio != 1 && !ratio_p)
!     cost += multiply_by_cost (ratio, Pmode, speed);
  
    if (s_offset && !offset_p && !symbol_present)
!     cost += add_cost (Pmode, speed);
  
!   acost = costs[mem_mode][symbol_present][var_present][offset_p][ratio_p];
    complexity = (symbol_present != 0) + (var_present != 0) + offset_p + ratio_p;
    return new_cost (cost + acost, complexity);
  }
--- 3241,3258 ----
  
    cost = 0;
    offset_p = (s_offset != 0
! 	      && data->min_offset <= s_offset
! 	      && s_offset <= data->max_offset);
    ratio_p = (ratio != 1
! 	     && multiplier_allowed_in_address_p (ratio, mem_mode, as));
  
    if (ratio != 1 && !ratio_p)
!     cost += multiply_by_cost (ratio, address_mode, speed);
  
    if (s_offset && !offset_p && !symbol_present)
!     cost += add_cost (address_mode, speed);
  
!   acost = data->costs[symbol_present][var_present][offset_p][ratio_p];
    complexity = (symbol_present != 0) + (var_present != 0) + offset_p + ratio_p;
    return new_cost (cost + acost, complexity);
  }
*************** get_computation_cost_at (struct ivopts_d
*** 3633,3640 ****
      }
    else if (address_p
  	   && !POINTER_TYPE_P (ctype)
! 	   && multiplier_allowed_in_address_p (ratio,
! 					       TYPE_MODE (TREE_TYPE (utype))))
      {
        cbase
  	= fold_build2 (MULT_EXPR, ctype, cbase, build_int_cst (ctype, ratio));
--- 3669,3677 ----
      }
    else if (address_p
  	   && !POINTER_TYPE_P (ctype)
! 	   && multiplier_allowed_in_address_p
! 		(ratio, TYPE_MODE (TREE_TYPE (utype)),
! 			TYPE_ADDR_SPACE (TREE_TYPE (utype))))
      {
        cbase
  	= fold_build2 (MULT_EXPR, ctype, cbase, build_int_cst (ctype, ratio));
*************** get_computation_cost_at (struct ivopts_d
*** 3666,3672 ****
      return add_costs (cost,
  		      get_address_cost (symbol_present, var_present,
  					offset, ratio,
! 					TYPE_MODE (TREE_TYPE (utype)), speed));
  
    /* Otherwise estimate the costs for computing the expression.  */
    if (!symbol_present && !var_present && !offset)
--- 3703,3711 ----
      return add_costs (cost,
  		      get_address_cost (symbol_present, var_present,
  					offset, ratio,
! 					TYPE_MODE (TREE_TYPE (utype)),
! 					TYPE_ADDR_SPACE (TREE_TYPE (utype)),
! 					speed));
  
    /* Otherwise estimate the costs for computing the expression.  */
    if (!symbol_present && !var_present && !offset)
Index: gcc/ifcvt.c
===================================================================
*** gcc/ifcvt.c	(revision 150188)
--- gcc/ifcvt.c	(working copy)
*************** noce_try_cmove_arith (struct noce_if_inf
*** 1328,1338 ****
    /* ??? FIXME: Magic number 5.  */
    if (cse_not_expected
        && MEM_P (a) && MEM_P (b)
        && if_info->branch_cost >= 5)
      {
        a = XEXP (a, 0);
        b = XEXP (b, 0);
!       x = gen_reg_rtx (Pmode);
        is_mem = 1;
      }
  
--- 1328,1342 ----
    /* ??? FIXME: Magic number 5.  */
    if (cse_not_expected
        && MEM_P (a) && MEM_P (b)
+       && MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b)
        && if_info->branch_cost >= 5)
      {
+       enum machine_mode address_mode
+ 	= targetm.addr_space.address_mode (MEM_ADDR_SPACE (a));
+ 
        a = XEXP (a, 0);
        b = XEXP (b, 0);
!       x = gen_reg_rtx (address_mode);
        is_mem = 1;
      }
  
Index: gcc/expr.c
===================================================================
*** gcc/expr.c	(revision 150758)
--- gcc/expr.c	(working copy)
*************** move_by_pieces (rtx to, rtx from, unsign
*** 877,882 ****
--- 877,884 ----
  		unsigned int align, int endp)
  {
    struct move_by_pieces_d data;
+   enum machine_mode to_addr_mode, from_addr_mode
+     = targetm.addr_space.address_mode (MEM_ADDR_SPACE (from));
    rtx to_addr, from_addr = XEXP (from, 0);
    unsigned int max_size = MOVE_MAX_PIECES + 1;
    enum machine_mode mode = VOIDmode, tmode;
*************** move_by_pieces (rtx to, rtx from, unsign
*** 888,893 ****
--- 890,896 ----
    data.from_addr = from_addr;
    if (to)
      {
+       to_addr_mode = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to));
        to_addr = XEXP (to, 0);
        data.to = to;
        data.autinc_to
*************** move_by_pieces (rtx to, rtx from, unsign
*** 898,903 ****
--- 901,907 ----
      }
    else
      {
+       to_addr_mode = VOIDmode;
        to_addr = NULL_RTX;
        data.to = NULL_RTX;
        data.autinc_to = 1;
*************** move_by_pieces (rtx to, rtx from, unsign
*** 933,964 ****
  
        if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
  	{
! 	  data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
  	  data.autinc_from = 1;
  	  data.explicit_inc_from = -1;
  	}
        if (USE_LOAD_POST_INCREMENT (mode) && ! data.autinc_from)
  	{
! 	  data.from_addr = copy_addr_to_reg (from_addr);
  	  data.autinc_from = 1;
  	  data.explicit_inc_from = 1;
  	}
        if (!data.autinc_from && CONSTANT_P (from_addr))
! 	data.from_addr = copy_addr_to_reg (from_addr);
        if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
  	{
! 	  data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
  	  data.autinc_to = 1;
  	  data.explicit_inc_to = -1;
  	}
        if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
  	{
! 	  data.to_addr = copy_addr_to_reg (to_addr);
  	  data.autinc_to = 1;
  	  data.explicit_inc_to = 1;
  	}
        if (!data.autinc_to && CONSTANT_P (to_addr))
! 	data.to_addr = copy_addr_to_reg (to_addr);
      }
  
    tmode = mode_for_size (MOVE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
--- 937,970 ----
  
        if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
  	{
! 	  data.from_addr = copy_to_mode_reg (from_addr_mode,
! 					     plus_constant (from_addr, len));
  	  data.autinc_from = 1;
  	  data.explicit_inc_from = -1;
  	}
        if (USE_LOAD_POST_INCREMENT (mode) && ! data.autinc_from)
  	{
! 	  data.from_addr = copy_to_mode_reg (from_addr_mode, from_addr);
  	  data.autinc_from = 1;
  	  data.explicit_inc_from = 1;
  	}
        if (!data.autinc_from && CONSTANT_P (from_addr))
! 	data.from_addr = copy_to_mode_reg (from_addr_mode, from_addr);
        if (USE_STORE_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_to)
  	{
! 	  data.to_addr = copy_to_mode_reg (to_addr_mode,
! 					   plus_constant (to_addr, len));
  	  data.autinc_to = 1;
  	  data.explicit_inc_to = -1;
  	}
        if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
  	{
! 	  data.to_addr = copy_to_mode_reg (to_addr_mode, to_addr);
  	  data.autinc_to = 1;
  	  data.explicit_inc_to = 1;
  	}
        if (!data.autinc_to && CONSTANT_P (to_addr))
! 	data.to_addr = copy_to_mode_reg (to_addr_mode, to_addr);
      }
  
    tmode = mode_for_size (MOVE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
*************** move_by_pieces (rtx to, rtx from, unsign
*** 1013,1019 ****
  	      if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
  		emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
  	      else
! 		data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
  								-1));
  	    }
  	  to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
--- 1019,1026 ----
  	      if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
  		emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
  	      else
! 		data.to_addr = copy_to_mode_reg (to_addr_mode,
! 						 plus_constant (data.to_addr,
  								-1));
  	    }
  	  to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
*************** emit_block_move_hints (rtx x, rtx y, rtx
*** 1215,1221 ****
    else if (emit_block_move_via_movmem (x, y, size, align,
  				       expected_align, expected_size))
      ;
!   else if (may_use_call)
      retval = emit_block_move_via_libcall (x, y, size,
  					  method == BLOCK_OP_TAILCALL);
    else
--- 1222,1229 ----
    else if (emit_block_move_via_movmem (x, y, size, align,
  				       expected_align, expected_size))
      ;
!   else if (may_use_call
! 	   && MEM_ADDR_SPACE (x) == 0 && MEM_ADDR_SPACE (y) == 0)
      retval = emit_block_move_via_libcall (x, y, size,
  					  method == BLOCK_OP_TAILCALL);
    else
*************** emit_block_move_via_loop (rtx x, rtx y, 
*** 1466,1471 ****
--- 1474,1483 ----
  			  unsigned int align ATTRIBUTE_UNUSED)
  {
    rtx cmp_label, top_label, iter, x_addr, y_addr, tmp;
+   enum machine_mode x_addr_mode
+     = targetm.addr_space.address_mode (MEM_ADDR_SPACE (x));
+   enum machine_mode y_addr_mode
+     = targetm.addr_space.address_mode (MEM_ADDR_SPACE (y));
    enum machine_mode iter_mode;
  
    iter_mode = GET_MODE (size);
*************** emit_block_move_via_loop (rtx x, rtx y, 
*** 1485,1493 ****
    emit_jump (cmp_label);
    emit_label (top_label);
  
!   tmp = convert_modes (Pmode, iter_mode, iter, true);
!   x_addr = gen_rtx_PLUS (Pmode, x_addr, tmp);
!   y_addr = gen_rtx_PLUS (Pmode, y_addr, tmp);
    x = change_address (x, QImode, x_addr);
    y = change_address (y, QImode, y_addr);
  
--- 1497,1509 ----
    emit_jump (cmp_label);
    emit_label (top_label);
  
!   tmp = convert_modes (x_addr_mode, iter_mode, iter, true);
!   x_addr = gen_rtx_PLUS (x_addr_mode, x_addr, tmp);
! 
!   if (x_addr_mode != y_addr_mode)
!     tmp = convert_modes (y_addr_mode, iter_mode, iter, true);
!   y_addr = gen_rtx_PLUS (y_addr_mode, y_addr, tmp);
! 
    x = change_address (x, QImode, x_addr);
    y = change_address (y, QImode, y_addr);
  
*************** store_by_pieces (rtx to, unsigned HOST_W
*** 2382,2387 ****
--- 2398,2405 ----
  		 rtx (*constfun) (void *, HOST_WIDE_INT, enum machine_mode),
  		 void *constfundata, unsigned int align, bool memsetp, int endp)
  {
+   enum machine_mode to_addr_mode
+     = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to));
    struct store_by_pieces_d data;
  
    if (len == 0)
*************** store_by_pieces (rtx to, unsigned HOST_W
*** 2410,2416 ****
  	      if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
  		emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
  	      else
! 		data.to_addr = copy_addr_to_reg (plus_constant (data.to_addr,
  								-1));
  	    }
  	  to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
--- 2428,2435 ----
  	      if (HAVE_POST_INCREMENT && data.explicit_inc_to > 0)
  		emit_insn (gen_add2_insn (data.to_addr, constm1_rtx));
  	      else
! 		data.to_addr = copy_to_mode_reg (to_addr_mode,
! 						 plus_constant (data.to_addr,
  								-1));
  	    }
  	  to1 = adjust_automodify_address (data.to, QImode, data.to_addr,
*************** static void
*** 2465,2470 ****
--- 2484,2491 ----
  store_by_pieces_1 (struct store_by_pieces_d *data ATTRIBUTE_UNUSED,
  		   unsigned int align ATTRIBUTE_UNUSED)
  {
+   enum machine_mode to_addr_mode
+     = targetm.addr_space.address_mode (MEM_ADDR_SPACE (data->to));
    rtx to_addr = XEXP (data->to, 0);
    unsigned int max_size = STORE_MAX_PIECES + 1;
    enum machine_mode mode = VOIDmode, tmode;
*************** store_by_pieces_1 (struct store_by_piece
*** 2496,2502 ****
  
        if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
  	{
! 	  data->to_addr = copy_addr_to_reg (plus_constant (to_addr, data->len));
  	  data->autinc_to = 1;
  	  data->explicit_inc_to = -1;
  	}
--- 2517,2524 ----
  
        if (USE_STORE_PRE_DECREMENT (mode) && data->reverse && ! data->autinc_to)
  	{
! 	  data->to_addr = copy_to_mode_reg (to_addr_mode,
! 					    plus_constant (to_addr, data->len));
  	  data->autinc_to = 1;
  	  data->explicit_inc_to = -1;
  	}
*************** store_by_pieces_1 (struct store_by_piece
*** 2504,2516 ****
        if (USE_STORE_POST_INCREMENT (mode) && ! data->reverse
  	  && ! data->autinc_to)
  	{
! 	  data->to_addr = copy_addr_to_reg (to_addr);
  	  data->autinc_to = 1;
  	  data->explicit_inc_to = 1;
  	}
  
        if ( !data->autinc_to && CONSTANT_P (to_addr))
! 	data->to_addr = copy_addr_to_reg (to_addr);
      }
  
    tmode = mode_for_size (STORE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
--- 2526,2538 ----
        if (USE_STORE_POST_INCREMENT (mode) && ! data->reverse
  	  && ! data->autinc_to)
  	{
! 	  data->to_addr = copy_to_mode_reg (to_addr_mode, to_addr);
  	  data->autinc_to = 1;
  	  data->explicit_inc_to = 1;
  	}
  
        if ( !data->autinc_to && CONSTANT_P (to_addr))
! 	data->to_addr = copy_to_mode_reg (to_addr_mode, to_addr);
      }
  
    tmode = mode_for_size (STORE_MAX_PIECES * BITS_PER_UNIT, MODE_INT, 1);
*************** clear_storage_hints (rtx object, rtx siz
*** 2641,2649 ****
    else if (set_storage_via_setmem (object, size, const0_rtx, align,
  				   expected_align, expected_size))
      ;
!   else
      return set_storage_via_libcall (object, size, const0_rtx,
  				    method == BLOCK_OP_TAILCALL);
  
    return NULL;
  }
--- 2663,2673 ----
    else if (set_storage_via_setmem (object, size, const0_rtx, align,
  				   expected_align, expected_size))
      ;
!   else if (MEM_ADDR_SPACE (object) == 0)
      return set_storage_via_libcall (object, size, const0_rtx,
  				    method == BLOCK_OP_TAILCALL);
+   else
+     gcc_unreachable ();
  
    return NULL;
  }
*************** expand_assignment (tree to, tree from, b
*** 4210,4215 ****
--- 4234,4240 ----
  
        if (offset != 0)
  	{
+ 	  enum machine_mode address_mode;
  	  rtx offset_rtx;
  
  	  if (!MEM_P (to_rtx))
*************** expand_assignment (tree to, tree from, b
*** 4222,4234 ****
  	    }
  
  	  offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
! #ifdef POINTERS_EXTEND_UNSIGNED
! 	  if (GET_MODE (offset_rtx) != Pmode)
! 	    offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
! #else
! 	  if (GET_MODE (offset_rtx) != ptr_mode)
! 	    offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
! #endif
  
  	  /* A constant address in TO_RTX can have VOIDmode, we must not try
  	     to call force_reg for that case.  Avoid that case.  */
--- 4247,4256 ----
  	    }
  
  	  offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
! 	  address_mode
! 	    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to_rtx));
! 	  if (GET_MODE (offset_rtx) != address_mode)
! 	    offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
  
  	  /* A constant address in TO_RTX can have VOIDmode, we must not try
  	     to call force_reg for that case.  Avoid that case.  */
*************** expand_assignment (tree to, tree from, b
*** 4367,4373 ****
        else
  	{
  	  if (POINTER_TYPE_P (TREE_TYPE (to)))
! 	    value = convert_memory_address (GET_MODE (to_rtx), value);
  	  emit_move_insn (to_rtx, value);
  	}
        preserve_temp_slots (to_rtx);
--- 4389,4398 ----
        else
  	{
  	  if (POINTER_TYPE_P (TREE_TYPE (to)))
! 	    value = convert_memory_address_addr_space
! 		      (GET_MODE (to_rtx), value,
! 		       TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (to))));
! 
  	  emit_move_insn (to_rtx, value);
  	}
        preserve_temp_slots (to_rtx);
*************** store_expr (tree exp, rtx target, int ca
*** 4748,4753 ****
--- 4773,4783 ----
  			      ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
  	  else
  	    {
+ 	      enum machine_mode pointer_mode
+ 		= targetm.addr_space.pointer_mode (MEM_ADDR_SPACE (target));
+ 	      enum machine_mode address_mode
+ 		= targetm.addr_space.address_mode (MEM_ADDR_SPACE (target));
+ 
  	      /* Compute the size of the data to copy from the string.  */
  	      tree copy_size
  		= size_binop_loc (loc, MIN_EXPR,
*************** store_expr (tree exp, rtx target, int ca
*** 4760,4773 ****
  	      rtx label = 0;
  
  	      /* Copy that much.  */
! 	      copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx,
  					       TYPE_UNSIGNED (sizetype));
  	      emit_block_move (target, temp, copy_size_rtx,
  			       (call_param_p
  				? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
  
  	      /* Figure out how much is left in TARGET that we have to clear.
! 		 Do all calculations in ptr_mode.  */
  	      if (CONST_INT_P (copy_size_rtx))
  		{
  		  size = plus_constant (size, -INTVAL (copy_size_rtx));
--- 4790,4803 ----
  	      rtx label = 0;
  
  	      /* Copy that much.  */
! 	      copy_size_rtx = convert_to_mode (pointer_mode, copy_size_rtx,
  					       TYPE_UNSIGNED (sizetype));
  	      emit_block_move (target, temp, copy_size_rtx,
  			       (call_param_p
  				? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL));
  
  	      /* Figure out how much is left in TARGET that we have to clear.
! 		 Do all calculations in pointer_mode.  */
  	      if (CONST_INT_P (copy_size_rtx))
  		{
  		  size = plus_constant (size, -INTVAL (copy_size_rtx));
*************** store_expr (tree exp, rtx target, int ca
*** 4780,4790 ****
  				       copy_size_rtx, NULL_RTX, 0,
  				       OPTAB_LIB_WIDEN);
  
! #ifdef POINTERS_EXTEND_UNSIGNED
! 		  if (GET_MODE (copy_size_rtx) != Pmode)
! 		    copy_size_rtx = convert_to_mode (Pmode, copy_size_rtx,
  						     TYPE_UNSIGNED (sizetype));
- #endif
  
  		  target = offset_address (target, copy_size_rtx,
  					   highest_pow2_factor (copy_size));
--- 4810,4819 ----
  				       copy_size_rtx, NULL_RTX, 0,
  				       OPTAB_LIB_WIDEN);
  
! 		  if (GET_MODE (copy_size_rtx) != address_mode)
! 		    copy_size_rtx = convert_to_mode (address_mode,
! 						     copy_size_rtx,
  						     TYPE_UNSIGNED (sizetype));
  
  		  target = offset_address (target, copy_size_rtx,
  					   highest_pow2_factor (copy_size));
*************** store_constructor (tree exp, rtx target,
*** 5274,5279 ****
--- 5303,5309 ----
  
  	    if (offset)
  	      {
+ 	        enum machine_mode address_mode;
  		rtx offset_rtx;
  
  		offset
*************** store_constructor (tree exp, rtx target,
*** 5284,5296 ****
  		offset_rtx = expand_normal (offset);
  		gcc_assert (MEM_P (to_rtx));
  
! #ifdef POINTERS_EXTEND_UNSIGNED
! 		if (GET_MODE (offset_rtx) != Pmode)
! 		  offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
! #else
! 		if (GET_MODE (offset_rtx) != ptr_mode)
! 		  offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
! #endif
  
  		to_rtx = offset_address (to_rtx, offset_rtx,
  					 highest_pow2_factor (offset));
--- 5314,5323 ----
  		offset_rtx = expand_normal (offset);
  		gcc_assert (MEM_P (to_rtx));
  
! 		address_mode
! 		  = targetm.addr_space.address_mode (MEM_ADDR_SPACE (to_rtx));
! 		if (GET_MODE (offset_rtx) != address_mode)
! 		  offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
  
  		to_rtx = offset_address (to_rtx, offset_rtx,
  					 highest_pow2_factor (offset));
*************** expand_expr_constant (tree exp, int defe
*** 6819,6825 ****
  
  static rtx
  expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
! 		         enum expand_modifier modifier)
  {
    rtx result, subtarget;
    tree inner, offset;
--- 6846,6852 ----
  
  static rtx
  expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
! 		         enum expand_modifier modifier, addr_space_t as)
  {
    rtx result, subtarget;
    tree inner, offset;
*************** expand_expr_addr_expr_1 (tree exp, rtx t
*** 6846,6852 ****
      case CONST_DECL:
        /* Recurse and make the output_constant_def clause above handle this.  */
        return expand_expr_addr_expr_1 (DECL_INITIAL (exp), target,
! 				      tmode, modifier);
  
      case REALPART_EXPR:
        /* The real part of the complex number is always first, therefore
--- 6873,6879 ----
      case CONST_DECL:
        /* Recurse and make the output_constant_def clause above handle this.  */
        return expand_expr_addr_expr_1 (DECL_INITIAL (exp), target,
! 				      tmode, modifier, as);
  
      case REALPART_EXPR:
        /* The real part of the complex number is always first, therefore
*************** expand_expr_addr_expr_1 (tree exp, rtx t
*** 6936,6942 ****
        TYPE_ALIGN (TREE_TYPE (inner)) = TYPE_ALIGN (TREE_TYPE (exp));
        TYPE_USER_ALIGN (TREE_TYPE (inner)) = 1;
      }
!   result = expand_expr_addr_expr_1 (inner, subtarget, tmode, modifier);
  
    if (offset)
      {
--- 6963,6969 ----
        TYPE_ALIGN (TREE_TYPE (inner)) = TYPE_ALIGN (TREE_TYPE (exp));
        TYPE_USER_ALIGN (TREE_TYPE (inner)) = 1;
      }
!   result = expand_expr_addr_expr_1 (inner, subtarget, tmode, modifier, as);
  
    if (offset)
      {
*************** expand_expr_addr_expr_1 (tree exp, rtx t
*** 6948,6955 ****
  			 modifier == EXPAND_INITIALIZER
  			  ? EXPAND_INITIALIZER : EXPAND_NORMAL);
  
!       result = convert_memory_address (tmode, result);
!       tmp = convert_memory_address (tmode, tmp);
  
        if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
  	result = gen_rtx_PLUS (tmode, result, tmp);
--- 6975,6982 ----
  			 modifier == EXPAND_INITIALIZER
  			  ? EXPAND_INITIALIZER : EXPAND_NORMAL);
  
!       result = convert_memory_address_addr_space (tmode, result, as);
!       tmp = convert_memory_address_addr_space (tmode, tmp, as);
  
        if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
  	result = gen_rtx_PLUS (tmode, result, tmp);
*************** static rtx
*** 6982,6987 ****
--- 7009,7015 ----
  expand_expr_addr_expr (tree exp, rtx target, enum machine_mode tmode,
  		       enum expand_modifier modifier)
  {
+   addr_space_t as = 0;
    enum machine_mode address_mode = Pmode;
    enum machine_mode pointer_mode = ptr_mode;
    enum machine_mode rmode;
*************** expand_expr_addr_expr (tree exp, rtx tar
*** 6993,6999 ****
  
    if (POINTER_TYPE_P (TREE_TYPE (exp)))
      {
!       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)));
        address_mode = targetm.addr_space.address_mode (as);
        pointer_mode = targetm.addr_space.pointer_mode (as);
      }
--- 7021,7027 ----
  
    if (POINTER_TYPE_P (TREE_TYPE (exp)))
      {
!       as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)));
        address_mode = targetm.addr_space.address_mode (as);
        pointer_mode = targetm.addr_space.pointer_mode (as);
      }
*************** expand_expr_addr_expr (tree exp, rtx tar
*** 7005,7011 ****
      tmode = address_mode;
  
    result = expand_expr_addr_expr_1 (TREE_OPERAND (exp, 0), target,
! 				    tmode, modifier);
  
    /* Despite expand_expr claims concerning ignoring TMODE when not
       strictly convenient, stuff breaks if we don't honor it.  Note
--- 7033,7039 ----
      tmode = address_mode;
  
    result = expand_expr_addr_expr_1 (TREE_OPERAND (exp, 0), target,
! 				    tmode, modifier, as);
  
    /* Despite expand_expr claims concerning ignoring TMODE when not
       strictly convenient, stuff breaks if we don't honor it.  Note
*************** expand_expr_addr_expr (tree exp, rtx tar
*** 7014,7020 ****
    if (rmode == VOIDmode)
      rmode = tmode;
    if (rmode != tmode)
!     result = convert_memory_address (tmode, result);
  
    return result;
  }
--- 7042,7048 ----
    if (rmode == VOIDmode)
      rmode = tmode;
    if (rmode != tmode)
!     result = convert_memory_address_addr_space (tmode, result, as);
  
    return result;
  }
*************** expand_expr_real_1 (tree exp, rtx target
*** 7669,7681 ****
  
      case TARGET_MEM_REF:
        {
  	struct mem_address addr;
  
  	get_address_description (exp, &addr);
! 	op0 = addr_for_mem_ref (&addr, true);
! 	op0 = memory_address (mode, op0);
  	temp = gen_rtx_MEM (mode, op0);
  	set_mem_attributes (temp, TMR_ORIGINAL (exp), 0);
        }
        return temp;
  
--- 7697,7711 ----
  
      case TARGET_MEM_REF:
        {
+ 	addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
  	struct mem_address addr;
  
  	get_address_description (exp, &addr);
! 	op0 = addr_for_mem_ref (&addr, as, true);
! 	op0 = memory_address_addr_space (mode, op0, as);
  	temp = gen_rtx_MEM (mode, op0);
  	set_mem_attributes (temp, TMR_ORIGINAL (exp), 0);
+ 	set_mem_addr_space (temp, as);
        }
        return temp;
  
*************** expand_expr_real_1 (tree exp, rtx target
*** 7936,7953 ****
  
  	if (offset)
  	  {
  	    rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
  					  EXPAND_SUM);
  
  	    gcc_assert (MEM_P (op0));
  
! #ifdef POINTERS_EXTEND_UNSIGNED
! 	    if (GET_MODE (offset_rtx) != Pmode)
! 	      offset_rtx = convert_to_mode (Pmode, offset_rtx, 0);
! #else
! 	    if (GET_MODE (offset_rtx) != ptr_mode)
! 	      offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
! #endif
  
  	    if (GET_MODE (op0) == BLKmode
  		/* A constant address in OP0 can have VOIDmode, we must
--- 7966,7981 ----
  
  	if (offset)
  	  {
+ 	    enum machine_mode address_mode;
  	    rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode,
  					  EXPAND_SUM);
  
  	    gcc_assert (MEM_P (op0));
  
! 	    address_mode
! 	      = targetm.addr_space.address_mode (MEM_ADDR_SPACE (op0));
! 	    if (GET_MODE (offset_rtx) != address_mode)
! 	      offset_rtx = convert_to_mode (address_mode, offset_rtx, 0);
  
  	    if (GET_MODE (op0) == BLKmode
  		/* A constant address in OP0 can have VOIDmode, we must
Index: gcc/recog.c
===================================================================
*** gcc/recog.c	(revision 150188)
--- gcc/recog.c	(working copy)
*************** verify_changes (int num)
*** 376,382 ****
  
        if (MEM_P (object))
  	{
! 	  if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
  	    break;
  	}
        else if (REG_P (changes[i].old)
--- 376,384 ----
  
        if (MEM_P (object))
  	{
! 	  if (! memory_address_addr_space_p (GET_MODE (object),
! 					     XEXP (object, 0),
! 					     MEM_ADDR_SPACE (object)))
  	    break;
  	}
        else if (REG_P (changes[i].old)
*************** general_operand (rtx op, enum machine_mo
*** 975,981 ****
  	return 0;
  
        /* Use the mem's mode, since it will be reloaded thus.  */
!       if (memory_address_p (GET_MODE (op), y))
  	return 1;
      }
  
--- 977,983 ----
  	return 0;
  
        /* Use the mem's mode, since it will be reloaded thus.  */
!       if (memory_address_addr_space_p (GET_MODE (op), y, MEM_ADDR_SPACE (op)))
  	return 1;
      }
  
*************** pop_operand (rtx op, enum machine_mode m
*** 1259,1291 ****
    return XEXP (op, 0) == stack_pointer_rtx;
  }
  
! /* Return 1 if ADDR is a valid memory address for mode MODE.  */
  
  int
! memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
  {
  #ifdef GO_IF_LEGITIMATE_ADDRESS
    GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
    return 0;
  
   win:
    return 1;
  #else
!   return targetm.legitimate_address_p (mode, addr, 0);
  #endif
  }
  
- /* Like memory_address_p, expect for a distinct named address space.  */
- 
- int
- memory_address_addr_space_p (enum machine_mode mode, rtx addr, addr_space_t as)
- {
-   if (!as)
-     return memory_address_p (mode, addr);
-   else
-     return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
- }
- 
  /* Return 1 if OP is a valid memory reference with mode MODE,
     including a valid address.
  
--- 1261,1285 ----
    return XEXP (op, 0) == stack_pointer_rtx;
  }
  
! /* Return 1 if ADDR is a valid memory address
!    for mode MODE in address space AS.  */
  
  int
! memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
! 			     rtx addr, addr_space_t as)
  {
  #ifdef GO_IF_LEGITIMATE_ADDRESS
+   gcc_assert (as == 0);
    GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
    return 0;
  
   win:
    return 1;
  #else
!   return targetm.addr_space.legitimate_address_p (mode, addr, 0, as);
  #endif
  }
  
  /* Return 1 if OP is a valid memory reference with mode MODE,
     including a valid address.
  
*************** int
*** 1881,1887 ****
  offsettable_memref_p (rtx op)
  {
    return ((MEM_P (op))
! 	  && offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)));
  }
  
  /* Similar, but don't require a strictly valid mem ref:
--- 1875,1882 ----
  offsettable_memref_p (rtx op)
  {
    return ((MEM_P (op))
! 	  && offsettable_address_addr_space_p (1, GET_MODE (op), XEXP (op, 0),
! 					       MEM_ADDR_SPACE (op)));
  }
  
  /* Similar, but don't require a strictly valid mem ref:
*************** int
*** 1891,1902 ****
  offsettable_nonstrict_memref_p (rtx op)
  {
    return ((MEM_P (op))
! 	  && offsettable_address_p (0, GET_MODE (op), XEXP (op, 0)));
  }
  
  /* Return 1 if Y is a memory address which contains no side effects
!    and would remain valid after the addition of a positive integer
!    less than the size of that mode.
  
     We assume that the original address is valid and do not check it.
     We do check that it is valid for narrower modes.
--- 1886,1898 ----
  offsettable_nonstrict_memref_p (rtx op)
  {
    return ((MEM_P (op))
! 	  && offsettable_address_addr_space_p (0, GET_MODE (op), XEXP (op, 0),
! 					       MEM_ADDR_SPACE (op)));
  }
  
  /* Return 1 if Y is a memory address which contains no side effects
!    and would remain valid for address space AS after the addition of
!    a positive integer less than the size of that mode.
  
     We assume that the original address is valid and do not check it.
     We do check that it is valid for narrower modes.
*************** offsettable_nonstrict_memref_p (rtx op)
*** 1905,1918 ****
     for the sake of use in reload.c.  */
  
  int
! offsettable_address_p (int strictp, enum machine_mode mode, rtx y)
  {
    enum rtx_code ycode = GET_CODE (y);
    rtx z;
    rtx y1 = y;
    rtx *y2;
!   int (*addressp) (enum machine_mode, rtx) =
!     (strictp ? strict_memory_address_p : memory_address_p);
    unsigned int mode_sz = GET_MODE_SIZE (mode);
  
    if (CONSTANT_ADDRESS_P (y))
--- 1901,1916 ----
     for the sake of use in reload.c.  */
  
  int
! offsettable_address_addr_space_p (int strictp, enum machine_mode mode, rtx y,
! 				  addr_space_t as)
  {
    enum rtx_code ycode = GET_CODE (y);
    rtx z;
    rtx y1 = y;
    rtx *y2;
!   int (*addressp) (enum machine_mode, rtx, addr_space_t) =
!     (strictp ? strict_memory_address_addr_space_p
! 	     : memory_address_addr_space_p);
    unsigned int mode_sz = GET_MODE_SIZE (mode);
  
    if (CONSTANT_ADDRESS_P (y))
*************** offsettable_address_p (int strictp, enum
*** 1942,1948 ****
        *y2 = plus_constant (*y2, mode_sz - 1);
        /* Use QImode because an odd displacement may be automatically invalid
  	 for any wider mode.  But it should be valid for a single byte.  */
!       good = (*addressp) (QImode, y);
  
        /* In any case, restore old contents of memory.  */
        *y2 = y1;
--- 1940,1946 ----
        *y2 = plus_constant (*y2, mode_sz - 1);
        /* Use QImode because an odd displacement may be automatically invalid
  	 for any wider mode.  But it should be valid for a single byte.  */
!       good = (*addressp) (QImode, y, as);
  
        /* In any case, restore old contents of memory.  */
        *y2 = y1;
*************** offsettable_address_p (int strictp, enum
*** 1967,1973 ****
  
    /* Use QImode because an odd displacement may be automatically invalid
       for any wider mode.  But it should be valid for a single byte.  */
!   return (*addressp) (QImode, z);
  }
  
  /* Return 1 if ADDR is an address-expression whose effect depends
--- 1965,1971 ----
  
    /* Use QImode because an odd displacement may be automatically invalid
       for any wider mode.  But it should be valid for a single byte.  */
!   return (*addressp) (QImode, z, as);
  }
  
  /* Return 1 if ADDR is an address-expression whose effect depends
*************** constrain_operands (int strict)
*** 2511,2521 ****
  		if (MEM_P (op))
  		  {
  		    if (strict > 0
! 			&& !strict_memory_address_p (GET_MODE (op),
! 						     XEXP (op, 0)))
  		      break;
  		    if (strict == 0
! 			&& !memory_address_p (GET_MODE (op), XEXP (op, 0)))
  		      break;
  		    win = 1;
  		  }
--- 2509,2522 ----
  		if (MEM_P (op))
  		  {
  		    if (strict > 0
! 			&& !strict_memory_address_addr_space_p
! 			     (GET_MODE (op), XEXP (op, 0),
! 			      MEM_ADDR_SPACE (op)))
  		      break;
  		    if (strict == 0
! 			&& !memory_address_addr_space_p
! 			     (GET_MODE (op), XEXP (op, 0),
! 			      MEM_ADDR_SPACE (op)))
  		      break;
  		    win = 1;
  		  }
Index: gcc/recog.h
===================================================================
*** gcc/recog.h	(revision 150188)
--- gcc/recog.h	(working copy)
*************** extern int num_validated_changes (void);
*** 84,94 ****
  extern void cancel_changes (int);
  extern int constrain_operands (int);
  extern int constrain_operands_cached (int);
- extern int memory_address_p (enum machine_mode, rtx);
  extern int memory_address_addr_space_p (enum machine_mode, rtx, addr_space_t);
! extern int strict_memory_address_p (enum machine_mode, rtx);
  extern int strict_memory_address_addr_space_p (enum machine_mode, rtx,
  					       addr_space_t);
  extern int validate_replace_rtx_subexp (rtx, rtx, rtx, rtx *);
  extern int validate_replace_rtx (rtx, rtx, rtx);
  extern int validate_replace_rtx_part (rtx, rtx, rtx *, rtx);
--- 84,96 ----
  extern void cancel_changes (int);
  extern int constrain_operands (int);
  extern int constrain_operands_cached (int);
  extern int memory_address_addr_space_p (enum machine_mode, rtx, addr_space_t);
! #define memory_address_p(mode,addr) \
! 	memory_address_addr_space_p ((mode), (addr), 0)
  extern int strict_memory_address_addr_space_p (enum machine_mode, rtx,
  					       addr_space_t);
+ #define strict_memory_address_p(mode,addr) \
+ 	strict_memory_address_addr_space_p ((mode), (addr), 0)
  extern int validate_replace_rtx_subexp (rtx, rtx, rtx, rtx *);
  extern int validate_replace_rtx (rtx, rtx, rtx);
  extern int validate_replace_rtx_part (rtx, rtx, rtx *, rtx);
*************** extern int reg_fits_class_p (rtx, enum r
*** 104,110 ****
  
  extern int offsettable_memref_p (rtx);
  extern int offsettable_nonstrict_memref_p (rtx);
! extern int offsettable_address_p (int, enum machine_mode, rtx);
  extern int mode_dependent_address_p (rtx);
  
  extern int recog (rtx, rtx, int *);
--- 106,115 ----
  
  extern int offsettable_memref_p (rtx);
  extern int offsettable_nonstrict_memref_p (rtx);
! extern int offsettable_address_addr_space_p (int, enum machine_mode, rtx,
! 					     addr_space_t);
! #define offsettable_address_p(strict,mode,addr) \
! 	offsettable_address_addr_space_p ((strict), (mode), (addr), 0)
  extern int mode_dependent_address_p (rtx);
  
  extern int recog (rtx, rtx, int *);
Index: gcc/tree-ssa-address.c
===================================================================
*** gcc/tree-ssa-address.c	(revision 150188)
--- gcc/tree-ssa-address.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 42,47 ****
--- 42,48 ----
  #include "expr.h"
  #include "ggc.h"
  #include "tree-affine.h"
+ #include "target.h"
  
  /* TODO -- handling of symbols (according to Richard Hendersons
     comments, http://gcc.gnu.org/ml/gcc-patches/2005-04/msg00949.html):
*************** along with GCC; see the file COPYING3.  
*** 70,101 ****
  /* A "template" for memory address, used to determine whether the address is
     valid for mode.  */
  
! struct GTY (()) mem_addr_template {
    rtx ref;			/* The template.  */
    rtx * GTY ((skip)) step_p;	/* The point in template where the step should be
  				   filled in.  */
    rtx * GTY ((skip)) off_p;	/* The point in template where the offset should
  				   be filled in.  */
! };
  
! /* The templates.  Each of the five bits of the index corresponds to one
!    component of TARGET_MEM_REF being present, see TEMPL_IDX.  */
  
! static GTY (()) struct mem_addr_template templates[32];
  
! #define TEMPL_IDX(SYMBOL, BASE, INDEX, STEP, OFFSET) \
!   (((SYMBOL != 0) << 4) \
     | ((BASE != 0) << 3) \
     | ((INDEX != 0) << 2) \
     | ((STEP != 0) << 1) \
     | (OFFSET != 0))
  
  /* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
!    STEP and OFFSET to *ADDR.  Stores pointers to where step is placed to
!    *STEP_P and offset to *OFFSET_P.  */
  
  static void
! gen_addr_rtx (rtx symbol, rtx base, rtx index, rtx step, rtx offset,
  	      rtx *addr, rtx **step_p, rtx **offset_p)
  {
    rtx act_elem;
--- 71,108 ----
  /* A "template" for memory address, used to determine whether the address is
     valid for mode.  */
  
! typedef struct GTY (()) mem_addr_template {
    rtx ref;			/* The template.  */
    rtx * GTY ((skip)) step_p;	/* The point in template where the step should be
  				   filled in.  */
    rtx * GTY ((skip)) off_p;	/* The point in template where the offset should
  				   be filled in.  */
! } mem_addr_template;
  
! DEF_VEC_O (mem_addr_template);
! DEF_VEC_ALLOC_O (mem_addr_template, gc);
  
! /* The templates.  Each of the low five bits of the index corresponds to one
!    component of TARGET_MEM_REF being present, while the high bits identify
!    the address space.  See TEMPL_IDX.  */
  
! static GTY(()) VEC (mem_addr_template, gc) *mem_addr_template_list;
! 
! #define TEMPL_IDX(AS, SYMBOL, BASE, INDEX, STEP, OFFSET) \
!   (((int) (AS) << 5) \
!    | ((SYMBOL != 0) << 4) \
     | ((BASE != 0) << 3) \
     | ((INDEX != 0) << 2) \
     | ((STEP != 0) << 1) \
     | (OFFSET != 0))
  
  /* Stores address for memory reference with parameters SYMBOL, BASE, INDEX,
!    STEP and OFFSET to *ADDR using address mode ADDRESS_MODE.  Stores pointers
!    to where step is placed to *STEP_P and offset to *OFFSET_P.  */
  
  static void
! gen_addr_rtx (enum machine_mode address_mode,
! 	      rtx symbol, rtx base, rtx index, rtx step, rtx offset,
  	      rtx *addr, rtx **step_p, rtx **offset_p)
  {
    rtx act_elem;
*************** gen_addr_rtx (rtx symbol, rtx base, rtx 
*** 111,117 ****
        act_elem = index;
        if (step)
  	{
! 	  act_elem = gen_rtx_MULT (Pmode, act_elem, step);
  
  	  if (step_p)
  	    *step_p = &XEXP (act_elem, 1);
--- 118,124 ----
        act_elem = index;
        if (step)
  	{
! 	  act_elem = gen_rtx_MULT (address_mode, act_elem, step);
  
  	  if (step_p)
  	    *step_p = &XEXP (act_elem, 1);
*************** gen_addr_rtx (rtx symbol, rtx base, rtx 
*** 123,129 ****
    if (base)
      {
        if (*addr)
! 	*addr = simplify_gen_binary (PLUS, Pmode, base, *addr);
        else
  	*addr = base;
      }
--- 130,136 ----
    if (base)
      {
        if (*addr)
! 	*addr = simplify_gen_binary (PLUS, address_mode, base, *addr);
        else
  	*addr = base;
      }
*************** gen_addr_rtx (rtx symbol, rtx base, rtx 
*** 133,139 ****
        act_elem = symbol;
        if (offset)
  	{
! 	  act_elem = gen_rtx_PLUS (Pmode, act_elem, offset);
  
  	  if (offset_p)
  	    *offset_p = &XEXP (act_elem, 1);
--- 140,146 ----
        act_elem = symbol;
        if (offset)
  	{
! 	  act_elem = gen_rtx_PLUS (address_mode, act_elem, offset);
  
  	  if (offset_p)
  	    *offset_p = &XEXP (act_elem, 1);
*************** gen_addr_rtx (rtx symbol, rtx base, rtx 
*** 141,151 ****
  	  if (GET_CODE (symbol) == SYMBOL_REF
  	      || GET_CODE (symbol) == LABEL_REF
  	      || GET_CODE (symbol) == CONST)
! 	    act_elem = gen_rtx_CONST (Pmode, act_elem);
  	}
  
        if (*addr)
! 	*addr = gen_rtx_PLUS (Pmode, *addr, act_elem);
        else
  	*addr = act_elem;
      }
--- 148,158 ----
  	  if (GET_CODE (symbol) == SYMBOL_REF
  	      || GET_CODE (symbol) == LABEL_REF
  	      || GET_CODE (symbol) == CONST)
! 	    act_elem = gen_rtx_CONST (address_mode, act_elem);
  	}
  
        if (*addr)
! 	*addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
        else
  	*addr = act_elem;
      }
*************** gen_addr_rtx (rtx symbol, rtx base, rtx 
*** 153,159 ****
      {
        if (*addr)
  	{
! 	  *addr = gen_rtx_PLUS (Pmode, *addr, offset);
  	  if (offset_p)
  	    *offset_p = &XEXP (*addr, 1);
  	}
--- 160,166 ----
      {
        if (*addr)
  	{
! 	  *addr = gen_rtx_PLUS (address_mode, *addr, offset);
  	  if (offset_p)
  	    *offset_p = &XEXP (*addr, 1);
  	}
*************** gen_addr_rtx (rtx symbol, rtx base, rtx 
*** 169,223 ****
      *addr = const0_rtx;
  }
  
! /* Returns address for TARGET_MEM_REF with parameters given by ADDR.
     If REALLY_EXPAND is false, just make fake registers instead 
     of really expanding the operands, and perform the expansion in-place
     by using one of the "templates".  */
  
  rtx
! addr_for_mem_ref (struct mem_address *addr, bool really_expand)
  {
    rtx address, sym, bse, idx, st, off;
-   static bool templates_initialized = false;
-   struct mem_addr_template *templ;
  
    if (addr->step && !integer_onep (addr->step))
      st = immed_double_const (TREE_INT_CST_LOW (addr->step),
! 			     TREE_INT_CST_HIGH (addr->step), Pmode);
    else
      st = NULL_RTX;
  
    if (addr->offset && !integer_zerop (addr->offset))
      off = immed_double_const (TREE_INT_CST_LOW (addr->offset),
! 			      TREE_INT_CST_HIGH (addr->offset), Pmode);
    else
      off = NULL_RTX;
  
    if (!really_expand)
      {
        /* Reuse the templates for addresses, so that we do not waste memory.  */
!       if (!templates_initialized)
  	{
! 	  unsigned i;
! 
! 	  templates_initialized = true;
! 	  sym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup ("test_symbol"));
! 	  bse = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
! 	  idx = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 2);
! 
! 	  for (i = 0; i < 32; i++)
! 	    gen_addr_rtx ((i & 16 ? sym : NULL_RTX),
! 			  (i & 8 ? bse : NULL_RTX),
! 			  (i & 4 ? idx : NULL_RTX),
! 			  (i & 2 ? const0_rtx : NULL_RTX),
! 			  (i & 1 ? const0_rtx : NULL_RTX),
! 			  &templates[i].ref,
! 			  &templates[i].step_p,
! 			  &templates[i].off_p);
  	}
  
-       templ = templates + TEMPL_IDX (addr->symbol, addr->base, addr->index,
- 				     st, off);
        if (st)
  	*templ->step_p = st;
        if (off)
--- 176,239 ----
      *addr = const0_rtx;
  }
  
! /* Returns address for TARGET_MEM_REF with parameters given by ADDR
!    in address space AS.
     If REALLY_EXPAND is false, just make fake registers instead 
     of really expanding the operands, and perform the expansion in-place
     by using one of the "templates".  */
  
  rtx
! addr_for_mem_ref (struct mem_address *addr, addr_space_t as,
! 		  bool really_expand)
  {
+   enum machine_mode address_mode = targetm.addr_space.address_mode (as);
    rtx address, sym, bse, idx, st, off;
  
    if (addr->step && !integer_onep (addr->step))
      st = immed_double_const (TREE_INT_CST_LOW (addr->step),
! 			     TREE_INT_CST_HIGH (addr->step), address_mode);
    else
      st = NULL_RTX;
  
    if (addr->offset && !integer_zerop (addr->offset))
      off = immed_double_const (TREE_INT_CST_LOW (addr->offset),
! 			      TREE_INT_CST_HIGH (addr->offset), address_mode);
    else
      off = NULL_RTX;
  
    if (!really_expand)
      {
+       mem_addr_template *templ = NULL;
+       unsigned int templ_index
+ 	= TEMPL_IDX (as, addr->symbol, addr->base, addr->index, st, off);
+ 
+       if (templ_index
+ 	  >= VEC_length (mem_addr_template, mem_addr_template_list))
+ 	VEC_safe_grow_cleared (mem_addr_template, gc, mem_addr_template_list,
+ 			       templ_index + 1);
+ 
        /* Reuse the templates for addresses, so that we do not waste memory.  */
!       templ = VEC_index (mem_addr_template, mem_addr_template_list, templ_index);
!       if (!templ->ref)
  	{
! 	  sym = (addr->symbol ?
! 		 gen_rtx_SYMBOL_REF (address_mode, ggc_strdup ("test_symbol"))
! 		 : NULL_RTX);
! 	  bse = (addr->base ?
! 		 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1)
! 		 : NULL_RTX);
! 	  idx = (addr->index ?
! 		 gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2)
! 		 : NULL_RTX);
! 
! 	  gen_addr_rtx (address_mode, sym, bse, idx,
! 			st? const0_rtx : NULL_RTX,
! 			off? const0_rtx : NULL_RTX,
! 			&templ->ref,
! 			&templ->step_p,
! 			&templ->off_p);
  	}
  
        if (st)
  	*templ->step_p = st;
        if (off)
*************** addr_for_mem_ref (struct mem_address *ad
*** 229,244 ****
    /* Otherwise really expand the expressions.  */
    sym = (addr->symbol
  	 ? expand_expr (build_addr (addr->symbol, current_function_decl),
! 			NULL_RTX, Pmode, EXPAND_NORMAL)
  	 : NULL_RTX);
    bse = (addr->base
! 	 ? expand_expr (addr->base, NULL_RTX, Pmode, EXPAND_NORMAL)
  	 : NULL_RTX);
    idx = (addr->index
! 	 ? expand_expr (addr->index, NULL_RTX, Pmode, EXPAND_NORMAL)
  	 : NULL_RTX);
  
!   gen_addr_rtx (sym, bse, idx, st, off, &address, NULL, NULL);
    return address;
  }
  
--- 245,260 ----
    /* Otherwise really expand the expressions.  */
    sym = (addr->symbol
  	 ? expand_expr (build_addr (addr->symbol, current_function_decl),
! 			NULL_RTX, address_mode, EXPAND_NORMAL)
  	 : NULL_RTX);
    bse = (addr->base
! 	 ? expand_expr (addr->base, NULL_RTX, address_mode, EXPAND_NORMAL)
  	 : NULL_RTX);
    idx = (addr->index
! 	 ? expand_expr (addr->index, NULL_RTX, address_mode, EXPAND_NORMAL)
  	 : NULL_RTX);
  
!   gen_addr_rtx (address_mode, sym, bse, idx, st, off, &address, NULL, NULL);
    return address;
  }
  
*************** tree_mem_ref_addr (tree type, tree mem_r
*** 305,319 ****
     ADDR is valid on the current target.  */
  
  static bool
! valid_mem_ref_p (enum machine_mode mode, struct mem_address *addr)
  {
    rtx address;
  
!   address = addr_for_mem_ref (addr, false);
    if (!address)
      return false;
  
!   return memory_address_p (mode, address);
  }
  
  /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
--- 321,336 ----
     ADDR is valid on the current target.  */
  
  static bool
! valid_mem_ref_p (enum machine_mode mode, addr_space_t as,
! 		 struct mem_address *addr)
  {
    rtx address;
  
!   address = addr_for_mem_ref (addr, as, false);
    if (!address)
      return false;
  
!   return memory_address_addr_space_p (mode, address, as);
  }
  
  /* Checks whether a TARGET_MEM_REF with type TYPE and parameters given by ADDR
*************** valid_mem_ref_p (enum machine_mode mode,
*** 323,329 ****
  static tree
  create_mem_ref_raw (tree type, struct mem_address *addr)
  {
!   if (!valid_mem_ref_p (TYPE_MODE (type), addr))
      return NULL_TREE;
  
    if (addr->step && integer_onep (addr->step))
--- 340,346 ----
  static tree
  create_mem_ref_raw (tree type, struct mem_address *addr)
  {
!   if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr))
      return NULL_TREE;
  
    if (addr->step && integer_onep (addr->step))
*************** most_expensive_mult_to_index (struct mem
*** 456,462 ****
  
        coef = double_int_to_shwi (addr->elts[i].coef);
        if (coef == 1
! 	  || !multiplier_allowed_in_address_p (coef, Pmode))
  	continue;
  
        acost = multiply_by_cost (coef, Pmode, speed);
--- 473,479 ----
  
        coef = double_int_to_shwi (addr->elts[i].coef);
        if (coef == 1
! 	  || !multiplier_allowed_in_address_p (coef, Pmode, 0))
  	continue;
  
        acost = multiply_by_cost (coef, Pmode, speed);
Index: gcc/dse.c
===================================================================
*** gcc/dse.c	(revision 150188)
--- gcc/dse.c	(working copy)
*************** replace_inc_dec (rtx *r, void *d)
*** 826,834 ****
      case POST_INC:
        {
  	rtx r1 = XEXP (x, 0);
! 	rtx c = gen_int_mode (data->size, Pmode);
! 	emit_insn_before (gen_rtx_SET (Pmode, r1, 
! 				       gen_rtx_PLUS (Pmode, r1, c)),
  			  data->insn);
  	return -1;
        }
--- 826,834 ----
      case POST_INC:
        {
  	rtx r1 = XEXP (x, 0);
! 	rtx c = gen_int_mode (data->size, GET_MODE (r1));
! 	emit_insn_before (gen_rtx_SET (VOIDmode, r1, 
! 				       gen_rtx_PLUS (GET_MODE (r1), r1, c)),
  			  data->insn);
  	return -1;
        }
*************** replace_inc_dec (rtx *r, void *d)
*** 837,845 ****
      case POST_DEC:
        {
  	rtx r1 = XEXP (x, 0);
! 	rtx c = gen_int_mode (-data->size, Pmode);
! 	emit_insn_before (gen_rtx_SET (Pmode, r1, 
! 				       gen_rtx_PLUS (Pmode, r1, c)),
  			  data->insn);
  	return -1;
        }
--- 837,845 ----
      case POST_DEC:
        {
  	rtx r1 = XEXP (x, 0);
! 	rtx c = gen_int_mode (-data->size, GET_MODE (r1));
! 	emit_insn_before (gen_rtx_SET (VOIDmode, r1, 
! 				       gen_rtx_PLUS (GET_MODE (r1), r1, c)),
  			  data->insn);
  	return -1;
        }
*************** replace_inc_dec (rtx *r, void *d)
*** 851,857 ****
  	   insn that contained it.  */
  	rtx add = XEXP (x, 0);
  	rtx r1 = XEXP (add, 0);
! 	emit_insn_before (gen_rtx_SET (Pmode, r1, add), data->insn);
  	return -1;
        }
  
--- 851,857 ----
  	   insn that contained it.  */
  	rtx add = XEXP (x, 0);
  	rtx r1 = XEXP (add, 0);
! 	emit_insn_before (gen_rtx_SET (VOIDmode, r1, add), data->insn);
  	return -1;
        }
  
*************** canon_address (rtx mem,
*** 1068,1073 ****
--- 1068,1075 ----
  	       HOST_WIDE_INT *offset, 
  	       cselib_val **base)
  {
+   enum machine_mode address_mode
+     = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem));
    rtx mem_address = XEXP (mem, 0);
    rtx expanded_address, address;
    /* Make sure that cselib is has initialized all of the operands of
*************** canon_address (rtx mem,
*** 1105,1111 ****
  
    *alias_set_out = 0;
  
!   cselib_lookup (mem_address, Pmode, 1);
  
    if (dump_file)
      {
--- 1107,1113 ----
  
    *alias_set_out = 0;
  
!   cselib_lookup (mem_address, address_mode, 1);
  
    if (dump_file)
      {
*************** canon_address (rtx mem,
*** 1156,1162 ****
        address = XEXP (address, 0);
      }
  
!   if (const_or_frame_p (address))
      {
        group_info_t group = get_group_info (address);
  
--- 1158,1164 ----
        address = XEXP (address, 0);
      }
  
!   if (MEM_ADDR_SPACE (mem) == 0 && const_or_frame_p (address))
      {
        group_info_t group = get_group_info (address);
  
*************** canon_address (rtx mem,
*** 1167,1173 ****
      }
    else
      {
!       *base = cselib_lookup (address, Pmode, true);
        *group_id = -1;
  
        if (*base == NULL)
--- 1169,1175 ----
      }
    else
      {
!       *base = cselib_lookup (address, address_mode, true);
        *group_id = -1;
  
        if (*base == NULL)
Index: gcc/regmove.c
===================================================================
*** gcc/regmove.c	(revision 150188)
--- gcc/regmove.c	(working copy)
*************** try_auto_increment (rtx insn, rtx inc_in
*** 184,190 ****
  		   &SET_SRC (inc_insn_set),
  		   XEXP (SET_SRC (inc_insn_set), 0), 1);
  	      validate_change (insn, &XEXP (use, 0),
! 			       gen_rtx_fmt_e (inc_code, Pmode, reg), 1);
  	      if (apply_change_group ())
  		{
  		  /* If there is a REG_DEAD note on this insn, we must
--- 184,192 ----
  		   &SET_SRC (inc_insn_set),
  		   XEXP (SET_SRC (inc_insn_set), 0), 1);
  	      validate_change (insn, &XEXP (use, 0),
! 			       gen_rtx_fmt_e (inc_code,
! 					      GET_MODE (XEXP (use, 0)), reg),
! 			       1);
  	      if (apply_change_group ())
  		{
  		  /* If there is a REG_DEAD note on this insn, we must
Index: gcc/sel-sched-dump.c
===================================================================
*** gcc/sel-sched-dump.c	(revision 150188)
--- gcc/sel-sched-dump.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 34,39 ****
--- 34,40 ----
  #include "output.h"
  #include "basic-block.h"
  #include "cselib.h"
+ #include "target.h"
  
  #ifdef INSN_SCHEDULING
  #include "sel-sched-ir.h"
*************** rtx
*** 931,940 ****
  debug_mem_addr_value (rtx x)
  {
    rtx t, addr;
  
    gcc_assert (MEM_P (x));
    t = shallow_copy_rtx (x);
!   if (cselib_lookup (XEXP (t, 0), Pmode, 0))
      XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
  
    t = canon_rtx (t);
--- 932,944 ----
  debug_mem_addr_value (rtx x)
  {
    rtx t, addr;
+   enum machine_mode address_mode;
  
    gcc_assert (MEM_P (x));
+   address_mode = targetm.addr_space.address_mode (MEM_ADDR_SPACE (x));
+ 
    t = shallow_copy_rtx (x);
!   if (cselib_lookup (XEXP (t, 0), address_mode, 0))
      XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
  
    t = canon_rtx (t);
Index: gcc/alias.c
===================================================================
*** gcc/alias.c	(revision 150758)
--- gcc/alias.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 49,54 ****
--- 49,55 ----
  #include "tree-ssa-alias.h"
  #include "pointer-set.h"
  #include "tree-flow.h"
+ #include "targhooks.h"
  
  /* The aliasing API provided here solves related but different problems:
  
*************** find_base_value (rtx src)
*** 1040,1045 ****
--- 1041,1052 ----
        return 0;
  
      case TRUNCATE:
+       /* As we do not know which address space the pointer is refering to, we can
+ 	 handle this only if the target does not support different pointer or
+ 	 address modes depending on the address space.  */
+       if (targetm.addr_space.address_mode != default_addr_space_address_mode
+           || targetm.addr_space.pointer_mode != default_addr_space_pointer_mode)
+ 	break;
        if (GET_MODE_SIZE (GET_MODE (src)) < GET_MODE_SIZE (Pmode))
  	break;
        /* Fall through.  */
*************** find_base_value (rtx src)
*** 1054,1059 ****
--- 1061,1072 ----
  
      case ZERO_EXTEND:
      case SIGN_EXTEND:	/* used for NT/Alpha pointers */
+       /* As we do not know which address space the pointer is refering to, we can
+ 	 handle this only if the target does not support different pointer or
+ 	 address modes depending on the address space.  */
+       if (targetm.addr_space.address_mode != default_addr_space_address_mode
+           || targetm.addr_space.pointer_mode != default_addr_space_pointer_mode)
+ 	break;
        {
  	rtx temp = find_base_value (XEXP (src, 0));
  
*************** find_base_term (rtx x)
*** 1446,1451 ****
--- 1459,1470 ----
        return REG_BASE_VALUE (x);
  
      case TRUNCATE:
+       /* As we do not know which address space the pointer is refering to, we can
+ 	 handle this only if the target does not support different pointer or
+ 	 address modes depending on the address space.  */
+       if (targetm.addr_space.address_mode != default_addr_space_address_mode
+           || targetm.addr_space.pointer_mode != default_addr_space_pointer_mode)
+ 	return 0;
        if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (Pmode))
  	return 0;
        /* Fall through.  */
*************** find_base_term (rtx x)
*** 1460,1465 ****
--- 1479,1490 ----
  
      case ZERO_EXTEND:
      case SIGN_EXTEND:	/* Used for Alpha/NT pointers */
+       /* As we do not know which address space the pointer is refering to, we can
+ 	 handle this only if the target does not support different pointer or
+ 	 address modes depending on the address space.  */
+       if (targetm.addr_space.address_mode != default_addr_space_address_mode
+           || targetm.addr_space.pointer_mode != default_addr_space_pointer_mode)
+ 	return 0;
        {
  	rtx temp = find_base_term (XEXP (x, 0));
  
Index: gcc/tree-vect-data-refs.c
===================================================================
*** gcc/tree-vect-data-refs.c	(revision 150188)
--- gcc/tree-vect-data-refs.c	(working copy)
*************** vect_create_data_ref_ptr (gimple stmt, s
*** 2380,2387 ****
  	  if (!alias_sets_conflict_p (get_deref_alias_set (vect_ptr),
  				      get_alias_set (lhs)))
  	    {
! 	      vect_ptr_type = build_pointer_type_for_mode (vectype,
! 							   ptr_mode, true);
  	      vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
  						get_name (base_name));
  	      break;
--- 2380,2388 ----
  	  if (!alias_sets_conflict_p (get_deref_alias_set (vect_ptr),
  				      get_alias_set (lhs)))
  	    {
! 	      vect_ptr_type
! 		= build_pointer_type_for_mode (vectype,
! 					       TYPE_MODE (vect_ptr_type), true);
  	      vect_ptr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
  						get_name (base_name));
  	      break;
Index: gcc/expmed.c
===================================================================
*** gcc/expmed.c	(revision 150188)
--- gcc/expmed.c	(working copy)
*************** make_tree (tree type, rtx x)
*** 5089,5098 ****
      default:
        t = build_decl (RTL_LOCATION (x), VAR_DECL, NULL_TREE, type);
  
!       /* If TYPE is a POINTER_TYPE, X might be Pmode with TYPE_MODE being
! 	 ptr_mode.  So convert.  */
        if (POINTER_TYPE_P (type))
! 	x = convert_memory_address (TYPE_MODE (type), x);
  
        /* Note that we do *not* use SET_DECL_RTL here, because we do not
  	 want set_decl_rtl to go adjusting REG_ATTRS for this temporary.  */
--- 5089,5099 ----
      default:
        t = build_decl (RTL_LOCATION (x), VAR_DECL, NULL_TREE, type);
  
!       /* If TYPE is a POINTER_TYPE, we might need to convert X from
! 	 address mode to pointer mode.  */
        if (POINTER_TYPE_P (type))
! 	x = convert_memory_address_addr_space
! 	      (TYPE_MODE (type), x, TYPE_ADDR_SPACE (TREE_TYPE (type)));
  
        /* Note that we do *not* use SET_DECL_RTL here, because we do not
  	 want set_decl_rtl to go adjusting REG_ATTRS for this temporary.  */
Index: gcc/emit-rtl.c
===================================================================
*** gcc/emit-rtl.c	(revision 150758)
--- gcc/emit-rtl.c	(working copy)
*************** operand_subword (rtx op, unsigned int of
*** 1390,1396 ****
  
        else if (reload_completed)
  	{
! 	  if (! strict_memory_address_p (word_mode, XEXP (new_rtx, 0)))
  	    return 0;
  	}
        else
--- 1390,1398 ----
  
        else if (reload_completed)
  	{
! 	  if (! strict_memory_address_addr_space_p (word_mode,
! 						    XEXP (new_rtx, 0),
! 						    MEM_ADDR_SPACE (op)))
  	    return 0;
  	}
        else
Index: gcc/cselib.c
===================================================================
*** gcc/cselib.c	(revision 150188)
--- gcc/cselib.c	(working copy)
*************** cselib_record_sets (rtx insn)
*** 1689,1695 ****
  	    src = gen_rtx_IF_THEN_ELSE (GET_MODE (dest), cond, src, dest);
  	  sets[i].src_elt = cselib_lookup (src, GET_MODE (dest), 1);
  	  if (MEM_P (dest))
! 	    sets[i].dest_addr_elt = cselib_lookup (XEXP (dest, 0), Pmode, 1);
  	  else
  	    sets[i].dest_addr_elt = 0;
  	}
--- 1689,1701 ----
  	    src = gen_rtx_IF_THEN_ELSE (GET_MODE (dest), cond, src, dest);
  	  sets[i].src_elt = cselib_lookup (src, GET_MODE (dest), 1);
  	  if (MEM_P (dest))
! 	    {
! 	      enum machine_mode address_mode
! 		= targetm.addr_space.address_mode (MEM_ADDR_SPACE (dest));
! 
! 	      sets[i].dest_addr_elt = cselib_lookup (XEXP (dest, 0),
! 						     address_mode, 1);
! 	    }
  	  else
  	    sets[i].dest_addr_elt = 0;
  	}
Index: gcc/simplify-rtx.c
===================================================================
*** gcc/simplify-rtx.c	(revision 150188)
--- gcc/simplify-rtx.c	(working copy)
*************** simplify_unary_operation_1 (enum rtx_cod
*** 863,869 ****
  	return rtl_hooks.gen_lowpart_no_emit (mode, op);
  
  #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
!       if (! POINTERS_EXTEND_UNSIGNED
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
  	      || (GET_CODE (op) == SUBREG
--- 863,874 ----
  	return rtl_hooks.gen_lowpart_no_emit (mode, op);
  
  #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
!       /* As we do not know which address space the pointer is refering to,
! 	 we can do this only if the target does not support different pointer
! 	 or address modes depending on the address space.  */
!       if (targetm.addr_space.address_mode == default_addr_space_address_mode
! 	  && targetm.addr_space.pointer_mode == default_addr_space_pointer_mode
! 	  && ! POINTERS_EXTEND_UNSIGNED
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
  	      || (GET_CODE (op) == SUBREG
*************** simplify_unary_operation_1 (enum rtx_cod
*** 885,891 ****
  	return rtl_hooks.gen_lowpart_no_emit (mode, op);
  
  #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
!       if (POINTERS_EXTEND_UNSIGNED > 0
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
  	      || (GET_CODE (op) == SUBREG
--- 890,901 ----
  	return rtl_hooks.gen_lowpart_no_emit (mode, op);
  
  #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
!       /* As we do not know which address space the pointer is refering to,
! 	 we can do this only if the target does not support different pointer
! 	 or address modes depending on the address space.  */
!       if (targetm.addr_space.address_mode == default_addr_space_address_mode
! 	  && targetm.addr_space.pointer_mode == default_addr_space_pointer_mode
! 	  && POINTERS_EXTEND_UNSIGNED > 0
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
  	      || (GET_CODE (op) == SUBREG
Index: gcc/explow.c
===================================================================
*** gcc/explow.c	(revision 150758)
--- gcc/explow.c	(working copy)
*************** break_out_memory_refs (rtx x)
*** 312,332 ****
    return x;
  }
  
! /* Given X, a memory address in ptr_mode, convert it to an address
!    in Pmode, or vice versa (TO_MODE says which way).  We take advantage of
!    the fact that pointers are not allowed to overflow by commuting arithmetic
!    operations over conversions so that address arithmetic insns can be
!    used.  */
  
  rtx
! convert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED, 
! 			rtx x)
  {
  #ifndef POINTERS_EXTEND_UNSIGNED
    gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
    return x;
  #else /* defined(POINTERS_EXTEND_UNSIGNED) */
!   enum machine_mode from_mode;
    rtx temp;
    enum rtx_code code;
  
--- 312,332 ----
    return x;
  }
  
! /* Given X, a memory address in address space AS' pointer mode, convert it to
!    an address in the address space's address mode, or vice versa (TO_MODE says
!    which way).  We take advantage of the fact that pointers are not allowed to
!    overflow by commuting arithmetic operations over conversions so that address
!    arithmetic insns can be used.  */
  
  rtx
! convert_memory_address_addr_space (enum machine_mode to_mode ATTRIBUTE_UNUSED, 
! 				   rtx x, addr_space_t as ATTRIBUTE_UNUSED)
  {
  #ifndef POINTERS_EXTEND_UNSIGNED
    gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
    return x;
  #else /* defined(POINTERS_EXTEND_UNSIGNED) */
!   enum machine_mode pointer_mode, address_mode, from_mode;
    rtx temp;
    enum rtx_code code;
  
*************** convert_memory_address (enum machine_mod
*** 334,340 ****
    if (GET_MODE (x) == to_mode)
      return x;
  
!   from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
  
    /* Here we handle some special cases.  If none of them apply, fall through
       to the default case.  */
--- 334,342 ----
    if (GET_MODE (x) == to_mode)
      return x;
  
!   pointer_mode = targetm.addr_space.pointer_mode (as);
!   address_mode = targetm.addr_space.address_mode (as);
!   from_mode = to_mode == pointer_mode ? address_mode : pointer_mode;
  
    /* Here we handle some special cases.  If none of them apply, fall through
       to the default case.  */
*************** convert_memory_address (enum machine_mod
*** 375,381 ****
  
      case CONST:
        return gen_rtx_CONST (to_mode,
! 			    convert_memory_address (to_mode, XEXP (x, 0)));
        break;
  
      case PLUS:
--- 377,384 ----
  
      case CONST:
        return gen_rtx_CONST (to_mode,
! 			    convert_memory_address_addr_space
! 			      (to_mode, XEXP (x, 0), as));
        break;
  
      case PLUS:
*************** convert_memory_address (enum machine_mod
*** 389,398 ****
        if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
  	  || (GET_CODE (x) == PLUS
  	      && CONST_INT_P (XEXP (x, 1))
! 	      && (XEXP (x, 1) == convert_memory_address (to_mode, XEXP (x, 1))
                   || POINTERS_EXTEND_UNSIGNED < 0)))
  	return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
! 			       convert_memory_address (to_mode, XEXP (x, 0)),
  			       XEXP (x, 1));
        break;
  
--- 392,403 ----
        if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
  	  || (GET_CODE (x) == PLUS
  	      && CONST_INT_P (XEXP (x, 1))
! 	      && (XEXP (x, 1) == convert_memory_address_addr_space
! 				   (to_mode, XEXP (x, 1), as)
                   || POINTERS_EXTEND_UNSIGNED < 0)))
  	return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
! 			       convert_memory_address_addr_space
! 				 (to_mode, XEXP (x, 0), as),
  			       XEXP (x, 1));
        break;
  
*************** memory_address_addr_space (enum machine_
*** 414,423 ****
  {
    rtx oldx = x;
    enum machine_mode address_mode = targetm.addr_space.address_mode (as);
-   enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
  
!   if (address_mode != pointer_mode)
!     x = convert_memory_address (address_mode, x);
  
    /* By passing constant addresses through registers
       we get a chance to cse them.  */
--- 419,426 ----
  {
    rtx oldx = x;
    enum machine_mode address_mode = targetm.addr_space.address_mode (as);
  
!   x = convert_memory_address_addr_space (address_mode, x, as);
  
    /* By passing constant addresses through registers
       we get a chance to cse them.  */
Index: gcc/loop-invariant.c
===================================================================
*** gcc/loop-invariant.c	(revision 150188)
--- gcc/loop-invariant.c	(working copy)
*************** create_new_invariant (struct def *def, r
*** 685,691 ****
    if (def)
      {
        inv->cost = rtx_cost (set, SET, speed);
!       inv->cheap_address = address_cost (SET_SRC (set), word_mode,
  					 speed) < COSTS_N_INSNS (1);
      }
    else
--- 685,691 ----
    if (def)
      {
        inv->cost = rtx_cost (set, SET, speed);
!       inv->cheap_address = address_cost (SET_SRC (set), word_mode, 0,
  					 speed) < COSTS_N_INSNS (1);
      }
    else
Index: gcc/varasm.c
===================================================================
*** gcc/varasm.c	(revision 150758)
--- gcc/varasm.c	(working copy)
*************** initializer_constant_valid_p (tree value
*** 4341,4347 ****
      case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        if (! INTEGRAL_TYPE_P (endtype)
! 	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
  	{
  	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
  						      endtype);
--- 4341,4347 ----
      case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
        if (! INTEGRAL_TYPE_P (endtype)
! 	  || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
  	{
  	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
  						      endtype);
*************** initializer_constant_valid_p (tree value
*** 4363,4369 ****
  
      case MINUS_EXPR:
        if (! INTEGRAL_TYPE_P (endtype)
! 	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
  	{
  	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
  						      endtype);
--- 4363,4369 ----
  
      case MINUS_EXPR:
        if (! INTEGRAL_TYPE_P (endtype)
! 	  || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
  	{
  	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
  						      endtype);
*************** output_constant (tree exp, unsigned HOST
*** 4484,4490 ****
       resolving it.  */
    if (TREE_CODE (exp) == NOP_EXPR
        && POINTER_TYPE_P (TREE_TYPE (exp))
!       && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
      {
        tree saved_type = TREE_TYPE (exp);
  
--- 4484,4492 ----
       resolving it.  */
    if (TREE_CODE (exp) == NOP_EXPR
        && POINTER_TYPE_P (TREE_TYPE (exp))
!       && targetm.addr_space.valid_pointer_mode
! 	   (TYPE_MODE (TREE_TYPE (exp)),
! 	    TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))))
      {
        tree saved_type = TREE_TYPE (exp);
  
*************** output_constant (tree exp, unsigned HOST
*** 4492,4498 ****
  	 pointer modes.  */
        while (TREE_CODE (exp) == NOP_EXPR
  	     && POINTER_TYPE_P (TREE_TYPE (exp))
! 	     && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
  	exp = TREE_OPERAND (exp, 0);
  
        /* If what we're left with is the address of something, we can
--- 4494,4502 ----
  	 pointer modes.  */
        while (TREE_CODE (exp) == NOP_EXPR
  	     && POINTER_TYPE_P (TREE_TYPE (exp))
! 	     && targetm.addr_space.valid_pointer_mode
! 		  (TYPE_MODE (TREE_TYPE (exp)),
! 		   TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))))
  	exp = TREE_OPERAND (exp, 0);
  
        /* If what we're left with is the address of something, we can
Index: gcc/sched-deps.c
===================================================================
*** gcc/sched-deps.c	(revision 150188)
--- gcc/sched-deps.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 41,46 ****
--- 41,47 ----
  #include "sched-int.h"
  #include "params.h"
  #include "cselib.h"
+ #include "target.h"
  
  #ifdef INSN_SCHEDULING
  
*************** sched_analyze_1 (struct deps *deps, rtx 
*** 1907,1914 ****
  
        if (sched_deps_info->use_cselib)
  	{
  	  t = shallow_copy_rtx (dest);
! 	  cselib_lookup (XEXP (t, 0), Pmode, 1);
  	  XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
  	}
        t = canon_rtx (t);
--- 1908,1918 ----
  
        if (sched_deps_info->use_cselib)
  	{
+ 	  enum machine_mode address_mode
+ 	    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (dest));
+ 
  	  t = shallow_copy_rtx (dest);
! 	  cselib_lookup (XEXP (t, 0), address_mode, 1);
  	  XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
  	}
        t = canon_rtx (t);
*************** sched_analyze_2 (struct deps *deps, rtx 
*** 2061,2068 ****
  
  	if (sched_deps_info->use_cselib)
  	  {
  	    t = shallow_copy_rtx (t);
! 	    cselib_lookup (XEXP (t, 0), Pmode, 1);
  	    XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
  	  }
  	t = canon_rtx (t);
--- 2065,2075 ----
  
  	if (sched_deps_info->use_cselib)
  	  {
+ 	    enum machine_mode address_mode
+ 	      = targetm.addr_space.address_mode (MEM_ADDR_SPACE (t));
+ 
  	    t = shallow_copy_rtx (t);
! 	    cselib_lookup (XEXP (t, 0), address_mode, 1);
  	    XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
  	  }
  	t = canon_rtx (t);
Index: gcc/target-def.h
===================================================================
*** gcc/target-def.h	(revision 150758)
--- gcc/target-def.h	(working copy)
***************
*** 471,476 ****
--- 471,481 ----
  #define TARGET_ADDR_SPACE_ADDRESS_MODE default_addr_space_address_mode
  #endif
  
+ #ifndef TARGET_ADDR_SPACE_VALID_POINTER_MODE
+ #define TARGET_ADDR_SPACE_VALID_POINTER_MODE \
+ 	default_addr_space_valid_pointer_mode
+ #endif
+ 
  #ifndef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
  #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
    default_addr_space_legitimate_address_p
***************
*** 493,498 ****
--- 498,504 ----
    {						\
      TARGET_ADDR_SPACE_POINTER_MODE,		\
      TARGET_ADDR_SPACE_ADDRESS_MODE,		\
+     TARGET_ADDR_SPACE_VALID_POINTER_MODE,	\
      TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P,	\
      TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS,	\
      TARGET_ADDR_SPACE_SUBSET_P,			\
Index: gcc/rtl.h
===================================================================
*** gcc/rtl.h	(revision 150188)
--- gcc/rtl.h	(working copy)
*************** rhs_regno (const_rtx x)
*** 1079,1085 ****
  
  extern void init_rtlanal (void);
  extern int rtx_cost (rtx, enum rtx_code, bool);
! extern int address_cost (rtx, enum machine_mode, bool);
  extern unsigned int subreg_lsb (const_rtx);
  extern unsigned int subreg_lsb_1 (enum machine_mode, enum machine_mode,
  				  unsigned int);
--- 1079,1085 ----
  
  extern void init_rtlanal (void);
  extern int rtx_cost (rtx, enum rtx_code, bool);
! extern int address_cost (rtx, enum machine_mode, addr_space_t, bool);
  extern unsigned int subreg_lsb (const_rtx);
  extern unsigned int subreg_lsb_1 (enum machine_mode, enum machine_mode,
  				  unsigned int);
*************** extern unsigned int subreg_highpart_offs
*** 1550,1556 ****
  					    enum machine_mode);
  extern int byte_lowpart_offset (enum machine_mode, enum machine_mode);
  extern rtx make_safe_from (rtx, rtx);
! extern rtx convert_memory_address (enum machine_mode, rtx);
  extern rtx get_insns (void);
  extern const char *get_insn_name (int);
  extern rtx get_last_insn (void);
--- 1550,1559 ----
  					    enum machine_mode);
  extern int byte_lowpart_offset (enum machine_mode, enum machine_mode);
  extern rtx make_safe_from (rtx, rtx);
! extern rtx convert_memory_address_addr_space (enum machine_mode, rtx,
! 					      addr_space_t);
! #define convert_memory_address(to_mode,x) \
! 	convert_memory_address_addr_space ((to_mode), (x), 0)
  extern rtx get_insns (void);
  extern const char *get_insn_name (int);
  extern rtx get_last_insn (void);
Index: gcc/combine.c
===================================================================
*** gcc/combine.c	(revision 150188)
--- gcc/combine.c	(working copy)
*************** find_split_point (rtx *loc, rtx insn)
*** 3913,3921 ****
        if (GET_CODE (XEXP (x, 0)) == CONST
  	  || GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
  	{
  	  SUBST (XEXP (x, 0),
! 		 gen_rtx_LO_SUM (Pmode,
! 				 gen_rtx_HIGH (Pmode, XEXP (x, 0)),
  				 XEXP (x, 0)));
  	  return &XEXP (XEXP (x, 0), 0);
  	}
--- 3913,3924 ----
        if (GET_CODE (XEXP (x, 0)) == CONST
  	  || GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
  	{
+ 	  enum machine_mode address_mode
+ 	    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (x));
+ 
  	  SUBST (XEXP (x, 0),
! 		 gen_rtx_LO_SUM (address_mode,
! 				 gen_rtx_HIGH (address_mode, XEXP (x, 0)),
  				 XEXP (x, 0)));
  	  return &XEXP (XEXP (x, 0), 0);
  	}
*************** find_split_point (rtx *loc, rtx insn)
*** 3928,3934 ****
  	 it will not remain in the result.  */
        if (GET_CODE (XEXP (x, 0)) == PLUS
  	  && CONST_INT_P (XEXP (XEXP (x, 0), 1))
! 	  && ! memory_address_p (GET_MODE (x), XEXP (x, 0)))
  	{
  	  rtx reg = regno_reg_rtx[FIRST_PSEUDO_REGISTER];
  	  rtx seq = combine_split_insns (gen_rtx_SET (VOIDmode, reg,
--- 3931,3938 ----
  	 it will not remain in the result.  */
        if (GET_CODE (XEXP (x, 0)) == PLUS
  	  && CONST_INT_P (XEXP (XEXP (x, 0), 1))
! 	  && ! memory_address_addr_space_p (GET_MODE (x), XEXP (x, 0),
! 					    MEM_ADDR_SPACE (x)))
  	{
  	  rtx reg = regno_reg_rtx[FIRST_PSEUDO_REGISTER];
  	  rtx seq = combine_split_insns (gen_rtx_SET (VOIDmode, reg,
*************** find_split_point (rtx *loc, rtx insn)
*** 3951,3958 ****
  	      && NONJUMP_INSN_P (NEXT_INSN (seq))
  	      && GET_CODE (PATTERN (NEXT_INSN (seq))) == SET
  	      && SET_DEST (PATTERN (NEXT_INSN (seq))) == reg
! 	      && memory_address_p (GET_MODE (x),
! 				   SET_SRC (PATTERN (NEXT_INSN (seq)))))
  	    {
  	      rtx src1 = SET_SRC (PATTERN (seq));
  	      rtx src2 = SET_SRC (PATTERN (NEXT_INSN (seq)));
--- 3955,3963 ----
  	      && NONJUMP_INSN_P (NEXT_INSN (seq))
  	      && GET_CODE (PATTERN (NEXT_INSN (seq))) == SET
  	      && SET_DEST (PATTERN (NEXT_INSN (seq))) == reg
! 	      && memory_address_addr_space_p
! 		   (GET_MODE (x), SET_SRC (PATTERN (NEXT_INSN (seq))),
! 		    MEM_ADDR_SPACE (x)))
  	    {
  	      rtx src1 = SET_SRC (PATTERN (seq));
  	      rtx src2 = SET_SRC (PATTERN (NEXT_INSN (seq)));
*************** find_split_point (rtx *loc, rtx insn)
*** 3991,3997 ****
        /* If we have a PLUS whose first operand is complex, try computing it
           separately by making a split there.  */
        if (GET_CODE (XEXP (x, 0)) == PLUS
!           && ! memory_address_p (GET_MODE (x), XEXP (x, 0))
            && ! OBJECT_P (XEXP (XEXP (x, 0), 0))
            && ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG
                  && OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
--- 3996,4003 ----
        /* If we have a PLUS whose first operand is complex, try computing it
           separately by making a split there.  */
        if (GET_CODE (XEXP (x, 0)) == PLUS
!           && ! memory_address_addr_space_p (GET_MODE (x), XEXP (x, 0),
! 					    MEM_ADDR_SPACE (x))
            && ! OBJECT_P (XEXP (XEXP (x, 0), 0))
            && ! (GET_CODE (XEXP (XEXP (x, 0), 0)) == SUBREG
                  && OBJECT_P (SUBREG_REG (XEXP (XEXP (x, 0), 0)))))
Index: gcc/c-common.c
===================================================================
*** gcc/c-common.c	(revision 150758)
--- gcc/c-common.c	(working copy)
*************** handle_mode_attribute (tree *node, tree 
*** 6418,6426 ****
  
        if (POINTER_TYPE_P (type))
  	{
  	  tree (*fn)(tree, enum machine_mode, bool);
  
! 	  if (!targetm.valid_pointer_mode (mode))
  	    {
  	      error ("invalid pointer mode %qs", p);
  	      return NULL_TREE;
--- 6418,6427 ----
  
        if (POINTER_TYPE_P (type))
  	{
+ 	  addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
  	  tree (*fn)(tree, enum machine_mode, bool);
  
! 	  if (!targetm.addr_space.valid_pointer_mode (mode, as))
  	    {
  	      error ("invalid pointer mode %qs", p);
  	      return NULL_TREE;
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h	(revision 150188)
--- gcc/tree-flow.h	(working copy)
*************** extern void tree_check_data_deps (void);
*** 875,881 ****
  /* In tree-ssa-loop-ivopts.c  */
  bool expr_invariant_in_loop_p (struct loop *, tree);
  bool stmt_invariant_in_loop_p (struct loop *, gimple);
! bool multiplier_allowed_in_address_p (HOST_WIDE_INT, enum machine_mode);
  unsigned multiply_by_cost (HOST_WIDE_INT, enum machine_mode, bool);
  
  /* In tree-ssa-threadupdate.c.  */
--- 875,882 ----
  /* In tree-ssa-loop-ivopts.c  */
  bool expr_invariant_in_loop_p (struct loop *, tree);
  bool stmt_invariant_in_loop_p (struct loop *, gimple);
! bool multiplier_allowed_in_address_p (HOST_WIDE_INT, enum machine_mode,
! 				      addr_space_t);
  unsigned multiply_by_cost (HOST_WIDE_INT, enum machine_mode, bool);
  
  /* In tree-ssa-threadupdate.c.  */
*************** struct mem_address
*** 906,912 ****
  struct affine_tree_combination;
  tree create_mem_ref (gimple_stmt_iterator *, tree, 
  		     struct affine_tree_combination *, bool);
! rtx addr_for_mem_ref (struct mem_address *, bool);
  void get_address_description (tree, struct mem_address *);
  tree maybe_fold_tmr (tree);
  
--- 907,913 ----
  struct affine_tree_combination;
  tree create_mem_ref (gimple_stmt_iterator *, tree, 
  		     struct affine_tree_combination *, bool);
! rtx addr_for_mem_ref (struct mem_address *, addr_space_t, bool);
  void get_address_description (tree, struct mem_address *);
  tree maybe_fold_tmr (tree);
  
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in	(revision 150758)
--- gcc/Makefile.in	(working copy)
*************** tree-ssa-address.o : tree-ssa-address.c 
*** 2318,2324 ****
     $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) \
     output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
     $(TREE_PASS_H) $(FLAGS_H) $(TREE_INLINE_H) $(RECOG_H) insn-config.h \
!    $(EXPR_H) gt-tree-ssa-address.h $(GGC_H) tree-affine.h
  tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \
     $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
     $(TREE_INLINE_H) output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
--- 2318,2324 ----
     $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) \
     output.h $(DIAGNOSTIC_H) $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
     $(TREE_PASS_H) $(FLAGS_H) $(TREE_INLINE_H) $(RECOG_H) insn-config.h \
!    $(EXPR_H) gt-tree-ssa-address.h $(GGC_H) tree-affine.h $(TARGET_H)
  tree-ssa-loop-niter.o : tree-ssa-loop-niter.c $(TREE_FLOW_H) $(CONFIG_H) \
     $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(CFGLOOP_H) $(PARAMS_H) \
     $(TREE_INLINE_H) output.h $(DIAGNOSTIC_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
*************** alias.o : alias.c $(CONFIG_H) $(SYSTEM_H
*** 2977,2983 ****
     $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
     langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
     $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) $(DF_H) $(TREE_PASS_H) \
!    tree-ssa-alias.h pointer-set.h $(TREE_FLOW_H)
  stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) $(TREE_PASS_H) \
     $(BASIC_BLOCK_H) $(FLAGS_H) output.h $(DF_H)
--- 2977,2983 ----
     $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
     langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
     $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) $(DF_H) $(TREE_PASS_H) \
!    tree-ssa-alias.h pointer-set.h $(TREE_FLOW_H) targhooks.h
  stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) $(TREE_PASS_H) \
     $(BASIC_BLOCK_H) $(FLAGS_H) output.h $(DF_H)
*************** haifa-sched.o : haifa-sched.c $(CONFIG_H
*** 3041,3047 ****
  sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
     $(FUNCTION_H) $(INSN_ATTR_H) $(TOPLEV_H) $(RECOG_H) $(EXCEPT_H) cselib.h \
!    $(PARAMS_H) $(TM_P_H)
  sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
     $(FUNCTION_H) $(INSN_ATTR_H) $(TOPLEV_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
--- 3041,3047 ----
  sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
     $(FUNCTION_H) $(INSN_ATTR_H) $(TOPLEV_H) $(RECOG_H) $(EXCEPT_H) cselib.h \
!    $(TARGET_H) $(PARAMS_H) $(TM_P_H)
  sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     $(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
     $(FUNCTION_H) $(INSN_ATTR_H) $(TOPLEV_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
Index: gcc/config/spu/spu.c
===================================================================
*** gcc/config/spu/spu.c	(revision 150758)
--- gcc/config/spu/spu.c	(working copy)
*************** static tree spu_builtin_mask_for_load (v
*** 212,218 ****
  static int spu_builtin_vectorization_cost (bool);
  static bool spu_vector_alignment_reachable (const_tree, bool);
  static tree spu_builtin_vec_perm (tree, tree *);
- static bool spu_valid_pointer_mode (enum machine_mode mode);
  static enum machine_mode spu_addr_space_pointer_mode (addr_space_t);
  static enum machine_mode spu_addr_space_address_mode (addr_space_t);
  static bool spu_addr_space_subset_p (addr_space_t, addr_space_t);
--- 212,217 ----
*************** static const struct attribute_spec spu_a
*** 314,322 ****
  #undef TARGET_ADDR_SPACE_CONVERT
  #define TARGET_ADDR_SPACE_CONVERT spu_addr_space_convert
  
- #undef TARGET_VALID_POINTER_MODE
- #define TARGET_VALID_POINTER_MODE spu_valid_pointer_mode
- 
  #undef TARGET_INIT_BUILTINS
  #define TARGET_INIT_BUILTINS spu_init_builtins
  
--- 313,318 ----
*************** spu_builtin_vec_perm (tree type, tree *m
*** 6770,6783 ****
    return d->fndecl;
  }
  
- /* Return valid pointer modes.  */
- static bool
- spu_valid_pointer_mode (enum machine_mode mode)
- {
-   return (mode == ptr_mode || mode == Pmode ||
- 	  (spu_ea_model != 32 && mode == DImode));
- }
- 
  /* Return the appropriate mode for a named address pointer.  */
  static enum machine_mode
  spu_addr_space_pointer_mode (addr_space_t addrspace)
--- 6766,6771 ----
Index: gcc/regcprop.c
===================================================================
*** gcc/regcprop.c	(revision 150188)
--- gcc/regcprop.c	(working copy)
*************** kill_autoinc_value (rtx *px, void *data)
*** 247,253 ****
      {
        x = XEXP (x, 0);
        kill_value (x, vd);
!       set_value_regno (REGNO (x), Pmode, vd);
        return -1;
      }
  
--- 247,253 ----
      {
        x = XEXP (x, 0);
        kill_value (x, vd);
!       set_value_regno (REGNO (x), GET_MODE (x), vd);
        return -1;
      }
  
Index: gcc/reload1.c
===================================================================
*** gcc/reload1.c	(revision 150188)
--- gcc/reload1.c	(working copy)
*************** reload (rtx first, int global)
*** 1000,1007 ****
  	    rtx x = eliminate_regs (reg_equiv_memory_loc[i], VOIDmode,
  				    NULL_RTX);
  
! 	    if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]),
! 					 XEXP (x, 0)))
  	      reg_equiv_mem[i] = x, reg_equiv_address[i] = 0;
  	    else if (CONSTANT_P (XEXP (x, 0))
  		     || (REG_P (XEXP (x, 0))
--- 1000,1008 ----
  	    rtx x = eliminate_regs (reg_equiv_memory_loc[i], VOIDmode,
  				    NULL_RTX);
  
! 	    if (strict_memory_address_addr_space_p
! 		  (GET_MODE (regno_reg_rtx[i]), XEXP (x, 0),
! 		   MEM_ADDR_SPACE (x)))
  	      reg_equiv_mem[i] = x, reg_equiv_address[i] = 0;
  	    else if (CONSTANT_P (XEXP (x, 0))
  		     || (REG_P (XEXP (x, 0))
*************** eliminate_regs_1 (rtx x, enum machine_mo
*** 2611,2617 ****
  		     && reg_equiv_constant[REGNO (new0)] != 0)
  	      new0 = reg_equiv_constant[REGNO (new0)];
  
! 	    new_rtx = form_sum (new0, new1);
  
  	    /* As above, if we are not inside a MEM we do not want to
  	       turn a PLUS into something else.  We might try to do so here
--- 2612,2618 ----
  		     && reg_equiv_constant[REGNO (new0)] != 0)
  	      new0 = reg_equiv_constant[REGNO (new0)];
  
! 	    new_rtx = form_sum (GET_MODE (x), new0, new1);
  
  	    /* As above, if we are not inside a MEM we do not want to
  	       turn a PLUS into something else.  We might try to do so here
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]