Commit 92d0b058 by Jeff Law Committed by Jeff Law

pa.c (mem_shadd_or_shadd_rtx_p): New function factored out of…

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
parent 9b789cc1
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> 2015-05-22 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR target/65491 PR target/65491
......
...@@ -997,6 +997,23 @@ legitimize_tls_address (rtx addr) ...@@ -997,6 +997,23 @@ legitimize_tls_address (rtx addr)
return ret; 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 /* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid 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. This macro is used in only one place: `memory_address' in explow.c.
...@@ -1042,6 +1059,13 @@ legitimize_tls_address (rtx addr) ...@@ -1042,6 +1059,13 @@ legitimize_tls_address (rtx addr)
manner if Y is 2, 4, or 8. (allows more shadd insns and shifted indexed manner if Y is 2, 4, or 8. (allows more shadd insns and shifted indexed
addressing modes to be used). 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 Put X and Z into registers. Then put the entire expression into
a register. */ a register. */
...@@ -1138,18 +1162,21 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1138,18 +1162,21 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return plus_constant (Pmode, ptr_reg, offset - newoffset); 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 if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && mem_shadd_or_shadd_rtx_p (XEXP (x, 0))
&& pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
&& (OBJECT_P (XEXP (x, 1)) && (OBJECT_P (XEXP (x, 1))
|| GET_CODE (XEXP (x, 1)) == SUBREG) || GET_CODE (XEXP (x, 1)) == SUBREG)
&& GET_CODE (XEXP (x, 1)) != CONST) && GET_CODE (XEXP (x, 1)) != CONST)
{ {
int val = INTVAL (XEXP (XEXP (x, 0), 1)); /* If we were given a MULT, we must fix the constant
rtx reg1, reg2; 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); reg1 = XEXP (x, 1);
if (GET_CODE (reg1) != REG) if (GET_CODE (reg1) != REG)
reg1 = force_reg (Pmode, force_operand (reg1, 0)); reg1 = force_reg (Pmode, force_operand (reg1, 0));
...@@ -1158,26 +1185,30 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1158,26 +1185,30 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (reg2) != REG) if (GET_CODE (reg2) != REG)
reg2 = force_reg (Pmode, force_operand (reg2, 0)); reg2 = force_reg (Pmode, force_operand (reg2, 0));
return force_reg (Pmode, gen_rtx_PLUS (Pmode, return force_reg (Pmode,
gen_rtx_MULT (Pmode, gen_rtx_PLUS (Pmode,
reg2, gen_rtx_ASHIFT (Pmode, reg2,
GEN_INT (val)), GEN_INT (shift_val)),
reg1)); 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 Only do so for floating point modes since this is more speculative
and we lose if it's an integer store. */ and we lose if it's an integer store. */
if (GET_CODE (x) == PLUS if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT && mem_shadd_or_shadd_rtx_p (XEXP (XEXP (x, 0), 0))
&& GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
&& pa_shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
&& (mode == SFmode || mode == DFmode)) && (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; rtx reg1, reg2, base, idx;
reg1 = XEXP (XEXP (x, 0), 1); reg1 = XEXP (XEXP (x, 0), 1);
...@@ -1201,9 +1232,9 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1201,9 +1232,9 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
{ {
base = reg1; base = reg1;
idx = gen_rtx_PLUS (Pmode, idx = gen_rtx_PLUS (Pmode,
gen_rtx_MULT (Pmode, gen_rtx_ASHIFT (Pmode,
XEXP (XEXP (XEXP (x, 0), 0), 0), XEXP (XEXP (XEXP (x, 0), 0), 0),
XEXP (XEXP (XEXP (x, 0), 0), 1)), GEN_INT (shift_val)),
XEXP (x, 1)); XEXP (x, 1));
} }
else if (GET_CODE (reg2) == REG else if (GET_CODE (reg2) == REG
...@@ -1225,8 +1256,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -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. */ /* Divide the CONST_INT by the scale factor, then add it to A. */
int val = INTVAL (XEXP (idx, 1)); int val = INTVAL (XEXP (idx, 1));
val /= (1 << shift_val);
val /= INTVAL (XEXP (XEXP (idx, 0), 1));
reg1 = XEXP (XEXP (idx, 0), 0); reg1 = XEXP (XEXP (idx, 0), 0);
if (GET_CODE (reg1) != REG) if (GET_CODE (reg1) != REG)
reg1 = force_reg (Pmode, force_operand (reg1, 0)); reg1 = force_reg (Pmode, force_operand (reg1, 0));
...@@ -1237,8 +1268,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1237,8 +1268,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return return
force_reg force_reg
(Pmode, gen_rtx_PLUS (Pmode, (Pmode, gen_rtx_PLUS (Pmode,
gen_rtx_MULT (Pmode, reg1, gen_rtx_ASHIFT (Pmode, reg1,
XEXP (XEXP (idx, 0), 1)), GEN_INT (shift_val)),
base)); base));
} }
...@@ -1247,7 +1278,6 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1247,7 +1278,6 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& INTVAL (XEXP (idx, 1)) <= 4096 && INTVAL (XEXP (idx, 1)) <= 4096
&& INTVAL (XEXP (idx, 1)) >= -4096) && INTVAL (XEXP (idx, 1)) >= -4096)
{ {
int val = INTVAL (XEXP (XEXP (idx, 0), 1));
rtx reg1, reg2; rtx reg1, reg2;
reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, XEXP (idx, 1))); reg1 = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, XEXP (idx, 1)));
...@@ -1256,10 +1286,10 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1256,10 +1286,10 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (reg2) != CONST_INT) if (GET_CODE (reg2) != CONST_INT)
reg2 = force_reg (Pmode, force_operand (reg2, 0)); reg2 = force_reg (Pmode, force_operand (reg2, 0));
return force_reg (Pmode, gen_rtx_PLUS (Pmode, return force_reg (Pmode,
gen_rtx_MULT (Pmode, gen_rtx_PLUS (Pmode,
reg2, gen_rtx_ASHIFT (Pmode, reg2,
GEN_INT (val)), GEN_INT (shift_val)),
reg1)); reg1));
} }
...@@ -1278,8 +1308,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1278,8 +1308,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
reg1 = force_reg (Pmode, reg1 = force_reg (Pmode,
gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode,
gen_rtx_MULT (Pmode, reg1, gen_rtx_ASHIFT (Pmode, reg1,
XEXP (XEXP (idx, 0), 1)), GEN_INT (shift_val)),
reg2)); reg2));
/* Add the result to our base register and return. */ /* Add the result to our base register and return. */
...@@ -1315,7 +1345,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1315,7 +1345,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS) if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
{ {
/* See if this looks like /* See if this looks like
(plus (mult (reg) (shadd_const)) (plus (mult (reg) (mem_shadd_const))
(const (plus (symbol_ref) (const_int)))) (const (plus (symbol_ref) (const_int))))
Where const_int is small. In that case the const Where const_int is small. In that case the const
...@@ -1324,14 +1354,18 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -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 If const_int is big, but can be divided evenly by shadd_const
and added to (reg). This allows more scaled indexed addresses. */ and added to (reg). This allows more scaled indexed addresses. */
if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF 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 && GET_CODE (XEXP (y, 1)) == CONST_INT
&& INTVAL (XEXP (y, 1)) >= -4096 && INTVAL (XEXP (y, 1)) >= -4096
&& INTVAL (XEXP (y, 1)) <= 4095 && INTVAL (XEXP (y, 1)) <= 4095)
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
&& pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
{ {
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; rtx reg1, reg2;
reg1 = XEXP (x, 1); reg1 = XEXP (x, 1);
...@@ -1342,21 +1376,27 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1342,21 +1376,27 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (reg2) != REG) if (GET_CODE (reg2) != REG)
reg2 = force_reg (Pmode, force_operand (reg2, 0)); reg2 = force_reg (Pmode, force_operand (reg2, 0));
return force_reg (Pmode, return
force_reg (Pmode,
gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode,
gen_rtx_MULT (Pmode, gen_rtx_ASHIFT (Pmode,
reg2, reg2,
GEN_INT (val)), GEN_INT (shift_val)),
reg1)); reg1));
} }
else if ((mode == DFmode || mode == SFmode) else if ((mode == DFmode || mode == SFmode)
&& GET_CODE (XEXP (y, 0)) == SYMBOL_REF && 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 && GET_CODE (XEXP (y, 1)) == CONST_INT
&& INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0 && INTVAL (XEXP (y, 1)) % (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))))
{ {
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 regx1
= force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1)) = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
/ INTVAL (XEXP (XEXP (x, 0), 1)))); / INTVAL (XEXP (XEXP (x, 0), 1))));
...@@ -1368,8 +1408,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -1368,8 +1408,8 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return return
force_reg (Pmode, force_reg (Pmode,
gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode,
gen_rtx_MULT (Pmode, regx2, gen_rtx_ASHIFT (Pmode, regx2,
XEXP (XEXP (x, 0), 1)), GEN_INT (shift_val)),
force_reg (Pmode, XEXP (y, 0)))); force_reg (Pmode, XEXP (y, 0))));
} }
else if (GET_CODE (XEXP (y, 1)) == CONST_INT else if (GET_CODE (XEXP (y, 1)) == CONST_INT
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment