On Fri, Jul 25, 2025 at 1:05 AM Uros Bizjak <[email protected]> wrote:
>
> On Thu, Jul 24, 2025 at 9:30 PM H.J. Lu <[email protected]> wrote:
> >
> > On x86-64, __tls_get_addr is a normal function which doesn't preserve
> > vector registers. On i386, ___tls_get_addr preserve vector registers
> > only with the commit:
>
> Can you please rephrase the above part? What does it mean to be a
> normal function in the context of this patch? Does the x86_64 compiler
Normal functions mean all vector registers are caller-saved registers.
Functions with no_caller_saved_registers attribute need to save and
restore vector registers. When a normal function is called from
a function with no_caller_saved_registers attribute compiled with
SSE, YMM registers may not be preserved since a normal function
may clobber YMM registers.
> emit the normal ABI call (so the caller has to save and restore
> call-clobbered regs)? What is the difference to i386 ___tls_get_addr
> call?
On i386, ___tls_get_addr isn't a CALL insn:
(define_insn "*tls_global_dynamic_32_gnu"
[(set (match_operand:SI 0 "register_operand" "=a")
(unspec:SI
[(match_operand:SI 1 "register_operand" "Yb")
(match_operand 2 "tls_symbolic_operand")
(match_operand 3 "constant_call_address_operand" "Bz")
(reg:SI SP_REG)]
UNSPEC_TLS_GD))
(clobber (match_scratch:SI 4 "=d"))
(clobber (match_scratch:SI 5 "=c"))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_GNU_TLS"
and ___tls_get_addr preserves vector registers.
> > 848f0e46f0 i386: Update ___tls_get_addr to preserve vector registers
> >
> > which fixed:
> >
> > https://sourceware.org/bugzilla/show_bug.cgi?id=32996
> >
> > -mtls-dialect=gnu2 should be used instead with a fixed glibc for
> >
> > https://sourceware.org/bugzilla/show_bug.cgi?id=31372
> >
> > with the commit:
> >
> > 0aac205a81 x86: Update _dl_tlsdesc_dynamic to preserve caller-saved
> > registers
> >
> > Issue an error for -mtls-dialect=gnu with no_caller_saved_registers
> > attribute and suggest -mtls-dialect=gnu2 when __tls_get_addr is used.
>
> If these are fixed, why do we need to use -mtls-dialect=gnu2?
Because x86-64 __tls_get_addr doesn't preserve caller-saved registers
while _dl_tlsdesc_dynamic used by -mtls-dialect=gnu2 preserve caller-saved
registers after
0aac205a81 x86: Update _dl_tlsdesc_dynamic to preserve caller-saved registers
> > gcc/
> >
> > PR target/121208
> > * config/i386/i386.cc (ix86_tls_get_addr): Issue an error for
> > -mtls-dialect=gnu with no_caller_saved_registers attribute and
> > suggest -mtls-dialect=gnu2.
> >
> > gcc/testsuite/
> >
> > PR target/121208
> > * gcc.target/i386/pr121208-1a.c: New test.
> > * gcc.target/i386/pr121208-1b.c: Likewise.
> > * gcc.target/i386/pr121208-2a.c: Likewise.
> > * gcc.target/i386/pr121208-2b.c: Likewise.
> > * gcc.target/i386/pr121208-3a.c: Likewise.
> > * gcc.target/i386/pr121208-3b.c: Likewise.
> >
> > Signed-off-by: H.J. Lu <[email protected]>
> > ---
> > gcc/config/i386/i386.cc | 38 +++++++++++++++++++++
> > gcc/testsuite/gcc.target/i386/pr121208-1a.c | 15 ++++++++
> > gcc/testsuite/gcc.target/i386/pr121208-1b.c | 4 +++
> > gcc/testsuite/gcc.target/i386/pr121208-2a.c | 17 +++++++++
> > gcc/testsuite/gcc.target/i386/pr121208-2b.c | 4 +++
> > gcc/testsuite/gcc.target/i386/pr121208-3a.c | 17 +++++++++
> > gcc/testsuite/gcc.target/i386/pr121208-3b.c | 4 +++
> > 7 files changed, 99 insertions(+)
> > create mode 100644 gcc/testsuite/gcc.target/i386/pr121208-1a.c
> > create mode 100644 gcc/testsuite/gcc.target/i386/pr121208-1b.c
> > create mode 100644 gcc/testsuite/gcc.target/i386/pr121208-2a.c
> > create mode 100644 gcc/testsuite/gcc.target/i386/pr121208-2b.c
> > create mode 100644 gcc/testsuite/gcc.target/i386/pr121208-3a.c
> > create mode 100644 gcc/testsuite/gcc.target/i386/pr121208-3b.c
> >
> > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
> > index 4682db85ce4..7a2037ab6b4 100644
> > --- a/gcc/config/i386/i386.cc
> > +++ b/gcc/config/i386/i386.cc
> > @@ -12442,6 +12442,44 @@ static GTY(()) rtx ix86_tls_symbol;
> > static rtx
> > ix86_tls_get_addr (void)
> > {
> > + if (cfun->machine->call_saved_registers
> > + == TYPE_NO_CALLER_SAVED_REGISTERS)
> > + {
> > + /* On x86-64, __tls_get_addr is a normal function which doesn't
> > + preserve vector registers. On i386, ___tls_get_addr preserve
> > + vector registers only with the commit:
> > +
> > + 848f0e46f0 i386: Update ___tls_get_addr to preserve vector
> > registers
> > +
> > + which fixed:
> > +
> > + https://sourceware.org/bugzilla/show_bug.cgi?id=32996
> > +
> > + -mtls-dialect=gnu2 should be used instead with a fixed glibc
> > + for
> > +
> > + https://sourceware.org/bugzilla/show_bug.cgi?id=31372
> > +
> > + with the commit:
> > +
> > + 0aac205a81 x86: Update _dl_tlsdesc_dynamic to preserve
> > caller-saved registers
>
> The comment here does not need to be so verbose.
>
> Uros.
>
> > +
> > + */
> > + if (cfun->machine->func_type != TYPE_NORMAL)
> > + error (cfun->machine->func_type == TYPE_EXCEPTION
> > + ? G_("%<-mtls-dialect=gnu2%> must be used with an"
> > + " exception service routine")
> > + : G_("%<-mtls-dialect=gnu2%> must be used with an"
> > + " interrupt service routine"));
> > + else
> > + error (G_("%<-mtls-dialect=gnu2%> must be used with a function"
> > + " with the %<no_caller_saved_registers%> attribute"));
> > + /* Don't issue the same error twice. */
> > + cfun->machine->func_type = TYPE_NORMAL;
> > + cfun->machine->call_saved_registers
> > + = TYPE_DEFAULT_CALL_SAVED_REGISTERS;
> > + }
> > +
> > if (!ix86_tls_symbol)
> > {
> > const char *sym
> > diff --git a/gcc/testsuite/gcc.target/i386/pr121208-1a.c
> > b/gcc/testsuite/gcc.target/i386/pr121208-1a.c
> > new file mode 100644
> > index 00000000000..ac851cb50d8
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr121208-1a.c
> > @@ -0,0 +1,15 @@
> > +/* { dg-do compile { target *-*-linux* } } */
> > +/* { dg-options "-O2 -fPIC -mtls-dialect=gnu" } */
> > +
> > +extern __thread int bar;
> > +extern void func (void);
> > +
> > +__attribute__((no_caller_saved_registers))
> > +void
> > +foo (int error)
> > +{
> > + bar = 1; /* { dg-error -mtls-dialect=gnu2 } */
> > + if (error == 0)
> > + func ();
> > + bar = 0;
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr121208-1b.c
> > b/gcc/testsuite/gcc.target/i386/pr121208-1b.c
> > new file mode 100644
> > index 00000000000..b97ac715c65
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr121208-1b.c
> > @@ -0,0 +1,4 @@
> > +/* { dg-do compile { target *-*-linux* } } */
> > +/* { dg-options "-O2 -fPIC -mtls-dialect=gnu2" } */
> > +
> > +#include "pr121208-1a.c"
> > diff --git a/gcc/testsuite/gcc.target/i386/pr121208-2a.c
> > b/gcc/testsuite/gcc.target/i386/pr121208-2a.c
> > new file mode 100644
> > index 00000000000..c1891ae322c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr121208-2a.c
> > @@ -0,0 +1,17 @@
> > +/* { dg-do compile { target *-*-linux* } } */
> > +/* { dg-options "-O2 -fPIC -mtls-dialect=gnu" } */
> > +
> > +typedef unsigned int uword_t __attribute__ ((mode (__word__)));
> > +extern __thread int bar;
> > +extern void func (void);
> > +
> > +__attribute__((target("general-regs-only")))
> > +__attribute__((interrupt))
> > +void
> > +foo (void *frame, uword_t error)
> > +{
> > + bar = 1; /* { dg-error -mtls-dialect=gnu2 } */
> > + if (error == 0)
> > + func ();
> > + bar = 0;
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr121208-2b.c
> > b/gcc/testsuite/gcc.target/i386/pr121208-2b.c
> > new file mode 100644
> > index 00000000000..269b120f990
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr121208-2b.c
> > @@ -0,0 +1,4 @@
> > +/* { dg-do compile { target *-*-linux* } } */
> > +/* { dg-options "-O2 -fPIC -mtls-dialect=gnu2" } */
> > +
> > +#include "pr121208-2a.c"
> > diff --git a/gcc/testsuite/gcc.target/i386/pr121208-3a.c
> > b/gcc/testsuite/gcc.target/i386/pr121208-3a.c
> > new file mode 100644
> > index 00000000000..26fe6870155
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr121208-3a.c
> > @@ -0,0 +1,17 @@
> > +/* { dg-do compile { target *-*-linux* } } */
> > +/* { dg-options "-O2 -fPIC -mtls-dialect=gnu" } */
> > +
> > +typedef unsigned int uword_t __attribute__ ((mode (__word__)));
> > +extern __thread int bar;
> > +extern void func (void);
> > +
> > +__attribute__((target("general-regs-only")))
> > +__attribute__((interrupt))
> > +void
> > +foo (void *frame)
> > +{
> > + bar = 1; /* { dg-error -mtls-dialect=gnu2 } */
> > + if (frame == 0)
> > + func ();
> > + bar = 0;
> > +}
> > diff --git a/gcc/testsuite/gcc.target/i386/pr121208-3b.c
> > b/gcc/testsuite/gcc.target/i386/pr121208-3b.c
> > new file mode 100644
> > index 00000000000..b672d751d7f
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/i386/pr121208-3b.c
> > @@ -0,0 +1,4 @@
> > +/* { dg-do compile { target *-*-linux* } } */
> > +/* { dg-options "-O2 -fPIC -mtls-dialect=gnu2" } */
> > +
> > +#include "pr121208-3a.c"
> > --
> > 2.50.1
> >
--
H.J.