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.

> 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?

> 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?

> 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.

>  
>  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?

Thanks.
Alexander


> +           if (new_model > model)
>               set_decl_tls_model (decl, new_model);
>           }
>       }
> diff --git a/gcc/testsuite/gcc.dg/tls/vis-attr-hidden-gd.c 
> b/gcc/testsuite/gcc.dg/tls/vis-attr-hidden-gd.c
> index e32565588c8..4512bff04ad 100644
> --- a/gcc/testsuite/gcc.dg/tls/vis-attr-hidden-gd.c
> +++ b/gcc/testsuite/gcc.dg/tls/vis-attr-hidden-gd.c
> @@ -3,11 +3,11 @@
>  /* { dg-require-effective-target tls } */
>  /* { dg-options "-O2 -fPIC -fdump-ipa-whole-program" } */
>  
> -// tls_model should be global-dynamic due to explicitly specified attribute
>  __attribute__((visibility("hidden")))
>  __attribute__((tls_model("global-dynamic")))
>  __thread int x;
>  
>  void reference() { x++; }
>  
> -/* { dg-final { scan-ipa-dump "Varpool flags: tls-global-dynamic" 
> "whole-program" } } */
> +// tls_model should be local-dynamic due to hidden visibility. 
> +/* { dg-final { scan-ipa-dump "Varpool flags: tls-local-dynamic" 
> "whole-program" } } */
> diff --git a/gcc/testsuite/gcc.dg/tls/vis-flag-hidden-gd.c 
> b/gcc/testsuite/gcc.dg/tls/vis-flag-hidden-gd.c
> index cad41e0c8e6..fba79cfd75a 100644
> --- a/gcc/testsuite/gcc.dg/tls/vis-flag-hidden-gd.c
> +++ b/gcc/testsuite/gcc.dg/tls/vis-flag-hidden-gd.c
> @@ -4,10 +4,10 @@
>  /* { dg-options "-O2 -fPIC -fdump-ipa-whole-program -fvisibility=hidden" } */
>  
>  
> -// tls_model should be global-dynamic due to explicitly specified attribute
>  __attribute__((tls_model("global-dynamic")))
>  __thread int x;
>  
>  void reference() { x++; }
>  
> -/* { dg-final { scan-ipa-dump "Varpool flags: tls-global-dynamic" 
> "whole-program" } } */
> +// tls_model should be local-dynamic due to hidden visibility. 
> +/* { dg-final { scan-ipa-dump "Varpool flags: tls-local-dynamic" 
> "whole-program" } } */
> diff --git a/gcc/testsuite/gcc.dg/tls/vis-pragma-hidden-gd.c 
> b/gcc/testsuite/gcc.dg/tls/vis-pragma-hidden-gd.c
> index 3b3598134fe..3649b6f7272 100644
> --- a/gcc/testsuite/gcc.dg/tls/vis-pragma-hidden-gd.c
> +++ b/gcc/testsuite/gcc.dg/tls/vis-pragma-hidden-gd.c
> @@ -6,7 +6,6 @@
>  
>  #pragma GCC visibility push(hidden)
>  
> -// tls_model should be global-dynamic due to explicitly specified attribute
>  __attribute__((tls_model("global-dynamic")))
>  __thread int x;
>  
> @@ -14,4 +13,5 @@ __thread int x;
>  
>  void reference() { x++; }
>  
> -/* { dg-final { scan-ipa-dump "Varpool flags: tls-global-dynamic" 
> "whole-program" } } */
> +// tls_model should be local-dynamic due to hidden visibility. 
> +/* { dg-final { scan-ipa-dump "Varpool flags: tls-local-dynamic" 
> "whole-program" } } */
> 

Reply via email to