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