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.