On Mon, Sep 8, 2025 at 11:50 PM Alexander Monakov <amona...@ispras.ru> wrote: > > > On Mon, 8 Sep 2025, H.J. Lu wrote: > > > Don't check tls_model attribute when optimizing TLS access since > > > > 1. -ftls-model=initial-exec also can specify tls_model without tls_model > > attribute. > > There's a difference: -ftls-model is usable only for upgrading the model; > if you pass -ftls-model=global-dynamic without -fpic, you still get local-exec > or initial-exec. Just a correction in case you missed it.
True, just like tls_model attribute, -ftls-model specifies the weakest TLS access model. > > 2. Linker can optimize TLS access at link-time. > > 3. LTO should perform the similar optimization. > > I generally agree that GCC should perform this optimization. That said, with > this patch we arrive at a situation with both > > a) ld.bfd does not obey --no-relax to switch off TLS relaxation, and > b) gcc unconditionally performs TLS access optimization > > which makes investigation of TLS-related toolchain bugs difficult. Would you > consider adding a GCC flag to control this optimization? And using the flag > in the testcases? Will do. > > Since C, C++, and Fortran front-ends now set the TLS access model after > > a variable has been fully processed, not in the middle of processing it, > > partially revert > > > > commit 82e629c26647313be406c41a01e6868cfad0f289 > > Author: Alexander Monakov <amona...@ispras.ru> > > Date: Wed Oct 26 16:37:34 2022 +0300 > > > > ipa-visibility: remove assert in TLS optimization [PR107353] > > > > to restore assert if not compiling for shared library. When compiling > > for shared library, the recomputed model may be weaker. > > I don't understand why (for shared libraries), can you explain? Another shared library or executable may override any global symbols with the default visibility in a shared library. > > Linker may > > issue an error if the front-end assigned model isn't supported in shared > > library. But compiler doesn't know if the generated code will be linked > > into executable or shared library. > > > > gcc/ > > > > PR other/107353 > > PR middle-end/121352 > > * ipa-visibility.cc (function_and_variable_visibility): Don't > > check tls_model attribute. Restore assert if not compiling for > > shared library. > > * doc/extend.texi: Update the tls_model attribute. > > > > gcc/testsuite/ > > > > PR middle-end/121352 > > * gcc.dg/tls/vis-attr-hidden-gd.c: Scan for tls-local-dynamic. > > * gcc.dg/tls/vis-flag-hidden-gd.c: Likewise. > > * gcc.dg/tls/vis-pragma-hidden-gd.c: Likewise. > > > > Signed-off-by: H.J. Lu <hjl.to...@gmail.com> > > --- > > gcc/doc/extend.texi | 5 ++++- > > gcc/ipa-visibility.cc | 19 ++++++++++++------- > > gcc/testsuite/gcc.dg/tls/vis-attr-hidden-gd.c | 4 ++-- > > gcc/testsuite/gcc.dg/tls/vis-flag-hidden-gd.c | 4 ++-- > > .../gcc.dg/tls/vis-pragma-hidden-gd.c | 4 ++-- > > 5 files changed, 22 insertions(+), 14 deletions(-) > > > > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > > index 2922d9e9839..879a759714b 100644 > > --- a/gcc/doc/extend.texi > > +++ b/gcc/doc/extend.texi > > @@ -7563,7 +7563,10 @@ The @code{tls_model} attribute sets thread-local > > storage model > > overriding @option{-ftls-model=} command-line switch on a per-variable > > basis. > > The @var{tls_model} argument should be one of @code{global-dynamic}, > > -@code{local-dynamic}, @code{initial-exec} or @code{local-exec}. > > +@code{local-dynamic}, @code{initial-exec} or @code{local-exec}. The > > +@code{tls_model} attribute specifies the weakest @acronym{TLS} access > > +model. GCC may optimize @acronym{TLS} access to a stronger @acronym{TLS} > > +access model. > > I think with this patch the attribute does not fully override the -ftls-model > option. If so, the 'overriding' claim in the previous paragraph should be > changed. If you add a command-line flag to control the optimization, this > section will have to be reworded. Will do. > > > > Not all targets support this attribute. > > > > diff --git a/gcc/ipa-visibility.cc b/gcc/ipa-visibility.cc > > index 8097a03e240..d2283507a31 100644 > > --- a/gcc/ipa-visibility.cc > > +++ b/gcc/ipa-visibility.cc > > @@ -883,17 +883,22 @@ function_and_variable_visibility (bool whole_program) > > tree decl = vnode->decl; > > > > /* Upgrade TLS access model based on optimized visibility status, > > - unless it was specified explicitly or no references remain. */ > > + unless no references remain. */ > > if (DECL_THREAD_LOCAL_P (decl) > > - && !lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl)) > > && vnode->ref_list.referring.length ()) > > { > > enum tls_model new_model = decl_default_tls_model (decl); > > - STATIC_ASSERT (TLS_MODEL_GLOBAL_DYNAMIC < > > TLS_MODEL_LOCAL_DYNAMIC); > > - STATIC_ASSERT (TLS_MODEL_INITIAL_EXEC < TLS_MODEL_LOCAL_EXEC); > > - /* We'd prefer to assert that recomputed model is not weaker > > than > > - what the front-end assigned, but cannot: see PR 107353. */ > > - if (new_model >= decl_tls_model (decl)) > > + /* Assert that the recomputed model is not weaker than > > + what the front-end assigned if not comping for shared > > + library. When compiling for shared library, the > > + recomputed model may be weaker. Linker may issue an > > + error if the front-end assigned model isn't supported > > + in shared library. But compiler doesn't know if the > > + generated code will be linked into executable or shared > > + library. */ > > + tls_model model = decl_tls_model (decl); > > + gcc_checking_assert (flag_shlib || new_model >= model); > > I think this can trip if a variable is redeclared such that initial > declaration > implies a stronger model: > > // compile with gcc -O2 -std=c11 -fno-common > __thread int x; > > __attribute__((common)) > __thread int x; > > int *f() > { > return &x; > } > > Can you check? > [hjl@gnu-zen4-1 gcc]$ cat /tmp/x.c __thread int x; __attribute__((common)) __thread int x; int *f() { return &x; } [hjl@gnu-zen4-1 gcc]$ ./xgcc -B./ -O2 -std=c11 -fno-common -S /tmp/x.c -fdump-ipa-whole-program [hjl@gnu-zen4-1 gcc]$ cat x.c.084i.whole-program Marking local functions: Marking externally visible functions: f/3 Marking externally visible variables: x/1 Clearing variable flags: Reclaiming functions: Reclaiming variables: Clearing address taken flags: Symbol table: f/3 (f) Type: function definition analyzed Visibility: externally_visible semantic_interposition public References: x/1 (addr) Referring: Availability: available Function flags: count:1073741824 (estimated locally) body Called by: Calls: x/1 (x) Type: variable definition analyzed Visibility: externally_visible semantic_interposition public common References: Referring: f/3 (addr) Availability: overwritable Varpool flags: tls-local-exec __attribute__((returns_nonnull)) int * f () { <bb 2> [local count: 1073741824]: return &x; } [hjl@gnu-zen4-1 gcc]$ -- H.J.