public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer   modes
@ 2009-11-14 20:53 Dmitry Gorbachev
  2009-11-16 20:06 ` Ulrich Weigand
  0 siblings, 1 reply; 20+ messages in thread
From: Dmitry Gorbachev @ 2009-11-14 20:53 UTC (permalink / raw)
  To: gcc-patches

There seems to be a mistake in find_reloads_address(). Shouldn't it be so:

--- gcc/reload.c
+++ gcc/reload.c
@@ -5239,7 +5239,7 @@
   if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as))
     {
       enum machine_mode address_mode = GET_MODE (ad);
-      if (ad == VOIDmode)
+      if (address_mode == VOIDmode)
 	address_mode = targetm.addr_space.address_mode (as);

       /* If AD is an address in the constant pool, the MEM rtx may be shared.

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer     modes
  2009-11-14 20:53 [PATCH PING 2/5] Named address spaces: support multiple pointer modes Dmitry Gorbachev
@ 2009-11-16 20:06 ` Ulrich Weigand
  2009-11-17  6:13   ` Dmitry Gorbachev
  0 siblings, 1 reply; 20+ messages in thread
From: Ulrich Weigand @ 2009-11-16 20:06 UTC (permalink / raw)
  To: Dmitry Gorbachev; +Cc: gcc-patches

Dmitry Gorbachev wrote:

> There seems to be a mistake in find_reloads_address(). Shouldn't it be so:
> 
> --- gcc/reload.c
> +++ gcc/reload.c
> @@ -5239,7 +5239,7 @@
>    if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as))
>      {
>        enum machine_mode address_mode = GET_MODE (ad);
> -      if (ad == VOIDmode)
> +      if (address_mode == VOIDmode)
>  	address_mode = targetm.addr_space.address_mode (as);
> 
>        /* If AD is an address in the constant pool, the MEM rtx may be shared.

Right, thanks for catching this!

Can you check this fix in?  Thanks!

Bye,
Ulrich

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

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer   modes
  2009-11-16 20:06 ` Ulrich Weigand
@ 2009-11-17  6:13   ` Dmitry Gorbachev
  2009-11-17 16:18     ` Ulrich Weigand
  0 siblings, 1 reply; 20+ messages in thread
From: Dmitry Gorbachev @ 2009-11-17  6:13 UTC (permalink / raw)
  To: gcc-patches; +Cc: Ulrich Weigand

> Right, thanks for catching this!
>
> Can you check this fix in?  Thanks!

No, somebody with write access, please commit it.

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer     modes
  2009-11-17  6:13   ` Dmitry Gorbachev
@ 2009-11-17 16:18     ` Ulrich Weigand
  0 siblings, 0 replies; 20+ messages in thread
From: Ulrich Weigand @ 2009-11-17 16:18 UTC (permalink / raw)
  To: Dmitry Gorbachev; +Cc: gcc-patches

Dmitry Gorbachev wrote:
> > Right, thanks for catching this!
> >
> > Can you check this fix in?  Thanks!
> 
> No, somebody with write access, please commit it.

OK, I've checked this in now.
Tested on s390x-ibm-linux.

Bye,
Ulrich

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

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer          modes
  2009-09-24 18:43                     ` Richard Henderson
@ 2009-09-24 20:40                       ` Ulrich Weigand
  0 siblings, 0 replies; 20+ messages in thread
From: Ulrich Weigand @ 2009-09-24 20:40 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Richard Guenther, gcc-patches, joseph

Richard Henderson wrote:
> On 09/24/2009 11:19 AM, Ulrich Weigand wrote:
> > 	* target-def.h (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P): Remove.
> > 	* targhooks.c (target_default_address_pointer_modes_p): New function.
> > 	* target.h (target_default_address_pointer_modes_p): Add prototype.
> >
> > 	* alias.c (find_base_value): Use target_default_address_pointer_modes_p
> > 	instead of TARGET_DEFAULT_ADDRESS_POINTER_MODES_P.
> > 	(find_base_term): Likewise.
> > 	* rtlanal.c (nonzero_bits1): Likewise.
> > 	(num_sign_bit_copies1): Likewise.
> > 	* simplify-rtx.c (simplify_unary_operation_1): Likewise.
> >
> > 	* alias.c: Do not include "targhooks.h".
> > 	* rtlanal.c: Likewise.
> > 	* simplify-rtx.c: Likewise.
> > 	* Makefile.in (alias.o): Update dependencies.
> > 	(rtlanal.o): Likewise.
> > 	(simplify-rtx.o): Likewise.
> 
> Better, thanks.  Patch is ok.

Thanks, I've committed the patch to the branch now.  Appended below is the
resulting version of the complete 2/5 patch against 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 (target_default_address_pointer_modes_p): New function.
	* target.h (target_default_address_pointer_modes_p): Add prototype.
	* 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 (find_base_value): Guard pointer size optimizations.
	(find_base_term): Likewise.
	* rtlanal.c (nonzero_bits1): Likewise.
	(num_sign_bit_copies1): Likewise.
	* simplify-rtx.c (simplify_unary_operation_1): Likewise.

	* Makefile.in (tree-ssa-address.o): Add $(TARGET_H) dependency.
	(emit-rtl.o): Likewise.
	(auto-inc-dec.o): Likewise.
	(sched-deps.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) \
@@ -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) \
@@ -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 \
@@ -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
@@ -1049,6 +1049,11 @@ 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 (!target_default_pointer_address_modes_p ())
+	break;
       if (GET_MODE_SIZE (GET_MODE (src)) < GET_MODE_SIZE (Pmode))
 	break;
       /* Fall through.  */
@@ -1063,6 +1068,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 (!target_default_pointer_address_modes_p ())
+	break;
+
       {
 	rtx temp = find_base_value (XEXP (src, 0));
 
@@ -1455,6 +1466,11 @@ 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 (!target_default_pointer_address_modes_p ())
+	return 0;
       if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (Pmode))
 	return 0;
       /* Fall through.  */
@@ -1469,6 +1485,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 (!target_default_pointer_address_modes_p ())
+	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)
     {
@@ -1187,7 +1189,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,
@@ -1468,6 +1475,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);
@@ -1487,9 +1498,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);
 
@@ -2384,6 +2399,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)
@@ -2412,7 +2429,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,
@@ -2467,6 +2485,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;
@@ -2498,7 +2518,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;
 	}
@@ -2506,13 +2527,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);
@@ -4214,6 +4235,7 @@ expand_assignment (tree to, tree from, b
 
       if (offset != 0)
 	{
+	  enum machine_mode address_mode;
 	  rtx offset_rtx;
 
 	  if (!MEM_P (to_rtx))
@@ -4226,13 +4248,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.  */
@@ -4371,7 +4390,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);
@@ -4731,6 +4753,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,
@@ -4743,14 +4770,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));
@@ -4763,11 +4790,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));
@@ -5257,6 +5283,7 @@ store_constructor (tree exp, rtx target,
 
 	    if (offset)
 	      {
+	        enum machine_mode address_mode;
 		rtx offset_rtx;
 
 		offset
@@ -5267,13 +5294,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));
@@ -6796,7 +6820,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;
@@ -6823,7 +6847,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
@@ -6913,7 +6937,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)
     {
@@ -6925,8 +6949,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);
@@ -6959,6 +6983,9 @@ static rtx
 expand_expr_addr_expr (tree exp, rtx target, enum machine_mode tmode,
 		       enum expand_modifier modifier)
 {
+  addr_space_t as = ADDR_SPACE_GENERIC;
+  enum machine_mode address_mode = Pmode;
+  enum machine_mode pointer_mode = ptr_mode;
   enum machine_mode rmode;
   rtx result;
 
@@ -6966,14 +6993,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
@@ -6982,7 +7016,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;
 }
@@ -8658,6 +8692,7 @@ expand_expr_real_1 (tree exp, rtx target
       {
 	tree exp1 = treeop0;
 	addr_space_t as = ADDR_SPACE_GENERIC;
+	enum machine_mode address_mode = Pmode;
 
 	if (modifier != EXPAND_WRITE)
 	  {
@@ -8669,7 +8704,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);
@@ -8677,7 +8715,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);
 	  }
 
@@ -8720,7 +8758,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);
@@ -9012,18 +9050,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,
@@ -5113,7 +5116,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;
     }
@@ -5235,6 +5238,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
@@ -5247,7 +5254,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;
     }
 
@@ -5334,16 +5341,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));
@@ -5353,12 +5356,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.  */
@@ -5425,9 +5428,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;
     }
@@ -5827,7 +5830,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
@@ -5835,9 +5839,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), ADDR_SPACE_GENERIC)
 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
@@ -3748,7 +3748,11 @@ 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 (target_default_address_pointer_modes_p ()
+	  && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
 	  && REG_POINTER (x))
 	nonzero &= GET_MODE_MASK (ptr_mode);
 #endif
@@ -3985,7 +3989,11 @@ 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 (target_default_address_pointer_modes_p ()
+	    && 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 +4267,12 @@ 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 (target_default_address_pointer_modes_p ()
+	  && ! 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 +4468,11 @@ 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 (target_default_address_pointer_modes_p ()
+	  && ! 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
@@ -963,7 +963,11 @@ 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 (target_default_address_pointer_modes_p ()
+	  && ! POINTERS_EXTEND_UNSIGNED
 	  && mode == Pmode && GET_MODE (op) == ptr_mode
 	  && (CONSTANT_P (op)
 	      || (GET_CODE (op) == SUBREG
@@ -985,7 +989,11 @@ 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 (target_default_address_pointer_modes_p ()
+	  && 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
@@ -68,6 +68,12 @@ typedef int (* print_switch_fn_type) (pr
 /* An example implementation for ELF targets.  Defined in varasm.c  */
 extern int elf_record_gcc_switches (print_switch_type type, const char *);
 
+/* Some places still assume that all pointer or address modes are the
+   standard Pmode and ptr_mode.  These optimizations become invalid if
+   the target actually supports multiple different modes.  For now,
+   we disable such optimizations on such targets, using this function.  */
+extern bool target_default_pointer_address_modes_p (void);
+
 struct stdarg_info;
 struct spec_info_def;
 
@@ -682,6 +688,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 address 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,62 @@ 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 (ADDR_SPACE_GENERIC_P (addrspace));
+  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 (ADDR_SPACE_GENERIC_P (addrspace));
+  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 (!ADDR_SPACE_GENERIC_P (as))
+    return (mode == targetm.addr_space.pointer_mode (as)
+	    || mode == targetm.addr_space.address_mode (as));
+
+  return targetm.valid_pointer_mode (mode);
+}
+
+/* Some places still assume that all pointer or address modes are the
+   standard Pmode and ptr_mode.  These optimizations become invalid if
+   the target actually supports multiple different modes.  For now,
+   we disable such optimizations on such targets, using this function.  */
+
+bool
+target_default_pointer_address_modes_p (void)
+{
+  if (targetm.addr_space.address_mode != default_addr_space_address_mode)
+    return false;
+  if (targetm.addr_space.pointer_mode != default_addr_space_pointer_mode)
+    return false;
+
+  return true;
+}
+
 /* 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,10 @@ 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? ADDR_SPACE_GENERIC
+					      : 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 +6727,10 @@ 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? ADDR_SPACE_GENERIC
+					      : 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 +9564,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 +10452,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
@@ -4683,6 +4683,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
@@ -1447,7 +1447,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);
 
@@ -4317,7 +4325,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);
@@ -4339,7 +4347,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);
@@ -4460,7 +4468,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);
 
@@ -4468,7 +4478,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
@@ -6559,14 +6571,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 = ADDR_SPACE_GENERIC;
 
-      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

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer          modes
  2009-09-24 18:26                   ` Ulrich Weigand
@ 2009-09-24 18:43                     ` Richard Henderson
  2009-09-24 20:40                       ` Ulrich Weigand
  0 siblings, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2009-09-24 18:43 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Richard Guenther, gcc-patches, joseph

On 09/24/2009 11:19 AM, Ulrich Weigand wrote:
> 	* target-def.h (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P): Remove.
> 	* targhooks.c (target_default_address_pointer_modes_p): New function.
> 	* target.h (target_default_address_pointer_modes_p): Add prototype.
>
> 	* alias.c (find_base_value): Use target_default_address_pointer_modes_p
> 	instead of TARGET_DEFAULT_ADDRESS_POINTER_MODES_P.
> 	(find_base_term): Likewise.
> 	* rtlanal.c (nonzero_bits1): Likewise.
> 	(num_sign_bit_copies1): Likewise.
> 	* simplify-rtx.c (simplify_unary_operation_1): Likewise.
>
> 	* alias.c: Do not include "targhooks.h".
> 	* rtlanal.c: Likewise.
> 	* simplify-rtx.c: Likewise.
> 	* Makefile.in (alias.o): Update dependencies.
> 	(rtlanal.o): Likewise.
> 	(simplify-rtx.o): Likewise.

Better, thanks.  Patch is ok.


r~

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer         modes
  2009-09-24 16:50                 ` Richard Henderson
@ 2009-09-24 18:26                   ` Ulrich Weigand
  2009-09-24 18:43                     ` Richard Henderson
  0 siblings, 1 reply; 20+ messages in thread
From: Ulrich Weigand @ 2009-09-24 18:26 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Richard Guenther, gcc-patches, joseph

Richard Henderson wrote:
> On 09/24/2009 09:06 AM, Ulrich Weigand wrote:
> > Putting the macro into targhooks.h actually looks quite straightforward.
> 
> No.  targhooks.h is (again) used only by files that need to implement
> the target structure.  It should not be pulled in to other files.

OK, I see.  I guess this means going back to your suggestion to use
a helper function instead of a macro.  The patch below implements this
(function in targhooks.c, prototype in target.h).

Does this look better?

Thanks,
Ulrich


ChangeLog:

	* target-def.h (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P): Remove.
	* targhooks.c (target_default_address_pointer_modes_p): New function.
	* target.h (target_default_address_pointer_modes_p): Add prototype.

	* alias.c (find_base_value): Use target_default_address_pointer_modes_p
	instead of TARGET_DEFAULT_ADDRESS_POINTER_MODES_P.
	(find_base_term): Likewise.
	* rtlanal.c (nonzero_bits1): Likewise.
	(num_sign_bit_copies1): Likewise.
	* simplify-rtx.c (simplify_unary_operation_1): Likewise.

	* alias.c: Do not include "targhooks.h".
	* rtlanal.c: Likewise.
	* simplify-rtx.c: Likewise.
	* Makefile.in (alias.o): Update dependencies.
	(rtlanal.o): Likewise.
	(simplify-rtx.o): Likewise.


Index: gcc/targhooks.c
===================================================================
*** gcc/targhooks.c	(revision 152125)
--- gcc/targhooks.c	(working copy)
*************** default_addr_space_valid_pointer_mode (e
*** 811,816 ****
--- 811,832 ----
    return targetm.valid_pointer_mode (mode);
  }
  
+ /* Some places still assume that all pointer or address modes are the
+    standard Pmode and ptr_mode.  These optimizations become invalid if
+    the target actually supports multiple different modes.  For now,
+    we disable such optimizations on such targets, using this function.  */
+ 
+ bool
+ target_default_pointer_address_modes_p (void)
+ {
+   if (targetm.addr_space.address_mode != default_addr_space_address_mode)
+     return false;
+   if (targetm.addr_space.pointer_mode != default_addr_space_pointer_mode)
+     return false;
+ 
+   return true;
+ }
+ 
  /* Named address space version of legitimate_address_p.  */
  
  bool
Index: gcc/target.h
===================================================================
*** gcc/target.h	(revision 151838)
--- gcc/target.h	(working copy)
*************** typedef int (* print_switch_fn_type) (pr
*** 68,73 ****
--- 68,79 ----
  /* An example implementation for ELF targets.  Defined in varasm.c  */
  extern int elf_record_gcc_switches (print_switch_type type, const char *);
  
+ /* Some places still assume that all pointer or address modes are the
+    standard Pmode and ptr_mode.  These optimizations become invalid if
+    the target actually supports multiple different modes.  For now,
+    we disable such optimizations on such targets, using this function.  */
+ extern bool target_default_pointer_address_modes_p (void);
+ 
  struct stdarg_info;
  struct spec_info_def;
  
Index: gcc/rtlanal.c
===================================================================
*** gcc/rtlanal.c	(revision 151919)
--- gcc/rtlanal.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 38,44 ****
  #include "function.h"
  #include "df.h"
  #include "tree.h"
- #include "target-def.h"
  
  /* Forward declarations */
  static void set_of_1 (rtx, const_rtx, void *);
--- 38,43 ----
*************** nonzero_bits1 (const_rtx x, enum machine
*** 3752,3758 ****
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && REG_POINTER (x))
  	nonzero &= GET_MODE_MASK (ptr_mode);
--- 3751,3757 ----
        /* 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 (target_default_address_pointer_modes_p ()
  	  && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && REG_POINTER (x))
  	nonzero &= GET_MODE_MASK (ptr_mode);
*************** nonzero_bits1 (const_rtx x, enum machine
*** 3993,3999 ****
  	/* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	    && POINTERS_EXTEND_UNSIGNED > 0 && GET_MODE (x) == Pmode
  	    && (code == PLUS || code == MINUS)
  	    && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
--- 3992,3998 ----
  	/* 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 (target_default_address_pointer_modes_p ()
  	    && POINTERS_EXTEND_UNSIGNED > 0 && GET_MODE (x) == Pmode
  	    && (code == PLUS || code == MINUS)
  	    && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
*************** num_sign_bit_copies1 (const_rtx x, enum 
*** 4271,4277 ****
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && mode == Pmode && REG_POINTER (x))
  	return GET_MODE_BITSIZE (Pmode) - GET_MODE_BITSIZE (ptr_mode) + 1;
--- 4270,4276 ----
        /* 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 (target_default_address_pointer_modes_p ()
  	  && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && mode == Pmode && REG_POINTER (x))
  	return GET_MODE_BITSIZE (Pmode) - GET_MODE_BITSIZE (ptr_mode) + 1;
*************** num_sign_bit_copies1 (const_rtx x, enum 
*** 4472,4478 ****
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && (code == PLUS || code == MINUS)
  	  && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
--- 4471,4477 ----
        /* 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 (target_default_address_pointer_modes_p ()
  	  && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && (code == PLUS || code == MINUS)
  	  && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
Index: gcc/alias.c
===================================================================
*** gcc/alias.c	(revision 151919)
--- gcc/alias.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 49,55 ****
  #include "tree-ssa-alias.h"
  #include "pointer-set.h"
  #include "tree-flow.h"
- #include "target-def.h"
  
  /* The aliasing API provided here solves related but different problems:
  
--- 49,54 ----
*************** find_base_value (rtx src)
*** 1053,1059 ****
        /* 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 (!TARGET_DEFAULT_POINTER_ADDRESS_MODES_P)
  	break;
        if (GET_MODE_SIZE (GET_MODE (src)) < GET_MODE_SIZE (Pmode))
  	break;
--- 1052,1058 ----
        /* 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 (!target_default_pointer_address_modes_p ())
  	break;
        if (GET_MODE_SIZE (GET_MODE (src)) < GET_MODE_SIZE (Pmode))
  	break;
*************** find_base_value (rtx src)
*** 1072,1078 ****
        /* 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 (!TARGET_DEFAULT_POINTER_ADDRESS_MODES_P)
  	break;
  
        {
--- 1071,1077 ----
        /* 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 (!target_default_pointer_address_modes_p ())
  	break;
  
        {
*************** find_base_term (rtx x)
*** 1470,1476 ****
        /* 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 (!TARGET_DEFAULT_POINTER_ADDRESS_MODES_P)
  	return 0;
        if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (Pmode))
  	return 0;
--- 1469,1475 ----
        /* 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 (!target_default_pointer_address_modes_p ())
  	return 0;
        if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (Pmode))
  	return 0;
*************** find_base_term (rtx x)
*** 1489,1495 ****
        /* 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 (!TARGET_DEFAULT_POINTER_ADDRESS_MODES_P)
  	return 0;
  
        {
--- 1488,1494 ----
        /* 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 (!target_default_pointer_address_modes_p ())
  	return 0;
  
        {
Index: gcc/simplify-rtx.c
===================================================================
*** gcc/simplify-rtx.c	(revision 151919)
--- gcc/simplify-rtx.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 39,45 ****
  #include "output.h"
  #include "ggc.h"
  #include "target.h"
- #include "target-def.h"
  
  /* Simplification and canonicalization of RTL.  */
  
--- 39,44 ----
*************** simplify_unary_operation_1 (enum rtx_cod
*** 967,973 ****
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && ! POINTERS_EXTEND_UNSIGNED
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
--- 966,972 ----
        /* 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 (target_default_address_pointer_modes_p ()
  	  && ! POINTERS_EXTEND_UNSIGNED
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
*************** simplify_unary_operation_1 (enum rtx_cod
*** 993,999 ****
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && POINTERS_EXTEND_UNSIGNED > 0
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
--- 992,998 ----
        /* 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 (target_default_address_pointer_modes_p ()
  	  && POINTERS_EXTEND_UNSIGNED > 0
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
Index: gcc/target-def.h
===================================================================
*** gcc/target-def.h	(revision 151919)
--- gcc/target-def.h	(working copy)
***************
*** 505,518 ****
      TARGET_ADDR_SPACE_CONVERT,			\
    }
  
- /* Some places still assume that all pointer or address modes are the
-    standard Pmode and ptr_mode.  These optimizations become invalid if
-    the target actually supports multiple different modes.  For now,
-    we disable such optimizations on such targets, using this macro.  */
- #define TARGET_DEFAULT_POINTER_ADDRESS_MODES_P \
-   (targetm.addr_space.address_mode == default_addr_space_address_mode \
-    && targetm.addr_space.pointer_mode == default_addr_space_pointer_mode)
- 
  #ifndef TARGET_SCALAR_MODE_SUPPORTED_P
  #define TARGET_SCALAR_MODE_SUPPORTED_P default_scalar_mode_supported_p
  #endif
--- 505,510 ----
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in	(revision 151919)
--- gcc/Makefile.in	(working copy)
*************** print-rtl.o : print-rtl.c $(CONFIG_H) $(
*** 2659,2665 ****
  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) $(TARGET_DEF_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) \
--- 2659,2665 ----
  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)
  
  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) \
*************** jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) 
*** 2763,2769 ****
  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) $(TARGET_DEF_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) \
--- 2763,2769 ----
  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)
  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) \
*************** alias.o : alias.c $(CONFIG_H) $(SYSTEM_H
*** 3068,3074 ****
     $(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) $(TARGET_DEF_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)
--- 3068,3074 ----
     $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
     langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
     $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) $(DF_H) $(TREE_PASS_H) \
!    tree-ssa-alias.h pointer-set.h $(TREE_FLOW_H)
  stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) $(TREE_PASS_H) \
     $(BASIC_BLOCK_H) $(FLAGS_H) output.h $(DF_H)


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

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer         modes
  2009-09-24 16:08               ` Ulrich Weigand
@ 2009-09-24 16:50                 ` Richard Henderson
  2009-09-24 18:26                   ` Ulrich Weigand
  0 siblings, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2009-09-24 16:50 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Richard Guenther, gcc-patches, joseph

On 09/24/2009 09:06 AM, Ulrich Weigand wrote:
> Putting the macro into targhooks.h actually looks quite straightforward.

No.  targhooks.h is (again) used only by files that need to implement
the target structure.  It should not be pulled in to other files.


r~

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer        modes
  2009-09-23 15:26             ` Richard Henderson
@ 2009-09-24 16:08               ` Ulrich Weigand
  2009-09-24 16:50                 ` Richard Henderson
  0 siblings, 1 reply; 20+ messages in thread
From: Ulrich Weigand @ 2009-09-24 16:08 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Richard Guenther, gcc-patches, joseph

Richard Henderson wrote:
> On 09/22/2009 05:55 PM, Ulrich Weigand wrote:
> > So I guess the macro can either go into targhooks.h after all,
> > or maybe it should go into target.h with the additional rule
> > that you need to also include targhooks.h if you want to use it.
> 
> When I get into those kind of nasty header situations,
> I usually break down and put the thing in a function
> somewhere.

Putting the macro into targhooks.h actually looks quite straightforward.
For completeness, targhooks.h should then itself include target.h, which
seems reasonable in any case (and all existing users of targhooks.h
already include target.h anyway).

The patch below implements this on top of the named-addr-spaces-branch.
Does this look good to you?

Thanks,
Ulrich

ChangeLog:

	* target-def.h (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P): Move ...
	* targhooks.h (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P): ... here.

	* targhooks.h: Include "target.h".
	* Makefile.in (TARGHOOKS_H): New macro.
	(TARGET_DEF_H): Use it instead of targhooks.h.
	(varasm.o): Likewise.

	* alias.c: Include "targhooks.h" instead of "target-def.h".
	* rtlanal.c: Likewise.
	* simplify-rtx.c: Likewise.
	* Makefile.in (alias.o): Update dependencies.
	(rtlanal.o): Likewise.
	(simplify-rtx.o): Likewise.

Index: gcc/targhooks.h
===================================================================
*** gcc/targhooks.h	(revision 151726)
--- gcc/targhooks.h	(working copy)
*************** You should have received a copy of the G
*** 18,23 ****
--- 18,25 ----
  along with GCC; see the file COPYING3.  If not see
  <http://www.gnu.org/licenses/>.  */
  
+ #include "target.h"
+ 
  extern bool default_legitimate_address_p (enum machine_mode, rtx, bool);
  
  extern void default_external_libcall (rtx);
*************** extern rtx default_addr_space_legitimize
*** 125,127 ****
--- 127,138 ----
  extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
  extern rtx default_addr_space_convert (rtx, tree, tree);
  extern unsigned int default_case_values_threshold (void);
+ 
+ /* Some places still assume that all pointer or address modes are the
+    standard Pmode and ptr_mode.  These optimizations become invalid if
+    the target actually supports multiple different modes.  For now,
+    we disable such optimizations on such targets, using this macro.  */
+ #define TARGET_DEFAULT_POINTER_ADDRESS_MODES_P \
+   (targetm.addr_space.address_mode == default_addr_space_address_mode \
+    && targetm.addr_space.pointer_mode == default_addr_space_pointer_mode)
+ 
Index: gcc/rtlanal.c
===================================================================
*** gcc/rtlanal.c	(revision 151919)
--- gcc/rtlanal.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 38,44 ****
  #include "function.h"
  #include "df.h"
  #include "tree.h"
! #include "target-def.h"
  
  /* Forward declarations */
  static void set_of_1 (rtx, const_rtx, void *);
--- 38,44 ----
  #include "function.h"
  #include "df.h"
  #include "tree.h"
! #include "targhooks.h"
  
  /* Forward declarations */
  static void set_of_1 (rtx, const_rtx, void *);
Index: gcc/alias.c
===================================================================
*** gcc/alias.c	(revision 151919)
--- gcc/alias.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 49,55 ****
  #include "tree-ssa-alias.h"
  #include "pointer-set.h"
  #include "tree-flow.h"
! #include "target-def.h"
  
  /* The aliasing API provided here solves related but different problems:
  
--- 49,55 ----
  #include "tree-ssa-alias.h"
  #include "pointer-set.h"
  #include "tree-flow.h"
! #include "targhooks.h"
  
  /* The aliasing API provided here solves related but different problems:
  
Index: gcc/simplify-rtx.c
===================================================================
*** gcc/simplify-rtx.c	(revision 151919)
--- gcc/simplify-rtx.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 39,45 ****
  #include "output.h"
  #include "ggc.h"
  #include "target.h"
! #include "target-def.h"
  
  /* Simplification and canonicalization of RTL.  */
  
--- 39,45 ----
  #include "output.h"
  #include "ggc.h"
  #include "target.h"
! #include "targhooks.h"
  
  /* Simplification and canonicalization of RTL.  */
  
Index: gcc/target-def.h
===================================================================
*** gcc/target-def.h	(revision 151919)
--- gcc/target-def.h	(working copy)
***************
*** 505,518 ****
      TARGET_ADDR_SPACE_CONVERT,			\
    }
  
- /* Some places still assume that all pointer or address modes are the
-    standard Pmode and ptr_mode.  These optimizations become invalid if
-    the target actually supports multiple different modes.  For now,
-    we disable such optimizations on such targets, using this macro.  */
- #define TARGET_DEFAULT_POINTER_ADDRESS_MODES_P \
-   (targetm.addr_space.address_mode == default_addr_space_address_mode \
-    && targetm.addr_space.pointer_mode == default_addr_space_pointer_mode)
- 
  #ifndef TARGET_SCALAR_MODE_SUPPORTED_P
  #define TARGET_SCALAR_MODE_SUPPORTED_P default_scalar_mode_supported_p
  #endif
--- 505,510 ----
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in	(revision 151919)
--- gcc/Makefile.in	(working copy)
*************** MACHMODE_H = machmode.h mode-classes.def
*** 833,839 ****
  HOOKS_H = hooks.h $(MACHMODE_H)
  HOSTHOOKS_DEF_H = hosthooks-def.h $(HOOKS_H)
  LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H)
! TARGET_DEF_H = target-def.h $(HOOKS_H) targhooks.h
  RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H) reg-notes.def insn-notes.def \
    $(INPUT_H) $(REAL_H) statistics.h vec.h $(FIXED_VALUE_H) alias.h
  FIXED_VALUE_H = fixed-value.h $(MACHMODE_H) double-int.h
--- 833,840 ----
  HOOKS_H = hooks.h $(MACHMODE_H)
  HOSTHOOKS_DEF_H = hosthooks-def.h $(HOOKS_H)
  LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H)
! TARGHOOKS_H = targhooks.h $(TARGET_H)
! TARGET_DEF_H = target-def.h $(HOOKS_H) $(TARGHOOKS_H)
  RTL_BASE_H = rtl.h rtl.def $(MACHMODE_H) reg-notes.def insn-notes.def \
    $(INPUT_H) $(REAL_H) statistics.h vec.h $(FIXED_VALUE_H) alias.h
  FIXED_VALUE_H = fixed-value.h $(MACHMODE_H) double-int.h
*************** print-rtl.o : print-rtl.c $(CONFIG_H) $(
*** 2659,2671 ****
  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) $(TARGET_DEF_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) \
     output.h $(TOPLEV_H) xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
     $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h $(BASIC_BLOCK_H) \
!    $(CFGLAYOUT_H) $(CGRAPH_H) targhooks.h tree-mudflap.h $(REAL_H) tree-iterator.h
  function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(TREE_H) $(CFGLAYOUT_H) $(GIMPLE_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) \
     $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
--- 2660,2673 ----
  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)
  
  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) \
     output.h $(TOPLEV_H) xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
     $(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h $(BASIC_BLOCK_H) \
!    $(CFGLAYOUT_H) $(CGRAPH_H) $(TARGHOOKS_H) tree-mudflap.h $(REAL_H) \
!    tree-iterator.h
  function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(TREE_H) $(CFGLAYOUT_H) $(GIMPLE_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) \
     $(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
*************** jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) 
*** 2763,2769 ****
  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) $(TARGET_DEF_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) \
--- 2765,2771 ----
  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) $(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) \
*************** alias.o : alias.c $(CONFIG_H) $(SYSTEM_H
*** 3068,3074 ****
     $(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) $(TARGET_DEF_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)
--- 3070,3076 ----
     $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
     langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
     $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) $(DF_H) $(TREE_PASS_H) \
!    tree-ssa-alias.h pointer-set.h $(TREE_FLOW_H) $(TARGHOOKS_H)
  stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) $(TREE_PASS_H) \
     $(BASIC_BLOCK_H) $(FLAGS_H) output.h $(DF_H)


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

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer        modes
  2009-09-23  1:17           ` Ulrich Weigand
@ 2009-09-23 15:26             ` Richard Henderson
  2009-09-24 16:08               ` Ulrich Weigand
  0 siblings, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2009-09-23 15:26 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Richard Guenther, gcc-patches, joseph

On 09/22/2009 05:55 PM, Ulrich Weigand wrote:
> So I guess the macro can either go into targhooks.h after all,
> or maybe it should go into target.h with the additional rule
> that you need to also include targhooks.h if you want to use it.

When I get into those kind of nasty header situations,
I usually break down and put the thing in a function
somewhere.


r~

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer       modes
  2009-09-23  0:11         ` Richard Henderson
@ 2009-09-23  1:17           ` Ulrich Weigand
  2009-09-23 15:26             ` Richard Henderson
  0 siblings, 1 reply; 20+ messages in thread
From: Ulrich Weigand @ 2009-09-23  1:17 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Richard Guenther, gcc-patches, joseph

Richard Henderson wrote:
> On 09/22/2009 03:50 PM, Ulrich Weigand wrote:
> > It seemed to me that of the two, target-def.h was a more natural
> > place for the new macro.  If you have a better suggestion where
> > to place it, I'll be happy to do so ...
> 
> The macro you're defining would seem to belong
> possibly in target.h.  Though normally there's
> some sort of good place in tree.h or rtl.h that
> gets used instead.

Well, the problem with this is that the macro refers to
function names declared in targhooks.h, which is not
included by any of the standard headers.  So I thought
it would be best to place the macro into either targhooks.h
or target-def.h (which is the only header that itself
includes targhooks.h).  The latter seemed more appropriate
as the former doesn't define any macros today, however ...

Joseph Myers wrote:
> target-def.h should only be included in the target-specific .c files that 
> define the target structure using an initializer whose default values come 
> from target-def.h; no file not defining such an initializer should include 
> it. 

... it seems my reasoning was wrong here.

So I guess the macro can either go into targhooks.h after all,
or maybe it should go into target.h with the additional rule
that you need to also include targhooks.h if you want to use it.

Bye,
Ulrich

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

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer       modes
  2009-09-22 22:51       ` Ulrich Weigand
  2009-09-22 23:21         ` Joseph S. Myers
@ 2009-09-23  0:11         ` Richard Henderson
  2009-09-23  1:17           ` Ulrich Weigand
  1 sibling, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2009-09-23  0:11 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Richard Guenther, gcc-patches

On 09/22/2009 03:50 PM, Ulrich Weigand wrote:
> It seemed to me that of the two, target-def.h was a more natural
> place for the new macro.  If you have a better suggestion where
> to place it, I'll be happy to do so ...

The macro you're defining would seem to belong
possibly in target.h.  Though normally there's
some sort of good place in tree.h or rtl.h that
gets used instead.


r~

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer       modes
  2009-09-22 22:51       ` Ulrich Weigand
@ 2009-09-22 23:21         ` Joseph S. Myers
  2009-09-23  0:11         ` Richard Henderson
  1 sibling, 0 replies; 20+ messages in thread
From: Joseph S. Myers @ 2009-09-22 23:21 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Richard Henderson, Richard Guenther, gcc-patches

On Wed, 23 Sep 2009, Ulrich Weigand wrote:

> Note that this patch applies to the branch; mainline currently
> contains neither of the includes.  So this basically only changes
> the resulting mainline patch into adding #include "target-def.h"
> instead of adding #include "targhooks.h" ...
> 
> It seemed to me that of the two, target-def.h was a more natural
> place for the new macro.  If you have a better suggestion where
> to place it, I'll be happy to do so ...

target-def.h should only be included in the target-specific .c files that 
define the target structure using an initializer whose default values come 
from target-def.h; no file not defining such an initializer should include 
it.  (c-common.c includes it to define the default C-family target 
structure initializer.  I don't know why df-scan.c includes it, but it is 
wrong to do so.)

If you think you need it elsewhere, you may be putting a macro in 
target-def.h that is not the default value of an initializer for the 
target structure and so does not belong there.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer      modes
  2009-09-22 20:26     ` Richard Henderson
@ 2009-09-22 22:51       ` Ulrich Weigand
  2009-09-22 23:21         ` Joseph S. Myers
  2009-09-23  0:11         ` Richard Henderson
  0 siblings, 2 replies; 20+ messages in thread
From: Ulrich Weigand @ 2009-09-22 22:51 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Richard Guenther, gcc-patches

Richard Henderson wrote:
> On 09/21/2009 06:41 AM, Ulrich Weigand wrote:
> > --- gcc/alias.c	(working copy)
> > *************** along with GCC; see the file COPYING3.
> > *** 49,55 ****
> >    #include "tree-ssa-alias.h"
> >    #include "pointer-set.h"
> >    #include "tree-flow.h"
> > ! #include "targhooks.h"
> >
> >    /* The aliasing API provided here solves related but different problems:
> >
> > --- 49,55 ----
> >    #include "tree-ssa-alias.h"
> >    #include "pointer-set.h"
> >    #include "tree-flow.h"
> > ! #include "target-def.h"
> 
> 
> If you have to make this change, you've placed the macro
> in the wrong place.

Note that this patch applies to the branch; mainline currently
contains neither of the includes.  So this basically only changes
the resulting mainline patch into adding #include "target-def.h"
instead of adding #include "targhooks.h" ...

It seemed to me that of the two, target-def.h was a more natural
place for the new macro.  If you have a better suggestion where
to place it, I'll be happy to do so ...

Thanks,
Ulrich

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

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer      modes
  2009-09-21 13:52   ` Ulrich Weigand
  2009-09-21 15:31     ` Richard Guenther
@ 2009-09-22 20:26     ` Richard Henderson
  2009-09-22 22:51       ` Ulrich Weigand
  1 sibling, 1 reply; 20+ messages in thread
From: Richard Henderson @ 2009-09-22 20:26 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Richard Guenther, gcc-patches

On 09/21/2009 06:41 AM, Ulrich Weigand wrote:
> --- gcc/alias.c	(working copy)
> *************** along with GCC; see the file COPYING3.
> *** 49,55 ****
>    #include "tree-ssa-alias.h"
>    #include "pointer-set.h"
>    #include "tree-flow.h"
> ! #include "targhooks.h"
>
>    /* The aliasing API provided here solves related but different problems:
>
> --- 49,55 ----
>    #include "tree-ssa-alias.h"
>    #include "pointer-set.h"
>    #include "tree-flow.h"
> ! #include "target-def.h"


If you have to make this change, you've placed the macro
in the wrong place.


r~

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer     modes
  2009-09-21 15:31     ` Richard Guenther
@ 2009-09-21 15:35       ` Ulrich Weigand
  0 siblings, 0 replies; 20+ messages in thread
From: Ulrich Weigand @ 2009-09-21 15:35 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

Richard Guenther wrote:

> With expand and UNSPECs I was thinking of just using integral
> modes for the address-space qualified pointers and relying on
> the UNSPECs doing the right things with them.  I agree that they
> might have different sizes, but do we need different _pointer_ modes
> for them?  I guess not necessarily...

Huh?  The pointer modes *are* just integral modes, the question is
only, which ones (i.e. which size)?

Typically, a back-end defines Pmode to be either SImode or DImode.
With the new hooks, it simply can make the SImode vs. DImode choice
depending on the address space pointed to, instead of this being
an overall global decision ...

Bye,
Ulrich

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

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer   modes
  2009-09-21 13:52   ` Ulrich Weigand
@ 2009-09-21 15:31     ` Richard Guenther
  2009-09-21 15:35       ` Ulrich Weigand
  2009-09-22 20:26     ` Richard Henderson
  1 sibling, 1 reply; 20+ messages in thread
From: Richard Guenther @ 2009-09-21 15:31 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc-patches

On Mon, Sep 21, 2009 at 3:41 PM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
> Richard Guenther wrote:
>
>> +      /* 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 !=3D default_addr_space_address_=
>> mode
>> +          || targetm.addr_space.pointer_mode !=3D
>> default_addr_space_pointer_mode)
>>
>> I think these changes are ugly.  Please at least add a macro
>> TARGET_SUPPORTS_ADDR_SPACE_P that expands to this test.
>
> OK, I've checked the patch below into the named-addr-spaces-branch.

Thanks.

>> It seems that really you should test if the current TU uses address
>> space qualified types, no?
>
> Well, that could be an optimization, I guess.  (A more specific one
> would be to actually encode the address space pointed to for registers
> marked as REG_POINTER.  Then we could just use the proper mode ...)
>
> I'm not sure this is worth the effort at this point, as all these
> checks make a difference only on targets that simultaneously support
> named address spaces and pointer mode != address mode scenarios.  We
> currently do not have any such targets, the check is just a fail-safe ...
>
>> Why do we need different modes for address spaces at all?  As I don't
>> really understand the issues here I don't feel qualified to review the
>> patch.  Sorry.  Why would a single mode for all address spaces be enough?
>> Isn't everything lowered during expansion, maybe simply using UNSPECs?
>
> Well, we (may) need different modes for pointers to different address
> spaces because those pointers may be differently sized.  For example,
> on the SPU (when using the -mea64 mode), generic pointers are 32-bit
> values (or more precisely, 18-bit values stored in a 32-bit field)
> refering to the SPU local store, while __ea pointers are 64-bit values
> refering to the PowerPC process address space.  So you have
>  sizeof (void *) == 4
>  sizeof (__ea void *) == 8
>
> Other potential uses of the named address space infrastructure may
> likewise require different pointer sizes, e.g. you could implement a
> 16-bit Intel mode with near / far pointers (2 vs. 4 bytes) and so on ...
>
> I don't quite see where expansion comes in here; the different pointer
> sizes are even visible on the language level.  In any case, even while
> the current SPU patch does indeed lower all non-generic address space
> accesses during expansion (because we use a software-emulated cache),
> other implementations may well have actual instructions to access
> non-generic address spaces, so those will need to be represented
> throughout the RTL stages.
>
> (Actually, even on the SPU, operations on __ea pointers *except*
> dereference  -- copying a pointer value, pointer arithmetic etc. --
> *is* expanded into RTL and has to use the proper mode throughout
> the RTL stages ...)

With expand and UNSPECs I was thinking of just using integral
modes for the address-space qualified pointers and relying on
the UNSPECs doing the right things with them.  I agree that they
might have different sizes, but do we need different _pointer_ modes
for them?  I guess not necessarily...

Well - defering to others here ;)

Thanks,
Richard.

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer     modes
  2009-09-20  1:52 ` Richard Guenther
@ 2009-09-21 13:52   ` Ulrich Weigand
  2009-09-21 15:31     ` Richard Guenther
  2009-09-22 20:26     ` Richard Henderson
  0 siblings, 2 replies; 20+ messages in thread
From: Ulrich Weigand @ 2009-09-21 13:52 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

Richard Guenther wrote:

> +      /* 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 !=3D default_addr_space_address_=
> mode
> +          || targetm.addr_space.pointer_mode !=3D
> default_addr_space_pointer_mode)
> 
> I think these changes are ugly.  Please at least add a macro
> TARGET_SUPPORTS_ADDR_SPACE_P that expands to this test.

OK, I've checked the patch below into the named-addr-spaces-branch.

> It seems that really you should test if the current TU uses address
> space qualified types, no?

Well, that could be an optimization, I guess.  (A more specific one
would be to actually encode the address space pointed to for registers
marked as REG_POINTER.  Then we could just use the proper mode ...)

I'm not sure this is worth the effort at this point, as all these
checks make a difference only on targets that simultaneously support
named address spaces and pointer mode != address mode scenarios.  We
currently do not have any such targets, the check is just a fail-safe ...

> Why do we need different modes for address spaces at all?  As I don't
> really understand the issues here I don't feel qualified to review the
> patch.  Sorry.  Why would a single mode for all address spaces be enough?
> Isn't everything lowered during expansion, maybe simply using UNSPECs?

Well, we (may) need different modes for pointers to different address
spaces because those pointers may be differently sized.  For example,
on the SPU (when using the -mea64 mode), generic pointers are 32-bit
values (or more precisely, 18-bit values stored in a 32-bit field)
refering to the SPU local store, while __ea pointers are 64-bit values
refering to the PowerPC process address space.  So you have
  sizeof (void *) == 4
  sizeof (__ea void *) == 8

Other potential uses of the named address space infrastructure may
likewise require different pointer sizes, e.g. you could implement a
16-bit Intel mode with near / far pointers (2 vs. 4 bytes) and so on ...

I don't quite see where expansion comes in here; the different pointer
sizes are even visible on the language level.  In any case, even while
the current SPU patch does indeed lower all non-generic address space
accesses during expansion (because we use a software-emulated cache),
other implementations may well have actual instructions to access
non-generic address spaces, so those will need to be represented
throughout the RTL stages.

(Actually, even on the SPU, operations on __ea pointers *except*
dereference  -- copying a pointer value, pointer arithmetic etc. --
*is* expanded into RTL and has to use the proper mode throughout
the RTL stages ...)


Bye,
Ulrich


ChangeLog:

	* target-def.h (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P): New macro.

	* alias.c: (find_base_value): Use TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
	to guard pointer size optimizations.
	(find_base_term): Likewise.
	* rtlanal.c: (nonzero_bits1): Likewise.
	(num_sign_bit_copies1): Likewise.
	* simplify-rtx.c: (simplify_unary_operation_1): Likewise.

	* alias.c: Include "target-def.h" instead of "targhooks.h".
	* rtlanal.c: Likewise.
	* simplify-rtx.c: Likewise.
	* Makefile.in (alias.o): Update dependencies.
	(rtlanal.o): Likewise.
	(simplify-rtx.o): Likewise.

Index: gcc/rtlanal.c
===================================================================
*** gcc/rtlanal.c	(revision 151727)
--- gcc/rtlanal.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 38,44 ****
  #include "function.h"
  #include "df.h"
  #include "tree.h"
! #include "targhooks.h"
  
  /* Forward declarations */
  static void set_of_1 (rtx, const_rtx, void *);
--- 38,44 ----
  #include "function.h"
  #include "df.h"
  #include "tree.h"
! #include "target-def.h"
  
  /* Forward declarations */
  static void set_of_1 (rtx, const_rtx, void *);
*************** nonzero_bits1 (const_rtx x, enum machine
*** 3752,3759 ****
        /* 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);
--- 3752,3758 ----
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && REG_POINTER (x))
  	nonzero &= GET_MODE_MASK (ptr_mode);
*************** nonzero_bits1 (const_rtx x, enum machine
*** 3994,4002 ****
  	/* 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)))
--- 3993,3999 ----
  	/* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	    && POINTERS_EXTEND_UNSIGNED > 0 && GET_MODE (x) == Pmode
  	    && (code == PLUS || code == MINUS)
  	    && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
*************** num_sign_bit_copies1 (const_rtx x, enum 
*** 4274,4281 ****
        /* 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;
--- 4271,4277 ----
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && mode == Pmode && REG_POINTER (x))
  	return GET_MODE_BITSIZE (Pmode) - GET_MODE_BITSIZE (ptr_mode) + 1;
*************** num_sign_bit_copies1 (const_rtx x, enum 
*** 4476,4483 ****
        /* 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)))
--- 4472,4478 ----
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
  	  && (code == PLUS || code == MINUS)
  	  && REG_P (XEXP (x, 0)) && REG_POINTER (XEXP (x, 0)))
Index: gcc/alias.c
===================================================================
*** gcc/alias.c	(revision 151726)
--- gcc/alias.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 49,55 ****
  #include "tree-ssa-alias.h"
  #include "pointer-set.h"
  #include "tree-flow.h"
! #include "targhooks.h"
  
  /* The aliasing API provided here solves related but different problems:
  
--- 49,55 ----
  #include "tree-ssa-alias.h"
  #include "pointer-set.h"
  #include "tree-flow.h"
! #include "target-def.h"
  
  /* The aliasing API provided here solves related but different problems:
  
*************** find_base_value (rtx src)
*** 1053,1060 ****
        /* 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;
--- 1053,1059 ----
        /* 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 (!TARGET_DEFAULT_POINTER_ADDRESS_MODES_P)
  	break;
        if (GET_MODE_SIZE (GET_MODE (src)) < GET_MODE_SIZE (Pmode))
  	break;
*************** find_base_value (rtx src)
*** 1073,1081 ****
        /* 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));
  
--- 1072,1080 ----
        /* 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 (!TARGET_DEFAULT_POINTER_ADDRESS_MODES_P)
  	break;
+ 
        {
  	rtx temp = find_base_value (XEXP (src, 0));
  
*************** find_base_term (rtx x)
*** 1471,1478 ****
        /* 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;
--- 1470,1476 ----
        /* 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 (!TARGET_DEFAULT_POINTER_ADDRESS_MODES_P)
  	return 0;
        if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (Pmode))
  	return 0;
*************** find_base_term (rtx x)
*** 1491,1499 ****
        /* 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));
  
--- 1489,1497 ----
        /* 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 (!TARGET_DEFAULT_POINTER_ADDRESS_MODES_P)
  	return 0;
+ 
        {
  	rtx temp = find_base_term (XEXP (x, 0));
  
Index: gcc/simplify-rtx.c
===================================================================
*** gcc/simplify-rtx.c	(revision 151727)
--- gcc/simplify-rtx.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 39,45 ****
  #include "output.h"
  #include "ggc.h"
  #include "target.h"
! #include "targhooks.h"
  
  /* Simplification and canonicalization of RTL.  */
  
--- 39,45 ----
  #include "output.h"
  #include "ggc.h"
  #include "target.h"
! #include "target-def.h"
  
  /* Simplification and canonicalization of RTL.  */
  
*************** simplify_unary_operation_1 (enum rtx_cod
*** 967,974 ****
        /* 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)
--- 967,973 ----
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && ! POINTERS_EXTEND_UNSIGNED
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
*************** simplify_unary_operation_1 (enum rtx_cod
*** 994,1001 ****
        /* 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)
--- 993,999 ----
        /* 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 (TARGET_DEFAULT_ADDRESS_POINTER_MODES_P
  	  && POINTERS_EXTEND_UNSIGNED > 0
  	  && mode == Pmode && GET_MODE (op) == ptr_mode
  	  && (CONSTANT_P (op)
Index: gcc/target-def.h
===================================================================
*** gcc/target-def.h	(revision 151727)
--- gcc/target-def.h	(working copy)
***************
*** 505,510 ****
--- 505,518 ----
      TARGET_ADDR_SPACE_CONVERT,			\
    }
  
+ /* Some places still assume that all pointer or address modes are the
+    standard Pmode and ptr_mode.  These optimizations become invalid if
+    the target actually supports multiple different modes.  For now,
+    we disable such optimizations on such targets, using this macro.  */
+ #define TARGET_DEFAULT_POINTER_ADDRESS_MODES_P \
+   (targetm.addr_space.address_mode == default_addr_space_address_mode \
+    && targetm.addr_space.pointer_mode == default_addr_space_pointer_mode)
+ 
  #ifndef TARGET_SCALAR_MODE_SUPPORTED_P
  #define TARGET_SCALAR_MODE_SUPPORTED_P default_scalar_mode_supported_p
  #endif
Index: gcc/Makefile.in
===================================================================
*** gcc/Makefile.in	(revision 151727)
--- gcc/Makefile.in	(working copy)
*************** print-rtl.o : print-rtl.c $(CONFIG_H) $(
*** 2659,2665 ****
  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) \
!    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) \
--- 2659,2665 ----
  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) $(TARGET_DEF_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) \
*************** jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) 
*** 2763,2769 ****
  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) 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) \
--- 2763,2769 ----
  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) $(TARGET_DEF_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) \
*************** alias.o : alias.c $(CONFIG_H) $(SYSTEM_H
*** 3068,3074 ****
     $(ALIAS_H) $(EMIT_RTL_H) $(GGC_H) $(FUNCTION_H) cselib.h $(TREE_H) $(TM_P_H) \
     langhooks.h $(TARGET_H) gt-alias.h $(TIMEVAR_H) $(CGRAPH_H) \
     $(SPLAY_TREE_H) $(VARRAY_H) $(IPA_TYPE_ESCAPE_H) $(DF_H) $(TREE_PASS_H) \
!    tree-ssa-alias.h pointer-set.h $(TREE_FLOW_H) targhooks.h
  stack-ptr-mod.o : stack-ptr-mod.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
     $(TM_H) $(TREE_H) $(RTL_H) $(REGS_H) $(EXPR_H) $(TREE_PASS_H) \
     $(BASIC_BLOCK_H) $(FLAGS_H) output.h $(DF_H)
--- 3068,3074 ----
     $(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) $(TARGET_DEF_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)

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

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

* Re: [PATCH PING 2/5] Named address spaces: support multiple pointer   modes
  2009-09-16 16:50 Ulrich Weigand
@ 2009-09-20  1:52 ` Richard Guenther
  2009-09-21 13:52   ` Ulrich Weigand
  0 siblings, 1 reply; 20+ messages in thread
From: Richard Guenther @ 2009-09-20  1:52 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc-patches

On Wed, Sep 16, 2009 at 6:49 PM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
> 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?

+      /* 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)

I think these changes are ugly.  Please at least add a macro
TARGET_SUPPORTS_ADDR_SPACE_P that expands to this test.

It seems that really you should test if the current TU uses address
space qualified types, no?

Why do we need different modes for address spaces at all?  As I don't
really understand the issues here I don't feel qualified to review the
patch.  Sorry.  Why would a single mode for all address spaces be enough?
Isn't everything lowered during expansion, maybe simply using UNSPECs?

Thanks,
Richard.

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

* [PATCH PING 2/5] Named address spaces: support multiple pointer modes
@ 2009-09-16 16:50 Ulrich Weigand
  2009-09-20  1:52 ` Richard Guenther
  0 siblings, 1 reply; 20+ messages in thread
From: Ulrich Weigand @ 2009-09-16 16:50 UTC (permalink / raw)
  To: gcc-patches

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

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

end of thread, other threads:[~2009-11-17 16:14 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-14 20:53 [PATCH PING 2/5] Named address spaces: support multiple pointer modes Dmitry Gorbachev
2009-11-16 20:06 ` Ulrich Weigand
2009-11-17  6:13   ` Dmitry Gorbachev
2009-11-17 16:18     ` Ulrich Weigand
  -- strict thread matches above, loose matches on Subject: below --
2009-09-16 16:50 Ulrich Weigand
2009-09-20  1:52 ` Richard Guenther
2009-09-21 13:52   ` Ulrich Weigand
2009-09-21 15:31     ` Richard Guenther
2009-09-21 15:35       ` Ulrich Weigand
2009-09-22 20:26     ` Richard Henderson
2009-09-22 22:51       ` Ulrich Weigand
2009-09-22 23:21         ` Joseph S. Myers
2009-09-23  0:11         ` Richard Henderson
2009-09-23  1:17           ` Ulrich Weigand
2009-09-23 15:26             ` Richard Henderson
2009-09-24 16:08               ` Ulrich Weigand
2009-09-24 16:50                 ` Richard Henderson
2009-09-24 18:26                   ` Ulrich Weigand
2009-09-24 18:43                     ` Richard Henderson
2009-09-24 20:40                       ` Ulrich Weigand

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