diff options
author | Jeff Law <law@redhat.com> | 2015-05-22 10:13:07 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2015-05-22 10:13:07 -0600 |
commit | 92d0b05816f5bd8f811177892459727097fe41a2 (patch) | |
tree | a9da7740f72ab1d83c847b331e93174b76926f42 /gcc/config/pa | |
parent | 9b789cc15c38f6c67de873408e8397fbd7ada75b (diff) | |
download | gcc-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')
-rw-r--r-- | gcc/config/pa/pa.c | 136 |
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 |