On Thu, Jul 30, 2026 at 12:18 AM <[email protected]> wrote:
>
> From: Reshma Roy <[email protected]>
>
> Backported from master:
> 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.
>
> (cherry picked from commit af8dbc9ccf8209007e38a923c3c158e9e8f4396d)
> ---
>
> Hi Richard,
>
>    This is a backport of the regression fix done for PR126382 to the
>    releases/gcc-16 branch.
>
>    Master commit:  af8dbc9ccf8209007e38a923c3c158e9e8f4396d
>    PR link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126382
>
>    Bootstrapped and regression tested on x86_64-linux.
>
>    Given the upcoming 16.2 release, is this OK for the releases/gcc-16 branch?
>
> Thanks
> Reshma Roy
>
>  gcc/config/i386/i386-features.cc         | 11 +++++++
>  gcc/testsuite/gcc.target/i386/pr126382.c | 40 ++++++++++++++++++++++++
>  2 files changed, 51 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 cef1e24da34..ddd5eca5ef0 100644
> --- a/gcc/config/i386/i386-features.cc
> +++ b/gcc/config/i386/i386-features.cc
> @@ -4026,6 +4026,17 @@ 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)

This should be inside of the

if (kind != X86_CSE_TLSDESC)

block.  I properly backported it to GCC 16 for you.

> +       {
> +         /* DRAP has no reaching definition at this point, so df_live drops
> +            it above.  Its hard register can also go dead mid-function once
> +            copied elsewhere (e.g. right after the prologue), so query
> +            DF_LR_IN per-block rather than treating it as live whenever
> +            crtl->drap_reg is set.  */
> +         i = REGNO (crtl->drap_reg);
> +         if (bitmap_bit_p (DF_LR_IN (bb), i))
> +           bitmap_set_bit (live_caller_saved_regs, i);
> +       }
>
>        if (bitmap_empty_p (live_caller_saved_regs))
>         {
> diff --git a/gcc/testsuite/gcc.target/i386/pr126382.c 
> b/gcc/testsuite/gcc.target/i386/pr126382.c
> new file mode 100644
> index 00000000000..2ffe0074c21
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr126382.c
> @@ -0,0 +1,40 @@
> +/* { dg-do compile { target { *-*-linux* && lp64 } } } */
> +/* { dg-options "-O3 -fPIC -march=x86-64-v4 -fno-asynchronous-unwind-tables 
> -mtls-dialect=gnu" } */
> +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc').  */
> +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} 
>  } } */
> +
> +/*
> +**func:
> +**     pushq   %rbp
> +**     movq    %rsp, %rbp
> +**     pushq   %r12
> +**     pushq   %r10
> +**     leaq    16\(%rbp\), %r10
> +**     pushq   %rbx
> +**     movq    %r10, %r12
> +**     subq    \$8, %rsp
> +**     data16  leaq    FLA_ONE@tlsgd\(%rip\), %rdi
> +**     .value  0x6666
> +**     rex64
> +**     call    __tls_get_addr@PLT
> +**...
> +*/
> +
> +typedef struct
> +{
> +   long n;
> +   long m_inner;
> +   long n_inner;
> +   int base;
> + } FLA_Obj;
> +extern __thread FLA_Obj FLA_ONE, W12;
> +extern long FLA_Obj_length (FLA_Obj);
> +extern void FLA_Obj_width (FLA_Obj, ...);
> +void func (FLA_Obj A)
> +{
> +  while (FLA_Obj_length (A))
> +    FLA_Obj_width (FLA_ONE);
> +  FLA_Obj_width (FLA_ONE, W12);
> +}
> +
> +/* { dg-final { scan-assembler-times "call\[ \t\]__tls_get_addr@PLT" 2 } } */
> --
> 2.34.1
>


-- 
H.J.

Reply via email to