re PR target/54908 (misc regressions on emutls targets remain from dynamic initialization of non-function-local TLS variables)

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
This commit is contained in:
Jason Merrill 2013-01-19 00:25:25 -05:00 committed by Jason Merrill
parent fd36469e79
commit 5af057d8bd
9 changed files with 113 additions and 27 deletions

View 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

View 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

View 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)

View 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

View 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);

View 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

View 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" } }

View 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" } }

View 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);