This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[AARCH64][PATCH] Fix legitimate address checking for TImode and TFmode
- From: Marcus Shawcroft <marcus dot shawcroft at arm dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 11 Jun 2012 15:50:02 +0100
- Subject: [AARCH64][PATCH] Fix legitimate address checking for TImode and TFmode
This patch fixes the behaviour of legitimate address checking for TImode
and TFmode values.
The current implementation does not correctly distinguish between the
address modes available for ldp/stp X,X versus ldr/str Q.
/Marcus
ChangeLog:
* config/aarch64/aarch64.c
(aarch64_regno_ok_for_index_p): Handle NULL reg_renumber.
(aarch64_regno_ok_for_base_p): Likewise.
(offset_7bit_signed_scaled_p): New.
(offset_9bit_signed_unscaled_p): New.
(offset_12bit_unsigned_scaled_p): New.
(aarch64_classify_address): Replace pair_p with allow_reg_index_p.
Conservative test for valid TImode and TFmode addresses. Use
offset_7bit_signed_scaled_p offset_9bit_signed_unscaled_p and
offset_12bit_unsigned_scaled_p. Remove explicit TImode and TFmode
tests.
* config/aarch64/aarch64.md (movti_aarch64): Replace 'm' with 'Ump'.
(movtf_aarch64): Replace 'm' with 'Ump', replace 'Utf' with 'm'.
* config/aarch64/constraints.md (Utf): Remove.
(Ump) Pass strict.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 34d04755900a75376c0afe5b9b4b8b3cd1ac84e2..b985d63c4fd591c7ae17d519a7b858c0264edec7 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2441,6 +2441,10 @@ aarch64_regno_ok_for_index_p (int regno,
{
if (!strict_p)
return true;
+
+ if (!reg_renumber)
+ return false;
+
regno = reg_renumber[regno];
}
return GP_REGNUM_P (regno);
@@ -2456,6 +2460,10 @@ aarch64_regno_ok_for_base_p (int regno,
{
if (!strict_p)
return true;
+
+ if (!reg_renumber)
+ return false;
+
regno = reg_renumber[regno];
}
@@ -2639,6 +2647,29 @@ aarch64_classify_index (struct aarch64_a
return false;
}
+static inline bool
+offset_7bit_signed_scaled_p (enum machine_mode mode, HOST_WIDE_INT offset)
+{
+ return (offset >= -64 * GET_MODE_SIZE (mode)
+ && offset < 64 * GET_MODE_SIZE (mode)
+ && offset % GET_MODE_SIZE (mode) == 0);
+}
+
+static inline bool
+offset_9bit_signed_unscaled_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT offset)
+{
+ return offset >= -256 && offset < 256;
+}
+
+static inline bool
+offset_12bit_unsigned_scaled_p (enum machine_mode mode, HOST_WIDE_INT offset)
+{
+ return (offset >= 0
+ && offset < 4096 * GET_MODE_SIZE (mode)
+ && offset % GET_MODE_SIZE (mode) == 0);
+}
+
/* Return true if X is a valid address for machine mode MODE. If it is,
fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in
effect. OUTER_CODE is PARALLEL for a load/store pair. */
@@ -2650,7 +2681,8 @@ aarch64_classify_address (struct aarch64
{
enum rtx_code code = GET_CODE (x);
rtx op0, op1;
- bool pair_p = (outer_code == PARALLEL || mode == TImode);
+ bool allow_reg_index_p =
+ outer_code != PARALLEL && GET_MODE_SIZE(mode) != 16;
/* Don't support anything other than POST_INC or REG addressing for
AdvSIMD. */
@@ -2679,25 +2711,27 @@ aarch64_classify_address (struct aarch64
info->type = ADDRESS_REG_IMM;
info->base = op0;
info->offset = op1;
+
+ /* TImode and TFmode values are allowed in both pairs of X
+ registers and individual Q registers. The available
+ address modes are:
+ X,X: 7-bit signed scaled offset
+ Q: 9-bit signed offset
+ We conservatively require an offset representable in either mode.
+ */
+ if (mode == TImode || mode == TFmode)
+ return (offset_7bit_signed_scaled_p (mode, offset)
+ && offset_9bit_signed_unscaled_p (mode, offset));
+
if (outer_code == PARALLEL)
- /* load/store pair: 7-bit signed, scaled offset. */
return ((GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)
- && offset >= -64 * GET_MODE_SIZE (mode)
- && offset < 64 * GET_MODE_SIZE (mode)
- && offset % GET_MODE_SIZE (mode) == 0);
- else if (mode == TImode)
- /* load/store pair of dwords: 7-bit signed, scaled offset. */
- return offset >= -512 && offset < 512 && offset % 8 == 0;
+ && offset_7bit_signed_scaled_p (mode, offset));
else
- /* load/store single: 9-bit signed, unscaled offset. */
- /* load/store single: 12-bit unsigned, scaled offset. */
- return ((offset >= -256 && offset < 256)
- || (offset >= 0
- && offset < 4096 * GET_MODE_SIZE (mode)
- && offset % GET_MODE_SIZE (mode) == 0));
+ return (offset_9bit_signed_unscaled_p (mode, offset)
+ || offset_12bit_unsigned_scaled_p (mode, offset));
}
- if (!pair_p)
+ if (allow_reg_index_p)
{
/* Look for base + (scaled/extended) index register. */
if (aarch64_base_register_rtx_p (op0, strict_p)
@@ -2737,18 +2771,23 @@ aarch64_classify_address (struct aarch64
HOST_WIDE_INT offset;
info->offset = XEXP (XEXP (x, 1), 1);
offset = INTVAL (info->offset);
+
+ /* TImode and TFmode values are allowed in both pairs of X
+ registers and individual Q registers. The available
+ address modes are:
+ X,X: 7-bit signed scaled offset
+ Q: 9-bit signed offset
+ We conservatively require an offset representable in either mode.
+ */
+ if (mode == TImode || mode == TFmode)
+ return (offset_7bit_signed_scaled_p (mode, offset)
+ && offset_9bit_signed_unscaled_p (mode, offset));
+
if (outer_code == PARALLEL)
- /* load/store pair: 7-bit signed, scaled offset. */
return ((GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)
- && offset >= -64 * GET_MODE_SIZE (mode)
- && offset < 64 * GET_MODE_SIZE (mode)
- && offset % GET_MODE_SIZE (mode) == 0);
- else if (mode == TImode)
- /* load/store pair of dwords: 7-bit signed, scaled offset. */
- return offset >= -512 && offset < 512 && offset % 8 == 0;
+ && offset_7bit_signed_scaled_p (mode, offset));
else
- /* load/store single: 9-bit signed, unscaled offset. */
- return offset >= -256 && offset < 256;
+ return offset_9bit_signed_unscaled_p (mode, offset);
}
return false;
@@ -2759,10 +2798,10 @@ aarch64_classify_address (struct aarch64
info->type = ADDRESS_SYMBOLIC;
if (outer_code != PARALLEL
&& (GET_MODE_SIZE (mode) == 4
- || GET_MODE_SIZE (mode) == 8
- || mode == TFmode))
+ || GET_MODE_SIZE (mode) == 8))
{
rtx sym, addend;
+
split_const (x, &sym, &addend);
return (GET_CODE (sym) == LABEL_REF
|| (GET_CODE (sym) == SYMBOL_REF
@@ -2774,7 +2813,7 @@ aarch64_classify_address (struct aarch64
info->type = ADDRESS_LO_SUM;
info->base = XEXP (x, 0);
info->offset = XEXP (x, 1);
- if (!pair_p
+ if (allow_reg_index_p
&& aarch64_base_register_rtx_p (info->base, strict_p))
{
rtx sym, offs;
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 456fab743ca301e596d147322266bbb10ed85507..3ce99941ecb4b0c89e02979c14df10c7080c1ff7 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -987,8 +987,10 @@ (define_expand "movti"
)
(define_insn "*movti_aarch64"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=r, *w,r,*w,r,m,m,*w, m")
- (match_operand:TI 1 "aarch64_movti_operand" " rn,r,*w,*w,m,r,Z, m,*w"))]
+ [(set (match_operand:TI 0
+ "nonimmediate_operand" "=r, *w,r ,*w,r ,Ump,Ump,*w,m")
+ (match_operand:TI 1
+ "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r ,Z , m,*w"))]
"(register_operand (operands[0], TImode)
|| aarch64_reg_or_zero (operands[1], TImode))"
"@
@@ -1002,7 +1004,7 @@ (define_insn "*movti_aarch64"
ldr\\t%q0, %1
str\\t%q1, %0"
[(set_attr "v8type" "move2,fmovi2f,fmovf2i,*, \
- load2,store2,store2,fpsimd_load,fpsimd_store")
+ load2,store2,store2,fpsimd_load,fpsimd_store")
(set_attr "simd_type" "*,*,*,simd_move,*,*,*,*,*")
(set_attr "mode" "DI,DI,DI,TI,DI,DI,DI,TI,TI")
(set_attr "length" "8,8,8,4,4,4,4,4,4")
@@ -1091,8 +1093,10 @@ (define_expand "movtf"
)
(define_insn "*movtf_aarch64"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Utf")
- (match_operand:TF 1 "general_operand" " w,?r,?r,w ,Y,Y ,m,w,Utf,?rY"))]
+ [(set (match_operand:TF 0
+ "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump")
+ (match_operand:TF 1
+ "general_operand" " w,?r, ?r,w ,Y,Y ,m,w,Ump,?rY"))]
"TARGET_FLOAT && (register_operand (operands[0], TFmode)
|| register_operand (operands[1], TFmode))"
"@
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index 47d638400c546051ba1a3db67231f07cf120870f..91eba09f02cc5f61cac18649b55f6f469b418eea 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -121,14 +121,7 @@ (define_memory_constraint "Ump"
A memory address suitable for a load/store pair operation."
(and (match_code "mem")
(match_test "aarch64_legitimate_address_p (GET_MODE (op), XEXP (op, 0),
- PARALLEL, 0)")))
-
-(define_memory_constraint "Utf"
- "@internal
- A memory address suitable for a load/store pair operation."
- (and (match_code "mem")
- (match_test "aarch64_legitimate_address_p (TImode, XEXP (op, 0),
- UNKNOWN, 0)")))
+ PARALLEL, 1)")))
(define_constraint "Dn"
"@internal