On Fri, Jul 25, 2025 at 1:05 AM Uros Bizjak <ubiz...@gmail.com> wrote: > > On Thu, Jul 24, 2025 at 9:30 PM H.J. Lu <hjl.to...@gmail.com> 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 <hjl.to...@gmail.com> > > --- > > 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.