aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2011-08-16 18:33:15 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2011-08-16 18:33:15 +0000
commit2ea0be597eaacb6ca34f0fc8a9249949bcf97d64 (patch)
tree6e28f379a4706d4b9a7e2349ef3514928ddd453d
parentb05933f5277f7a0f09670f205af31b082e0e4976 (diff)
downloadgcc-2ea0be597eaacb6ca34f0fc8a9249949bcf97d64.zip
gcc-2ea0be597eaacb6ca34f0fc8a9249949bcf97d64.tar.gz
gcc-2ea0be597eaacb6ca34f0fc8a9249949bcf97d64.tar.bz2
spu.h (LEGITIMIZE_RELOAD_ADDRESS): New macro.
* config/spu/spu.h (LEGITIMIZE_RELOAD_ADDRESS): New macro. * config/spu/spu-protos.h (spu_legitimize_reload_address): Add prototype. * config/spu/spu.c (spu_legitimize_reload_address): New function. (spu_legitimate_address_p): Do not check displacement if the base is an eliminable stack register. From-SVN: r177794
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/spu/spu-protos.h1
-rw-r--r--gcc/config/spu/spu.c49
-rw-r--r--gcc/config/spu/spu.h11
4 files changed, 68 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 59176fc..67ae4ed8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2011-08-16 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/spu/spu.h (LEGITIMIZE_RELOAD_ADDRESS): New macro.
+ * config/spu/spu-protos.h (spu_legitimize_reload_address): Add
+ prototype.
+ * config/spu/spu.c (spu_legitimize_reload_address): New function.
+ (spu_legitimate_address_p): Do not check displacement if the base
+ is an eliminable stack register.
+
2011-08-16 Anatoly Sokolov <aesok@post.ru>
* config/m32c/m32c.h (PREFERRED_RELOAD_CLASS,
diff --git a/gcc/config/spu/spu-protos.h b/gcc/config/spu/spu-protos.h
index cb5cc24..9485f38 100644
--- a/gcc/config/spu/spu-protos.h
+++ b/gcc/config/spu/spu-protos.h
@@ -76,6 +76,7 @@ extern void spu_builtin_insert (rtx ops[]);
extern void spu_builtin_promote (rtx ops[]);
extern void spu_expand_sign_extend (rtx ops[]);
extern void spu_expand_vector_init (rtx target, rtx vals);
+extern rtx spu_legitimize_reload_address (rtx, enum machine_mode, int, int);
#endif /* RTX_CODE */
extern void spu_init_expanders (void);
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index c6db6c3..7868c7f 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -3803,8 +3803,14 @@ spu_legitimate_address_p (enum machine_mode mode,
if (GET_CODE (op0) == REG
&& INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
&& GET_CODE (op1) == CONST_INT
- && INTVAL (op1) >= -0x2000
- && INTVAL (op1) <= 0x1fff
+ && ((INTVAL (op1) >= -0x2000 && INTVAL (op1) <= 0x1fff)
+ /* If virtual registers are involved, the displacement will
+ change later on anyway, so checking would be premature.
+ Reload will make sure the final displacement after
+ register elimination is OK. */
+ || op0 == arg_pointer_rtx
+ || op0 == frame_pointer_rtx
+ || op0 == virtual_stack_vars_rtx)
&& (!aligned || (INTVAL (op1) & 15) == 0))
return TRUE;
if (GET_CODE (op0) == REG
@@ -3877,6 +3883,45 @@ spu_addr_space_legitimize_address (rtx x, rtx oldx, enum machine_mode mode,
return spu_legitimize_address (x, oldx, mode);
}
+/* Reload reg + const_int for out-of-range displacements. */
+rtx
+spu_legitimize_reload_address (rtx ad, enum machine_mode mode ATTRIBUTE_UNUSED,
+ int opnum, int type)
+{
+ bool removed_and = false;
+
+ if (GET_CODE (ad) == AND
+ && CONST_INT_P (XEXP (ad, 1))
+ && INTVAL (XEXP (ad, 1)) == (HOST_WIDE_INT) - 16)
+ {
+ ad = XEXP (ad, 0);
+ removed_and = true;
+ }
+
+ if (GET_CODE (ad) == PLUS
+ && REG_P (XEXP (ad, 0))
+ && CONST_INT_P (XEXP (ad, 1))
+ && !(INTVAL (XEXP (ad, 1)) >= -0x2000
+ && INTVAL (XEXP (ad, 1)) <= 0x1fff))
+ {
+ /* Unshare the sum. */
+ ad = copy_rtx (ad);
+
+ /* Reload the displacement. */
+ push_reload (XEXP (ad, 1), NULL_RTX, &XEXP (ad, 1), NULL,
+ BASE_REG_CLASS, GET_MODE (ad), VOIDmode, 0, 0,
+ opnum, (enum reload_type) type);
+
+ /* Add back AND for alignment if we stripped it. */
+ if (removed_and)
+ ad = gen_rtx_AND (GET_MODE (ad), ad, GEN_INT (-16));
+
+ return ad;
+ }
+
+ return NULL_RTX;
+}
+
/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
struct attribute_spec.handler. */
static tree
diff --git a/gcc/config/spu/spu.h b/gcc/config/spu/spu.h
index c69cf7e..d89bf49 100644
--- a/gcc/config/spu/spu.h
+++ b/gcc/config/spu/spu.h
@@ -390,6 +390,17 @@ targetm.resolve_overloaded_builtin = spu_resolve_overloaded_builtin; \
#define MAX_REGS_PER_ADDRESS 2
+#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN) \
+do { \
+ rtx new_rtx = spu_legitimize_reload_address (AD, MODE, OPNUM, \
+ (int)(TYPE)); \
+ if (new_rtx) \
+ { \
+ (AD) = new_rtx; \
+ goto WIN; \
+ } \
+} while (0)
+
/* Costs */