AMD General

> -----Original Message-----
> From: Uros Bizjak <[email protected]>
> Sent: Tuesday, July 28, 2026 11:56 AM
> To: Roy, Reshma <[email protected]>
> Cc: [email protected]; [email protected]; Kumar, Venkataramanan
> <[email protected]>; Aloor, Raghesh
> <[email protected]>
> Subject: Re: [PATCH] x86_cse: Check if DRAP is live with DF_LR_IN.
>
> [You don't often get email from [email protected]. Learn why this is 
> important at
> https://aka.ms/LearnAboutSenderIdentification ]
>
> Caution: This message originated from an External Source. Use proper caution
> when opening attachments, clicking links, or responding.
>
>
> On Fri, Jul 24, 2026 at 6:47 PM <[email protected]> wrote:
> >
> > From: Reshma Roy <[email protected]>
> >
> > The DRAP register has no reaching definition on function entry, so it
> > never shows up in DF_LIVE_IN.  When collecting the live caller-saved
> > registers, additionally set DRAP's bit whenever it is live-in per
> > DF_LR_IN, so the hoisted TLS call is kept after the DRAP save.
> >
> > PR target/126382
> >
> > gcc/ChangeLog:
> >
> >         * config/i386/i386-features.cc (ix86_emit_tls_call): Additional
> >           check to see if DRAP register is live in basic block with 
> > DF_LR_IN.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * gcc.target/i386/pr126382.c: New test.
> >
> > ---
> >
> > Hi,
> >
> >   This patch fix the bug reported in
> >   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126382
> >   x86_cse uses DF_LIVE_IN to place the hoisted __tls_get_addr call, but
> >   the DRAP register is missing there (no reaching def on entry), so the
> >   call can land before the DRAP (%r10) save and clobber the by-value 
> > argument
> >   re-read through %r10.
> >
> >   Fix: mark the DRAP register live when DF_LR_IN reports it, keeping
> >   the TLS call after the DRAP save.
> >
> >   Bootstrapped and regression tested on x86_64-linux.
> >
> > Thanks,
> >   Reshma Roy
> >
> >  gcc/config/i386/i386-features.cc         |  7 +++++
> >  gcc/testsuite/gcc.target/i386/pr126382.c | 40
> > ++++++++++++++++++++++++
> >  2 files changed, 47 insertions(+)
> >  create mode 100644 gcc/testsuite/gcc.target/i386/pr126382.c
> >
> > diff --git a/gcc/config/i386/i386-features.cc
> > b/gcc/config/i386/i386-features.cc
> > index d65b6ce7672..2c0685a0863 100644
> > --- a/gcc/config/i386/i386-features.cc
> > +++ b/gcc/config/i386/i386-features.cc
> > @@ -4357,6 +4357,13 @@ ix86_emit_tls_call (rtx tls_set, x86_cse_kind kind,
> basic_block bb,
> >                 && !fixed_regs[i]
> >                 && bitmap_bit_p (in, i))
> >               bitmap_set_bit (live_caller_saved_regs, i);
> > +         if (df_live && crtl->drap_reg)
> > +           {
> > +             /* Check if DRAP is live in this BB with DF_LR_IN.  */
> > +             i = REGNO (crtl->drap_reg);
> > +             if (bitmap_bit_p (DF_LR_IN (bb), i))
> > +               bitmap_set_bit (live_caller_saved_regs, i);
> > +           }
> >         }
>
> DF_LR without any def to kill it will propagate "live" backward through 
> essentially
> every block reachable from entry. So once
> crtl->drap_reg is set, won't bitmap_bit_p (DF_LR_IN (bb), i) end up
> true for every bb in the function? If that's the case, it would be simpler to 
> drop the
> bitmap query entirely:
>
>       if (df_live && crtl->drap_reg)
>         {
>           /* DRAP has no reaching definition at this point, so it's
>          dropped from df_live's live-in set above.  It is live
>          for the whole function once assigned, so mark it here
>          unconditionally rather than querying DF_LR_IN.  */
>           bitmap_set_bit (live_caller_saved_regs, REGNO (crtl->drap_reg));
>         }
>
> Is there a path where crtl->drap_reg is set but DF_LR_IN(bb) is false for 
> some bb in
> the function?

We could find a test case where crtl->drap_reg is set but DF_LR_IN(bb) is false 
for some bb.
Its value is copied into another register right in the entry block, and after 
that DRAP has no further uses.
PS: The reference from rtl dump for block number is added in the comment.

FLA_Hess_UT_blk_var5 (FLA_Obj A, int p, int q)
{                                            // bb2 (entry): DRAP (%r10) copied 
out to a register here, which is the last use of %r10
  long r = 0;
  FLA_Obj_width (FLA_ONE);
                                                           // bb2  >> FLA_ONE 
__tls_get_addr HOISTED into bb2 from bb7
  if (p)
    {
                                                           // bb3  >> FLA_TWO 
__tls_get_addr HOISTED into bb3 from bb6
      while (q--)
        FLA_Obj_width (FLA_TWO);
      r = FLA_Obj_length (A);
      FLA_Obj_width (FLA_TWO);       // bb6
    }
  FLA_Obj_width (FLA_ONE);            // bb7
  return r;
}

If we print the DF_LR_IN for the blocks:

 bb=2 drap_reg=38 df_live=1 DF_LR_IN=1 DF_LR_OUT=0
 bb=3 drap_reg=38 df_live=1 DF_LR_IN=0 DF_LR_OUT=0


Here crtl->drap_reg is set for the whole function, but at the TLS-call sites 
DF_LR_IN(DRAP)
is 1 in bb2 and 0 in bb3.

>
> Uros.

Reply via email to