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)
+ {
+ /* 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