[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 } } */