On Wed, Apr 23, 2025 at 04:23:37PM +0200, Stefan Schulze Frielinghaus wrote:
> > So, the following patch checks for this special case, where the argument
> > which uses %r6 is passed in a single register and it is passed default
> > definition of SSA_NAME of a PARM_DECL with the same DECL_INCOMING_RTL.
> 
> Do we really need a check for nregs==1 here?  Only, for -m31 we pass
> parameters in register pairs.  With check nregs==1 we fail on -m31 for
> the following example and without we pass:
> 
> extern int bar (int p1, int p2, int p3, long long p4, int p5);
> int foo (int p1, int p2, int p3, long long p4, int p5)
> {
>   [[gnu::musttail]] return bar (p1, p2, p3, p4, p5);
> }
> 
> Parameter p4 should be passed in r5,r6 and p5 via stack.

I guess the nregs==1 check can be dropped.
I didn't want to test it multiple times for each nregs, but guess it
will happen only for the %r6 normally as for other regs
call_used_or_fixed_reg_p will be true unless user uses -ffixed- etc.
options.

> > It won't really work at -O0 but should work for -O1 and above, at least when
> > one doesn't really try to modify the parameter conditionally and hope it 
> > will
> > be optimized away in the end.
> 
> It also fails for
> 
> extern int bar (int p1, int p2, int p3, int p4, int p5);
> int foo (int p1, int p2, int p3, int p4, int p5)
> {
>   [[gnu::musttail]] return bar (p1, p2, p3, p4, p5);
> }
> 
> since rtx_equal_p (parm, parm_rtx) does not hold for p5
> 
> (gdb) call debug_rtx(parm_rtx)
> (reg:SI 6 %r6)
> (gdb) call debug_rtx(parm)
> (reg:DI 6 %r6 [ p5+-4 ])
> 
> due to a missmatch between extended and non-extended values.  Maybe a
> check like
> 
> REGNO (parm) == REGNO (parm_rtx)
> && REG_NREGS (parm) == REG_NREGS (parm_rtx)
> 
> is sufficient?

I think it depends the details of the ABI.
I believe when the argument is SSA_NAME (D) of a PARM_DECL it means
the parameter and the argument have (GIMPLE) compatible types.
Are the upper 32 bits always sign extended (or zero extended, or
sign vs. zero extended depending on if it is signed or unsigned < 64bit
type)?
If it must be extended, then yes, testing REGNO and REG_NREGS might be
enough, if the upper bits are unspecified, I'd worry we could sometimes
try to change those bits and break the caller that way.
If {un,}signed {char,short,int} are always zero/sign extended to 64-bit,
what about BITINT_TYPEs?

Another question is if it shouldn't be handled in the PARALLEL case as well
(e.g. if some -m32 long long parameter could be partly passed in %r6 and
partly on the stack).

        Jakub

Reply via email to