Richard Henderson <r...@redhat.com> writes:
> On 12/10/2013 10:44 AM, Richard Sandiford wrote:
>> Sorry, I don't understand.  I never said it was invalid.  I said
>> (subreg:SF (reg:V4SF X) 1) was invalid if (reg:V4SF X) represents
>> a single register.  On a little-endian target, the offset cannot be
>> anything other than 0 in that case.
>> 
>> So the CANNOT_CHANGE_MODE_CLASS code above seems to be checking for
>> something that is always invalid, regardless of the target.  That kind
>> of situation should be rejected by target-independent code instead.
>
> But, we want to disable the subreg before we know whether or not (reg:V4SF X)
> will be allocated to a single hard register.  That is something that we can't
> know in target-independent code before register allocation.

I was thinking that if we've got a class, we've also got things like
CLASS_MAX_NREGS.  Maybe that doesn't cope with padding properly though.
But even in the padding cases an offset-based check in C_C_M_C could
be derived from other information.

subreg_get_info handles padding with:

      nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
      if (GET_MODE_INNER (xmode) == VOIDmode)
        xmode_unit = xmode;
      else
        xmode_unit = GET_MODE_INNER (xmode);
      gcc_assert (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode_unit));
      gcc_assert (nregs_xmode
                  == (GET_MODE_NUNITS (xmode)
                      * HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode_unit)));
      gcc_assert (hard_regno_nregs[xregno][xmode]
                  == (hard_regno_nregs[xregno][xmode_unit]
                      * GET_MODE_NUNITS (xmode)));

      /* You can only ask for a SUBREG of a value with holes in the middle
         if you don't cross the holes.  (Such a SUBREG should be done by
         picking a different register class, or doing it in memory if
         necessary.)  An example of a value with holes is XCmode on 32-bit
         x86 with -m128bit-long-double; it's represented in 6 32-bit registers,
         3 for each part, but in memory it's two 128-bit parts.
         Padding is assumed to be at the end (not necessarily the 'high part')
         of each unit.  */
      if ((offset / GET_MODE_SIZE (xmode_unit) + 1
           < GET_MODE_NUNITS (xmode))
          && (offset / GET_MODE_SIZE (xmode_unit)
              != ((offset + GET_MODE_SIZE (ymode) - 1)
                  / GET_MODE_SIZE (xmode_unit))))
        {
          info->representable_p = false;
          rknown = true;
        }

and I wouldn't really want to force targets to individually reproduce
that kind of logic at the class level.  If the worst comes to the worst
we could cache the difficult cases.

Thanks,
Richard

Reply via email to