Jeff Law <[email protected]> writes:
> On 8/12/24 3:50 PM, Jeff Law wrote:
>>
>>
>> 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).
> So rewinding this discussion a bit.
>
> Focusing on this insn:
>
>> (insn 77 75 80 6 (parallel [
>> (set (reg:DI 75 [ _32 ])
>> (plus:DI (reg:DI 73 [ _31 ])
>> (subreg:DI (reg/v:SI 41 [ __n ]) 0)))
>> (clobber (scratch:SI))
>> ]) "j.C":50:38 discrim 1 155 {adddi3}
>> (expr_list:REG_DEAD (reg:DI 73 [ _31 ])
>> (expr_list:REG_DEAD (reg/v:SI 41 [ __n ])
>> (nil))))
>
> Not surprisingly we're focused on the subreg expression in there.
>
> The first checkpoint in my mind is IRA's allocation where we assign it
> to reg 0.
>
>
>> Popping a0(r41,l0) -- assign reg 0
>
>
> So given the use inside a paradoxical subreg, do we consider this valid?
>
> After the discussion from last week, I'm leaning a bit more towards no
> than before.
I thought it wasn't valid. AIUI, there are two mechanisms that try
to prevent it:
- valid_mode_changes_for_regno, which says which hard registers can
form all subregs required by a pseudo. This is only used to restrict
class choices though, rather than forbid individual registers.
- This code in ira_build_conflicts:
/* Now we deal with paradoxical subreg cases where certain registers
cannot be accessed in the widest mode. */
machine_mode outer_mode = ALLOCNO_WMODE (a);
machine_mode inner_mode = ALLOCNO_MODE (a);
if (paradoxical_subreg_p (outer_mode, inner_mode))
{
enum reg_class aclass = ALLOCNO_CLASS (a);
for (int j = ira_class_hard_regs_num[aclass] - 1; j >= 0; --j)
{
int inner_regno = ira_class_hard_regs[aclass][j];
int outer_regno = simplify_subreg_regno (inner_regno,
inner_mode, 0,
outer_mode);
if (outer_regno < 0
|| !in_hard_reg_set_p (reg_class_contents[aclass],
outer_mode, outer_regno))
{
SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
inner_regno);
SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj),
inner_regno);
}
}
}
which operates at the level of individual registers.
So yeah, I think the first question is why ira_build_conflicts isn't
kicking in for this register or (if it is) why we still get register 0.
Thanks,
Richard