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
This commit is contained in:
Jeff Law 2015-05-22 10:13:07 -06:00 committed by Jeff Law
parent 9b789cc15c
commit 92d0b05816
2 changed files with 98 additions and 48 deletions

View file

@ -1,3 +1,13 @@
2015-05-22 Jeff Law <law@redhat.com>
* 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.
2015-05-22 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR target/65491

View file

@ -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));
/* First, try and figure out what to use as a base register. */
/* 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);
/* 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