From e89b01f2b1bb7b4a689502dd23775301ef36eb0d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 30 Jan 2018 09:45:58 +0000 Subject: [PATCH] Fix LRA subreg calculation for big-endian targets LRA was using a subreg offset of 0 whenever constraints matched two operands with different modes. That leads to an invalid offset (and ICE) on big-endian targets if one of the modes is narrower than a word. E.g. if a (reg:SI X) is matched to a (reg:QI Y), the big-endian subreg should be (subreg:QI (reg:SI X) 3) rather than (subreg:QI (reg:SI X) 0). But this raises the issue of what the behaviour should be when the matched operands occupy different numbers of registers. Should the register numbers match, or should the locations of the lsbs match? Although the documentation isn't clear, reload went for the second interpretation (which seems the most natural to me): /* On a REG_WORDS_BIG_ENDIAN machine, point to the last register of a multiple hard register group of scalar integer registers, so that for example (reg:DI 0) and (reg:SI 1) will be considered the same register. */ So I think this means that we can/must use the lowpart offset unconditionally, rather than trying to separate out the multi-register case. This also matches the LRA handling of constant integers, which already uses lowpart subregs. The patch fixes gcc.target/aarch64/sve/extract_[34].c for aarch64_be. 2018-01-30 Richard Sandiford gcc/ * lra-constraints.c (match_reload): Use subreg_lowpart_offset rather than 0 when creating partial subregs. From-SVN: r257177 --- gcc/ChangeLog | 5 +++++ gcc/lra-constraints.c | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4aecf47e45a..771aa014ebd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2018-01-30 Richard Sandiford + + * lra-constraints.c (match_reload): Use subreg_lowpart_offset + rather than 0 when creating partial subregs. + 2018-01-30 Richard Sandiford * vec-perm-indices.c (vec_perm_indices::series_p): Give examples diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 64ee2fec3c5..c2443124566 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -945,7 +945,10 @@ match_reload (signed char out, signed char *ins, signed char *outs, if (SCALAR_INT_MODE_P (inmode)) new_out_reg = gen_lowpart_SUBREG (outmode, reg); else - new_out_reg = gen_rtx_SUBREG (outmode, reg, 0); + { + poly_uint64 offset = subreg_lowpart_offset (outmode, inmode); + new_out_reg = gen_rtx_SUBREG (outmode, reg, offset); + } LRA_SUBREG_P (new_out_reg) = 1; /* If the input reg is dying here, we can use the same hard register for REG and IN_RTX. We do it only for original @@ -965,7 +968,10 @@ match_reload (signed char out, signed char *ins, signed char *outs, if (SCALAR_INT_MODE_P (outmode)) new_in_reg = gen_lowpart_SUBREG (inmode, reg); else - new_in_reg = gen_rtx_SUBREG (inmode, reg, 0); + { + poly_uint64 offset = subreg_lowpart_offset (inmode, outmode); + new_in_reg = gen_rtx_SUBREG (inmode, reg, offset); + } /* NEW_IN_REG is non-paradoxical subreg. We don't want NEW_OUT_REG living above. We add clobber clause for this. This is just a temporary clobber. We can remove -- 2.30.2