Jeff Law <jeffreya...@gmail.com> 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

Reply via email to