Jeff Law <j...@ventanamicro.com> writes:
> On 8/12/24 4:02 PM, Richard Sandiford wrote:
>> Jeff Law <jeffreya...@gmail.com> writes:
>>> On 8/12/24 1:49 PM, Richard Sandiford wrote:
>>>
>>>>>    
>>>>> -   regno = subreg_regno (x);
>>>>> +   /* A paradoxical should always be REGNO (y) + 0.  Using subreg_regno
>>>>> +      for something like (subreg:DI (reg:SI N) 0) on a WORDS_BIG_ENDIAN
>>>>> +      target will return N-1 which is catastrophic for N == 0 and just
>>>>> +      wrong for other cases.
>>>>> +
>>>>> +      Fixing subreg_regno would be a better option, except that reload
>>>>> +      depends on its current behavior.  */
>>>>> +   if (paradoxical_subreg_p (x))
>>>>> +     regno = REGNO (y);
>>>>> +   else
>>>>> +     regno = subreg_regno (x);
>>>>
>>>> Are you sure that's right?  For a 32-bit big-endian target,
>>>> (subreg:DI (reg:SI 1) 0) really should simplify to (reg:DI 0) rather
>>>> than (reg:DI 1).
>>> Correct, we want to get (reg:DI 0).  We get "0" back from REGNO (y).
>>> And we get 0 back from byte_lowpart_offset (remember, it's paradoxical).
>>>    The sum is 0 resulting in (reg:DI 0).
>> 
>> But in my example, REGNO (y) is 1 (it's a different example from the
>> one that prompted the patch).  The simplified subreg should be the
>> (reg:DI 0) given by subreg_regno, rather than the (reg:DI 1) given
>> by using REGNO (y).
>> 
>> E.g.:
>> 
>>     (set (reg:SI 1) (mem:SI ADDR))
>>     (set (reg:DI 2) (and:DI (subreg:DI (reg:SI 1) 0)
>>                         (const_int 127)))
>> 
>> should (on big-endian targets) be equivalent to:
>> 
>>     (set (reg:SI 1) (mem:SI ADDR))
>>     (set (reg:DI 2) (and:DI (reg:DI 0)
>>                         (const_int 127)))
>> 
>> so that r2 is set to 0 and r3 is set to (mem:SI ADDR) & 127.
>> 
>> If instead we simplified it to:
>> 
>>     (set (reg:SI 1) (mem:SI ADDR))
>>     (set (reg:DI 2) (and:DI (reg:DI 1)
>>                         (const_int 127)))
>> 
>> then r2 would be set to 0 and r3 would be set to an indeterminate
>> value & 127.
> I've gone back and forth over this before I sent that patch.  I can 
> certainly see your logic.  I'd convinced myself that the subreg should 
> have simplified to (reg:DI 1).
>
> And the inconsistency was driving me bananas as my mental model is that 
> (reg:DI N) covers N and N+1 and all that changes in the order based on 
> endianness.   ie, if we have (set (reg:DI 0) (...)) that changes d0/d1. 
>   But maybe that's just 20 years of little endian thinking creeping in.
>
> In which case (subreg:DI (reg:SI d0) 0) is actually meaningless.

Yeah.  The same problem can happen for little-endian too, with e.g.
a doubleword paradoxical subreg of the final hard register leaking
into the virtual registers.  But the failure mode tends to be less
brutal then.  That case is probably more like big-endian
(subreg:DI (reg:SI a0) 0), where the combination d7+a0 would be
rejected for register class reasons.

Richard

Reply via email to