aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/pa/pa.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2015-05-22 10:13:07 -0600
committerJeff Law <law@gcc.gnu.org>2015-05-22 10:13:07 -0600
commit92d0b05816f5bd8f811177892459727097fe41a2 (patch)
treea9da7740f72ab1d83c847b331e93174b76926f42 /gcc/config/pa/pa.c
parent9b789cc15c38f6c67de873408e8397fbd7ada75b (diff)
downloadgcc-92d0b05816f5bd8f811177892459727097fe41a2.zip
gcc-92d0b05816f5bd8f811177892459727097fe41a2.tar.gz
gcc-92d0b05816f5bd8f811177892459727097fe41a2.tar.bz2
pa.c (mem_shadd_or_shadd_rtx_p): New function factored out of hppa_legitimize_address to handle both forms of a...
* pa.c (mem_shadd_or_shadd_rtx_p): New function factored out of hppa_legitimize_address to handle both forms of a multiply by 2, 4 or 8. (hppa_legitimize_address): Use mem_shadd_or_shadd_rtx_p. Always generate the ASHIFT variant as the result is not directly used in a MEM. Update comments and refactor slightly to improve readability. From-SVN: r223579
Diffstat (limited to 'gcc/config/pa/pa.c')
-rw-r--r--gcc/config/pa/pa.c136
1 files changed, 88 insertions, 48 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index f99cf33..090eeb4 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -997,6 +997,23 @@ legitimize_tls_address (rtx addr)
return ret;
}
+/* Helper for hppa_legitimize_address. Given X, return true if it
+ is a left shift by 1, 2 or 3 positions or a multiply by 2, 4 or 8.
+
+ This respectively represent canonical shift-add rtxs or scaled
+ memory addresses. */
+static bool
+mem_shadd_or_shadd_rtx_p (rtx x)
+{
+ return ((GET_CODE (x) == ASHIFT
+ || GET_CODE (x) == MULT)
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && ((GET_CODE (x) == ASHIFT
+ && pa_shadd_constant_p (INTVAL (XEXP (x, 1))))
+ || (GET_CODE (x) == MULT
+ && pa_mem_shadd_constant_p (INTVAL (XEXP (x, 1))))));
+}
+
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address.
This macro is used in only one place: `memory_address' in explow.c.
@@ -1042,6 +1059,13 @@ legitimize_tls_address (rtx addr)
manner if Y is 2, 4, or 8. (allows more shadd insns and shifted indexed
addressing modes to be used).
+ Note that the addresses passed into hppa_legitimize_address always
+ come from a MEM, so we only have to match the MULT form on incoming
+ addresses. But to be future proof we also match the ASHIFT form.
+
+ However, this routine always places those shift-add sequences into
+ registers, so we have to generate the ASHIFT form as our output.
+
Put X and Z into registers. Then put the entire expression into
a register. */
@@ -1138,18 +1162,21 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return plus_constant (Pmode, ptr_reg, offset - newoffset);
}
- /* Handle (plus (mult (a) (shadd_constant)) (b)). */
+ /* Handle (plus (mult (a) (mem_shadd_constant)) (b)). */
- if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
+ if (GET_CODE (x) == PLUS
+ && mem_shadd_or_shadd_rtx_p (XEXP (x, 0))
&& (OBJECT_P (XEXP (x, 1))
|| GET_CODE (XEXP (x, 1)) == SUBREG)
&& GET_CODE (XEXP (x, 1)) != CONST)
{
- int val = INTVAL (XEXP (XEXP (x, 0), 1));
- rtx reg1, reg2;
+ /* If we were given a MULT, we must fix the constant
+ as we're going to create the ASHIFT form. */
+ int shift_val = INTVAL (XEXP (XEXP (x, 0), 1));
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ shift_val = exact_log2 (shift_val);
+ rtx reg1, reg2;
reg1 = XEXP (x, 1);
if (GET_CODE (reg1) != REG)
reg1 = force_reg (Pmode, force_operand (reg1, 0));
@@ -1158,26 +1185,30 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (reg2) != REG)
reg2 = force_reg (Pmode, force_operand (reg2, 0));
- return force_reg (Pmode, gen_rtx_PLUS (Pmode,
- gen_rtx_MULT (Pmode,
- reg2,
- GEN_INT (val)),
- reg1));
+ return force_reg (Pmode,
+ gen_rtx_PLUS (Pmode,
+ gen_rtx_ASHIFT (Pmode, reg2,
+ GEN_INT (shift_val)),
+ reg1));
}
- /* Similarly for (plus (plus (mult (a) (shadd_constant)) (b)) (c)).
+ /* Similarly for (plus (plus (mult (a) (mem_shadd_constant)) (b)) (c)).
Only do so for floating point modes since this is more speculative
and we lose if it's an integer store. */
if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
- && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
- && pa_shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
+ && mem_shadd_or_shadd_rtx_p (XEXP (XEXP (x, 0), 0))
&& (mode == SFmode || mode == DFmode))
{
+ int shift_val = INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1));
+
+ /* If we were given a MULT, we must fix the constant
+ as we're going to create the ASHIFT form. */
+ if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT)
+ shift_val = exact_log2 (shift_val);
- /* First, try and figure out what to use as a base register. */
+ /* Try and figure out what to use as a base register. */
rtx reg1, reg2, base, idx;
reg1 = XEXP (XEXP (x, 0), 1);
@@ -1201,9 +1232,9 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
{
base = reg1;
idx = gen_rtx_PLUS (Pmode,
- gen_rtx_MULT (Pmode,
- XEXP (XEXP (XEXP (x, 0), 0), 0),
- XEXP (XEXP (XEXP (x, 0), 0), 1)),
+ gen_rtx_ASHIFT (Pmode,
+ XEXP (XEXP (XEXP (x, 0), 0), 0),
+ GEN_INT (shift_val)),
XEXP (x, 1));
}
else if (GET_CODE (reg2) == REG
@@ -1225,8 +1256,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
{
/* Divide the CONST_INT by the scale factor, then add it to A. */
int val = INTVAL (XEXP (idx, 1));
+ val /= (1 << shift_val);
- val /= INTVAL (XEXP (XEXP (idx, 0), 1));
reg1 = XEXP (XEXP (idx, 0), 0);
if (GET_CODE (reg1) != REG)
reg1 = force_reg (Pmode, force_operand (reg1, 0));
@@ -1237,8 +1268,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return
force_reg
(Pmode, gen_rtx_PLUS (Pmode,
- gen_rtx_MULT (Pmode, reg1,
- XEXP (XEXP (idx, 0), 1)),
+ gen_rtx_ASHIFT (Pmode, reg1,
+ GEN_INT (shift_val)),
base));
}
@@ -1247,7 +1278,6 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& INTVAL (XEXP (idx, 1)) <= 4096
&& INTVAL (XEXP (idx, 1)) >= -4096)
{
- int val = INTVAL (XEXP (XEXP (idx, 0), 1));
rtx reg1, reg2;
reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, XEXP (idx, 1)));
@@ -1256,11 +1286,11 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (reg2) != CONST_INT)
reg2 = force_reg (Pmode, force_operand (reg2, 0));
- return force_reg (Pmode, gen_rtx_PLUS (Pmode,
- gen_rtx_MULT (Pmode,
- reg2,
- GEN_INT (val)),
- reg1));
+ return force_reg (Pmode,
+ gen_rtx_PLUS (Pmode,
+ gen_rtx_ASHIFT (Pmode, reg2,
+ GEN_INT (shift_val)),
+ reg1));
}
/* Get the index into a register, then add the base + index and
@@ -1278,8 +1308,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
reg1 = force_reg (Pmode,
gen_rtx_PLUS (Pmode,
- gen_rtx_MULT (Pmode, reg1,
- XEXP (XEXP (idx, 0), 1)),
+ gen_rtx_ASHIFT (Pmode, reg1,
+ GEN_INT (shift_val)),
reg2));
/* Add the result to our base register and return. */
@@ -1315,7 +1345,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
{
/* See if this looks like
- (plus (mult (reg) (shadd_const))
+ (plus (mult (reg) (mem_shadd_const))
(const (plus (symbol_ref) (const_int))))
Where const_int is small. In that case the const
@@ -1324,14 +1354,18 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
If const_int is big, but can be divided evenly by shadd_const
and added to (reg). This allows more scaled indexed addresses. */
if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF
- && GET_CODE (XEXP (x, 0)) == MULT
+ && mem_shadd_or_shadd_rtx_p (XEXP (x, 0))
&& GET_CODE (XEXP (y, 1)) == CONST_INT
&& INTVAL (XEXP (y, 1)) >= -4096
- && INTVAL (XEXP (y, 1)) <= 4095
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+ && INTVAL (XEXP (y, 1)) <= 4095)
{
- int val = INTVAL (XEXP (XEXP (x, 0), 1));
+ int shift_val = INTVAL (XEXP (XEXP (x, 0), 1));
+
+ /* If we were given a MULT, we must fix the constant
+ as we're going to create the ASHIFT form. */
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ shift_val = exact_log2 (shift_val);
+
rtx reg1, reg2;
reg1 = XEXP (x, 1);
@@ -1342,21 +1376,27 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (reg2) != REG)
reg2 = force_reg (Pmode, force_operand (reg2, 0));
- return force_reg (Pmode,
- gen_rtx_PLUS (Pmode,
- gen_rtx_MULT (Pmode,
- reg2,
- GEN_INT (val)),
- reg1));
+ return
+ force_reg (Pmode,
+ gen_rtx_PLUS (Pmode,
+ gen_rtx_ASHIFT (Pmode,
+ reg2,
+ GEN_INT (shift_val)),
+ reg1));
}
else if ((mode == DFmode || mode == SFmode)
&& GET_CODE (XEXP (y, 0)) == SYMBOL_REF
- && GET_CODE (XEXP (x, 0)) == MULT
+ && mem_shadd_or_shadd_rtx_p (XEXP (x, 0))
&& GET_CODE (XEXP (y, 1)) == CONST_INT
- && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+ && INTVAL (XEXP (y, 1)) % (1 << INTVAL (XEXP (XEXP (x, 0), 1))) == 0)
{
+ int shift_val = INTVAL (XEXP (XEXP (x, 0), 1));
+
+ /* If we were given a MULT, we must fix the constant
+ as we're going to create the ASHIFT form. */
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ shift_val = exact_log2 (shift_val);
+
regx1
= force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
/ INTVAL (XEXP (XEXP (x, 0), 1))));
@@ -1368,8 +1408,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return
force_reg (Pmode,
gen_rtx_PLUS (Pmode,
- gen_rtx_MULT (Pmode, regx2,
- XEXP (XEXP (x, 0), 1)),
+ gen_rtx_ASHIFT (Pmode, regx2,
+ GEN_INT (shift_val)),
force_reg (Pmode, XEXP (y, 0))));
}
else if (GET_CODE (XEXP (y, 1)) == CONST_INT