From 92d0b05816f5bd8f811177892459727097fe41a2 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Fri, 22 May 2015 10:13:07 -0600 Subject: [PATCH] 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 --- gcc/ChangeLog | 10 ++++ gcc/config/pa/pa.c | 136 +++++++++++++++++++++++++++++---------------- 2 files changed, 98 insertions(+), 48 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 593877fe3a1..e2d49e67f13 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2015-05-22 Jeff Law + + * 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 PR target/65491 diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index f99cf335f49..090eeb4a808 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 -- 2.30.2