[PATCH PING 2/5] Named address spaces: support multiple pointer modes

Ulrich Weigand uweigand@de.ibm.com
Wed Sep 16 16:50:00 GMT 2009


Hello,

this patch provides another significant piece of middle-end support
for named address spaces.  It enables the target to specific different
pointer sizes and modes to be used for pointers to different address
spaces.  In particular:

- The hook TARGET_ADDR_SPACE_POINTER_MODE allows a target to specify
  the mode to be used for a language-level pointer variable pointing
  to a named address space.  This replaces ptr_mode (and implicitly
  POINTER_SIZE).

- The hook TARGET_ADDR_SPACE_ADDRESS_MODE allows a target to specify
  the mode to be used for machine addresses (i.e. inside a MEM RTX)
  refering to a named address space.  This replaces Pmode.

- The hook TARGET_ADDR_SPACE_VALID_POINTER_MODE is an address-space
  aware version of TARGET_VALID_POINTER_MODE.

The bulk of the patch consists of changes to middle-end code to
remove uses of Pmode, ptr_mode, and POINTER_SIZE, and replace them
by the appropriate address-space aware variant.  (In some cases,
the mode was already available, in other cases, one of the above
target hooks needs to be called to retrieve the mode.)

In particular, the patch introduces an address-space aware version
of convert_memory_address and changes the relevant call sites.

In tree-ssa-address.c:gen_addr_rtx, address RTX expresssions were
cached in a global cache; this needs to become a per-address-space
cache as well.

Unfortunately, there are a couple of places within the optimizers
where we operate just on an address with no idea which address space
(if any) is subsequently going to be accesses via this address, but
the optimizer still makes assumptions solely via the address's mode,
e.g. like the following code in rtlanal.c:nonzero_bits1:

#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

For now, I've changed such locations to simply disable the optimization
if the target supports multiple pointer modes, like so:

      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);

As a future enhancement, it might be possible to encode the information
that a register holds a pointer to a particular address space into a
register attribute structure ...


There is a small number of somewhat suspicious uses of ptr_mode or Pmode
that I've left unchanges as they apparently only influence heuristics,
like this code in expand_expr_real_1:

      /* If the result is to be ptr_mode and we are adding an integer to
         something, we might be forming a constant.  So try to use
         plus_constant.  If it produces a sum and we can't accept it,
         use force_operand.  This allows P = &ARR[const] to generate
         efficient code on machines where a SYMBOL_REF is not a valid
         address.

         If this is an EXPAND_SUM call, always return the sum.  */
      if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
          || (mode == ptr_mode && (unsignedp || ! flag_trapv)))
        {

(This seems odd anyway, as just because the mode is ptr_mode does not
at all imply we're operating on a pointer ...)

The whole series tested on spu-elf and s390x-ibm-linux.
OK for mainline?

Bye,
Ulrich


2009-09-14  Ben Elliston  <bje@au.ibm.com>
	    Michael Meissner  <meissner@linux.vnet.ibm.com>
	    Ulrich Weigand  <uweigand@de.ibm.com>

	* doc/tm.texi (TARGET_ADDR_SPACE_POINTER_MODE): Document.
	(TARGET_ADDR_SPACE_ADDRESS_MODE): Likewise.
	(TARGET_ADDR_SPACE_VALID_POINTER_MODE): Likewise.

	* target.h (struct target_def): Add pointer_mode, address_mode,
	and valid_pointer_mode to addr_space substructure.
	* target-def.h (TARGET_ADDR_SPACE_POINTER_MODE): Define.
	(TARGET_ADDR_SPACE_ADDRESS_MODE): Likewise.
	(TARGET_ADDR_SPACE_VALID_POINTER_MODE): Likewise.
	(TARGET_ADDR_SPACE_HOOKS): Add them.
	* targhooks.c (default_addr_space_pointer_mode): New function.
	(default_addr_space_address_mode): Likewise.
	(default_addr_space_valid_pointer_mode): Likewise.
	* targhooks.h (default_addr_space_pointer_mode): Add prototype.
	(default_addr_space_address_mode): Likewise.
	(default_addr_space_valid_pointer_mode): Likewise.
	* output.h (default_valid_pointer_mode): Move to ...
	* targhooks.h (default_valid_pointer_mode): ... here.
	* varasm.c (default_valid_pointer_mode): Move to ...
	* targhooks.c (default_valid_pointer_mode): ... here.

	* varasm.c (output_constant): Use targetm.addr_space.valid_pointer_mode
	instead of targetm.valid_pointer_mode.

	* fold-const.c (fit_double_type): Use int_or_pointer_precision.
	* tree.c (integer_pow2p): Likewise.
	(tree_log2): Likewise.
	(tree_floor_log2): Likewise.
	(signed_or_unsigned_type_for): Support pointer type of different size.
	(int_or_pointer_precision): New function.
	* tree.h (int_or_pointer_precision): Add prototype.
	* stor-layout.c (layout_type): Set TYPE_PRECISION for offset types.
	* varasm.c (initializer_constant_valid_p): Use TYPE_PRECISION of
	incoming pointer type instead of POINTER_SIZE.

	* tree.c (build_pointer_type): Use appropriate pointer mode
	instead of ptr_mode.
	(build_reference_type): Likewise.
	* expr.c (store_expr): Likewise.
	(expand_expr_addr_expr): Likewise.
	* tree-vect-data-refs.c (vect_create_data_ref_ptr): Likewise.
	
	* auto-inc-dec.c: Include "target.h".
	(try_merge): Use appropriate address mode instead of Pmode.
	(find_inc): Likewise.
	* combine.c (find_split_point): Likewise.
	* cselib.c (cselib_record_sets): Likewise.
	* dse.c (replace_inc_dec): Likewise.
	(canon_address): Likewise.
	* var-tracking.c (replace_expr_with_values): Likewise.
	(count_uses): Likewise.
	(add_uses): Likewise.
	(add_stores): Likewise.
	* emit-rtl.c: Include "target.h".
	(adjust_address_1): Use appropriate address mode instead of Pmode.
	(offset_address): Likewise.
	* explow.c (break_out_memory_refs): Likewise.
	(memory_address_addr_space): Likewise.
	(promote_mode): Likewise.
	* expr.c (move_by_pieces): Likewise.
	(emit_block_move_via_loop): Likewise.
	(store_by_pieces): Likewise.
	(store_by_pieces_1): Likewise.
	(expand_assignment): Likewise.
	(store_constructor): Likewise.
	(expand_expr_addr_expr): Likewise.
	(expand_expr_real_1): Likewise.
	* cfgexpand.c (expand_debug_expr): Likewise.
	* ifcvt.c (noce_try_cmove_arith): Likewise.
	* regcprop.c (kill_autoinc_value): Likewise.
	* regmove.c (try_auto_increment): Likewise.
	* reload.c (find_reloads): Likewise.
	(find_reloads_address): Likewise.
	(find_reloads_address_1): Likewise.
	* sched-deps.c: Include "target.h".
	(sched_analyze_1): Use appropriate address mode instead of Pmode.
	(sched_analyze_2): Likewise.
	* sel-sched-dump.c: Include "target.h".
	(debug_mem_addr_value): Use appropriate address mode instead of Pmode.
	* stor-layout.c (layout_type): Likewise.
	* tree-ssa-loop-ivopts.c (produce_memory_decl_rtl): Likewise.
	(multiplier_allowed_in_address_p): Likewise.
	(get_address_cost): Likewise.
	* varasm.c (make_decl_rtl): Likewise.
	
	* expr.c (expand_assignment): Always convert offsets to appropriate
	address mode.
	(store_expr): Likewise.
	(store_constructor): Likewise.
	(expand_expr_real_1): Likewise.

	* reload.h (form_sum): Add MODE argument.
	* reload.c (form_sum): Add MODE argument, use it instead of Pmode.
	Update recursive calls.
	(subst_indexed_address): Update calls to form_sum.
	
	* tree-flow.h (addr_for_mem_ref): Add ADDRSPACE argument.
	* tree-ssa-address.c: 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, use it instead of Pmode.
	(addr_for_mem_ref): Add ADDRSPACE argument.  Use per-address-space
	instead of global cache.  Update call to gen_addr_rtx.
	(valid_mem_ref_p): Update call to addr_for_mem_ref.
	* expr.c (expand_expr_real_1): Update call to addr_for_mem_ref.
	
	* rtl.h (convert_memory_address_addr_space): Add prototype.
	(convert_memory_address): Define as macro.
	* explow.c (convert_memory_address): Rename to ...
	(convert_memory_address_addr_space): ... this.  Add ADDRSPACE argument.
	Use appropriate pointer and address modes instead of ptr_mode / Pmode.
	Update recursive calls.
	(memory_address_addr_space): Call convert_memory_address_addr_space.
	* expmed.c (make_tree): Likewise.
	* expr.c (expand_assignment): Likewise.
	(expand_expr_addr_expr_1): Likewise.  Also, add ADDRSPACE argument.
	(expand_expr_addr_expr): Likewise.  Also, update call.

	* alias.c: Include "targhooks.h".
	(find_base_value): Guard pointer size optimizations.
	(find_base_term): Likewise.
	* rtlanal.c: Include "targhooks.h"
	(nonzero_bits1): Guard pointer size optimizations.
	(num_sign_bit_copies1): Likewise.
	* simplify-rtx.c: Include "targhooks.h".
	(simplify_unary_operation_1): Guard pointer size optimizations.

	* Makefile.in (tree-ssa-address.o): Add $(TARGET_H) dependency.
	(emit-rtl.o): Likewise.
	(auto-inc-dec.o): Likewise.
	(sched-deps.o): Likewise.
	(alias.o): Add targhooks.h dependency.
	(rtlanal.o): Likewise.
	(simplify-rtx.o): Likewise.

Index: gcc-head/gcc/Makefile.in
===================================================================
--- gcc-head.orig/gcc/Makefile.in
+++ gcc-head/gcc/Makefile.in
@@ -2355,7 +2355,7 @@ tree-ssa-address.o : tree-ssa-address.c 
    $(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
+   $(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) \
@@ -2659,7 +2659,7 @@ print-rtl.o : print-rtl.c $(CONFIG_H) $(
 rtlanal.o : rtlanal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TOPLEV_H) \
    $(RTL_H) hard-reg-set.h $(TM_P_H) insn-config.h $(RECOG_H) $(REAL_H) \
    $(FLAGS_H) $(REGS_H) output.h $(TARGET_H) $(FUNCTION_H) $(TREE_H) \
-   $(DF_H)
+   targhooks.h $(DF_H)
 
 varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    $(RTL_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) hard-reg-set.h $(REGS_H) \
@@ -2743,7 +2743,7 @@ emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SY
    $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) insn-config.h $(RECOG_H) \
    $(GGC_H) $(EXPR_H) hard-reg-set.h $(BITMAP_H) $(TOPLEV_H) $(BASIC_BLOCK_H) \
    $(HASHTAB_H) $(TM_P_H) debug.h langhooks.h $(TREE_PASS_H) gt-emit-rtl.h \
-   $(REAL_H) $(DF_H) pointer-set.h
+   $(REAL_H) $(DF_H) $(TARGET_H) pointer-set.h
 real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    $(TOPLEV_H) $(TM_P_H) $(REAL_H) dfp.h
 dfp.o : dfp.c dfp.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)	$(TREE_H) \
@@ -2763,7 +2763,7 @@ jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) 
 simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) $(REAL_H) insn-config.h \
    $(RECOG_H) $(EXPR_H) $(TOPLEV_H) output.h $(FUNCTION_H) $(GGC_H) $(TM_P_H) \
-   $(TREE_H) $(TARGET_H)
+   $(TREE_H) $(TARGET_H) targhooks.h
 cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
    langhooks.h $(TOPLEV_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
    gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
@@ -2949,7 +2949,7 @@ alloc-pool.o : alloc-pool.c $(CONFIG_H) 
 auto-inc-dec.o : auto-inc-dec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) $(RTL_H) $(TM_P_H) hard-reg-set.h $(BASIC_BLOCK_H) insn-config.h \
    $(REGS_H) $(FLAGS_H) output.h $(FUNCTION_H) $(EXCEPT_H) $(TOPLEV_H) $(RECOG_H) \
-   $(EXPR_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H)
+   $(EXPR_H) $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H)
 cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \
    $(REGS_H) hard-reg-set.h output.h $(TOPLEV_H) $(FUNCTION_H) $(EXCEPT_H) $(GGC_H) \
    $(TM_P_H) $(TIMEVAR_H) $(OBSTACK_H) $(TREE_H) alloc-pool.h \
@@ -3068,7 +3068,7 @@ alias.o : alias.c $(CONFIG_H) $(SYSTEM_H
    $(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)
+   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)
@@ -3132,7 +3132,7 @@ haifa-sched.o : haifa-sched.c $(CONFIG_H
 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 \
-   ira.h $(PARAMS_H) $(TM_P_H) ira.h
+   ira.h $(PARAMS_H) $(TM_P_H) ira.h $(TARGET_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-head/gcc/alias.c
===================================================================
--- gcc-head.orig/gcc/alias.c
+++ gcc-head/gcc/alias.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  
 #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:
 
@@ -1049,6 +1050,12 @@ find_base_value (rtx src)
       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.  */
@@ -1063,6 +1070,12 @@ find_base_value (rtx src)
 
     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));
 
@@ -1455,6 +1468,12 @@ find_base_term (rtx x)
       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.  */
@@ -1469,6 +1488,12 @@ find_base_term (rtx x)
 
     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-head/gcc/auto-inc-dec.c
===================================================================
--- gcc-head.orig/gcc/auto-inc-dec.c
+++ gcc-head/gcc/auto-inc-dec.c
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3.  
 #include "tree-pass.h"
 #include "df.h"
 #include "dbgcnt.h"
+#include "target.h"
 
 /* This pass was originally removed from flow.c. However there is
    almost nothing that remains of that code.
@@ -613,6 +614,7 @@ try_merge (void)
   /* The width of the mem being accessed.  */
   int size = GET_MODE_SIZE (GET_MODE (mem));
   rtx last_insn = NULL;
+  enum machine_mode reg_mode = GET_MODE (inc_reg);
 
   switch (inc_insn.form)
     {
@@ -667,33 +669,33 @@ try_merge (void)
     case SIMPLE_PRE_INC:     /* ++size  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_PRE_INC\n");
-      return attempt_change (gen_rtx_PRE_INC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_PRE_INC (reg_mode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_POST_INC:    /* size++  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_POST_INC\n");
-      return attempt_change (gen_rtx_POST_INC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_POST_INC (reg_mode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_PRE_DEC:     /* --size  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_PRE_DEC\n");
-      return attempt_change (gen_rtx_PRE_DEC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_PRE_DEC (reg_mode, inc_reg), inc_reg);
       break;
       
     case SIMPLE_POST_DEC:    /* size--  */
       if (dump_file)
 	fprintf (dump_file, "trying SIMPLE_POST_DEC\n");
-      return attempt_change (gen_rtx_POST_DEC (Pmode, inc_reg), inc_reg);
+      return attempt_change (gen_rtx_POST_DEC (reg_mode, inc_reg), inc_reg);
       break;
       
     case DISP_PRE:           /* ++con   */
       if (dump_file)
 	fprintf (dump_file, "trying DISP_PRE\n");
-      return attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
+      return attempt_change (gen_rtx_PRE_MODIFY (reg_mode,
 						 inc_reg,
-						 gen_rtx_PLUS (Pmode,
+						 gen_rtx_PLUS (reg_mode,
 							       inc_reg,
 							       inc_insn.reg1)),
 			     inc_reg);
@@ -702,9 +704,9 @@ try_merge (void)
     case DISP_POST:          /* con++   */
       if (dump_file)
 	fprintf (dump_file, "trying POST_DISP\n");
-      return attempt_change (gen_rtx_POST_MODIFY (Pmode,
+      return attempt_change (gen_rtx_POST_MODIFY (reg_mode,
 						  inc_reg,
-						  gen_rtx_PLUS (Pmode,
+						  gen_rtx_PLUS (reg_mode,
 								inc_reg,
 								inc_insn.reg1)),
 			     inc_reg);
@@ -713,9 +715,9 @@ try_merge (void)
     case REG_PRE:            /* ++reg   */
       if (dump_file)
 	fprintf (dump_file, "trying PRE_REG\n");
-      return attempt_change (gen_rtx_PRE_MODIFY (Pmode, 
+      return attempt_change (gen_rtx_PRE_MODIFY (reg_mode,
 						 inc_reg,
-						 gen_rtx_PLUS (Pmode,
+						 gen_rtx_PLUS (reg_mode,
 							       inc_reg,
 							       inc_insn.reg1)),
 			     inc_reg);
@@ -724,9 +726,9 @@ try_merge (void)
     case REG_POST:            /* reg++   */
       if (dump_file)
 	fprintf (dump_file, "trying POST_REG\n");
-      return attempt_change (gen_rtx_POST_MODIFY (Pmode, 
+      return attempt_change (gen_rtx_POST_MODIFY (reg_mode,
 						  inc_reg,
-						  gen_rtx_PLUS (Pmode,
+						  gen_rtx_PLUS (reg_mode,
 								inc_reg,
 								inc_insn.reg1)),
 			     inc_reg);
@@ -1089,7 +1091,9 @@ find_inc (bool first_try)
 		     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 (GET_MODE (inc_insn.reg_res) != Pmode)
+		  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");
@@ -1138,7 +1142,9 @@ find_inc (bool first_try)
 	{
 	  /* For this trick to be correct, the result reg of the inc
 	     must be a valid addressing reg.  */
-	  if (GET_MODE (inc_insn.reg_res) != Pmode)
+	  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-head/gcc/combine.c
===================================================================
--- gcc-head.orig/gcc/combine.c
+++ gcc-head/gcc/combine.c
@@ -4190,9 +4190,12 @@ find_split_point (rtx *loc, rtx insn)
       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 (Pmode,
-				 gen_rtx_HIGH (Pmode, 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);
 	}
Index: gcc-head/gcc/cselib.c
===================================================================
--- gcc-head.orig/gcc/cselib.c
+++ gcc-head/gcc/cselib.c
@@ -1875,7 +1875,13 @@ cselib_record_sets (rtx insn)
 	    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);
+	    {
+	      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-head/gcc/doc/tm.texi
===================================================================
--- gcc-head.orig/gcc/doc/tm.texi
+++ gcc-head/gcc/doc/tm.texi
@@ -9836,6 +9836,30 @@ Internally, address spaces are represent
 range 0 to 15 with address space 0 being reserved for the generic
 address space.
 
+@deftypefn {Target Hook} {enum machine_mode} TARGET_ADDR_SPACE_POINTER_MODE (addr_space_t @var{address_space})
+Define this to return the machine mode to use for pointers to
+@var{address_space} if the target supports named address spaces.
+The default version of this hook returns @code{ptr_mode} for the
+generic address space only.
+@end deftypefn
+
+@deftypefn {Target Hook} {enum machine_mode} TARGET_ADDR_SPACE_ADDRESS_MODE (addr_space_t @var{address_space})
+Define this to return the machine mode to use for addresses in
+@var{address_space} if the target supports named address spaces.
+The default version of this hook returns @code{Pmode} for the
+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-head/gcc/dse.c
===================================================================
--- gcc-head.orig/gcc/dse.c
+++ gcc-head/gcc/dse.c
@@ -826,9 +826,9 @@ replace_inc_dec (rtx *r, void *d)
     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)),
+	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;
       }
@@ -837,9 +837,9 @@ replace_inc_dec (rtx *r, void *d)
     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)),
+	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;
       }
@@ -851,7 +851,7 @@ replace_inc_dec (rtx *r, void *d)
 	   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);
+	emit_insn_before (gen_rtx_SET (VOIDmode, r1, add), data->insn);
 	return -1;
       }
 
@@ -1068,6 +1068,8 @@ canon_address (rtx mem,
 	       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;
   int expanded;
@@ -1107,7 +1109,7 @@ canon_address (rtx mem,
 
   *alias_set_out = 0;
 
-  cselib_lookup (mem_address, Pmode, 1);
+  cselib_lookup (mem_address, address_mode, 1);
 
   if (dump_file)
     {
@@ -1186,7 +1188,7 @@ canon_address (rtx mem,
 	}
     }
 
-  *base = cselib_lookup (address, Pmode, true);
+  *base = cselib_lookup (address, address_mode, true);
   *group_id = -1;
 
   if (*base == NULL)
Index: gcc-head/gcc/emit-rtl.c
===================================================================
--- gcc-head.orig/gcc/emit-rtl.c
+++ gcc-head/gcc/emit-rtl.c
@@ -59,6 +59,7 @@ along with GCC; see the file COPYING3.  
 #include "tree-pass.h"
 #include "df.h"
 #include "params.h"
+#include "target.h"
 
 /* Commonly used modes.  */
 
@@ -1977,6 +1978,7 @@ adjust_address_1 (rtx memref, enum machi
   rtx size = 0;
   unsigned int memalign = MEM_ALIGN (memref);
   addr_space_t as = MEM_ADDR_SPACE (memref);
+  enum machine_mode address_mode = targetm.addr_space.address_mode (as);
   int pbits;
 
   /* If there are no changes, just return the original memory reference.  */
@@ -1991,7 +1993,7 @@ adjust_address_1 (rtx memref, enum machi
 
   /* Convert a possibly large offset to a signed value within the
      range of the target address space.  */
-  pbits = GET_MODE_BITSIZE (Pmode);
+  pbits = GET_MODE_BITSIZE (address_mode);
   if (HOST_BITS_PER_WIDE_INT > pbits)
     {
       int shift = HOST_BITS_PER_WIDE_INT - pbits;
@@ -2007,7 +2009,7 @@ adjust_address_1 (rtx memref, enum machi
 	  && offset >= 0
 	  && (unsigned HOST_WIDE_INT) offset
 	      < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
-	addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0),
+	addr = gen_rtx_LO_SUM (address_mode, XEXP (addr, 0),
 			       plus_constant (XEXP (addr, 1), offset));
       else
 	addr = plus_constant (addr, offset);
@@ -2070,8 +2072,9 @@ offset_address (rtx memref, rtx offset, 
 {
   rtx new_rtx, addr = XEXP (memref, 0);
   addr_space_t as = MEM_ADDR_SPACE (memref);
+  enum machine_mode address_mode = targetm.addr_space.address_mode (as);
 
-  new_rtx = simplify_gen_binary (PLUS, Pmode, addr, offset);
+  new_rtx = simplify_gen_binary (PLUS, address_mode, addr, offset);
 
   /* At this point we don't know _why_ the address is invalid.  It
      could have secondary memory references, multiplies or anything.
@@ -2085,7 +2088,7 @@ offset_address (rtx memref, rtx offset, 
       && XEXP (addr, 0) == pic_offset_table_rtx)
     {
       addr = force_reg (GET_MODE (addr), addr);
-      new_rtx = simplify_gen_binary (PLUS, Pmode, addr, offset);
+      new_rtx = simplify_gen_binary (PLUS, address_mode, addr, offset);
     }
 
   update_temp_slot_address (XEXP (memref, 0), new_rtx);
Index: gcc-head/gcc/explow.c
===================================================================
--- gcc-head.orig/gcc/explow.c
+++ gcc-head/gcc/explow.c
@@ -306,27 +306,27 @@ break_out_memory_refs (rtx x)
       rtx op1 = break_out_memory_refs (XEXP (x, 1));
 
       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
-	x = simplify_gen_binary (GET_CODE (x), Pmode, op0, op1);
+	x = simplify_gen_binary (GET_CODE (x), GET_MODE (x), op0, op1);
     }
 
   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.  */
+/* 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 (enum machine_mode to_mode ATTRIBUTE_UNUSED, 
-			rtx x)
+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 from_mode;
+  enum machine_mode pointer_mode, address_mode, from_mode;
   rtx temp;
   enum rtx_code code;
 
@@ -334,7 +334,9 @@ convert_memory_address (enum machine_mod
   if (GET_MODE (x) == to_mode)
     return x;
 
-  from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
+  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.  */
@@ -375,7 +377,8 @@ convert_memory_address (enum machine_mod
 
     case CONST:
       return gen_rtx_CONST (to_mode,
-			    convert_memory_address (to_mode, XEXP (x, 0)));
+			    convert_memory_address_addr_space
+			      (to_mode, XEXP (x, 0), as));
       break;
 
     case PLUS:
@@ -389,10 +392,12 @@ convert_memory_address (enum machine_mod
       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))
+	      && (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 (to_mode, XEXP (x, 0)),
+			       convert_memory_address_addr_space
+				 (to_mode, XEXP (x, 0), as),
 			       XEXP (x, 1));
       break;
 
@@ -413,13 +418,14 @@ rtx
 memory_address_addr_space (enum machine_mode mode, rtx x, addr_space_t as)
 {
   rtx oldx = x;
+  enum machine_mode address_mode = targetm.addr_space.address_mode (as);
 
-  x = convert_memory_address (Pmode, x);
+  x = convert_memory_address_addr_space (address_mode, x, as);
 
   /* By passing constant addresses through registers
      we get a chance to cse them.  */
   if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
-    x = force_reg (Pmode, x);
+    x = force_reg (address_mode, x);
 
   /* We get better cse by rejecting indirect addressing at this stage.
      Let the combiner create indirect addresses where appropriate.
@@ -490,7 +496,7 @@ memory_address_addr_space (enum machine_
       /* Last resort: copy the value to a register, since
 	 the register is a valid address.  */
       else
-	x = force_reg (Pmode, x);
+	x = force_reg (address_mode, x);
     }
 
  done:
@@ -801,7 +807,8 @@ promote_mode (const_tree type ATTRIBUTE_
     case REFERENCE_TYPE:
     case POINTER_TYPE:
       *punsignedp = POINTERS_EXTEND_UNSIGNED;
-      return Pmode;
+      return targetm.addr_space.address_mode
+	       (TREE_ADDR_SPACE (TREE_TYPE (type)));
       break;
 #endif
 
Index: gcc-head/gcc/expmed.c
===================================================================
--- gcc-head.orig/gcc/expmed.c
+++ gcc-head/gcc/expmed.c
@@ -5089,10 +5089,11 @@ make_tree (tree type, rtx x)
     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 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 (TYPE_MODE (type), x);
+	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-head/gcc/expr.c
===================================================================
--- gcc-head.orig/gcc/expr.c
+++ gcc-head/gcc/expr.c
@@ -877,6 +877,8 @@ move_by_pieces (rtx to, rtx from, unsign
 		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;
@@ -888,6 +890,7 @@ move_by_pieces (rtx to, rtx from, unsign
   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
@@ -898,6 +901,7 @@ move_by_pieces (rtx to, rtx from, unsign
     }
   else
     {
+      to_addr_mode = VOIDmode;
       to_addr = NULL_RTX;
       data.to = NULL_RTX;
       data.autinc_to = 1;
@@ -933,32 +937,34 @@ move_by_pieces (rtx to, rtx from, unsign
 
       if (USE_LOAD_PRE_DECREMENT (mode) && data.reverse && ! data.autinc_from)
 	{
-	  data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
+	  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_addr_to_reg (from_addr);
+	  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_addr_to_reg (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_addr_to_reg (plus_constant (to_addr, len));
+	  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_addr_to_reg (to_addr);
+	  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_addr_to_reg (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);
@@ -1013,7 +1019,8 @@ move_by_pieces (rtx to, rtx from, unsign
 	      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,
+		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,
@@ -1467,6 +1474,10 @@ emit_block_move_via_loop (rtx x, rtx y, 
 			  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);
@@ -1486,9 +1497,13 @@ emit_block_move_via_loop (rtx x, rtx y, 
   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);
+  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);
 
@@ -2383,6 +2398,8 @@ store_by_pieces (rtx to, unsigned HOST_W
 		 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)
@@ -2411,7 +2428,8 @@ store_by_pieces (rtx to, unsigned HOST_W
 	      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,
+		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,
@@ -2466,6 +2484,8 @@ static void
 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;
@@ -2497,7 +2517,8 @@ store_by_pieces_1 (struct store_by_piece
 
       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->to_addr = copy_to_mode_reg (to_addr_mode,
+					    plus_constant (to_addr, data->len));
 	  data->autinc_to = 1;
 	  data->explicit_inc_to = -1;
 	}
@@ -2505,13 +2526,13 @@ store_by_pieces_1 (struct store_by_piece
       if (USE_STORE_POST_INCREMENT (mode) && ! data->reverse
 	  && ! data->autinc_to)
 	{
-	  data->to_addr = copy_addr_to_reg (to_addr);
+	  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_addr_to_reg (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);
@@ -4213,6 +4234,7 @@ expand_assignment (tree to, tree from, b
 
       if (offset != 0)
 	{
+	  enum machine_mode address_mode;
 	  rtx offset_rtx;
 
 	  if (!MEM_P (to_rtx))
@@ -4225,13 +4247,10 @@ expand_assignment (tree to, tree from, b
 	    }
 
 	  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
+	  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.  */
@@ -4370,7 +4389,10 @@ expand_assignment (tree to, tree from, b
       else
 	{
 	  if (POINTER_TYPE_P (TREE_TYPE (to)))
-	    value = convert_memory_address (GET_MODE (to_rtx), value);
+	    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);
@@ -4729,6 +4751,11 @@ store_expr (tree exp, rtx target, int ca
 			      ? 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,
@@ -4741,14 +4768,14 @@ store_expr (tree exp, rtx target, int ca
 	      rtx label = 0;
 
 	      /* Copy that much.  */
-	      copy_size_rtx = convert_to_mode (ptr_mode, copy_size_rtx,
+	      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 ptr_mode.  */
+		 Do all calculations in pointer_mode.  */
 	      if (CONST_INT_P (copy_size_rtx))
 		{
 		  size = plus_constant (size, -INTVAL (copy_size_rtx));
@@ -4761,11 +4788,10 @@ store_expr (tree exp, rtx target, int ca
 				       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,
+		  if (GET_MODE (copy_size_rtx) != address_mode)
+		    copy_size_rtx = convert_to_mode (address_mode,
+						     copy_size_rtx,
 						     TYPE_UNSIGNED (sizetype));
-#endif
 
 		  target = offset_address (target, copy_size_rtx,
 					   highest_pow2_factor (copy_size));
@@ -5255,6 +5281,7 @@ store_constructor (tree exp, rtx target,
 
 	    if (offset)
 	      {
+	        enum machine_mode address_mode;
 		rtx offset_rtx;
 
 		offset
@@ -5265,13 +5292,10 @@ store_constructor (tree exp, rtx target,
 		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
+		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));
@@ -6794,7 +6818,7 @@ expand_expr_constant (tree exp, int defe
 
 static rtx
 expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
-		         enum expand_modifier modifier)
+		         enum expand_modifier modifier, addr_space_t as)
 {
   rtx result, subtarget;
   tree inner, offset;
@@ -6821,7 +6845,7 @@ expand_expr_addr_expr_1 (tree exp, rtx t
     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);
+				      tmode, modifier, as);
 
     case REALPART_EXPR:
       /* The real part of the complex number is always first, therefore
@@ -6911,7 +6935,7 @@ expand_expr_addr_expr_1 (tree exp, rtx t
       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);
+  result = expand_expr_addr_expr_1 (inner, subtarget, tmode, modifier, as);
 
   if (offset)
     {
@@ -6923,8 +6947,8 @@ expand_expr_addr_expr_1 (tree exp, rtx t
 			 modifier == EXPAND_INITIALIZER
 			  ? EXPAND_INITIALIZER : EXPAND_NORMAL);
 
-      result = convert_memory_address (tmode, result);
-      tmp = convert_memory_address (tmode, tmp);
+      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);
@@ -6957,6 +6981,9 @@ static rtx
 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;
   rtx result;
 
@@ -6964,14 +6991,21 @@ expand_expr_addr_expr (tree exp, rtx tar
   if (tmode == VOIDmode)
     tmode = TYPE_MODE (TREE_TYPE (exp));
 
+  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);
+    }
+
   /* We can get called with some Weird Things if the user does silliness
      like "(short) &a".  In that case, convert_memory_address won't do
      the right thing, so ignore the given target mode.  */
-  if (tmode != Pmode && tmode != ptr_mode)
-    tmode = Pmode;
+  if (tmode != address_mode && tmode != pointer_mode)
+    tmode = address_mode;
 
   result = expand_expr_addr_expr_1 (TREE_OPERAND (exp, 0), target,
-				    tmode, modifier);
+				    tmode, modifier, as);
 
   /* Despite expand_expr claims concerning ignoring TMODE when not
      strictly convenient, stuff breaks if we don't honor it.  Note
@@ -6980,7 +7014,7 @@ expand_expr_addr_expr (tree exp, rtx tar
   if (rmode == VOIDmode)
     rmode = tmode;
   if (rmode != tmode)
-    result = convert_memory_address (tmode, result);
+    result = convert_memory_address_addr_space (tmode, result, as);
 
   return result;
 }
@@ -8656,6 +8690,7 @@ expand_expr_real_1 (tree exp, rtx target
       {
 	tree exp1 = treeop0;
 	addr_space_t as = 0;
+	enum machine_mode address_mode = Pmode;
 
 	if (modifier != EXPAND_WRITE)
 	  {
@@ -8667,7 +8702,10 @@ expand_expr_real_1 (tree exp, rtx target
 	  }
 
 	if (POINTER_TYPE_P (TREE_TYPE (exp1)))
-	  as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp1)));
+	  {
+	    as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp1)));
+	    address_mode = targetm.addr_space.address_mode (as);
+	  }
 
 	op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
 	op0 = memory_address_addr_space (mode, op0, as);
@@ -8675,7 +8713,7 @@ expand_expr_real_1 (tree exp, rtx target
 	if (code == ALIGN_INDIRECT_REF)
 	  {
 	    int align = TYPE_ALIGN_UNIT (type);
-	    op0 = gen_rtx_AND (Pmode, op0, GEN_INT (-align));
+	    op0 = gen_rtx_AND (address_mode, op0, GEN_INT (-align));
 	    op0 = memory_address_addr_space (mode, op0, as);
 	  }
 
@@ -8718,7 +8756,7 @@ expand_expr_real_1 (tree exp, rtx target
 	struct mem_address addr;
 
 	get_address_description (exp, &addr);
-	op0 = addr_for_mem_ref (&addr, true);
+	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);
@@ -9010,18 +9048,16 @@ expand_expr_real_1 (tree exp, rtx target
 
 	if (offset)
 	  {
+	    enum machine_mode address_mode;
 	    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
+	    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-head/gcc/fold-const.c
===================================================================
--- gcc-head.orig/gcc/fold-const.c
+++ gcc-head/gcc/fold-const.c
@@ -206,15 +206,9 @@ fit_double_type (unsigned HOST_WIDE_INT 
 {
   unsigned HOST_WIDE_INT low0 = l1;
   HOST_WIDE_INT high0 = h1;
-  unsigned int prec;
+  unsigned int prec = int_or_pointer_precision (type);
   int sign_extended_type;
 
-  if (POINTER_TYPE_P (type)
-      || TREE_CODE (type) == OFFSET_TYPE)
-    prec = POINTER_SIZE;
-  else
-    prec = TYPE_PRECISION (type);
-
   /* Size types *are* sign extended.  */
   sign_extended_type = (!TYPE_UNSIGNED (type)
 			|| (TREE_CODE (type) == INTEGER_TYPE
Index: gcc-head/gcc/ifcvt.c
===================================================================
--- gcc-head.orig/gcc/ifcvt.c
+++ gcc-head/gcc/ifcvt.c
@@ -1332,9 +1332,12 @@ noce_try_cmove_arith (struct noce_if_inf
       && 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 (Pmode);
+      x = gen_reg_rtx (address_mode);
       is_mem = 1;
     }
 
Index: gcc-head/gcc/output.h
===================================================================
--- gcc-head.orig/gcc/output.h
+++ gcc-head/gcc/output.h
@@ -626,7 +626,6 @@ extern void default_emit_except_table_la
 extern void default_internal_label (FILE *, const char *, unsigned long);
 extern void default_file_start (void);
 extern void file_end_indicate_exec_stack (void);
-extern bool default_valid_pointer_mode (enum machine_mode);
 
 extern void default_elf_asm_output_external (FILE *file, tree,
 					     const char *);
Index: gcc-head/gcc/regcprop.c
===================================================================
--- gcc-head.orig/gcc/regcprop.c
+++ gcc-head/gcc/regcprop.c
@@ -247,7 +247,7 @@ kill_autoinc_value (rtx *px, void *data)
     {
       x = XEXP (x, 0);
       kill_value (x, vd);
-      set_value_regno (REGNO (x), Pmode, vd);
+      set_value_regno (REGNO (x), GET_MODE (x), vd);
       return -1;
     }
 
Index: gcc-head/gcc/regmove.c
===================================================================
--- gcc-head.orig/gcc/regmove.c
+++ gcc-head/gcc/regmove.c
@@ -184,7 +184,9 @@ try_auto_increment (rtx insn, rtx inc_in
 		   &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);
+			       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-head/gcc/reload.c
===================================================================
--- gcc-head.orig/gcc/reload.c
+++ gcc-head/gcc/reload.c
@@ -3987,12 +3987,15 @@ find_reloads (rtx insn, int replace, int
 		 && MEM_P (recog_data.operand[i]))
 	  {
 	    /* If the address to be reloaded is a VOIDmode constant,
-	       use Pmode as mode of the reload register, as would have
-	       been done by find_reloads_address.  */
+	       use the default address mode as mode of the reload register,
+	       as would have been done by find_reloads_address.  */
 	    enum machine_mode address_mode;
 	    address_mode = GET_MODE (XEXP (recog_data.operand[i], 0));
 	    if (address_mode == VOIDmode)
-	      address_mode = Pmode;
+	      {
+		addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
+		address_mode = targetm.addr_space.address_mode (as);
+	      }
 
 	    operand_reloadnum[i]
 	      = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
@@ -5112,7 +5115,7 @@ find_reloads_address (enum machine_mode 
 	     That will at least work.  */
 	  find_reloads_address_part (ad, loc,
 				     base_reg_class (mode, MEM, SCRATCH),
-				     Pmode, opnum, type, ind_levels);
+				     GET_MODE (ad), opnum, type, ind_levels);
 	}
       return ! removed_and;
     }
@@ -5234,6 +5237,10 @@ find_reloads_address (enum machine_mode 
      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
@@ -5246,7 +5253,7 @@ find_reloads_address (enum machine_mode 
 	}
 
       find_reloads_address_part (ad, loc, base_reg_class (mode, MEM, SCRATCH),
-				 Pmode, opnum, type, ind_levels);
+				 address_mode, opnum, type, ind_levels);
       return ! removed_and;
     }
 
@@ -5333,16 +5340,12 @@ subst_reg_equivs (rtx ad, rtx insn)
    This routine assumes both inputs are already in canonical form.  */
 
 rtx
-form_sum (rtx x, rtx y)
+form_sum (enum machine_mode mode, rtx x, rtx y)
 {
   rtx tem;
-  enum machine_mode mode = GET_MODE (x);
-
-  if (mode == VOIDmode)
-    mode = GET_MODE (y);
 
-  if (mode == VOIDmode)
-    mode = Pmode;
+  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));
@@ -5352,12 +5355,12 @@ form_sum (rtx x, rtx y)
     tem = x, x = y, y = tem;
 
   if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
-    return form_sum (XEXP (x, 0), form_sum (XEXP (x, 1), y));
+    return form_sum (mode, XEXP (x, 0), form_sum (mode, XEXP (x, 1), y));
 
   /* Note that if the operands of Y are specified in the opposite
      order in the recursive calls below, infinite recursion will occur.  */
   if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
-    return form_sum (form_sum (x, XEXP (y, 0)), XEXP (y, 1));
+    return form_sum (mode, form_sum (mode, x, XEXP (y, 0)), XEXP (y, 1));
 
   /* If both constant, encapsulate sum.  Otherwise, just form sum.  A
      constant will have been placed second.  */
@@ -5424,9 +5427,9 @@ subst_indexed_address (rtx addr)
 
       /* Compute the sum.  */
       if (op2 != 0)
-	op1 = form_sum (op1, op2);
+	op1 = form_sum (GET_MODE (addr), op1, op2);
       if (op1 != 0)
-	op0 = form_sum (op0, op1);
+	op0 = form_sum (GET_MODE (addr), op0, op1);
 
       return op0;
     }
@@ -5826,7 +5829,8 @@ find_reloads_address_1 (enum machine_mod
 	      rtx equiv = (MEM_P (XEXP (x, 0))
 			   ? XEXP (x, 0)
 			   : reg_equiv_mem[regno]);
-	      int icode = (int) optab_handler (add_optab, Pmode)->insn_code;
+	      int icode
+		= (int) optab_handler (add_optab, GET_MODE (x))->insn_code;
 	      if (insn && NONJUMP_INSN_P (insn) && equiv
 		  && memory_operand (equiv, GET_MODE (equiv))
 #ifdef HAVE_cc0
@@ -5834,9 +5838,9 @@ find_reloads_address_1 (enum machine_mod
 #endif
 		  && ! (icode != CODE_FOR_nothing
 			&& ((*insn_data[icode].operand[0].predicate)
-			    (equiv, Pmode))
+			    (equiv, GET_MODE (x)))
 			&& ((*insn_data[icode].operand[1].predicate)
-			    (equiv, Pmode))))
+			    (equiv, GET_MODE (x)))))
 		{
 		  /* We use the original pseudo for loc, so that
 		     emit_reload_insns() knows which pseudo this
Index: gcc-head/gcc/reload.h
===================================================================
--- gcc-head.orig/gcc/reload.h
+++ gcc-head/gcc/reload.h
@@ -289,7 +289,7 @@ extern int find_reloads (rtx, int, int, 
    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);
+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-head/gcc/reload1.c
===================================================================
--- gcc-head.orig/gcc/reload1.c
+++ gcc-head/gcc/reload1.c
@@ -2655,7 +2655,7 @@ eliminate_regs_1 (rtx x, enum machine_mo
 		     && reg_equiv_constant[REGNO (new0)] != 0)
 	      new0 = reg_equiv_constant[REGNO (new0)];
 
-	    new_rtx = form_sum (new0, new1);
+	    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
Index: gcc-head/gcc/rtl.h
===================================================================
--- gcc-head.orig/gcc/rtl.h
+++ gcc-head/gcc/rtl.h
@@ -1606,7 +1606,10 @@ extern unsigned int subreg_highpart_offs
 					    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 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-head/gcc/rtlanal.c
===================================================================
--- gcc-head.orig/gcc/rtlanal.c
+++ gcc-head/gcc/rtlanal.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.  
 #include "function.h"
 #include "df.h"
 #include "tree.h"
+#include "targhooks.h"
 
 /* Forward declarations */
 static void set_of_1 (rtx, const_rtx, void *);
@@ -3748,7 +3749,12 @@ nonzero_bits1 (const_rtx x, enum machine
 #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
+      /* 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
@@ -3985,7 +3991,13 @@ nonzero_bits1 (const_rtx x, enum machine
 	/* 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
+	/* 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);
@@ -4259,8 +4271,13 @@ num_sign_bit_copies1 (const_rtx x, enum 
 #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))
+      /* 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
 
@@ -4456,7 +4473,12 @@ num_sign_bit_copies1 (const_rtx x, enum 
       /* 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
+      /* 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-head/gcc/sched-deps.c
===================================================================
--- gcc-head.orig/gcc/sched-deps.c
+++ gcc-head/gcc/sched-deps.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  
 #include "params.h"
 #include "cselib.h"
 #include "ira.h"
+#include "target.h"
 
 #ifdef INSN_SCHEDULING
 
@@ -2256,8 +2257,11 @@ sched_analyze_1 (struct deps *deps, rtx 
 
       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), Pmode, 1);
+	  cselib_lookup (XEXP (t, 0), address_mode, 1);
 	  XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
 	}
       t = canon_rtx (t);
@@ -2416,8 +2420,11 @@ sched_analyze_2 (struct deps *deps, rtx 
 
 	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), Pmode, 1);
+	    cselib_lookup (XEXP (t, 0), address_mode, 1);
 	    XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
 	  }
 	t = canon_rtx (t);
Index: gcc-head/gcc/sel-sched-dump.c
===================================================================
--- gcc-head.orig/gcc/sel-sched-dump.c
+++ gcc-head/gcc/sel-sched-dump.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  
 #include "output.h"
 #include "basic-block.h"
 #include "cselib.h"
+#include "target.h"
 
 #ifdef INSN_SCHEDULING
 #include "sel-sched-ir.h"
@@ -931,10 +932,13 @@ rtx
 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), Pmode, 0))
+  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-head/gcc/simplify-rtx.c
===================================================================
--- gcc-head.orig/gcc/simplify-rtx.c
+++ gcc-head/gcc/simplify-rtx.c
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  
 #include "output.h"
 #include "ggc.h"
 #include "target.h"
+#include "targhooks.h"
 
 /* Simplification and canonicalization of RTL.  */
 
@@ -963,7 +964,12 @@ simplify_unary_operation_1 (enum rtx_cod
 	return rtl_hooks.gen_lowpart_no_emit (mode, op);
 
 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
-      if (! POINTERS_EXTEND_UNSIGNED
+      /* 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
@@ -985,7 +991,12 @@ simplify_unary_operation_1 (enum rtx_cod
 	return rtl_hooks.gen_lowpart_no_emit (mode, op);
 
 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
-      if (POINTERS_EXTEND_UNSIGNED > 0
+      /* 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-head/gcc/stor-layout.c
===================================================================
--- gcc-head.orig/gcc/stor-layout.c
+++ gcc-head/gcc/stor-layout.c
@@ -52,9 +52,9 @@ unsigned int maximum_field_alignment = T
 /* ... and its original value in bytes, specified via -fpack-struct=<value>.  */
 unsigned int initial_max_fld_align = TARGET_DEFAULT_PACK_STRUCT;
 
-/* Nonzero if all REFERENCE_TYPEs are internal and hence should be
-   allocated in Pmode, not ptr_mode.   Set only by internal_reference_types
-   called only by a front end.  */
+/* Nonzero if all REFERENCE_TYPEs are internal and hence should be allocated
+   in the address spaces' address_mode, not pointer_mode.   Set only by
+   internal_reference_types called only by a front end.  */
 static int reference_types_internal = 0;
 
 static tree self_referential_size (tree);
@@ -71,8 +71,8 @@ extern void debug_rli (record_layout_inf
 
 static GTY(()) tree pending_sizes;
 
-/* Show that REFERENCE_TYPES are internal and should be Pmode.  Called only
-   by front end.  */
+/* Show that REFERENCE_TYPES are internal and should use address_mode.
+   Called only by front end.  */
 
 void
 internal_reference_types (void)
@@ -1915,6 +1915,7 @@ layout_type (tree type)
       /* A pointer might be MODE_PARTIAL_INT,
 	 but ptrdiff_t must be integral.  */
       SET_TYPE_MODE (type, mode_for_size (POINTER_SIZE, MODE_INT, 0));
+      TYPE_PRECISION (type) = POINTER_SIZE;
       break;
 
     case FUNCTION_TYPE:
@@ -1930,16 +1931,17 @@ layout_type (tree type)
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       {
-	enum machine_mode mode = ((TREE_CODE (type) == REFERENCE_TYPE
-				   && reference_types_internal)
-				  ? Pmode : TYPE_MODE (type));
-
-	int nbits = GET_MODE_BITSIZE (mode);
+	enum machine_mode mode = TYPE_MODE (type);
+	if (TREE_CODE (type) == REFERENCE_TYPE && reference_types_internal)
+	  {
+	    addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
+	    mode = targetm.addr_space.address_mode (as);
+	  }
 
-	TYPE_SIZE (type) = bitsize_int (nbits);
+	TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode));
 	TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
 	TYPE_UNSIGNED (type) = 1;
-	TYPE_PRECISION (type) = nbits;
+	TYPE_PRECISION (type) = GET_MODE_BITSIZE (mode);
       }
       break;
 
Index: gcc-head/gcc/target-def.h
===================================================================
--- gcc-head.orig/gcc/target-def.h
+++ gcc-head/gcc/target-def.h
@@ -463,6 +463,19 @@
 #define TARGET_VALID_POINTER_MODE default_valid_pointer_mode
 #endif
 
+#ifndef TARGET_ADDR_SPACE_POINTER_MODE
+#define TARGET_ADDR_SPACE_POINTER_MODE default_addr_space_pointer_mode
+#endif
+
+#ifndef TARGET_ADDR_SPACE_ADDRESS_MODE
+#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
@@ -483,6 +496,9 @@
 
 #define TARGET_ADDR_SPACE_HOOKS			\
   {						\
+    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-head/gcc/target.h
===================================================================
--- gcc-head.orig/gcc/target.h
+++ gcc-head/gcc/target.h
@@ -682,6 +682,16 @@ struct gcc_target
 
   /* Support for named address spaces.  */
   struct addr_space {
+    /* MODE to use for a pointer into another address space.  */
+    enum machine_mode (* pointer_mode) (addr_space_t);
+
+    /* 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-head/gcc/targhooks.c
===================================================================
--- gcc-head.orig/gcc/targhooks.c
+++ gcc-head/gcc/targhooks.c
@@ -771,6 +771,46 @@ default_builtin_vector_alignment_reachab
   return true;
 }
 
+/* Determine whether or not a pointer mode is valid. Assume defaults
+   of ptr_mode or Pmode - can be overridden.  */
+bool
+default_valid_pointer_mode (enum machine_mode mode)
+{
+  return (mode == ptr_mode || mode == Pmode);
+}
+
+/* Return the mode for a pointer to a given ADDRSPACE, defaulting to ptr_mode
+   for the generic address space only.  */
+
+enum machine_mode
+default_addr_space_pointer_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
+{
+  gcc_assert (addrspace == 0);
+  return ptr_mode;
+}
+
+/* Return the mode for an address in a given ADDRSPACE, defaulting to Pmode
+   for the generic address space only.  */
+
+enum machine_mode
+default_addr_space_address_mode (addr_space_t addrspace ATTRIBUTE_UNUSED)
+{
+  gcc_assert (addrspace == 0);
+  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-head/gcc/targhooks.h
===================================================================
--- gcc-head.orig/gcc/targhooks.h
+++ gcc-head/gcc/targhooks.h
@@ -113,6 +113,11 @@ extern bool default_hard_regno_scratch_o
 extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
 extern bool default_target_option_pragma_parse (tree, tree);
 extern bool default_target_can_inline_p (tree, tree);
+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-head/gcc/tree-ssa-address.c
===================================================================
--- gcc-head.orig/gcc/tree-ssa-address.c
+++ gcc-head/gcc/tree-ssa-address.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  
 #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):
@@ -70,32 +71,38 @@ along with GCC; see the file COPYING3.  
 /* A "template" for memory address, used to determine whether the address is
    valid for mode.  */
 
-struct GTY (()) mem_addr_template {
+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;
 
-/* The templates.  Each of the five bits of the index corresponds to one
-   component of TARGET_MEM_REF being present, see TEMPL_IDX.  */
+DEF_VEC_O (mem_addr_template);
+DEF_VEC_ALLOC_O (mem_addr_template, gc);
 
-static GTY (()) struct mem_addr_template templates[32];
+/* 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.  */
 
-#define TEMPL_IDX(SYMBOL, BASE, INDEX, STEP, OFFSET) \
-  (((SYMBOL != 0) << 4) \
+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.  Stores pointers to where step is placed to
-   *STEP_P and offset to *OFFSET_P.  */
+   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 (rtx symbol, rtx base, rtx index, rtx step, rtx offset,
+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;
@@ -111,7 +118,7 @@ gen_addr_rtx (rtx symbol, rtx base, rtx 
       act_elem = index;
       if (step)
 	{
-	  act_elem = gen_rtx_MULT (Pmode, act_elem, step);
+	  act_elem = gen_rtx_MULT (address_mode, act_elem, step);
 
 	  if (step_p)
 	    *step_p = &XEXP (act_elem, 1);
@@ -123,7 +130,7 @@ gen_addr_rtx (rtx symbol, rtx base, rtx 
   if (base)
     {
       if (*addr)
-	*addr = simplify_gen_binary (PLUS, Pmode, base, *addr);
+	*addr = simplify_gen_binary (PLUS, address_mode, base, *addr);
       else
 	*addr = base;
     }
@@ -133,7 +140,7 @@ gen_addr_rtx (rtx symbol, rtx base, rtx 
       act_elem = symbol;
       if (offset)
 	{
-	  act_elem = gen_rtx_PLUS (Pmode, act_elem, offset);
+	  act_elem = gen_rtx_PLUS (address_mode, act_elem, offset);
 
 	  if (offset_p)
 	    *offset_p = &XEXP (act_elem, 1);
@@ -141,11 +148,11 @@ gen_addr_rtx (rtx symbol, rtx base, rtx 
 	  if (GET_CODE (symbol) == SYMBOL_REF
 	      || GET_CODE (symbol) == LABEL_REF
 	      || GET_CODE (symbol) == CONST)
-	    act_elem = gen_rtx_CONST (Pmode, act_elem);
+	    act_elem = gen_rtx_CONST (address_mode, act_elem);
 	}
 
       if (*addr)
-	*addr = gen_rtx_PLUS (Pmode, *addr, act_elem);
+	*addr = gen_rtx_PLUS (address_mode, *addr, act_elem);
       else
 	*addr = act_elem;
     }
@@ -153,7 +160,7 @@ gen_addr_rtx (rtx symbol, rtx base, rtx 
     {
       if (*addr)
 	{
-	  *addr = gen_rtx_PLUS (Pmode, *addr, offset);
+	  *addr = gen_rtx_PLUS (address_mode, *addr, offset);
 	  if (offset_p)
 	    *offset_p = &XEXP (*addr, 1);
 	}
@@ -169,55 +176,64 @@ gen_addr_rtx (rtx symbol, rtx base, rtx 
     *addr = const0_rtx;
 }
 
-/* Returns address for TARGET_MEM_REF with parameters given by ADDR.
+/* 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, bool really_expand)
+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;
-  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);
+			     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), Pmode);
+			      TREE_INT_CST_HIGH (addr->offset), address_mode);
   else
     off = NULL_RTX;
 
   if (!really_expand)
     {
+      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.  */
-      if (!templates_initialized)
+      templ = VEC_index (mem_addr_template, mem_addr_template_list, templ_index);
+      if (!templ->ref)
 	{
-	  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);
+	  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);
 	}
 
-      templ = templates + TEMPL_IDX (addr->symbol, addr->base, addr->index,
-				     st, off);
       if (st)
 	*templ->step_p = st;
       if (off)
@@ -229,16 +245,16 @@ addr_for_mem_ref (struct mem_address *ad
   /* Otherwise really expand the expressions.  */
   sym = (addr->symbol
 	 ? expand_expr (build_addr (addr->symbol, current_function_decl),
-			NULL_RTX, Pmode, EXPAND_NORMAL)
+			NULL_RTX, address_mode, EXPAND_NORMAL)
 	 : NULL_RTX);
   bse = (addr->base
-	 ? expand_expr (addr->base, NULL_RTX, Pmode, EXPAND_NORMAL)
+	 ? expand_expr (addr->base, NULL_RTX, address_mode, EXPAND_NORMAL)
 	 : NULL_RTX);
   idx = (addr->index
-	 ? expand_expr (addr->index, NULL_RTX, Pmode, EXPAND_NORMAL)
+	 ? expand_expr (addr->index, NULL_RTX, address_mode, EXPAND_NORMAL)
 	 : NULL_RTX);
 
-  gen_addr_rtx (sym, bse, idx, st, off, &address, NULL, NULL);
+  gen_addr_rtx (address_mode, sym, bse, idx, st, off, &address, NULL, NULL);
   return address;
 }
 
@@ -310,7 +326,7 @@ valid_mem_ref_p (enum machine_mode mode,
 {
   rtx address;
 
-  address = addr_for_mem_ref (addr, false);
+  address = addr_for_mem_ref (addr, as, false);
   if (!address)
     return false;
 
Index: gcc-head/gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc-head.orig/gcc/tree-ssa-loop-ivopts.c
+++ gcc-head/gcc/tree-ssa-loop-ivopts.c
@@ -2643,13 +2643,14 @@ 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 (Pmode, name);
+      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);
@@ -2657,7 +2658,7 @@ produce_memory_decl_rtl (tree obj, int *
     }
   else
     {
-      x = gen_raw_REG (Pmode, (*regno)++);
+      x = gen_raw_REG (address_mode, (*regno)++);
       x = gen_rtx_MEM (DECL_MODE (obj), x);
       set_mem_addr_space (x, as);
     }
@@ -3045,16 +3046,17 @@ multiplier_allowed_in_address_p (HOST_WI
   valid_mult = VEC_index (sbitmap, valid_mult_list, data_index);
   if (!valid_mult)
     {
-      rtx reg1 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
+      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, Pmode, reg1, NULL_RTX);
+      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, Pmode);
+	  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);
 	}
@@ -3108,6 +3110,7 @@ get_address_cost (bool symbol_present, b
 		  addr_space_t as, bool speed,
 		  bool stmt_after_inc, bool *may_autoinc)
 {
+  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;
@@ -3136,12 +3139,12 @@ get_address_cost (bool symbol_present, b
 
       data = (address_cost_data) xcalloc (1, sizeof (*data));
 
-      reg1 = gen_raw_REG (Pmode, LAST_VIRTUAL_REGISTER + 1);
+      reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
 
-      addr = gen_rtx_fmt_ee (PLUS, Pmode, reg1, NULL_RTX);
+      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, Pmode);
+	  XEXP (addr, 1) = gen_int_mode (i, address_mode);
 	  if (!memory_address_addr_space_p (mem_mode, addr, as))
 	    break;
 	}
@@ -3150,7 +3153,7 @@ get_address_cost (bool symbol_present, b
 
       for (i = start; i <= 1 << 20; i <<= 1)
 	{
-	  XEXP (addr, 1) = gen_int_mode (-i, Pmode);
+	  XEXP (addr, 1) = gen_int_mode (-i, address_mode);
 	  if (!memory_address_addr_space_p (mem_mode, addr, as))
 	    break;
 	}
@@ -3177,30 +3180,30 @@ get_address_cost (bool symbol_present, b
 
       /* 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);
+      reg0 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
+      reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2);
 
       if (HAVE_PRE_DECREMENT)
 	{
-	  addr = gen_rtx_PRE_DEC (Pmode, reg0);
+	  addr = gen_rtx_PRE_DEC (address_mode, reg0);
 	  has_predec[mem_mode]
 	    = memory_address_addr_space_p (mem_mode, addr, as);
 	}
       if (HAVE_POST_DECREMENT)
 	{
-	  addr = gen_rtx_POST_DEC (Pmode, reg0);
+	  addr = gen_rtx_POST_DEC (address_mode, reg0);
 	  has_postdec[mem_mode]
 	    = memory_address_addr_space_p (mem_mode, addr, as);
 	}
       if (HAVE_PRE_INCREMENT)
 	{
-	  addr = gen_rtx_PRE_INC (Pmode, reg0);
+	  addr = gen_rtx_PRE_INC (address_mode, reg0);
 	  has_preinc[mem_mode]
 	    = memory_address_addr_space_p (mem_mode, addr, as);
 	}
       if (HAVE_POST_INCREMENT)
 	{
-	  addr = gen_rtx_POST_INC (Pmode, reg0);
+	  addr = gen_rtx_POST_INC (address_mode, reg0);
 	  has_postinc[mem_mode]
 	    = memory_address_addr_space_p (mem_mode, addr, as);
 	}
@@ -3213,15 +3216,15 @@ get_address_cost (bool symbol_present, b
 
 	  addr = reg0;
 	  if (rat_p)
-	    addr = gen_rtx_fmt_ee (MULT, Pmode, addr,
-				   gen_int_mode (rat, Pmode));
+	    addr = gen_rtx_fmt_ee (MULT, address_mode, addr,
+				   gen_int_mode (rat, address_mode));
 
 	  if (var_p)
-	    addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, reg1);
+	    addr = gen_rtx_fmt_ee (PLUS, address_mode, addr, reg1);
 
 	  if (sym_p)
 	    {
-	      base = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (""));
+	      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
@@ -3229,18 +3232,18 @@ get_address_cost (bool symbol_present, b
 	      SYMBOL_REF_FLAGS (base) = SYMBOL_FLAG_LOCAL;
 
 	      if (off_p)
-		base = gen_rtx_fmt_e (CONST, Pmode,
+		base = gen_rtx_fmt_e (CONST, address_mode,
 				      gen_rtx_fmt_ee
-					(PLUS, Pmode, base,
-					 gen_int_mode (off, Pmode)));
+					(PLUS, address_mode, base,
+					 gen_int_mode (off, address_mode)));
 	    }
 	  else if (off_p)
-	    base = gen_int_mode (off, Pmode);
+	    base = gen_int_mode (off, address_mode);
 	  else
 	    base = NULL_RTX;
     
 	  if (base)
-	    addr = gen_rtx_fmt_ee (PLUS, Pmode, addr, base);
+	    addr = gen_rtx_fmt_ee (PLUS, address_mode, addr, base);
 
 	  start_sequence ();
 	  /* To avoid splitting addressing modes, pretend that no cse will
@@ -3272,7 +3275,7 @@ get_address_cost (bool symbol_present, b
 	 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);
+      add_c = add_cost (address_mode, speed);
       for (i = 0; i < 8; i++)
 	{
 	  var_p = i & 1;
@@ -3321,7 +3324,7 @@ get_address_cost (bool symbol_present, b
 		   data_index, data);
     }
 
-  bits = GET_MODE_BITSIZE (Pmode);
+  bits = GET_MODE_BITSIZE (address_mode);
   mask = ~(~(unsigned HOST_WIDE_INT) 0 << (bits - 1) << 1);
   offset &= mask;
   if ((offset >> (bits - 1) & 1))
@@ -3353,10 +3356,10 @@ get_address_cost (bool symbol_present, b
 	     && multiplier_allowed_in_address_p (ratio, mem_mode, as));
 
   if (ratio != 1 && !ratio_p)
-    cost += multiply_by_cost (ratio, Pmode, speed);
+    cost += multiply_by_cost (ratio, address_mode, speed);
 
   if (s_offset && !offset_p && !symbol_present)
-    cost += add_cost (Pmode, speed);
+    cost += add_cost (address_mode, speed);
 
   if (may_autoinc)
     *may_autoinc = autoinc;
Index: gcc-head/gcc/tree-vect-data-refs.c
===================================================================
--- gcc-head.orig/gcc/tree-vect-data-refs.c
+++ gcc-head/gcc/tree-vect-data-refs.c
@@ -2380,8 +2380,9 @@ vect_create_data_ref_ptr (gimple stmt, s
 	  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_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-head/gcc/tree.c
===================================================================
--- gcc-head.orig/gcc/tree.c
+++ gcc-head/gcc/tree.c
@@ -1670,8 +1670,7 @@ integer_pow2p (const_tree expr)
   if (TREE_CODE (expr) != INTEGER_CST)
     return 0;
 
-  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
-	  ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
+  prec = int_or_pointer_precision (TREE_TYPE (expr));
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
@@ -1735,9 +1734,7 @@ tree_log2 (const_tree expr)
   if (TREE_CODE (expr) == COMPLEX_CST)
     return tree_log2 (TREE_REALPART (expr));
 
-  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
-	  ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
-
+  prec = int_or_pointer_precision (TREE_TYPE (expr));
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
@@ -1773,9 +1770,7 @@ tree_floor_log2 (const_tree expr)
   if (TREE_CODE (expr) == COMPLEX_CST)
     return tree_log2 (TREE_REALPART (expr));
 
-  prec = (POINTER_TYPE_P (TREE_TYPE (expr))
-	  ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
-
+  prec = int_or_pointer_precision (TREE_TYPE (expr));
   high = TREE_INT_CST_HIGH (expr);
   low = TREE_INT_CST_LOW (expr);
 
@@ -6665,7 +6660,9 @@ build_pointer_type_for_mode (tree to_typ
 tree
 build_pointer_type (tree to_type)
 {
-  return build_pointer_type_for_mode (to_type, ptr_mode, false);
+  addr_space_t as = to_type == error_mark_node? 0 : TYPE_ADDR_SPACE (to_type);
+  enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
+  return build_pointer_type_for_mode (to_type, pointer_mode, false);
 }
 
 /* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE.  */
@@ -6729,7 +6726,9 @@ build_reference_type_for_mode (tree to_t
 tree
 build_reference_type (tree to_type)
 {
-  return build_reference_type_for_mode (to_type, ptr_mode, false);
+  addr_space_t as = to_type == error_mark_node? 0 : TYPE_ADDR_SPACE (to_type);
+  enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
+  return build_reference_type_for_mode (to_type, pointer_mode, false);
 }
 
 /* Build a type that is compatible with t but has no cv quals anywhere
@@ -9563,7 +9562,19 @@ signed_or_unsigned_type_for (int unsigne
 {
   tree t = type;
   if (POINTER_TYPE_P (type))
-    t = size_type_node;
+    {
+      /* If the pointer points to the normal address space, use the
+	 size_type_node.  Otherwise use an appropriate size for the pointer
+	 based on the named address space it points to.  */
+      if (!TYPE_ADDR_SPACE (TREE_TYPE (t)))
+	t = size_type_node;
+
+      else
+	{
+	  int prec = int_or_pointer_precision (t);
+	  return lang_hooks.types.type_for_size (prec, unsignedp);
+	}
+    }
 
   if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp)
     return t;
@@ -10439,6 +10450,41 @@ build_target_option_node (void)
   return t;
 }
 
+/* Return the size in bits of an integer or pointer type.  TYPE_PRECISION
+   contains the bits, but in the past it was not set in some cases and there
+   was special purpose code that checked for POINTER_TYPE_P or OFFSET_TYPE, so
+   check that it is consitant when assertion checking is used.  */
+
+unsigned int
+int_or_pointer_precision (const_tree type)
+{
+#if ENABLE_ASSERT_CHECKING
+  unsigned int prec;
+
+  if (POINTER_TYPE_P (type))
+    {
+      addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
+      prec = GET_MODE_BITSIZE (targetm.addr_space.pointer_mode (as));
+      gcc_assert (prec == TYPE_PRECISION (type));
+    }
+  else if (TREE_CODE (type) == OFFSET_TYPE)
+    {
+      prec = POINTER_SIZE;
+      gcc_assert (prec == TYPE_PRECISION (type));
+    }
+  else
+    {
+      prec = TYPE_PRECISION (type);
+      gcc_assert (prec != 0);
+    }
+
+  return prec;
+
+#else
+  return TYPE_PRECISION (type);
+#endif
+}
+
 /* Determine the "ultimate origin" of a block.  The block may be an inlined
    instance of an inlined instance of a block which is local to an inline
    function, so we have to trace all of the way back through the origin chain
Index: gcc-head/gcc/tree.h
===================================================================
--- gcc-head.orig/gcc/tree.h
+++ gcc-head/gcc/tree.h
@@ -4679,6 +4679,7 @@ extern const char *get_name (tree);
 extern bool stdarg_p (tree);
 extern bool prototype_p (tree);
 extern bool auto_var_in_fn_p (const_tree, const_tree);
+extern unsigned int int_or_pointer_precision (const_tree);
 extern tree build_low_bits_mask (tree, unsigned);
 extern tree tree_strip_nop_conversions (tree);
 extern tree tree_strip_sign_nop_conversions (tree);
Index: gcc-head/gcc/varasm.c
===================================================================
--- gcc-head.orig/gcc/varasm.c
+++ gcc-head/gcc/varasm.c
@@ -1446,7 +1446,15 @@ make_decl_rtl (tree decl)
   if (use_object_blocks_p () && use_blocks_for_decl_p (decl))
     x = create_block_symbol (name, get_block_for_decl (decl), -1);
   else
-    x = gen_rtx_SYMBOL_REF (Pmode, name);
+    {
+      enum machine_mode address_mode = Pmode;
+      if (TREE_TYPE (decl) != error_mark_node)
+	{
+	  addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
+	  address_mode = targetm.addr_space.address_mode (as);
+	}
+      x = gen_rtx_SYMBOL_REF (address_mode, name);
+    }
   SYMBOL_REF_WEAK (x) = DECL_WEAK (decl);
   SET_SYMBOL_REF_DECL (x, decl);
 
@@ -4316,7 +4324,7 @@ initializer_constant_valid_p (tree value
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
       if (! INTEGRAL_TYPE_P (endtype)
-	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
+	  || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
 	{
 	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
 						      endtype);
@@ -4338,7 +4346,7 @@ initializer_constant_valid_p (tree value
 
     case MINUS_EXPR:
       if (! INTEGRAL_TYPE_P (endtype)
-	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
+	  || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
 	{
 	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
 						      endtype);
@@ -4459,7 +4467,9 @@ output_constant (tree exp, unsigned HOST
      resolving it.  */
   if (TREE_CODE (exp) == NOP_EXPR
       && POINTER_TYPE_P (TREE_TYPE (exp))
-      && targetm.valid_pointer_mode (TYPE_MODE (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);
 
@@ -4467,7 +4477,9 @@ output_constant (tree exp, unsigned HOST
 	 pointer modes.  */
       while (TREE_CODE (exp) == NOP_EXPR
 	     && POINTER_TYPE_P (TREE_TYPE (exp))
-	     && targetm.valid_pointer_mode (TYPE_MODE (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
@@ -6558,14 +6570,6 @@ default_binds_local_p_1 (const_tree exp,
   return local_p;
 }
 
-/* Determine whether or not a pointer mode is valid. Assume defaults
-   of ptr_mode or Pmode - can be overridden.  */
-bool
-default_valid_pointer_mode (enum machine_mode mode)
-{
-  return (mode == ptr_mode || mode == Pmode);
-}
-
 /* Default function to output code that will globalize a label.  A
    target must define GLOBAL_ASM_OP or provide its own function to
    globalize a label.  */
Index: gcc-head/gcc/tree-flow.h
===================================================================
--- gcc-head.orig/gcc/tree-flow.h
+++ gcc-head/gcc/tree-flow.h
@@ -915,7 +915,7 @@ struct mem_address
 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);
+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-head/gcc/cfgexpand.c
===================================================================
--- gcc-head.orig/gcc/cfgexpand.c
+++ gcc-head/gcc/cfgexpand.c
@@ -2248,6 +2248,7 @@ expand_debug_expr (tree exp)
   enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
   addr_space_t as;
+  enum machine_mode address_mode;
 
   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
     {
@@ -2419,14 +2420,16 @@ expand_debug_expr (tree exp)
       else
 	as = 0;
 
-      gcc_assert (GET_MODE (op0) == Pmode
+      address_mode = targetm.addr_space.address_mode (as);
+
+      gcc_assert (GET_MODE (op0) == address_mode
 		  || GET_CODE (op0) == CONST_INT
 		  || GET_CODE (op0) == CONST_DOUBLE);
 
       if (TREE_CODE (exp) == ALIGN_INDIRECT_REF)
 	{
 	  int align = TYPE_ALIGN_UNIT (TREE_TYPE (exp));
-	  op0 = gen_rtx_AND (Pmode, op0, GEN_INT (-align));
+	  op0 = gen_rtx_AND (address_mode, op0, GEN_INT (-align));
 	}
 
       op0 = gen_rtx_MEM (mode, op0);
@@ -2447,8 +2450,9 @@ expand_debug_expr (tree exp)
 	return NULL;
 
       as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
+      address_mode = targetm.addr_space.address_mode (as);
 
-      gcc_assert (GET_MODE (op0) == Pmode
+      gcc_assert (GET_MODE (op0) == address_mode
 		  || GET_CODE (op0) == CONST_INT
 		  || GET_CODE (op0) == CONST_DOUBLE);
 
Index: gcc-head/gcc/var-tracking.c
===================================================================
--- gcc-head.orig/gcc/var-tracking.c
+++ gcc-head/gcc/var-tracking.c
@@ -4355,7 +4355,9 @@ replace_expr_with_values (rtx loc)
     return NULL;
   else if (MEM_P (loc))
     {
-      cselib_val *addr = cselib_lookup (XEXP (loc, 0), Pmode, 0);
+      enum machine_mode address_mode
+	= targetm.addr_space.address_mode (MEM_ADDR_SPACE (loc));
+      cselib_val *addr = cselib_lookup (XEXP (loc, 0), address_mode, 0);
       if (addr)
 	return replace_equiv_address_nv (loc, addr->val_rtx);
       else
@@ -4489,7 +4491,9 @@ count_uses (rtx *loc, void *cuip)
 	  if (MEM_P (*loc)
 	      && !REG_P (XEXP (*loc, 0)) && !MEM_P (XEXP (*loc, 0)))
 	    {
-	      val = cselib_lookup (XEXP (*loc, 0), Pmode, false);
+	      enum machine_mode address_mode
+		= targetm.addr_space.address_mode (MEM_ADDR_SPACE (*loc));
+	      val = cselib_lookup (XEXP (*loc, 0), address_mode, false);
 
 	      if (val && !cselib_preserved_value_p (val))
 		{
@@ -4609,7 +4613,10 @@ add_uses (rtx *loc, void *data)
 	      && !REG_P (XEXP (vloc, 0)) && !MEM_P (XEXP (vloc, 0)))
 	    {
 	      rtx mloc = vloc;
-	      cselib_val *val = cselib_lookup (XEXP (mloc, 0), Pmode, 0);
+	      enum machine_mode address_mode
+		= targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc));
+	      cselib_val *val
+		= cselib_lookup (XEXP (mloc, 0), address_mode, 0);
 
 	      if (val && !cselib_preserved_value_p (val))
 		{
@@ -4620,7 +4627,8 @@ add_uses (rtx *loc, void *data)
 		  cselib_preserve_value (val);
 		  mo->type = MO_VAL_USE;
 		  mloc = cselib_subst_to_values (XEXP (mloc, 0));
-		  mo->u.loc = gen_rtx_CONCAT (Pmode, val->val_rtx, mloc);
+		  mo->u.loc = gen_rtx_CONCAT (address_mode,
+					      val->val_rtx, mloc);
 		  if (dump_file && (dump_flags & TDF_DETAILS))
 		    log_op_type (mo->u.loc, cui->bb, cui->insn,
 				 mo->type, dump_file);
@@ -4676,7 +4684,10 @@ add_uses (rtx *loc, void *data)
 	      && !REG_P (XEXP (oloc, 0)) && !MEM_P (XEXP (oloc, 0)))
 	    {
 	      rtx mloc = oloc;
-	      cselib_val *val = cselib_lookup (XEXP (mloc, 0), Pmode, 0);
+	      enum machine_mode address_mode
+		= targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc));
+	      cselib_val *val
+		= cselib_lookup (XEXP (mloc, 0), address_mode, 0);
 
 	      if (val && !cselib_preserved_value_p (val))
 		{
@@ -4687,7 +4698,8 @@ add_uses (rtx *loc, void *data)
 		  cselib_preserve_value (val);
 		  mo->type = MO_VAL_USE;
 		  mloc = cselib_subst_to_values (XEXP (mloc, 0));
-		  mo->u.loc = gen_rtx_CONCAT (Pmode, val->val_rtx, mloc);
+		  mo->u.loc = gen_rtx_CONCAT (address_mode,
+					      val->val_rtx, mloc);
 		  mo->insn = cui->insn;
 		  if (dump_file && (dump_flags & TDF_DETAILS))
 		    log_op_type (mo->u.loc, cui->bb, cui->insn,
@@ -4820,14 +4832,16 @@ add_stores (rtx loc, const_rtx expr, voi
 	  && !REG_P (XEXP (loc, 0)) && !MEM_P (XEXP (loc, 0)))
 	{
 	  rtx mloc = loc;
-	  cselib_val *val = cselib_lookup (XEXP (mloc, 0), Pmode, 0);
+	  enum machine_mode address_mode
+	    = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc));
+	  cselib_val *val = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
 
 	  if (val && !cselib_preserved_value_p (val))
 	    {
 	      cselib_preserve_value (val);
 	      mo->type = MO_VAL_USE;
 	      mloc = cselib_subst_to_values (XEXP (mloc, 0));
-	      mo->u.loc = gen_rtx_CONCAT (Pmode, val->val_rtx, mloc);
+	      mo->u.loc = gen_rtx_CONCAT (address_mode, val->val_rtx, mloc);
 	      mo->insn = cui->insn;
 	      if (dump_file && (dump_flags & TDF_DETAILS))
 		log_op_type (mo->u.loc, cui->bb, cui->insn,
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com



More information about the Gcc-patches mailing list