On Wed, Sep 10, 2025 at 11:11 AM H.J. Lu <[email protected]> wrote: > > 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, > add an option, -fipa-tls-access, for TLS access optimization as the part > of IPA whole-program visibility optimization. Enabled by default, it > doesn't check tls_model attribute when optimizing TLS access since > > 1. -ftls-model=initial-exec can specify the weakest TLS access model > without tls_model attribute. > 2. Linker can optimize TLS access at link-time. > 3. LTO should perform the similar optimization. > > The recomputed model of an undefined TLS variable with LOCAL_EXEC > attribute is INITIAL_EXEC. Linker will issue an error if the TLS > model isn't supported in shared library. But compiler doesn't know > where the TLS variable is defined nor if the generated code will be > linked into executable or shared library. > > gcc/ > > PR middle-end/121352 > * common.opt: Add -fipa-tls-access. > * common.opt.urls: Regenerated. > * ipa-visibility.cc (function_and_variable_visibility): Don't > check tls_model attribute. Update TLS access comments. > * doc/extend.texi: Update the tls_model attribute. > * doc/invoke.texi: Document -fipa-tls-access. > > gcc/testsuite/ > > PR middle-end/121352 > * c-c++-common/tls-attr-hidden-gd.c: New test. > * c-c++-common/tls-attr-le-undef.c: Likewise. > * c-c++-common/tls-flag-hidden-gd.c: Likewise. > * c-c++-common/tls-pragma-hidden-gd.c: Likewise. > * gcc.dg/tls/vis-attr-hidden-gd.c: Pass -fno-ipa-tls-access. > * gcc.dg/tls/vis-flag-hidden-gd.c: Likewise. > * gcc.dg/tls/vis-pragma-hidden-gd.c: Likewise. > > Signed-off-by: H.J. Lu <[email protected]> > --- > gcc/common.opt | 4 ++++ > gcc/common.opt.urls | 3 +++ > gcc/doc/extend.texi | 14 +++++++++----- > gcc/doc/invoke.texi | 6 ++++++ > gcc/ipa-visibility.cc | 14 ++++++++++---- > gcc/testsuite/c-c++-common/tls-attr-hidden-gd.c | 13 +++++++++++++ > gcc/testsuite/c-c++-common/tls-attr-le-undef.c | 15 +++++++++++++++ > gcc/testsuite/c-c++-common/tls-flag-hidden-gd.c | 13 +++++++++++++ > .../c-c++-common/tls-pragma-hidden-gd.c | 17 +++++++++++++++++ > gcc/testsuite/gcc.dg/tls/vis-attr-hidden-gd.c | 2 +- > gcc/testsuite/gcc.dg/tls/vis-flag-hidden-gd.c | 2 +- > gcc/testsuite/gcc.dg/tls/vis-pragma-hidden-gd.c | 2 +- > 12 files changed, 93 insertions(+), 12 deletions(-) > create mode 100644 gcc/testsuite/c-c++-common/tls-attr-hidden-gd.c > create mode 100644 gcc/testsuite/c-c++-common/tls-attr-le-undef.c > create mode 100644 gcc/testsuite/c-c++-common/tls-flag-hidden-gd.c > create mode 100644 gcc/testsuite/c-c++-common/tls-pragma-hidden-gd.c > > diff --git a/gcc/common.opt b/gcc/common.opt > index f6d93dc05fb..42c424b45d0 100644 > --- a/gcc/common.opt > +++ b/gcc/common.opt > @@ -2190,6 +2190,10 @@ fipa-icf-variables > Common Var(flag_ipa_icf_variables) Optimization > Perform Identical Code Folding for variables. > > +fipa-tls-access > +Common Var(flag_ipa_tls_access) Init(1) Optimization > +Perform TLS access optimization. > + > fipa-reference > Common Var(flag_ipa_reference) Init(0) Optimization > Discover read-only and non addressable static variables. > diff --git a/gcc/common.opt.urls b/gcc/common.opt.urls > index ddc5eaf9c6b..b1af1b500f5 100644 > --- a/gcc/common.opt.urls > +++ b/gcc/common.opt.urls > @@ -917,6 +917,9 @@ UrlSuffix(gcc/Optimize-Options.html#index-fipa-pure-const) > fipa-icf > UrlSuffix(gcc/Optimize-Options.html#index-fipa-icf) > > +fipa-tls-access > +UrlSuffix(gcc/Optimize-Options.html#index-fipa-tls-access) > + > fipa-reference > UrlSuffix(gcc/Optimize-Options.html#index-fipa-reference) > > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > index 2922d9e9839..9d55fbb61af 100644 > --- a/gcc/doc/extend.texi > +++ b/gcc/doc/extend.texi > @@ -7559,11 +7559,15 @@ information. > @cindex @code{tls_model} variable attribute > @item tls_model ("@var{tls_model}") > The @code{tls_model} attribute sets thread-local storage model > -(@pxref{Thread-Local}) of a particular @code{__thread} variable, > -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}. > +(@pxref{Thread-Local}) of a particular @code{__thread} variable 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}. The @code{tls_model} attribute specifies the > +weakest @acronym{TLS} model. It overrides @option{-ftls-model=} > +command-line switch if it is stronger than the @acronym{TLS} model > +specified by the command-line switch. GCC may optimize @acronym{TLS} > +access to a stronger @acronym{TLS} model by C/C++ front end as well > +as IPA optimization (see @option{-fno-ipa-tls-access}). > > Not all targets support this attribute. > > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index d0c13d4a24e..b6019cf2746 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -14216,6 +14216,12 @@ option is not enabled by default otherwise. > Reduce stack alignment on call sites if possible. > Enabled by default. > > +@opindex fno-ipa-tls-access > +@opindex fipa-tls-access > +@item -fno-ipa-tls-access > +Don't upgrade TLS model as the part of IPA whole-program visibility > +optimization. > + > @opindex fipa-pta > @item -fipa-pta > Perform interprocedural pointer analysis and interprocedural modification > diff --git a/gcc/ipa-visibility.cc b/gcc/ipa-visibility.cc > index 8097a03e240..56bc39816bf 100644 > --- a/gcc/ipa-visibility.cc > +++ b/gcc/ipa-visibility.cc > @@ -883,18 +883,24 @@ 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 TLS access optimization is disabled or no references > + remain. */ > if (DECL_THREAD_LOCAL_P (decl) > - && !lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl)) > + && flag_ipa_tls_access > && 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. */ > + /* decl_default_tls_model does not scan the attribute list > + and may return a weaker model than the attribute. If > + there was no attribute, we can expect that recomputed > + model is never weaker. */ > if (new_model >= decl_tls_model (decl)) > set_decl_tls_model (decl, new_model); > + else > + gcc_checking_assert (lookup_attribute ("tls_model", > + DECL_ATTRIBUTES > (decl))); > } > } > } > diff --git a/gcc/testsuite/c-c++-common/tls-attr-hidden-gd.c > b/gcc/testsuite/c-c++-common/tls-attr-hidden-gd.c > new file mode 100644 > index 00000000000..4512bff04ad > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/tls-attr-hidden-gd.c > @@ -0,0 +1,13 @@ > +/* { dg-do compile } */ > +/* { dg-require-effective-target fpic } */ > +/* { dg-require-effective-target tls } */ > +/* { dg-options "-O2 -fPIC -fdump-ipa-whole-program" } */ > + > +__attribute__((visibility("hidden"))) > +__attribute__((tls_model("global-dynamic"))) > +__thread int x; > + > +void reference() { x++; } > + > +// 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/c-c++-common/tls-attr-le-undef.c > b/gcc/testsuite/c-c++-common/tls-attr-le-undef.c > new file mode 100644 > index 00000000000..b11c5c9dabc > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/tls-attr-le-undef.c > @@ -0,0 +1,15 @@ > +/* { dg-do compile } */ > +/* { dg-require-effective-target tls } */ > +/* { dg-options "-O2 -fdump-ipa-whole-program" } */ > + > +__attribute__ ((tls_model ("local-exec"))) > +extern __thread int i; > + > +int * > +foo (void) > +{ > + return &i; > +} > + > +/* tls_model should be local-exec due to tls_model attribute. */ > +/* { dg-final { scan-ipa-dump "Varpool flags: tls-local-exec" > "whole-program" } } */ > diff --git a/gcc/testsuite/c-c++-common/tls-flag-hidden-gd.c > b/gcc/testsuite/c-c++-common/tls-flag-hidden-gd.c > new file mode 100644 > index 00000000000..fba79cfd75a > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/tls-flag-hidden-gd.c > @@ -0,0 +1,13 @@ > +/* { dg-do compile } */ > +/* { dg-require-effective-target fpic } */ > +/* { dg-require-effective-target tls } */ > +/* { dg-options "-O2 -fPIC -fdump-ipa-whole-program -fvisibility=hidden" } */ > + > + > +__attribute__((tls_model("global-dynamic"))) > +__thread int x; > + > +void reference() { x++; } > + > +// 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/c-c++-common/tls-pragma-hidden-gd.c > b/gcc/testsuite/c-c++-common/tls-pragma-hidden-gd.c > new file mode 100644 > index 00000000000..3649b6f7272 > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/tls-pragma-hidden-gd.c > @@ -0,0 +1,17 @@ > +/* { dg-do compile } */ > +/* { dg-require-effective-target fpic } */ > +/* { dg-require-effective-target tls } */ > +/* { dg-options "-O2 -fPIC -fdump-ipa-whole-program" } */ > + > + > +#pragma GCC visibility push(hidden) > + > +__attribute__((tls_model("global-dynamic"))) > +__thread int x; > + > +#pragma GCC visibility pop > + > +void reference() { x++; } > + > +// 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-attr-hidden-gd.c > b/gcc/testsuite/gcc.dg/tls/vis-attr-hidden-gd.c > index e32565588c8..05b04cc774b 100644 > --- a/gcc/testsuite/gcc.dg/tls/vis-attr-hidden-gd.c > +++ b/gcc/testsuite/gcc.dg/tls/vis-attr-hidden-gd.c > @@ -1,7 +1,7 @@ > /* { dg-do compile } */ > /* { dg-require-effective-target fpic } */ > /* { dg-require-effective-target tls } */ > -/* { dg-options "-O2 -fPIC -fdump-ipa-whole-program" } */ > +/* { dg-options "-O2 -fPIC -fno-ipa-tls-access -fdump-ipa-whole-program" } */ > > // tls_model should be global-dynamic due to explicitly specified attribute > __attribute__((visibility("hidden"))) > 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..85ee07fb563 100644 > --- a/gcc/testsuite/gcc.dg/tls/vis-flag-hidden-gd.c > +++ b/gcc/testsuite/gcc.dg/tls/vis-flag-hidden-gd.c > @@ -1,7 +1,7 @@ > /* { dg-do compile } */ > /* { dg-require-effective-target fpic } */ > /* { dg-require-effective-target tls } */ > -/* { dg-options "-O2 -fPIC -fdump-ipa-whole-program -fvisibility=hidden" } */ > +/* { dg-options "-O2 -fPIC -fno-ipa-tls-access -fdump-ipa-whole-program > -fvisibility=hidden" } */ > > > // tls_model should be global-dynamic due to explicitly specified attribute > 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..7b0a01b8629 100644 > --- a/gcc/testsuite/gcc.dg/tls/vis-pragma-hidden-gd.c > +++ b/gcc/testsuite/gcc.dg/tls/vis-pragma-hidden-gd.c > @@ -1,7 +1,7 @@ > /* { dg-do compile } */ > /* { dg-require-effective-target fpic } */ > /* { dg-require-effective-target tls } */ > -/* { dg-options "-O2 -fPIC -fdump-ipa-whole-program" } */ > +/* { dg-options "-O2 -fPIC -fno-ipa-tls-access -fdump-ipa-whole-program" } */ > > > #pragma GCC visibility push(hidden) > -- > 2.51.0 >
PING. -- H.J.
