This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[named-address-space-branch][Patch,committed] Update RTL memory functions for named address support
- From: Michael Meissner <meissner at linux dot vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 16 Dec 2008 18:18:15 -0500
- Subject: [named-address-space-branch][Patch,committed] Update RTL memory functions for named address support
This update is a checkpoint in my current work. The main part of the changes
is to update the RTL memory functions (change_address, adjust_address,
offset_address, replace_equiv_address, etc.) and make them namespace aware. I
did this usually by renaming the function and adding a new argument for the
named address space.
I added support for the backend to say that that two named address pointers
being subtracted might produce a result in a different type than ptrdiff_type.
I added a few execute tests, to test various static initializations. Most of
the test currently fail. I also added a hook, which isn't yet used for the
backend to say whether you can initialize something in a given named address
space. Right now, I'm looking for the place to put this, and I may change some
of the execute tests to compile tests checking for failure, when I resolve the
initialization support.
I updated a few of the files not to use Pmode, but to use the mode of the
memory that they are replacing.
[gcc]
2008-12-16 Michael Meissner <meissner@linux.vnet.ibm.com>
* targhooks.c (default_valid_pointer_mode): Move here from
varasm.c.
(default_addr_space_pointer_mode): Ditto.
(default_addr_space_minus_type): New hook to return the type used
for the difference of two pointers.
(default_addr_space_memory_address_p): New hook for the named
address space version of memory_address_p.
(default_addr_space_strict_memory_address_p): New hook for the
named address space version of strict_memory_address_p.
(default_addr_space_legitimize_address): New hook for the named
address space version of LEGITIMIZE_ADDRESS.
(default_addr_space_static_init_ok_p): New hook to determine if an
initialization can take place in another named address space.
* targhooks.h (default_valid_pointer_mode): Add declaration.
(default_addr_space_pointer_mode): Ditto.
(default_addr_space_minus_type): Ditto.
(default_addr_space_memory_address_p): Ditto.
(default_addr_space_strict_memory_address_p): Ditto.
(default_addr_space_legitimize_address): Ditto.
(default_addr_space_static_init_ok_p): Ditto.
* target.h (struct addr_space): Add minus_type, memory_address_p,
strict_memory_address_p, legitimize_address, and static_init_ok_p
hooks.
* auto-inc-dec.c (try_merge): Use GET_MODE instead of Pmode for
the mode of newly created RTL.
* expr.c (emit_move_insn): Add named address support.
(expand_expr_real_1): Ditto.
* expr.h (memory_address_addr_space): Add declaration.
(memory_address): Define in terms of memory_address_addr_space
with the generic address space.
* recog.c (memory_address_addr_space_p): New function, like
memory_address_p, except it takes an named address space
identifier.
* recog.h (memory_address_addr_space_p): Add declaration.
(strict_memory_address_addr_space_p): Ditto.
* c-typeck.c (parser_build_binary_op): Use the address space
minus_type hook to determine what type is used for subtraction of
two pointers to named address spaces.
(convert_for_assignment): Shorten a line to under 80 characters.
* emit-rtl.c (toplevel): Include target.h.
(change_address_1): Add named address space parameter. Switch
validation to be named address space aware.
(change_address_addr_space): Like change_address, but take the
address space to change the address to.
(change_address): Call change_address_addr_space with generic
address space argument.
(adjust_address_1): Add support for named address spaces.
(offset_address): Ditto.
(replace_equiv_address): Add address space argument.
(replace_equiv_address_nv): Ditto.
* explow.c (break_out_memory_refs): Use GET_MODE of the address
instead of assuming all pointers are Pmode.
(memory_address_addr_space): Rename from memory_address, add named
address space argument. Use named address space legitimize hook
instead of LEGITIMIZE_ADDRESS for memory addresse spaces other
than the generic address space.
(validize_mem): Add named address space support.
* varasm.c (make_decl_rtl): Reformat code somewhat.
(default_valid_pointer_mode): Move to targhooks.c.
(default_addr_space_pointer): Ditto.
* target-def.h (TARGET_ADDR_SPACE_MINUS_HOOK): New named address
space hook.
(TARGET_ADDR_SPACE_MEMORY_ADDRESS_P): Ditto.
(TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P): Ditto.
(TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS): Ditto.
(TARGET_ADDR_SPACE_STATIC_INIT_OK_P): Ditto.
(TARGET_ADDR_SPACE_HOOKS): Add new hooks.
* Makefile.in (emit-rtl.o): Add $(TARGET_H) dependencies.
* config/spu/spu-protos.h (spu_legitimate_address): Add named
address space argument.
(spu_legitimize_address): New hook.
* config/spu/spu.c (EAmode): Move earlier in the file.
(spu_addr_space_pointer_mode): Rename from spu_ea_pointer_mode for
consistancy. Simplify code somewhat.
(TARGET_ADDR_SPACE_POINTER_MODE): Use spu_addr_space_pointer_mode.
(spu_addr_space_minus_type): New named address space hook.
(spu_addr_space_memory_address_p): Ditto.
(spu_addr_space_strict_memory_address_p): Ditto.
(spu_addr_space_legitimize_address): Ditto.
(spu_addr_space_static_init_ok_p): Ditto.
(TARGET_ADDR_SPACE_MINUS_TYPE): Ditto.
(TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P): Ditto.
(TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS): Ditto.
(TARGET_ADDR_SPACE_STATIC_INIT_OK_P): Ditto.
(spu_legitimate_address): Add named address space argument.
(spu_legitimize_address): Ditto.
(expand_ea_mem): Use change_address_addr_space instead of
change_address.
(spu_valid_move): Add assert for being inside function context.
* config/spu/spu.h (GO_IF_LEGITIMATE_ADDRESS): Add default named
address space argument.
(LEGITIMIZE_ADDRESS): Ditto.
[gcc/testsuite]
2008-12-16 Michael Meissner <meissner@linux.vnet.ibm.com>
* gcc.target/spu/ea/compile3.c: Add static initializations.
* gcc.target/spu/ea/errors3.c: Ditto.
* gcc.target/spu/ea/compile4.c: New file to make sure __ea
structure references work.
* gcc.target/spu/ea/execute1.c: New file to make sure various
static initializations work for -mea32.
* gcc.target/spu/ea/execute2.c: Ditto.
* gcc.target/spu/ea/execute3.c: Ditto.
* gcc.target/spu/ea/execute4.c: Ditto.
* gcc.target/spu/ea/execute5.c: Ditto.
* gcc.target/spu/ea/execute6.c: Ditto.
* gcc.target/spu/ea/execute1-m64.c: New file to make sure various
static initializations work for -mea64.
* gcc.target/spu/ea/execute2-m64.c: Ditto.
* gcc.target/spu/ea/execute3-m64.c: Ditto.
* gcc.target/spu/ea/execute4-m64.c: Ditto.
* gcc.target/spu/ea/execute5-m64.c: Ditto.
* gcc.target/spu/ea/execute6-m64.c: Ditto.
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c (revision 142610)
+++ gcc/targhooks.c (working copy)
@@ -712,6 +712,35 @@ 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 integer mode for subtracting two pointers to named address
+ spaces. */
+
+tree
+default_addr_space_minus_type (addr_space_t as1 ATTRIBUTE_UNUSED,
+ addr_space_t as2 ATTRIBUTE_UNUSED)
+{
+ gcc_assert (as1 == 0 && as2 == 0);
+ return ptrdiff_type_node;
+}
+
/* The default hook for TARGET_ADDR_SPACE_NAME. This hook should
never be called for targets with only a generic address space. */
@@ -721,6 +750,41 @@ default_addr_space_name (addr_space_t ad
gcc_unreachable ();
}
+/* Named address space version of memory_address_p. */
+
+bool
+default_addr_space_memory_address_p (enum machine_mode mode, rtx mem,
+ addr_space_t as)
+{
+ if (!as)
+ return memory_address_p (mode, mem);
+
+ gcc_unreachable ();
+}
+
+/* Named address space version of strict_memory_address_p. */
+
+bool
+default_addr_space_strict_memory_address_p (enum machine_mode mode, rtx mem,
+ addr_space_t as)
+{
+ if (!as)
+ return strict_memory_address_p (mode, mem);
+
+ gcc_unreachable ();
+}
+
+/* Named address space version of LEGITIMIZE_ADDRESS. */
+
+rtx
+default_addr_space_legitimize_address (rtx x ATTRIBUTE_UNUSED,
+ rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ addr_space_t as ATTRIBUTE_UNUSED)
+{
+ return NULL_RTX;
+}
+
/* The default hook for determining whether you can convert from one address
space to another. */
@@ -782,6 +846,18 @@ default_addr_space_section_name (addr_sp
gcc_unreachable ();
}
+/* The default hook for determining if a static initialization is ok. For the
+ default case, only assume static initializations in the generic address
+ space are ok. */
+
+bool
+default_addr_space_static_init_ok_p (tree value ATTRIBUTE_UNUSED,
+ addr_space_t var_as,
+ addr_space_t element_as)
+{
+ return (var_as == 0) && (element_as == 0);
+}
+
bool
default_hard_regno_scratch_ok (unsigned int regno ATTRIBUTE_UNUSED)
{
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h (revision 142610)
+++ gcc/targhooks.h (working copy)
@@ -104,11 +104,22 @@ 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_option_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 tree default_addr_space_minus_type (addr_space_t, addr_space_t);
extern const char *default_addr_space_name (addr_space_t);
extern rtx default_addr_space_convert (rtx, enum machine_mode, addr_space_t,
addr_space_t);
+extern bool default_addr_space_memory_address_p (enum machine_mode, rtx,
+ addr_space_t);
+extern bool default_addr_space_strict_memory_address_p (enum machine_mode, rtx,
+ addr_space_t);
+extern rtx default_addr_space_legitimize_address (rtx, rtx, enum machine_mode,
+ addr_space_t);
extern bool default_addr_space_can_convert_p (addr_space_t, addr_space_t);
extern bool default_addr_space_nop_convert_p (addr_space_t, addr_space_t);
extern bool default_addr_space_subset_p (addr_space_t, addr_space_t,
addr_space_t *);
extern tree default_addr_space_section_name (addr_space_t);
+extern bool default_addr_space_static_init_ok_p (tree, addr_space_t,
+ addr_space_t);
Index: gcc/target.h
===================================================================
--- gcc/target.h (revision 142610)
+++ gcc/target.h (working copy)
@@ -667,15 +667,31 @@ struct gcc_target
/* MODE to use for a pointer into another address space. */
enum machine_mode (* pointer_mode) (addr_space_t);
+ /* Tree type to use for pointer subtraction. */
+ tree (* minus_type) (addr_space_t, addr_space_t);
+
/* Function to map an address space to a descriptive string. */
const char * (* name) (addr_space_t);
+ /* True if an addrress is a valid memory address to a given named address
+ space for a given mode. */
+ bool (* memory_address_p) (enum machine_mode, rtx, addr_space_t);
+
+ /* True if an addrress is a valid memory address for use after register
+ allocation to a given named address space for a given mode. */
+ bool (* strict_memory_address_p) (enum machine_mode, rtx, addr_space_t);
+
+ /* Return an updated address to convert an invalid pointer to a named
+ address space to a valid one. If NULL_RTX is returned use machine
+ independent methods to make the address valid. */
+ rtx (* legitimize_address) (rtx, rtx, enum machine_mode, addr_space_t);
+
/* True if it is legal to convert a pointer of one address space to
another. */
bool (* can_convert_p) (addr_space_t, addr_space_t);
/* True if converting a pointer of one address space to another is just a
- NOP. */
+ NOP and can be optimized away by the compiler. */
bool (* nop_convert_p) (addr_space_t, addr_space_t);
/* True if one named address space is a subset of another and if so, which
@@ -688,6 +704,11 @@ struct gcc_target
/* Section name to use for a named address space. */
tree (* section_name) (addr_space_t);
+
+ /* Return whether static initialization of a pointer to a named address
+ space is allowed. */
+ bool (* static_init_ok_p) (tree, addr_space_t, addr_space_t);
+
} addr_space;
/* True if MODE is valid for the target. By "valid", we mean able to
Index: gcc/auto-inc-dec.c
===================================================================
--- gcc/auto-inc-dec.c (revision 142610)
+++ gcc/auto-inc-dec.c (working copy)
@@ -651,6 +651,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)
{
@@ -705,33 +706,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);
@@ -740,9 +741,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);
@@ -751,9 +752,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);
@@ -762,9 +763,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);
@@ -1127,7 +1128,7 @@ 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)
+ if (targetm.valid_pointer_mode (GET_MODE (inc_insn.reg_res)))
{
if (dump_file)
fprintf (dump_file, "base reg mode failure.\n");
@@ -1176,7 +1177,7 @@ 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)
+ if (targetm.valid_pointer_mode (GET_MODE (inc_insn.reg_res)))
{
if (dump_file)
fprintf (dump_file, "base reg mode failure.\n");
Index: gcc/testsuite/gcc.target/spu/ea/errors3.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/errors3.c (revision 142610)
+++ gcc/testsuite/gcc.target/spu/ea/errors3.c (working copy)
@@ -4,8 +4,17 @@
/* This is the same as compile3.c except it should generate errors where
pointers are mixed. If you modify this code, please modify compile3.c as
well. */
+
+#define __lm
+
+__ea int ea_var = 1;
+__lm int lm_var = 2;
+
typedef __ea int *ea_ptr_t;
-typedef int *lm_ptr_t;
+typedef __lm int *lm_ptr_t;
+
+typedef __ea char *ea_cptr_t;
+typedef __lm char *lm_cptr_t;
ea_ptr_t ea, ea2;
lm_ptr_t lm, lm2;
@@ -42,3 +51,12 @@ int if_lm_with_cast (int test) { return
void void_ea (void) { ea = (void *)0; }
void void_lm (void) { lm = (__ea void *)0; }
+
+ea_ptr_t ea_init = &lm_var; /* { dg-error "initialization of a pointer to an incompatible address space" } */
+lm_ptr_t lm_init = &ea_var; /* { dg-error "initialization of a pointer to an incompatible address space" } */
+
+ea_ptr_t ea_init2 = (ea_ptr_t)&lm_var;
+lm_ptr_t lm_init2 = (lm_ptr_t)&ea_var;
+
+ea_cptr_t ea_str = "abc"; /* { dg-error "initialization of a pointer to an incompatible address space" } */
+ea_cptr_t ea_str2 = (ea_cptr_t)"def";
Index: gcc/testsuite/gcc.target/spu/ea/compile3.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/compile3.c (revision 142610)
+++ gcc/testsuite/gcc.target/spu/ea/compile3.c (working copy)
@@ -3,8 +3,17 @@
/* This is the same as errors3.c except it should not generate any errors.
If you modify this code, please modify errors3.c as well. */
+
+#define __lm
+
+__ea int ea_var = 1;
+__lm int lm_var = 2;
+
typedef __ea int *ea_ptr_t;
-typedef int *lm_ptr_t;
+typedef __lm int *lm_ptr_t;
+
+typedef __ea char *ea_cptr_t;
+typedef __lm char *lm_cptr_t;
ea_ptr_t ea, ea2;
lm_ptr_t lm, lm2;
@@ -40,3 +49,12 @@ int if_lm_with_cast (int test) { return
void void_ea (void) { ea = (void *)0; }
void void_lm (void) { lm = (__ea void *)0; }
+
+ea_ptr_t ea_init = &lm_var;
+lm_ptr_t lm_init = &ea_var;
+
+ea_ptr_t ea_init2 = (ea_ptr_t)&lm_var;
+lm_ptr_t lm_init2 = (lm_ptr_t)&ea_var;
+
+ea_cptr_t ea_str = "abc";
+ea_cptr_t ea_str2 = (ea_cptr_t)"def";
Index: gcc/testsuite/gcc.target/spu/ea/compile4.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/compile4.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/compile4.c (revision 0)
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu99 -pedantic-errors -mea64" } */
+/* Make sure __ea structure references work. */
+
+typedef unsigned long int uintptr_t;
+
+struct tostruct
+{
+ uintptr_t selfpc;
+ long count;
+ unsigned short link;
+};
+
+/* froms are indexing tos */
+static __ea unsigned short *froms;
+static __ea struct tostruct *tos = 0;
+
+void
+foo (uintptr_t frompc, uintptr_t selfpc)
+{
+ __ea unsigned short *frompcindex;
+
+ frompcindex = &froms[(frompc) / (4 * sizeof (*froms))];
+ *frompcindex = tos[0].link;
+
+ return;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute1.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute1.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute1.c (revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+__ea char *p = "abc";
+
+int
+main (void)
+{
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute2.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute2.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute2.c (revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+__ea char str[] = "abc";
+__ea char *p = str;
+
+int
+main (void)
+{
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute3.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute3.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute3.c (revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+char str[] = "abc";
+__ea char *p = (__ea char *)str;
+
+int
+main (void)
+{
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute4.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute4.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute4.c (revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+__ea char str[] = "abc";
+
+int
+main (void)
+{
+ __ea char *p = str;
+
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute1-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute1-m64.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute1-m64.c (revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+__ea char *p = "abc";
+
+int
+main (void)
+{
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute5.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute5.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute5.c (revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+char str[] = "abc";
+
+int
+main (void)
+{
+ __ea char *p = (__ea char *)str;
+
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute2-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute2-m64.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute2-m64.c (revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+__ea char str[] = "abc";
+__ea char *p = str;
+
+int
+main (void)
+{
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute6.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute6.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute6.c (revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea32" } */
+
+#include <stdlib.h>
+
+int
+main (void)
+{
+ __ea char *p = (__ea char *)"abc";
+
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute3-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute3-m64.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute3-m64.c (revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+char str[] = "abc";
+__ea char *p = (__ea char *)str;
+
+int
+main (void)
+{
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute4-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute4-m64.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute4-m64.c (revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+__ea char str[] = "abc";
+
+int
+main (void)
+{
+ __ea char *p = str;
+
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute5-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute5-m64.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute5-m64.c (revision 0)
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+char str[] = "abc";
+
+int
+main (void)
+{
+ __ea char *p = (__ea char *)str;
+
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/testsuite/gcc.target/spu/ea/execute6-m64.c
===================================================================
--- gcc/testsuite/gcc.target/spu/ea/execute6-m64.c (revision 0)
+++ gcc/testsuite/gcc.target/spu/ea/execute6-m64.c (revision 0)
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -std=gnu99 -g -pedantic-errors -mea64" } */
+
+#include <stdlib.h>
+
+int
+main (void)
+{
+ __ea char *p = (__ea char *)"abc";
+
+ if (*p++ != 'a')
+ abort ();
+
+ if (*p++ != 'b')
+ abort ();
+
+ if (*p++ != 'c')
+ abort ();
+
+ if (*p++ != '\0')
+ abort ();
+
+ return 0;
+}
Index: gcc/expr.c
===================================================================
--- gcc/expr.c (revision 142610)
+++ gcc/expr.c (working copy)
@@ -3430,12 +3430,14 @@ emit_move_insn (rtx x, rtx y)
/* If X or Y are memory references, verify that their addresses are valid
for the machine. */
if (MEM_P (x)
- && (! memory_address_p (GET_MODE (x), XEXP (x, 0))
+ && (! memory_address_addr_space_p (GET_MODE (x), XEXP (x, 0),
+ MEM_ADDR_SPACE (x))
&& ! push_operand (x, GET_MODE (x))))
x = validize_mem (x);
if (MEM_P (y)
- && ! memory_address_p (GET_MODE (y), XEXP (y, 0)))
+ && ! memory_address_addr_space_p (GET_MODE (y), XEXP (y, 0),
+ MEM_ADDR_SPACE (y)))
y = validize_mem (y);
gcc_assert (mode != BLKmode);
@@ -7340,7 +7342,9 @@ expand_expr_real_1 (tree exp, rtx target
decl_rtl = use_anchored_address (decl_rtl);
if (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_SUM
- && !memory_address_p (DECL_MODE (exp), XEXP (decl_rtl, 0)))
+ && !memory_address_addr_space_p (DECL_MODE (exp),
+ XEXP (decl_rtl, 0),
+ MEM_ADDR_SPACE (decl_rtl)))
temp = replace_equiv_address (decl_rtl,
copy_rtx (XEXP (decl_rtl, 0)));
}
@@ -7462,7 +7466,8 @@ expand_expr_real_1 (tree exp, rtx target
if (modifier != EXPAND_CONST_ADDRESS
&& modifier != EXPAND_INITIALIZER
&& modifier != EXPAND_SUM
- && ! memory_address_p (mode, XEXP (temp, 0)))
+ && ! memory_address_addr_space_p (mode, XEXP (temp, 0),
+ MEM_ADDR_SPACE (temp)))
return replace_equiv_address (temp,
copy_rtx (XEXP (temp, 0)));
return temp;
@@ -7522,6 +7527,8 @@ expand_expr_real_1 (tree exp, rtx target
case INDIRECT_REF:
{
tree exp1 = TREE_OPERAND (exp, 0);
+ addr_space_t as = 0;
+ enum machine_mode mem_Pmode = Pmode;
if (modifier != EXPAND_WRITE)
{
@@ -7532,20 +7539,30 @@ expand_expr_real_1 (tree exp, rtx target
return expand_expr (t, target, tmode, modifier);
}
+ if (POINTER_TYPE_P (TREE_TYPE (exp1)))
+ {
+ as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp1)));
+ if (as)
+ mem_Pmode = targetm.addr_space.pointer_mode (as);
+ }
+
op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
- op0 = memory_address (mode, op0);
+ op0 = memory_address_addr_space (mode, op0, as);
if (code == ALIGN_INDIRECT_REF)
{
int align = TYPE_ALIGN_UNIT (type);
- op0 = gen_rtx_AND (Pmode, op0, GEN_INT (-align));
- op0 = memory_address (mode, op0);
+ op0 = gen_rtx_AND (mem_Pmode, op0, GEN_INT (-align));
+ op0 = memory_address_addr_space (mode, op0, as);
}
temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, exp, 0);
+ if (as)
+ set_mem_addr_space (temp, as);
+
/* Resolve the misalignment now, so that we don't have to remember
to resolve it later. Of course, this only works for reads. */
/* ??? When we get around to supporting writes, we'll have to handle
Index: gcc/expr.h
===================================================================
--- gcc/expr.h (revision 142610)
+++ gcc/expr.h (working copy)
@@ -634,9 +634,14 @@ extern rtx force_label_rtx (tree);
The constant terms are added and stored via a second arg. */
extern rtx eliminate_constant_term (rtx, rtx *);
-/* Convert arg to a valid memory address for specified machine mode,
- by emitting insns to perform arithmetic if nec. */
-extern rtx memory_address (enum machine_mode, rtx);
+/* Convert arg to a valid memory address for specified machine mode that points
+ to a specific named address space, by emitting insns to perform arithmetic
+ if necessary. */
+extern rtx memory_address_addr_space (enum machine_mode, rtx, addr_space_t);
+
+/* Like memory_address_addr_space, except assume the memory address points to
+ the generic named address space. */
+#define memory_address(MODE,RTX) memory_address_addr_space (MODE, RTX, 0)
/* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address changed to ADDR.
@@ -644,6 +649,11 @@ extern rtx memory_address (enum machine_
NULL for ADDR means don't change the address.) */
extern rtx change_address (rtx, enum machine_mode, rtx);
+/* Like change_address, except we change the address space of the memory
+ returned. */
+extern rtx change_address_addr_space (rtx, enum machine_mode, rtx,
+ addr_space_t);
+
/* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address offset by OFFSET bytes. */
#define adjust_address(MEMREF, MODE, OFFSET) \
Index: gcc/recog.c
===================================================================
--- gcc/recog.c (revision 142610)
+++ gcc/recog.c (working copy)
@@ -1253,6 +1253,17 @@ memory_address_p (enum machine_mode mode
return 1;
}
+/* Like memory_address_p, expect for a distinct named address space. */
+
+int
+memory_address_addr_space_p (enum machine_mode mode, rtx addr, addr_space_t as)
+{
+ if (!as)
+ return memory_address_p (mode, addr);
+ else
+ return targetm.addr_space.memory_address_p (mode, addr, as);
+}
+
/* Return 1 if OP is a valid memory reference with mode MODE,
including a valid address.
Index: gcc/recog.h
===================================================================
--- gcc/recog.h (revision 142610)
+++ gcc/recog.h (working copy)
@@ -85,7 +85,10 @@ extern void cancel_changes (int);
extern int constrain_operands (int);
extern int constrain_operands_cached (int);
extern int memory_address_p (enum machine_mode, rtx);
+extern int memory_address_addr_space_p (enum machine_mode, rtx, addr_space_t);
extern int strict_memory_address_p (enum machine_mode, rtx);
+extern int strict_memory_address_addr_space_p (enum machine_mode, rtx,
+ addr_space_t);
extern int validate_replace_rtx (rtx, rtx, rtx);
extern int validate_replace_rtx_part (rtx, rtx, rtx *, rtx);
extern int validate_replace_rtx_part_nosimplify (rtx, rtx, rtx *, rtx);
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c (revision 142610)
+++ gcc/c-typeck.c (working copy)
@@ -2868,7 +2868,11 @@ parser_build_binary_op (location_t locat
static tree
pointer_diff (tree op0, tree op1)
{
- tree restype = ptrdiff_type_node;
+ addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
+ addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
+ tree restype = ((as0 == 0 && as1 == 0)
+ ? ptrdiff_type_node
+ : targetm.addr_space.minus_type (as0, as1));
tree target_type = TREE_TYPE (TREE_TYPE (op0));
tree con0, con1, lit0, lit1;
@@ -4390,8 +4394,8 @@ convert_for_assignment (tree type, tree
"space");
break;
case ic_init:
- error ("initialization of a pointer to an incompatible space"
- "address space");
+ error ("initialization of a pointer to an incompatible address "
+ "space");
break;
case ic_return:
error ("return of a pointer to an incompatible address space");
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c (revision 142610)
+++ gcc/emit-rtl.c (working copy)
@@ -58,6 +58,7 @@ along with GCC; see the file COPYING3.
#include "langhooks.h"
#include "tree-pass.h"
#include "df.h"
+#include "target.h"
/* Commonly used modes. */
@@ -179,7 +180,7 @@ static GTY ((if_marked ("ggc_marked_p"),
#define first_label_num (crtl->emit.x_first_label_num)
static rtx make_call_insn_raw (rtx);
-static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
+static rtx change_address_1 (rtx, enum machine_mode, rtx, int, addr_space_t);
static void set_used_decls (tree);
static void mark_label_nuses (rtx);
static hashval_t const_int_htab_hash (const void *);
@@ -1862,7 +1863,8 @@ set_mem_size (rtx mem, rtx size)
attributes are not changed. */
static rtx
-change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
+change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate,
+ addr_space_t as)
{
rtx new_rtx;
@@ -1872,15 +1874,15 @@ change_address_1 (rtx memref, enum machi
if (addr == 0)
addr = XEXP (memref, 0);
if (mode == GET_MODE (memref) && addr == XEXP (memref, 0)
- && (!validate || memory_address_p (mode, addr)))
+ && (!validate || memory_address_addr_space_p (mode, addr, as)))
return memref;
if (validate)
{
if (reload_in_progress || reload_completed)
- gcc_assert (memory_address_p (mode, addr));
+ gcc_assert (memory_address_addr_space_p (mode, addr, as));
else
- addr = memory_address (mode, addr);
+ addr = memory_address_addr_space (mode, addr, as);
}
if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref))
@@ -1888,16 +1890,23 @@ change_address_1 (rtx memref, enum machi
new_rtx = gen_rtx_MEM (mode, addr);
MEM_COPY_ATTRIBUTES (new_rtx, memref);
+
+ if (as != MEM_ADDR_SPACE (memref))
+ set_mem_addr_space (new_rtx, as);
+
return new_rtx;
}
-/* Like change_address_1 with VALIDATE nonzero, but we are not saying in what
- way we are changing MEMREF, so we only preserve the alias set. */
+/* Like change_address_1 with VALIDATE nonzero, and the address space set, but
+ we are not saying in what way we are changing MEMREF, so we only preserve
+ the alias set. */
rtx
-change_address (rtx memref, enum machine_mode mode, rtx addr)
+change_address_addr_space (rtx memref, enum machine_mode mode, rtx addr,
+ addr_space_t as)
{
- rtx new_rtx = change_address_1 (memref, mode, addr, 1), size;
+ rtx new_rtx = change_address_1 (memref, mode, addr, 1, as);
+ rtx size;
enum machine_mode mmode = GET_MODE (new_rtx);
unsigned int align;
@@ -1911,19 +1920,33 @@ change_address (rtx memref, enum machine
|| (MEM_EXPR (memref) == NULL
&& MEM_OFFSET (memref) == NULL
&& MEM_SIZE (memref) == size
+ && MEM_ADDR_SPACE (memref) == as
&& MEM_ALIGN (memref) == align))
return new_rtx;
new_rtx = gen_rtx_MEM (mmode, XEXP (memref, 0));
MEM_COPY_ATTRIBUTES (new_rtx, memref);
+
+ if (as != MEM_ADDR_SPACE (new_rtx))
+ set_mem_addr_space (new_rtx, as);
}
MEM_ATTRS (new_rtx)
- = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, MEM_ADDR_SPACE (memref), mmode);
+ = get_mem_attrs (MEM_ALIAS_SET (memref), 0, 0, size, align, as, mmode);
return new_rtx;
}
+/* Like change_address_addr_space, except we don't change the named address
+ space. */
+
+rtx
+change_address (rtx memref, enum machine_mode mode, rtx addr)
+{
+ return change_address_addr_space (memref, mode, addr,
+ MEM_ADDR_SPACE (memref));
+}
+
/* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address offset by OFFSET bytes. If VALIDATE is
nonzero, the memory address is forced to be valid.
@@ -1939,10 +1962,14 @@ adjust_address_1 (rtx memref, enum machi
rtx memoffset = MEM_OFFSET (memref);
rtx size = 0;
unsigned int memalign = MEM_ALIGN (memref);
+ addr_space_t as = MEM_ADDR_SPACE (memref);
+ enum machine_mode mem_Pmode = (!as
+ ? Pmode
+ : targetm.addr_space.pointer_mode (as));
/* If there are no changes, just return the original memory reference. */
if (mode == GET_MODE (memref) && !offset
- && (!validate || memory_address_p (mode, addr)))
+ && (!validate || memory_address_addr_space_p (mode, addr, as)))
return memref;
/* ??? Prefer to create garbage instead of creating shared rtl.
@@ -1958,13 +1985,13 @@ 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 (mem_Pmode, XEXP (addr, 0),
plus_constant (XEXP (addr, 1), offset));
else
addr = plus_constant (addr, offset);
}
- new_rtx = change_address_1 (memref, mode, addr, validate);
+ new_rtx = change_address_1 (memref, mode, addr, validate, as);
/* Compute the new values of the memory attributes due to this adjustment.
We add the offsets and update the alignment. */
@@ -1986,8 +2013,8 @@ adjust_address_1 (rtx memref, enum machi
size = plus_constant (MEM_SIZE (memref), -offset);
MEM_ATTRS (new_rtx) = get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref),
- memoffset, size, memalign, MEM_ADDR_SPACE (memref),
- GET_MODE (new_rtx));
+ memoffset, size, memalign, as,
+ GET_MODE (new_rtx));
/* At some point, we should validate that this offset is within the object,
if all the appropriate values are known. */
@@ -2003,7 +2030,8 @@ rtx
adjust_automodify_address_1 (rtx memref, enum machine_mode mode, rtx addr,
HOST_WIDE_INT offset, int validate)
{
- memref = change_address_1 (memref, VOIDmode, addr, validate);
+ memref = change_address_1 (memref, VOIDmode, addr, validate,
+ MEM_ADDR_SPACE (memref));
return adjust_address_1 (memref, mode, offset, validate, 0);
}
@@ -2015,8 +2043,12 @@ rtx
offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
{
rtx new_rtx, addr = XEXP (memref, 0);
+ addr_space_t as = MEM_ADDR_SPACE (memref);
+ enum machine_mode mem_Pmode = (!as
+ ? Pmode
+ : targetm.addr_space.pointer_mode (as));
- new_rtx = simplify_gen_binary (PLUS, Pmode, addr, offset);
+ new_rtx = simplify_gen_binary (PLUS, mem_Pmode, addr, offset);
/* At this point we don't know _why_ the address is invalid. It
could have secondary memory references, multiplies or anything.
@@ -2025,16 +2057,17 @@ offset_address (rtx memref, rtx offset,
being able to recognize the magic around pic_offset_table_rtx.
This stuff is fragile, and is yet another example of why it is
bad to expose PIC machinery too early. */
- if (! memory_address_p (GET_MODE (memref), new_rtx)
+ if (! memory_address_addr_space_p (GET_MODE (memref), new_rtx, as)
&& GET_CODE (addr) == PLUS
&& 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, mem_Pmode, addr, offset);
}
update_temp_slot_address (XEXP (memref, 0), new_rtx);
- new_rtx = change_address_1 (memref, VOIDmode, new_rtx, 1);
+ new_rtx = change_address_1 (memref, VOIDmode, new_rtx, 1,
+ MEM_ADDR_SPACE (memref));
/* If there are no changes, just return the original memory reference. */
if (new_rtx == memref)
@@ -2045,7 +2078,7 @@ offset_address (rtx memref, rtx offset,
MEM_ATTRS (new_rtx)
= get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0,
MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT),
- MEM_ADDR_SPACE (memref), GET_MODE (new_rtx));
+ as, GET_MODE (new_rtx));
return new_rtx;
}
@@ -2060,7 +2093,8 @@ replace_equiv_address (rtx memref, rtx a
/* change_address_1 copies the memory attribute structure without change
and that's exactly what we want here. */
update_temp_slot_address (XEXP (memref, 0), addr);
- return change_address_1 (memref, VOIDmode, addr, 1);
+ return change_address_1 (memref, VOIDmode, addr, 1,
+ MEM_ADDR_SPACE (memref));
}
/* Likewise, but the reference is not required to be valid. */
@@ -2068,7 +2102,7 @@ replace_equiv_address (rtx memref, rtx a
rtx
replace_equiv_address_nv (rtx memref, rtx addr)
{
- return change_address_1 (memref, VOIDmode, addr, 0);
+ return change_address_1 (memref, VOIDmode, addr, 0, MEM_ADDR_SPACE (memref));
}
/* Return a memory reference like MEMREF, but with its mode widened to
Index: gcc/explow.c
===================================================================
--- gcc/explow.c (revision 142610)
+++ gcc/explow.c (working copy)
@@ -306,7 +306,7 @@ 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;
@@ -405,22 +405,25 @@ convert_memory_address (enum machine_mod
#endif /* defined(POINTERS_EXTEND_UNSIGNED) */
}
-/* Return something equivalent to X but valid as a memory address
- for something of mode MODE. When X is not itself valid, this
- works by copying X or subexpressions of it into registers. */
+/* Return something equivalent to X but valid as a memory address for something
+ of mode MODE in the named address space AS. When X is not itself valid,
+ this works by copying X or subexpressions of it into registers. */
rtx
-memory_address (enum machine_mode mode, rtx x)
+memory_address_addr_space (enum machine_mode mode, rtx x, addr_space_t as)
{
rtx oldx = x;
+ enum machine_mode mem_Pmode = ((!as)
+ ? Pmode
+ : targetm.addr_space.pointer_mode (as));
- if (MEM_P (x) && !targetm.valid_pointer_mode (GET_MODE (x)))
- x = convert_memory_address (Pmode, x);
+ if (MEM_P (x) && GET_MODE (x) != mem_Pmode)
+ x = convert_memory_address (mem_Pmode, x);
/* 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 (mem_Pmode, x);
/* We get better cse by rejecting indirect addressing at this stage.
Let the combiner create indirect addresses where appropriate.
@@ -432,12 +435,12 @@ memory_address (enum machine_mode mode,
x = break_out_memory_refs (x);
/* At this point, any valid address is accepted. */
- if (memory_address_p (mode, x))
+ if (memory_address_addr_space_p (mode, x, as))
goto done;
/* If it was valid before but breaking out memory refs invalidated it,
use it the old way. */
- if (memory_address_p (mode, oldx))
+ if (memory_address_addr_space_p (mode, oldx, as))
{
x = oldx;
goto done;
@@ -447,7 +450,19 @@ memory_address (enum machine_mode mode,
in certain cases. This is not necessary since the code
below can handle all possible cases, but machine-dependent
transformations can make better code. */
- LEGITIMIZE_ADDRESS (x, oldx, mode, done);
+ if (!as)
+ {
+ LEGITIMIZE_ADDRESS (x, oldx, mode, done);
+ }
+ else
+ {
+ rtx y = targetm.addr_space.legitimize_address (x, oldx, mode, as);
+ if (y)
+ {
+ x = y;
+ goto done;
+ }
+ }
/* PLUS and MULT can appear in special ways
as the result of attempts to make an address usable for indexing.
@@ -463,12 +478,12 @@ memory_address (enum machine_mode mode,
rtx constant_term = const0_rtx;
rtx y = eliminate_constant_term (x, &constant_term);
if (constant_term == const0_rtx
- || ! memory_address_p (mode, y))
+ || ! memory_address_addr_space_p (mode, y, as))
x = force_operand (x, NULL_RTX);
else
{
y = gen_rtx_PLUS (GET_MODE (x), copy_to_reg (y), constant_term);
- if (! memory_address_p (mode, y))
+ if (! memory_address_addr_space_p (mode, y, as))
x = force_operand (x, NULL_RTX);
else
x = y;
@@ -485,15 +500,12 @@ memory_address (enum machine_mode mode,
/* Last resort: copy the value to a register, since
the register is a valid address. */
- else if (targetm.valid_pointer_mode (GET_MODE (x)))
- x = force_reg (GET_MODE (x), x);
- else
- x = force_reg (Pmode, x);
+ x = force_reg (mem_Pmode, x);
}
done:
- gcc_assert (memory_address_p (mode, x));
+ gcc_assert (memory_address_addr_space_p (mode, x, as));
/* If we didn't change the address, we are done. Otherwise, mark
a reg as a pointer if we have REG or REG + CONST_INT. */
if (oldx == x)
@@ -518,14 +530,21 @@ memory_address (enum machine_mode mode,
rtx
validize_mem (rtx ref)
{
+ addr_space_t as;
+ enum machine_mode mode;
+ rtx mem;
+
if (!MEM_P (ref))
return ref;
ref = use_anchored_address (ref);
- if (memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
+ mode = GET_MODE (ref);
+ mem = XEXP (ref, 0);
+ as = MEM_ADDR_SPACE (ref);
+ if (memory_address_addr_space_p (mode, mem, as))
return ref;
/* Don't alter REF itself, since that is probably a stack slot. */
- return replace_equiv_address (ref, XEXP (ref, 0));
+ return replace_equiv_address (ref, mem);
}
/* If X is a memory reference to a member of an object block, try rewriting
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c (revision 142610)
+++ gcc/varasm.c (working copy)
@@ -1430,10 +1430,16 @@ make_decl_rtl (tree decl)
x = create_block_symbol (name, get_block_for_decl (decl), -1);
else
{
- addrmode = (TREE_TYPE (decl) == error_mark_node)
- ? Pmode
- : targetm.addr_space.pointer_mode
- (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
+ if (TREE_TYPE (decl) == error_mark_node)
+ addrmode = Pmode;
+ else
+ {
+ addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
+ addrmode = ((as == 0)
+ ? Pmode
+ : targetm.addr_space.pointer_mode (as));
+ }
+
x = gen_rtx_SYMBOL_REF (addrmode, name);
}
SYMBOL_REF_WEAK (x) = DECL_WEAK (decl);
@@ -6336,23 +6342,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);
-}
-
-/* Return the pointer mode for 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)
-{
- gcc_assert (addrspace == 0);
- return ptr_mode;
-}
-
/* 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/target-def.h
===================================================================
--- gcc/target-def.h (revision 142610)
+++ gcc/target-def.h (working copy)
@@ -461,10 +461,28 @@
#define TARGET_ADDR_SPACE_POINTER_MODE default_addr_space_pointer_mode
#endif
+#ifndef TARGET_ADDR_SPACE_MINUS_TYPE
+#define TARGET_ADDR_SPACE_MINUS_TYPE default_addr_space_minus_type
+#endif
+
#ifndef TARGET_ADDR_SPACE_NAME
#define TARGET_ADDR_SPACE_NAME default_addr_space_name
#endif
+#ifndef TARGET_ADDR_SPACE_MEMORY_ADDRESS_P
+#define TARGET_ADDR_SPACE_MEMORY_ADDRESS_P default_addr_space_memory_address_p
+#endif
+
+#ifndef TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P
+#define TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P \
+ default_addr_space_strict_memory_address_p
+#endif
+
+#ifndef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
+#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS \
+ default_addr_space_legitimize_address
+#endif
+
#ifndef TARGET_ADDR_SPACE_CAN_CONVERT_P
#define TARGET_ADDR_SPACE_CAN_CONVERT_P default_addr_space_can_convert_p
#endif
@@ -485,15 +503,24 @@
#define TARGET_ADDR_SPACE_SECTION_NAME default_addr_space_section_name
#endif
+#ifndef TARGET_ADDR_SPACE_STATIC_INIT_OK_P
+#define TARGET_ADDR_SPACE_STATIC_INIT_OK_P default_addr_space_static_init_ok_p
+#endif
+
#define TARGET_ADDR_SPACE_HOOKS \
{ \
TARGET_ADDR_SPACE_POINTER_MODE, \
+ TARGET_ADDR_SPACE_MINUS_TYPE, \
TARGET_ADDR_SPACE_NAME, \
+ TARGET_ADDR_SPACE_MEMORY_ADDRESS_P, \
+ TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P, \
+ TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS, \
TARGET_ADDR_SPACE_CAN_CONVERT_P, \
TARGET_ADDR_SPACE_NOP_CONVERT_P, \
TARGET_ADDR_SPACE_SUBSET_P, \
TARGET_ADDR_SPACE_CONVERT, \
TARGET_ADDR_SPACE_SECTION_NAME, \
+ TARGET_ADDR_SPACE_STATIC_INIT_OK_P, \
}
#ifndef TARGET_SCALAR_MODE_SUPPORTED_P
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in (revision 142610)
+++ gcc/Makefile.in (working copy)
@@ -2574,7 +2574,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)
+ $(REAL_H) $(DF_H) $(TARGET_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) \
Index: gcc/config/spu/spu-protos.h
===================================================================
--- gcc/config/spu/spu-protos.h (revision 142610)
+++ gcc/config/spu/spu-protos.h (working copy)
@@ -54,8 +54,9 @@ extern int arith_immediate_p (rtx op, en
extern int spu_constant_address_p (rtx x);
extern int spu_legitimate_constant_p (rtx x);
extern int spu_legitimate_address (enum machine_mode mode, rtx x,
- int reg_ok_strict);
-extern rtx spu_legitimize_address (rtx x, rtx oldx, enum machine_mode mode);
+ int reg_ok_strict, addr_space_t);
+extern rtx spu_legitimize_address (rtx x, rtx oldx, enum machine_mode mode,
+ addr_space_t);
extern int spu_initial_elimination_offset (int from, int to);
extern rtx spu_function_value (const_tree type, const_tree func);
extern rtx spu_function_arg (int cum, enum machine_mode mode, tree type,
Index: gcc/config/spu/spu.c
===================================================================
--- gcc/config/spu/spu.c (revision 142610)
+++ gcc/config/spu/spu.c (working copy)
@@ -203,17 +203,38 @@ spu_libgcc_shift_count_mode (void);
/* Built in types. */
tree spu_builtin_types[SPU_BTI_MAX];
+
+/* Pointer mode for __ea references. */
+#define EAmode (spu_ea_model != 32 ? DImode : SImode)
/* TARGET overrides. */
-static enum machine_mode spu_ea_pointer_mode (addr_space_t);
+static enum machine_mode spu_addr_space_pointer_mode (addr_space_t);
#undef TARGET_ADDR_SPACE_POINTER_MODE
-#define TARGET_ADDR_SPACE_POINTER_MODE spu_ea_pointer_mode
+#define TARGET_ADDR_SPACE_POINTER_MODE spu_addr_space_pointer_mode
+
+static tree spu_addr_space_minus_type (addr_space_t, addr_space_t);
+#undef TARGET_ADDR_SPACE_MINUS_TYPE
+#define TARGET_ADDR_SPACE_MINUS_TYPE spu_addr_space_minus_type
static const char *spu_addr_space_name (addr_space_t);
#undef TARGET_ADDR_SPACE_NAME
#define TARGET_ADDR_SPACE_NAME spu_addr_space_name
+static bool spu_addr_space_memory_address_p (enum machine_mode, rtx,
+ addr_space_t);
+#undef TARGET_ADDR_SPACE_MEMORY_ADDRESS_P
+#define TARGET_ADDR_SPACE_MEMORY_ADDRESS_P spu_addr_space_memory_address_p
+
+static bool spu_addr_space_strict_memory_address_p (enum machine_mode, rtx,
+ addr_space_t);
+#undef TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P
+#define TARGET_ADDR_SPACE_STRICT_MEMORY_ADDRESS_P \
+ spu_addr_space_strict_memory_address_p
+
+#undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
+#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS spu_legitimize_address
+
static bool spu_addr_space_can_convert_p (addr_space_t, addr_space_t);
#undef TARGET_ADDR_SPACE_CAN_CONVERT_P
#define TARGET_ADDR_SPACE_CAN_CONVERT_P spu_addr_space_can_convert_p
@@ -236,6 +257,10 @@ static tree spu_addr_space_section_name
#undef TARGET_ADDR_SPACE_SECTION_NAME
#define TARGET_ADDR_SPACE_SECTION_NAME spu_addr_space_section_name
+static bool spu_addr_space_static_init_ok_p (tree, addr_space_t, addr_space_t);
+#undef TARGET_ADDR_SPACE_STATIC_INIT_OK_P
+#define TARGET_ADDR_SPACE_STATIC_INIT_OK_P spu_addr_space_static_init_ok_p
+
static unsigned int spu_section_type_flags (tree, const char *, int);
#undef TARGET_SECTION_TYPE_FLAGS
#define TARGET_SECTION_TYPE_FLAGS spu_section_type_flags
@@ -3530,8 +3555,15 @@ spu_legitimate_constant_p (rtx x)
preferable to allow any alignment and fix it up when splitting.) */
int
spu_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx x, int reg_ok_strict)
+ rtx x, int reg_ok_strict,
+ addr_space_t as)
{
+ if (as == ADDR_SPACE_EA)
+ return (REG_P (x) && (GET_MODE (x) == EAmode));
+
+ else if (as != ADDR_SPACE_GENERIC)
+ gcc_unreachable ();
+
if (mode == TImode && GET_CODE (x) == AND
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) -16)
@@ -3613,9 +3645,13 @@ spu_legitimate_address (enum machine_mod
register. */
rtx
spu_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
- enum machine_mode mode)
+ enum machine_mode mode, addr_space_t as)
{
rtx op0, op1;
+
+ if (as != ADDR_SPACE_GENERIC)
+ return NULL_RTX;
+
/* Make sure both operands are registers. */
if (GET_CODE (x) == PLUS)
{
@@ -3636,7 +3672,7 @@ spu_legitimize_address (rtx x, rtx oldx
else if (GET_CODE (op1) != REG)
op1 = force_reg (Pmode, op1);
x = gen_rtx_PLUS (Pmode, op0, op1);
- if (spu_legitimate_address (mode, x, 0))
+ if (spu_legitimate_address (mode, x, 0, as))
return x;
}
return NULL_RTX;
@@ -4169,9 +4205,6 @@ store_with_one_insn_p (rtx mem)
return 0;
}
-/* Pointer mode for __ea references. */
-#define EAmode (spu_ea_model != 32 ? DImode : SImode)
-
static GTY(()) rtx cache_fetch; /* __cache_fetch function */
static GTY(()) rtx cache_fetch_dirty; /* __cache_fetch_dirty function */
static alias_set_type ea_alias_set = -1; /* alias set for __ea memory */
@@ -4388,7 +4421,8 @@ expand_ea_mem (rtx mem, bool is_store)
if (ea_alias_set == -1)
ea_alias_set = new_alias_set ();
- new_mem = change_address (mem, VOIDmode, data_addr);
+ new_mem = change_address_addr_space (mem, VOIDmode, data_addr,
+ ADDR_SPACE_GENERIC);
/* We can't just change the alias set directly to ea_alias_set, because the
--enable-checking code may complain that the alias sets don't conflict */
@@ -4829,6 +4863,7 @@ spu_valid_move (rtx * ops)
the direct_load[] and direct_store[] arrays. We always want to
consider those loads and stores valid. init_expr_once is called in
the context of a dummy function which does not have a decl. */
+ gcc_assert (cfun);
if (cfun->decl == 0)
return 1;
@@ -6459,26 +6494,12 @@ spu_vector_alignment_reachable (const_tr
return true;
}
-/* Return the appropriate mode for a named address pointer. */
-static enum machine_mode
-spu_ea_pointer_mode (addr_space_t addrspace)
-{
- switch (addrspace)
- {
- case ADDR_SPACE_GENERIC:
- return ptr_mode;
- case ADDR_SPACE_EA:
- return (spu_ea_model == 64 ? DImode : ptr_mode);
- default:
- gcc_unreachable ();
- }
-}
-
/* Return valid pointer modes. */
static bool
spu_valid_pointer_mode (enum machine_mode mode)
{
- return (mode == ptr_mode || mode == Pmode || mode == spu_ea_pointer_mode (1));
+ return (mode == ptr_mode || mode == Pmode ||
+ (spu_ea_model != 32 && mode == DImode));
}
/* Adjust section flags for the __ea section. */
@@ -6603,6 +6624,38 @@ spu_libgcc_shift_count_mode (void)
return SImode;
}
+/* Return the appropriate mode for a named address pointer. */
+static enum machine_mode
+spu_addr_space_pointer_mode (addr_space_t addrspace)
+{
+ switch (addrspace)
+ {
+ case ADDR_SPACE_GENERIC:
+ return ptr_mode;
+ case ADDR_SPACE_EA:
+ return (EAmode);
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return the appropriate type for subtracting two pointers. */
+static tree
+spu_addr_space_minus_type (addr_space_t as1, addr_space_t as2)
+{
+ gcc_assert (as1 == ADDR_SPACE_GENERIC || as1 == ADDR_SPACE_EA);
+ gcc_assert (as2 == ADDR_SPACE_GENERIC || as2 == ADDR_SPACE_EA);
+
+ if (as1 == ADDR_SPACE_GENERIC && as2 == ADDR_SPACE_GENERIC)
+ return ptrdiff_type_node;
+
+ else if (spu_ea_model == 32)
+ return ptrdiff_type_node;
+
+ else
+ return unsigned_intDI_type_node;
+}
+
/* Map an address space number into a name. */
static const char *
spu_addr_space_name (addr_space_t addrspace)
@@ -6613,6 +6666,28 @@ spu_addr_space_name (addr_space_t addrsp
gcc_unreachable ();
}
+/* Return if an address is valid for a given mode that points to a given named
+ address space. */
+
+static bool
+spu_addr_space_memory_address_p (enum machine_mode mode, rtx x,
+ addr_space_t as)
+{
+ gcc_assert (as == ADDR_SPACE_GENERIC || as == ADDR_SPACE_EA);
+ return spu_legitimate_address (mode, x, 0, as);
+}
+
+/* Return if an address is valid for a given mode that points to a given named
+ address space after register allocation has been done. */
+
+static bool
+spu_addr_space_strict_memory_address_p (enum machine_mode mode, rtx x,
+ addr_space_t as)
+{
+ gcc_assert (as == ADDR_SPACE_GENERIC || as == ADDR_SPACE_EA);
+ return spu_legitimate_address (mode, x, 1, as);
+}
+
/* Determine if you can convert one address to another. */
static bool
@@ -6720,6 +6795,27 @@ spu_addr_space_section_name (addr_space_
return spu_ea_name;
}
+static bool
+spu_addr_space_static_init_ok_p (tree ARG_UNUSED (value),
+ addr_space_t asl,
+ addr_space_t asr)
+{
+ gcc_assert (asl == ADDR_SPACE_GENERIC || asl == ADDR_SPACE_EA);
+ gcc_assert (asr == ADDR_SPACE_GENERIC || asr == ADDR_SPACE_EA);
+
+#if 0
+ fprintf (stderr, "\nInitialize asl = %s, asr = %s:\n",
+ (asl) ? "generic" : "__ea",
+ (asr) ? "generic" : "__ea");
+
+ debug_tree (value);
+#endif
+
+ if (asl == ADDR_SPACE_GENERIC && asr == ADDR_SPACE_GENERIC)
+ return true;
+
+ return false;
+}
/* An early place to adjust some flags after GCC has finished processing
* them. */
Index: gcc/config/spu/spu.h
===================================================================
--- gcc/config/spu/spu.h (revision 142610)
+++ gcc/config/spu/spu.h (working copy)
@@ -423,12 +423,14 @@ targetm.resolve_overloaded_builtin = spu
#endif
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
- { if (spu_legitimate_address (MODE, X, REG_OK_STRICT_FLAG)) \
+ { if (spu_legitimate_address (MODE, X, REG_OK_STRICT_FLAG, \
+ ADDR_SPACE_GENERIC)) \
goto ADDR; \
}
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
- { rtx result = spu_legitimize_address (X, OLDX, MODE); \
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+ { rtx result = spu_legitimize_address (X, OLDX, MODE, \
+ ADDR_SPACE_GENERIC); \
if (result != NULL_RTX) \
{ \
(X) = result; \
--
Michael Meissner, IBM
4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA
meissner@linux.vnet.ibm.com