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 <hjl.to...@gmail.com>
---
 gcc/common.opt                                  |  4 ++++
 gcc/common.opt.urls                             |  3 +++
 gcc/doc/extend.texi                             | 13 ++++++++-----
 gcc/doc/invoke.texi                             |  5 +++++
 gcc/ipa-visibility.cc                           | 15 +++++++++++----
 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, 92 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..75b7b865902 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -7559,11 +7559,14 @@ 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.
 
 Not all targets support this attribute.
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d0c13d4a24e..9dd94f8c42c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -14216,6 +14216,11 @@ option is not enabled by default otherwise.
 Reduce stack alignment on call sites if possible.
 Enabled by default.
 
+@opindex fipa-tls-access
+@item -fipa-tls-access
+Perform TLS access optimization as the part of IPA whole-program
+visibility optimization.  Enabled by default.
+
 @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..8e33ef3e24c 100644
--- a/gcc/ipa-visibility.cc
+++ b/gcc/ipa-visibility.cc
@@ -883,16 +883,23 @@ 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, it was specified
+            explicitly or no references remain.  */
          if (DECL_THREAD_LOCAL_P (decl)
-             && !lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl))
+             && (flag_ipa_tls_access
+                 || !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.  */
+             /* 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.  */
              if (new_model >= decl_tls_model (decl))
                set_decl_tls_model (decl, new_model);
            }
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

Reply via email to