Fix LRA subreg calculation for big-endian targets
authorRichard Sandiford <richard.sandiford@linaro.org>
Tue, 30 Jan 2018 09:45:58 +0000 (09:45 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 30 Jan 2018 09:45:58 +0000 (09:45 +0000)
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  <richard.sandiford@linaro.org>

gcc/
* lra-constraints.c (match_reload): Use subreg_lowpart_offset
rather than 0 when creating partial subregs.

From-SVN: r257177

gcc/ChangeLog
gcc/lra-constraints.c

index 4aecf47e45a5127326085683a43e3d4792ec55f3..771aa014ebdc0085db6f3d6c393a1bebe25534a1 100644 (file)
@@ -1,3 +1,8 @@
+2018-01-30  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * lra-constraints.c (match_reload): Use subreg_lowpart_offset
+       rather than 0 when creating partial subregs.
+
 2018-01-30  Richard Sandiford  <richard.sandiford@linaro.org>
 
        * vec-perm-indices.c (vec_perm_indices::series_p): Give examples
index 64ee2fec3c55920ed1ab4c4f6687af4288b0ae45..c2443124566548bec03a8f53784c6fd2f391f270 100644 (file)
@@ -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