diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2017-09-04 10:48:40 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2017-09-04 10:48:40 +0000 |
commit | 3d09ba95c150d9676f9a2585fb61315e86fa644a (patch) | |
tree | 6c37f118811f8cff123ef56870a20145fd74b472 /gcc/simplify-rtx.c | |
parent | d8c40eff56f69877b33c697ded756d50fde90c27 (diff) | |
download | gcc-3d09ba95c150d9676f9a2585fb61315e86fa644a.zip gcc-3d09ba95c150d9676f9a2585fb61315e86fa644a.tar.gz gcc-3d09ba95c150d9676f9a2585fb61315e86fa644a.tar.bz2 |
Add subreg_memory_offset helper functions
This patch adds routines for converting a SUBREG_BYTE offset into a
memory address offset. The two only differ for paradoxical subregs,
where SUBREG_BYTE is always 0 but the memory address offset can be
negative.
2017-09-04 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
gcc/
* rtl.h (subreg_memory_offset): Declare.
* emit-rtl.c (subreg_memory_offset): New function.
* expmed.c (store_bit_field_1): Use it.
* expr.c (undefined_operand_subword_p): Likewise.
* simplify-rtx.c (simplify_subreg): Likewise.
Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r251644
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r-- | gcc/simplify-rtx.c | 64 |
1 files changed, 14 insertions, 50 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 6f4398e..97a0652 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -6069,34 +6069,18 @@ simplify_subreg (machine_mode outermode, rtx op, if (GET_CODE (op) == SUBREG) { machine_mode innermostmode = GET_MODE (SUBREG_REG (op)); - int final_offset = byte + SUBREG_BYTE (op); rtx newx; if (outermode == innermostmode && byte == 0 && SUBREG_BYTE (op) == 0) return SUBREG_REG (op); - /* The SUBREG_BYTE represents offset, as if the value were stored - in memory. Irritating exception is paradoxical subreg, where - we define SUBREG_BYTE to be 0. On big endian machines, this - value should be negative. For a moment, undo this exception. */ - if (byte == 0 && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) - { - int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode)); - if (WORDS_BIG_ENDIAN) - final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - final_offset += difference % UNITS_PER_WORD; - } - if (SUBREG_BYTE (op) == 0 - && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode)) - { - int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode)); - if (WORDS_BIG_ENDIAN) - final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - final_offset += difference % UNITS_PER_WORD; - } + /* Work out the memory offset of the final OUTERMODE value relative + to the inner value of OP. */ + HOST_WIDE_INT mem_offset = subreg_memory_offset (outermode, + innermode, byte); + HOST_WIDE_INT op_mem_offset = subreg_memory_offset (op); + HOST_WIDE_INT final_offset = mem_offset + op_mem_offset; /* See whether resulting subreg will be paradoxical. */ if (!paradoxical_subreg_p (outermode, innermostmode)) @@ -6111,19 +6095,12 @@ simplify_subreg (machine_mode outermode, rtx op, } else { - int offset = 0; - int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (outermode)); - - /* In paradoxical subreg, see if we are still looking on lower part. - If so, our SUBREG_BYTE will be 0. */ - if (WORDS_BIG_ENDIAN) - offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - offset += difference % UNITS_PER_WORD; - if (offset == final_offset) - final_offset = 0; - else + HOST_WIDE_INT required_offset + = subreg_memory_offset (outermode, innermostmode, 0); + if (final_offset != required_offset) return NULL_RTX; + /* Paradoxical subregs always have byte offset 0. */ + final_offset = 0; } /* Recurse for further possible simplifications. */ @@ -6164,22 +6141,9 @@ simplify_subreg (machine_mode outermode, rtx op, final_regno = simplify_subreg_regno (regno, innermode, byte, outermode); if (HARD_REGISTER_NUM_P (final_regno)) { - rtx x; - int final_offset = byte; - - /* Adjust offset for paradoxical subregs. */ - if (byte == 0 - && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode)) - { - int difference = (GET_MODE_SIZE (innermode) - - GET_MODE_SIZE (outermode)); - if (WORDS_BIG_ENDIAN) - final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD; - if (BYTES_BIG_ENDIAN) - final_offset += difference % UNITS_PER_WORD; - } - - x = gen_rtx_REG_offset (op, outermode, final_regno, final_offset); + rtx x = gen_rtx_REG_offset (op, outermode, final_regno, + subreg_memory_offset (outermode, + innermode, byte)); /* Propagate original regno. We don't have any way to specify the offset inside original regno, so do so only for lowpart. |