Richard Henderson <rth@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.