re PR target/54908 (misc regressions on emutls targets remain from dynamic initializa...
authorJason Merrill <jason@redhat.com>
Sat, 19 Jan 2013 05:25:25 +0000 (00:25 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 19 Jan 2013 05:25:25 +0000 (00:25 -0500)
PR target/54908
c-family/
* c.opt (-fextern-tls-init): New.
* c-opts.c (c_common_post_options): Handle it.
cp/
* decl2.c (get_local_tls_init_fn): New.
(get_tls_init_fn): Handle flag_extern_tls_init.  Don't bother
with aliases for internal variables.  Don't use weakrefs if
the variable needs destruction.
(generate_tls_wrapper): Mark the wrapper as const if no
initialization is needed.
(handle_tls_init): Don't require aliases.

From-SVN: r195310

gcc/c-family/ChangeLog
gcc/c-family/c-opts.c
gcc/c-family/c.opt
gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/gomp/tls-wrap3.C
gcc/testsuite/g++.dg/tls/thread_local-wrap3.C
libgomp/testsuite/libgomp.c++/pr24455.C

index 778be4b..d4f989b 100644 (file)
@@ -1,3 +1,9 @@
+2013-01-18  Jason Merrill  <jason@redhat.com>
+
+       PR target/54908
+       * c.opt (-fextern-tls-init): New.
+       * c-opts.c (c_common_post_options): Handle it.
+
 2013-01-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR c/48418
index 3fabb36..1a922a8 100644 (file)
@@ -901,6 +901,20 @@ c_common_post_options (const char **pfilename)
   else if (warn_narrowing == -1)
     warn_narrowing = 0;
 
+  if (flag_extern_tls_init)
+    {
+#if !defined (ASM_OUTPUT_DEF) || !SUPPORTS_WEAK
+      /* Lazy TLS initialization for a variable in another TU requires
+        alias and weak reference support. */
+      if (flag_extern_tls_init > 0)
+       sorry ("external TLS initialization functions not supported "
+              "on this target");
+      flag_extern_tls_init = 0;
+#else
+      flag_extern_tls_init = 1;
+#endif
+    }
+
   if (flag_preprocess_only)
     {
       /* Open the output now.  We must do so even if flag_no_output is
index 187f3be..10ae84d 100644 (file)
@@ -913,6 +913,9 @@ finput-charset=
 C ObjC C++ ObjC++ Joined RejectNegative
 -finput-charset=<cset> Specify the default character set for source files
 
+fextern-tls-init
+C++ ObjC++ Var(flag_extern_tls_init) Init(-1)
+Support dynamic initialization of thread-local variables in a different translation unit
 
 fexternal-templates
 C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
index 00bcb7a..6370f7f 100644 (file)
@@ -1,3 +1,14 @@
+2013-01-18  Jason Merrill  <jason@redhat.com>
+
+       PR target/54908
+       * decl2.c (get_local_tls_init_fn): New.
+       (get_tls_init_fn): Handle flag_extern_tls_init.  Don't bother
+       with aliases for internal variables.  Don't use weakrefs if
+       the variable needs destruction.
+       (generate_tls_wrapper): Mark the wrapper as const if no
+       initialization is needed.
+       (handle_tls_init): Don't require aliases.
+
 2013-01-15  Dodji Seketeli  <dodji@redhat.com>
 
        PR c++/55663
index 619d30d..4496395 100644 (file)
@@ -2812,6 +2812,28 @@ var_needs_tls_wrapper (tree var)
          && !var_defined_without_dynamic_init (var));
 }
 
+/* Get the FUNCTION_DECL for the shared TLS init function for this
+   translation unit.  */
+
+static tree
+get_local_tls_init_fn (void)
+{
+  tree sname = get_identifier ("__tls_init");
+  tree fn = IDENTIFIER_GLOBAL_VALUE (sname);
+  if (!fn)
+    {
+      fn = build_lang_decl (FUNCTION_DECL, sname,
+                            build_function_type (void_type_node,
+                                                 void_list_node));
+      SET_DECL_LANGUAGE (fn, lang_c);
+      TREE_PUBLIC (fn) = false;
+      DECL_ARTIFICIAL (fn) = true;
+      mark_used (fn);
+      SET_IDENTIFIER_GLOBAL_VALUE (sname, fn);
+    }
+  return fn;
+}
+
 /* Get a FUNCTION_DECL for the init function for the thread_local
    variable VAR.  The init function will be an alias to the function
    that initializes all the non-local TLS variables in the translation
@@ -2824,6 +2846,18 @@ get_tls_init_fn (tree var)
   if (!var_needs_tls_wrapper (var))
     return NULL_TREE;
 
+  /* If -fno-extern-tls-init, assume that we don't need to call
+     a tls init function for a variable defined in another TU.  */
+  if (!flag_extern_tls_init && DECL_EXTERNAL (var))
+    return NULL_TREE;
+
+#ifdef ASM_OUTPUT_DEF
+  /* If the variable is internal, or if we can't generate aliases,
+     call the local init function directly.  */
+  if (!TREE_PUBLIC (var))
+#endif
+    return get_local_tls_init_fn ();
+
   tree sname = mangle_tls_init_fn (var);
   tree fn = IDENTIFIER_GLOBAL_VALUE (sname);
   if (!fn)
@@ -2841,11 +2875,12 @@ get_tls_init_fn (tree var)
       if (TREE_PUBLIC (var))
        {
          tree obtype = strip_array_types (non_reference (TREE_TYPE (var)));
-         /* If the variable might have static initialization, make the
-            init function a weak reference.  */
+         /* If the variable is defined somewhere else and might have static
+            initialization, make the init function a weak reference.  */
          if ((!TYPE_NEEDS_CONSTRUCTING (obtype)
               || TYPE_HAS_CONSTEXPR_CTOR (obtype))
-             && TARGET_SUPPORTS_WEAK)
+             && TYPE_HAS_TRIVIAL_DESTRUCTOR (obtype)
+             && DECL_EXTERNAL (var))
            declare_weak (fn);
          else
            DECL_WEAK (fn) = DECL_WEAK (var);
@@ -2956,6 +2991,9 @@ generate_tls_wrapper (tree fn)
          finish_if_stmt (if_stmt);
        }
     }
+  else
+    /* If there's no initialization, the wrapper is a constant function.  */
+    TREE_READONLY (fn) = true;
   finish_return_stmt (convert_from_reference (var));
   finish_function_body (body);
   expand_or_defer_fn (finish_function (0));
@@ -3861,15 +3899,6 @@ handle_tls_init (void)
 
   location_t loc = DECL_SOURCE_LOCATION (TREE_VALUE (vars));
 
-  #ifndef ASM_OUTPUT_DEF
-  /* This currently requires alias support.  FIXME other targets could use
-     small thunks instead of aliases.  */
-  input_location = loc;
-  sorry ("dynamic initialization of non-function-local thread_local "
-        "variables not supported on this target");
-  return;
-  #endif
-
   write_out_vars (vars);
 
   tree guard = build_decl (loc, VAR_DECL, get_identifier ("__tls_guard"),
@@ -3882,14 +3911,7 @@ handle_tls_init (void)
   DECL_TLS_MODEL (guard) = decl_default_tls_model (guard);
   pushdecl_top_level_and_finish (guard, NULL_TREE);
 
-  tree fn = build_lang_decl (FUNCTION_DECL,
-                            get_identifier ("__tls_init"),
-                            build_function_type (void_type_node,
-                                                 void_list_node));
-  SET_DECL_LANGUAGE (fn, lang_c);
-  TREE_PUBLIC (fn) = false;
-  DECL_ARTIFICIAL (fn) = true;
-  mark_used (fn);
+  tree fn = get_local_tls_init_fn ();
   start_preparsed_function (fn, NULL_TREE, SF_PRE_PARSED);
   tree body = begin_function_body ();
   tree if_stmt = begin_if_stmt ();
@@ -3904,11 +3926,17 @@ handle_tls_init (void)
       tree init = TREE_PURPOSE (vars);
       one_static_initialization_or_destruction (var, init, true);
 
-      tree single_init_fn = get_tls_init_fn (var);
-      cgraph_node *alias
-       = cgraph_same_body_alias (cgraph_get_create_node (fn),
-                                 single_init_fn, fn);
-      gcc_assert (alias != NULL);
+#ifdef ASM_OUTPUT_DEF
+      /* Output init aliases even with -fno-extern-tls-init.  */
+      if (TREE_PUBLIC (var))
+       {
+          tree single_init_fn = get_tls_init_fn (var);
+         cgraph_node *alias
+           = cgraph_same_body_alias (cgraph_get_create_node (fn),
+                                     single_init_fn, fn);
+         gcc_assert (alias != NULL);
+       }
+#endif
     }
 
   finish_then_clause (if_stmt);
index 887d31e..d60ac9f 100644 (file)
@@ -2029,6 +2029,29 @@ exceptions in violation of the exception specifications; the compiler
 still optimizes based on the specifications, so throwing an
 unexpected exception results in undefined behavior at run time.
 
+@item -fextern-tls-init
+@itemx -fno-extern-tls-init
+@opindex fextern-tls-init
+@opindex fno-extern-tls-init
+The C++11 and OpenMP standards allow @samp{thread_local} and
+@samp{threadprivate} variables to have dynamic (runtime)
+initialization.  To support this, any use of such a variable goes
+through a wrapper function that performs any necessary initialization.
+When the use and definition of the variable are in the same
+translation unit, this overhead can be optimized away, but when the
+use is in a different translation unit there is significant overhead
+even if the variable doesn't actually need dynamic initialization.  If
+the programmer can be sure that no use of the variable in a
+non-defining TU needs to trigger dynamic initialization (either
+because the variable is statically initialized, or a use of the
+variable in the defining TU will be executed before any uses in
+another TU), they can avoid this overhead with the
+@option{-fno-extern-tls-init} option.
+
+On targets that support symbol aliases, the default is
+@option{-fextern-tls-init}.  On targets that do not support symbol
+aliases, the default is @option{-fno-extern-tls-init}.
+
 @item -ffor-scope
 @itemx -fno-for-scope
 @opindex ffor-scope
index 2504d99..abe5cb0 100644 (file)
@@ -1,6 +1,7 @@
 // If we can't see the definition at all, we need to assume there might be
 // an init function.
 
+// { dg-require-alias }
 // { dg-require-effective-target tls }
 // { dg-final { scan-assembler "_ZTW1i" } }
 // { dg-final { scan-assembler "_ZTH1i" } }
index 19e6ab8..6b2fb4f 100644 (file)
@@ -1,6 +1,7 @@
 // If we can't see the definition at all, we need to assume there might be
 // an init function.
 
+// { dg-require-alias }
 // { dg-require-effective-target tls }
 // { dg-options "-std=c++11" }
 // { dg-final { scan-assembler "_ZTW1i" } }
index 3185ca5..8256b66 100644 (file)
@@ -1,8 +1,7 @@
 // { dg-do run }
 // { dg-additional-sources pr24455-1.C }
 // { dg-require-effective-target tls_runtime }
-// { dg-options "-Wl,-G" { target powerpc-ibm-aix* } }
-// { dg-options "-Wl,-undefined,dynamic_lookup" { target *-*-darwin* } }
+// { dg-options "-fno-extern-tls-init" }
 
 extern "C" void abort (void);