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?

Uros.

Reply via email to