diff options
author | Jakub Jelinek <jakub@redhat.com> | 2018-01-20 10:58:31 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-01-20 10:58:31 +0100 |
commit | 37b7e7873d3a3e79523f4474a330fe41e1a90b36 (patch) | |
tree | 637882dab05745b1e461c3f9b187d24c7441155b /gcc/tree-emutls.c | |
parent | 09cbbded0d197f2da4f01be6f90c8535474b8200 (diff) |
re PR middle-end/83945 (internal compiler error: Segmentation fault with -O -fcode-hoisting)
PR middle-end/83945
* tree-emutls.c: Include gimplify.h.
(lower_emutls_2): New function.
(lower_emutls_1): If ADDR_EXPR is a gimple invariant and walk_tree
with lower_emutls_2 callback finds some TLS decl in it, unshare_expr
it before further processing.
* gcc.dg/tls/pr83945.c: New test.
From-SVN: r256916
Diffstat (limited to 'gcc/tree-emutls.c')
-rw-r--r-- | gcc/tree-emutls.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c index ae8c6e5f155..fa4b7e15c45 100644 --- a/gcc/tree-emutls.c +++ b/gcc/tree-emutls.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-walk.h" #include "langhooks.h" #include "tree-iterator.h" +#include "gimplify.h" /* Whenever a target does not support thread-local storage (TLS) natively, we can emulate it with some run-time support in libgcc. This will in @@ -429,6 +430,20 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d) return addr; } +/* Callback for lower_emutls_1, return non-NULL if there is any TLS + VAR_DECL in the subexpressions. */ + +static tree +lower_emutls_2 (tree *ptr, int *walk_subtrees, void *) +{ + tree t = *ptr; + if (TREE_CODE (t) == VAR_DECL) + return DECL_THREAD_LOCAL_P (t) ? t : NULL_TREE; + else if (!EXPR_P (t)) + *walk_subtrees = 0; + return NULL_TREE; +} + /* Callback for walk_gimple_op. D = WI->INFO is a struct lower_emutls_data. Given an operand *PTR within D->STMT, if the operand references a TLS variable, then lower the reference to a call to the runtime. Insert @@ -455,6 +470,13 @@ lower_emutls_1 (tree *ptr, int *walk_subtrees, void *cb_data) { bool save_changed; + /* Gimple invariants are shareable trees, so before changing + anything in them if we will need to change anything, unshare + them. */ + if (is_gimple_min_invariant (t) + && walk_tree (&TREE_OPERAND (t, 0), lower_emutls_2, NULL, NULL)) + *ptr = t = unshare_expr (t); + /* If we're allowed more than just is_gimple_val, continue. */ if (!wi->val_only) { |