[gcc r16-9436] x86_cse: Check if DRAP is live with DF_LR_IN.
"H.J. Lu via Gcc-cvs" <[email protected]> Wed, 29 Jul 2026 21:05:48 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:d00d5b7eddea4217ac6d85cf51e4604b9a187cc5 commit r16-9436-gd00d5b7eddea4217ac6d85cf51e4604b9a187cc5 Author: Reshma Roy <[email protected]> Date: Tue Jul 28 16:55:24 2026 +0530 x86_cse: Check if DRAP is live with DF_LR_IN. 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) Diff: --- gcc/config/i386/i386-features.cc | 23 ++++++++++++++---- gcc/testsuite/gcc.target/i386/pr126382.c | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index cef1e24da341..af0724a1e687 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -4021,11 +4021,24 @@ ix86_emit_tls_call (rtx tls_set, x86_cse_kind kind, basic_block bb, /* Get all live caller-saved registers for TLS_GD and TLS_LD_BASE instructions. */ if (kind != X86_CSE_TLSDESC) - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (call_used_regs[i] - && !fixed_regs[i] - && bitmap_bit_p (in, i)) - bitmap_set_bit (live_caller_saved_regs, i); + { + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (call_used_regs[i] + && !fixed_regs[i] + && bitmap_bit_p (in, i)) + bitmap_set_bit (live_caller_saved_regs, i); + if (df_live && crtl->drap_reg) + { + /* 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 000000000000..2ffe0074c213 --- /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 } } */