------- Comment #7 from hubicka at ucw dot cz 2010-05-15 09:35 ------- Subject: Re: [4.6 Regression] emutls is broken under a range of circumstances.
Hi, we can either go with DECL_PRESERVE that is kind of hack but makes situation no worse. Correct fix is to lower emultls earlier so both ipa-ref and LTO understands it. This might be bit too early, but I think we can stick it into gimplifier as follows Index: expr.c =================================================================== --- expr.c (revision 159421) +++ expr.c (working copy) @@ -6759,19 +6759,6 @@ highest_pow2_factor_for_target (const_tr return MAX (factor, talign); } -/* Return &VAR expression for emulated thread local VAR. */ - -static tree -emutls_var_address (tree var) -{ - tree emuvar = emutls_decl (var); - tree fn = built_in_decls [BUILT_IN_EMUTLS_GET_ADDRESS]; - tree arg = build_fold_addr_expr_with_type (emuvar, ptr_type_node); - tree arglist = build_tree_list (NULL_TREE, arg); - tree call = build_function_call_expr (UNKNOWN_LOCATION, fn, arglist); - return fold_convert (build_pointer_type (TREE_TYPE (var)), call); -} - /* Subroutine of expand_expr. Expand the two operands of a binary expression EXP0 and EXP1 placing the results in OP0 and OP1. @@ -6866,15 +6853,6 @@ expand_expr_addr_expr_1 (tree exp, rtx t break; case VAR_DECL: - /* TLS emulation hook - replace __thread VAR's &VAR with - __emutls_get_address (&_emutls.VAR). */ - if (! targetm.have_tls - && TREE_CODE (exp) == VAR_DECL - && DECL_THREAD_LOCAL_P (exp)) - { - exp = emutls_var_address (exp); - return expand_expr (exp, target, tmode, modifier); - } /* Fall through. */ default: @@ -8406,16 +8384,6 @@ expand_expr_real_1 (tree exp, rtx target && (TREE_STATIC (exp) || DECL_EXTERNAL (exp))) layout_decl (exp, 0); - /* TLS emulation hook - replace __thread vars with - *__emutls_get_address (&_emutls.var). */ - if (! targetm.have_tls - && TREE_CODE (exp) == VAR_DECL - && DECL_THREAD_LOCAL_P (exp)) - { - exp = build_fold_indirect_ref_loc (loc, emutls_var_address (exp)); - return expand_expr_real_1 (exp, target, tmode, modifier, NULL); - } - /* ... fall through ... */ case FUNCTION_DECL: Index: gimplify.c =================================================================== --- gimplify.c (revision 159421) +++ gimplify.c (working copy) @@ -1309,6 +1309,18 @@ gimplify_vla_decl (tree decl, gimple_seq gimplify_ctxp->save_stack = true; } +/* Return &VAR expression for emulated thread local VAR. */ + +static tree +emutls_var_address (tree var) +{ + tree emuvar = emutls_decl (var); + tree fn = built_in_decls [BUILT_IN_EMUTLS_GET_ADDRESS]; + tree arg = build_fold_addr_expr_with_type (emuvar, ptr_type_node); + tree arglist = build_tree_list (NULL_TREE, arg); + tree call = build_function_call_expr (UNKNOWN_LOCATION, fn, arglist); + return fold_convert (build_pointer_type (TREE_TYPE (var)), call); +} /* Gimplifies a DECL_EXPR node *STMT_P by making any necessary allocation and initialization explicit. */ @@ -1320,6 +1332,15 @@ gimplify_decl_expr (tree *stmt_p, gimple tree decl = DECL_EXPR_DECL (stmt); *stmt_p = NULL_TREE; + /* TLS emulation hook - replace __thread VAR's &VAR with + __emutls_get_address (&_emutls.VAR). */ + if (! targetm.have_tls + && TREE_CODE (decl) == VAR_DECL + && DECL_THREAD_LOCAL_P (decl)) + { + *stmt_p = build_fold_indirect_ref (emutls_var_address (decl)); + return GS_OK; + } if (TREE_TYPE (decl) == error_mark_node) return GS_ERROR; -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44132