This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [trunk] Addition to subreg section of rtl.text.
Kenneth Zadeck <zadeck@naturalbridge.com> writes:
>>>>> The other use of @code{subreg} is to extract the individual registers of
>>>>> a multi-register value. Machine modes such as @code{DImode} and
>>>>> @code{TImode} can indicate values longer than a word, values which
>>>>> usually require two or more consecutive registers. To access one of the
>>>>> registers, use a @code{subreg} with mode @code{SImode} and a
>>>>> -@var{bytenum} offset that says which register.
>>>>> +@var{bytenum} offset that says which register. In this case, the
>>>>> +@var(bytenum) must align the outer value to a word boundary if the inner
>>>>>
>>>> ^^^^^^^^^
>>>> Nit: {bytenum}
>>>>
>>>>
>>>>> +register is a psuedo or to a register boundary if the inner register is
>>>>> +a hard register.
>>>>>
>>>> As I understand it, this is only true if the _outer_ register is
>>>> word-sized or bigger. You can have (subreg:QI (reg:DI ...) 3) on
>>>> a 32-bit big-endian target, for example.
>>>>
>>> True in general, but that is not the specific case addressed in this
>>> paragraph, that of extracting the individual registers of a
>>> multi-register value. But perhaps this could be made more clear.
>>>
>>
>> Well, it is accessing an individual register of a multi-register value.
>> It just isn't accessing the individual register in its full width.
>>
>> The example is already talking about accessing an individual SImode-sized
>> register, so from that point of view, the example already implies that the
>> byte offset must correspond to a register boundary. So I was afraid
>> that the new sentence might be read more generally as "whenever you're
>> accessing one register in a multi-register value, whatever its mode,
>> the byte offset must be aligned to a register boundary.", especially
>> given that this paragraph flows into one that reads:
>>
> Richard, you are reading what i wrote in the manner that i intended it.
> It was my understanding from and irc chat with bonzini that if the inner
> reg was a multiword reg, the outer reg had to be the
> size and byte aligned on either words or regs depending on if it was a
> pseudo.
>
> If this is wrong, then i will pull it out. I have no stake in this
> except to get the rules as precise as possible.
Maybe I'm misunderstanding what you mean by "aligned". I thought
you meant that SUBREG_BYTE (...) % UNITS_PER_WORD had to be 0.
That isn't true: you can refer to subword pieces of a multiword
inner register. You can even do it for certain cases in which
the subword piece is not a lowpart of the whole multiword inner
register.
Perhaps instead you meant that the least significant byte of the
subreg has to correspond to the least significant byte of a word
of the inner register. If so, I agree (and I think that's a
general rule for all subregs).
Here's an attempt at rewriting the subreg section a little.
It's still very raw, and certainly not properly proof-read.
I just thought I'd throw it out to see if it chimes with what
other people think the semantics are. In particular, is what
I say about hard regs true? Does it have to meet the word-based
requirements _as well as_ the hard-register ones? The old version
gave a specific example:
-It is also not valid to access a single word of a multi-word value in a
-hard register when less registers can hold the value than would be
-expected from its size. For example, some 32-bit machines have
-floating-point registers that can hold an entire @code{DFmode} value.
-If register 10 were such a register @code{(subreg:SI (reg:DF 10) 4)}
-would be invalid because there is no way to convert that reference to
-a single machine register. The reload pass prevents @code{subreg}
-expressions such as these from being formed.
but I'm not sure we'd cope correctly with the opposite case,
such as (subreg:QI (reg:SI foo) 1) on a 32-bit target when
(reg:SI foo) is a pair of half-word registers.
I've attached this attempt as a quote and then a patch. I think
it needs some examples of valid and invalid uses too. I'll work
on some.
Please correct and clarify! Is this even an improvement?
Richard
@code{subreg} expressions are used to refer to a register in a machine
mode other than its natural one, or to refer to one register of
a multi-part @code{reg} that actually refers to several registers.
Each pseudo-register has a natural mode. If it is necessary to
operate on it in a different mode, the pseudo-register must be
enclosed in a @code{subreg}. It is seldom necessary to wrap
hard registers in @code{subreg}s; such registers would normally
reduce to a single @code{reg} rtx.
Usually @var{m} is at least as narrow as the mode of @var{reg},
in which case it is restricting consideration to certain bits of
@var{reg}. There are two cases. If @var{m} is smaller than a word,
the @code{subreg} must refer to the least-significant part (or
@dfn{lowpart}) of one word of @var{reg}. If @var{m} is word-sized or
greater, the @code{subreg} must refer to one or more complete words.
In these two cases, if @var{reg} is a hard register, the @code{subreg}
must also represent the lowpart of a particular hard register,
or represent one or more complete hard registers.
Sometimes @var{m} is wider than the mode of @var{reg}. These
@code{subreg} expressions are often called @dfn{paradoxical}. They are
used in cases where we want to refer to an object in a wider mode but do
not care what value the additional bits have. In such a case,
@var{bytenum} is zero, even for big-endian targets.
Storing in a non-paradoxical @code{subreg} is a word-based operation.
It modifies all the words of @var{reg} that overlap the @code{subreg},
but it leaves the other words of @var{reg} alone.
When storing to a non-paradoxical @code{subreg} that is smaller than
a word, the other bits of the referenced word are usually left in an
undefined state. This laxity makes it easier to generate efficient
code for such instructions. To represent an instruction that
preserves all the bits outside of those in the @code{subreg},
use @code{strict_low_part} around the @code{subreg}.
@cindex @code{WORDS_BIG_ENDIAN}, effect on @code{subreg}
The compilation parameter @code{WORDS_BIG_ENDIAN}, if set to 1, says
that byte number zero is part of the most significant word; otherwise,
it is part of the least significant word.
@cindex @code{BYTES_BIG_ENDIAN}, effect on @code{subreg}
The compilation parameter @code{BYTES_BIG_ENDIAN}, if set to 1, says
that byte number zero is the most significant byte within a word;
otherwise, it is the least significant byte within a word.
@cindex @code{FLOAT_WORDS_BIG_ENDIAN}, (lack of) effect on @code{subreg}
On a few targets, @code{FLOAT_WORDS_BIG_ENDIAN} disagrees with
@code{WORDS_BIG_ENDIAN}.
However, most parts of the compiler treat floating point values as if
they had the same endianness as integer values. This works because
they handle them solely as a collection of integer values, with no
particular numerical value. Only real.c and the runtime libraries
care about @code{FLOAT_WORDS_BIG_ENDIAN}.
Index: gcc/doc/rtl.texi
===================================================================
--- gcc/doc/rtl.texi (revision 133117)
+++ gcc/doc/rtl.texi (working copy)
@@ -1718,33 +1718,38 @@ mode other than its natural one, or to r
a multi-part @code{reg} that actually refers to several registers.
Each pseudo-register has a natural mode. If it is necessary to
-operate on it in a different mode---for example, to perform a fullword
-move instruction on a pseudo-register that contains a single
-byte---the pseudo-register must be enclosed in a @code{subreg}. In
-such a case, @var{bytenum} is zero.
-
-Usually @var{m} is at least as narrow as the mode of @var{reg}, in which
-case it is restricting consideration to only the bits of @var{reg} that
-are in @var{m}.
+operate on it in a different mode, the pseudo-register must be
+enclosed in a @code{subreg}. It is seldom necessary to wrap
+hard registers in @code{subreg}s; such registers would normally
+reduce to a single @code{reg} rtx.
+
+Usually @var{m} is at least as narrow as the mode of @var{reg},
+in which case it is restricting consideration to certain bits of
+@var{reg}. There are two cases. If @var{m} is smaller than a word,
+the @code{subreg} must refer to the least-significant part (or
+@dfn{lowpart}) of one word of @var{reg}. If @var{m} is word-sized or
+greater, the @code{subreg} must refer to one or more complete words.
+
+In these two cases, if @var{reg} is a hard register, the @code{subreg}
+must also represent the lowpart of a particular hard register,
+or represent one or more complete hard registers.
Sometimes @var{m} is wider than the mode of @var{reg}. These
@code{subreg} expressions are often called @dfn{paradoxical}. They are
used in cases where we want to refer to an object in a wider mode but do
-not care what value the additional bits have. The reload pass ensures
-that paradoxical references are only made to hard registers.
+not care what value the additional bits have. In such a case,
+@var{bytenum} is zero, even for big-endian targets.
-The other use of @code{subreg} is to extract the individual registers of
-a multi-register value. Machine modes such as @code{DImode} and
-@code{TImode} can indicate values longer than a word, values which
-usually require two or more consecutive registers. To access one of the
-registers, use a @code{subreg} with mode @code{SImode} and a
-@var{bytenum} offset that says which register.
-
-Storing in a non-paradoxical @code{subreg} has undefined results for
-bits belonging to the same word as the @code{subreg}. This laxity makes
-it easier to generate efficient code for such instructions. To
-represent an instruction that preserves all the bits outside of those in
-the @code{subreg}, use @code{strict_low_part} around the @code{subreg}.
+Storing in a non-paradoxical @code{subreg} is a word-based operation.
+It modifies all the words of @var{reg} that overlap the @code{subreg},
+but it leaves the other words of @var{reg} alone.
+
+When storing to a non-paradoxical @code{subreg} that is smaller than
+a word, the other bits of the referenced word are usually left in an
+undefined state. This laxity makes it easier to generate efficient
+code for such instructions. To represent an instruction that
+preserves all the bits outside of those in the @code{subreg},
+use @code{strict_low_part} around the @code{subreg}.
@cindex @code{WORDS_BIG_ENDIAN}, effect on @code{subreg}
The compilation parameter @code{WORDS_BIG_ENDIAN}, if set to 1, says
@@ -1770,24 +1775,14 @@ care about @code{FLOAT_WORDS_BIG_ENDIAN}
@cindex @code{subreg}, special reload handling
Between the combiner pass and the reload pass, it is possible to have a
paradoxical @code{subreg} which contains a @code{mem} instead of a
-@code{reg} as its first operand. After the reload pass, it is also
-possible to have a non-paradoxical @code{subreg} which contains a
-@code{mem}; this usually occurs when the @code{mem} is a stack slot
-which replaced a pseudo register.
-
-Note that it is not valid to access a @code{DFmode} value in @code{SFmode}
-using a @code{subreg}. On some machines the most significant part of a
-@code{DFmode} value does not have the same format as a single-precision
-floating value.
-
-It is also not valid to access a single word of a multi-word value in a
-hard register when less registers can hold the value than would be
-expected from its size. For example, some 32-bit machines have
-floating-point registers that can hold an entire @code{DFmode} value.
-If register 10 were such a register @code{(subreg:SI (reg:DF 10) 4)}
-would be invalid because there is no way to convert that reference to
-a single machine register. The reload pass prevents @code{subreg}
-expressions such as these from being formed.
+@code{reg} as its first operand.
+
+Note that there are various restrictions on the type of mode change
+that a @code{subreg} can make. For example, it is not valid to access
+a @code{DFmode} value in @code{SFmode} using a @code{subreg}, because
+on some machines the most significant part of a @code{DFmode} value
+does not have the same format as a single-precision floating value.
+The current rules are enforced by the function @code{validate_subreg}.
@findex SUBREG_REG
@findex SUBREG_BYTE