re PR middle-end/83945 (internal compiler error: Segmentation fault with -O -fcode...
authorJakub Jelinek <jakub@redhat.com>
Sat, 20 Jan 2018 09:58:31 +0000 (10:58 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 20 Jan 2018 09:58:31 +0000 (10:58 +0100)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tls/pr83945.c [new file with mode: 0644]
gcc/tree-emutls.c

index 983675622ae0e4b1a5c37e3aee421d5e8cd71266..321066c6b0ac2ac8baf935b8035137f702023441 100644 (file)
@@ -1,5 +1,12 @@
 2018-01-20  Jakub Jelinek  <jakub@redhat.com>
 
+       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.
+
        PR target/83930
        * simplify-rtx.c (simplify_binary_operation_1) <case UMOD>: Use
        UINTVAL (trueop1) instead of INTVAL (op1).
index e58ae1e28173fd823f9a6c3e0539c98e6c406881..a88e459c73a6a49a7464538cbab47fe7649400e0 100644 (file)
@@ -1,5 +1,8 @@
 2018-01-20  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/83945
+       * gcc.dg/tls/pr83945.c: New test.
+
        PR target/83930
        * gcc.dg/pr83930.c: New test.
 
diff --git a/gcc/testsuite/gcc.dg/tls/pr83945.c b/gcc/testsuite/gcc.dg/tls/pr83945.c
new file mode 100644 (file)
index 0000000..dade238
--- /dev/null
@@ -0,0 +1,21 @@
+/* PR middle-end/83945 */
+/* { dg-do compile { target tls } } */
+/* { dg-options "-O2" } */
+
+struct S { int a[1]; };
+__thread struct T { int c; } e;
+int f;
+void bar (int);
+
+void
+foo (int f, int x)
+{
+  struct S *h = (struct S *) &e.c;
+  for (;;)
+    {
+      int *a = h->a, i;
+      for (i = x; i; i--)
+       bar (a[f]);
+      bar (a[f]);
+    }
+}
index ae8c6e5f155b6cf39e3ca64036f001812399001f..fa4b7e15c45d45ce25134f176828c336673aed21 100644 (file)
@@ -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)
            {