diff options
| author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-01-24 23:50:56 +0000 |
|---|---|---|
| committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-01-24 23:50:56 +0000 |
| commit | 2eceb3926c04feacb55ee9815334da25fe71b3de (patch) | |
| tree | b56353a0eed78434279ea535f0b49194fb4a6e06 /gcc/reload.c | |
| parent | 59d9fcad06d20be689ce1baf650875a85c60a21f (diff) | |
| download | ppe42-gcc-2eceb3926c04feacb55ee9815334da25fe71b3de.tar.gz ppe42-gcc-2eceb3926c04feacb55ee9815334da25fe71b3de.zip | |
* reload.c (find_reloads_subreg_address): Fail the substitution
if the resulting address is insufficiently aligned.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@39250 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reload.c')
| -rw-r--r-- | gcc/reload.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/gcc/reload.c b/gcc/reload.c index 533c28c9249..5f27744057d 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -5648,21 +5648,42 @@ find_reloads_subreg_address (x, force_replace, opnum, type, || ! rtx_equal_p (tem, reg_equiv_mem[regno])) { int offset = SUBREG_WORD (x) * UNITS_PER_WORD; + unsigned outer_size = GET_MODE_SIZE (GET_MODE (x)); + unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))); if (BYTES_BIG_ENDIAN) { - int size; - - size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))); - offset += MIN (size, UNITS_PER_WORD); - size = GET_MODE_SIZE (GET_MODE (x)); - offset -= MIN (size, UNITS_PER_WORD); + offset += MIN (inner_size, UNITS_PER_WORD); + offset -= MIN (outer_size, UNITS_PER_WORD); } XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset); PUT_MODE (tem, GET_MODE (x)); + + /* If this was a paradoxical subreg that we replaced, the + resulting memory must be sufficiently aligned to allow + us to widen the mode of the memory. */ + if (outer_size > inner_size && STRICT_ALIGNMENT) + { + rtx base; + + base = XEXP (tem, 0); + if (GET_CODE (base) == PLUS) + { + if (GET_CODE (XEXP (base, 1)) == CONST_INT + && INTVAL (XEXP (base, 1)) % outer_size != 0) + return x; + base = XEXP (base, 0); + } + if (GET_CODE (base) != REG + || (REGNO_POINTER_ALIGN (REGNO (base)) + < outer_size * BITS_PER_UNIT)) + return x; + } + find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0), &XEXP (tem, 0), opnum, ADDR_TYPE (type), ind_levels, insn); + /* If this is not a toplevel operand, find_reloads doesn't see this substitution. We have to emit a USE of the pseudo so that delete_output_reload can see it. */ |

