Hi!

GCC before r237607 used to mishandle TLS in -mcmodel=large - forcing
TLS symbols in constant pool, which obviously doesn't work, because they
aren't constant.  For all other models aarch64_tls_symbol_p is checked
first.

The following patch backports just the bug fix for this PR part to 6.x,
the whole patch has not been declared as a bugfix, came with no testcases,
so I have no idea on what it actually fixes.

I want to roll GCC 6.3rc1 today, is this ok for 6.3 before that, or do you
prefer to backport it yourself later (post 6.3)?  Bootstrapped/regtested
successfully on aarch64-linux on 6 branch.

Is the testcase alone ok for trunk (additionally I've included it in my
x86_64-linux and i686-linux bootstraps)?

2016-12-14  Wilco Dijkstra  <wdijk...@arm.com>
            Jakub Jelinek  <ja...@redhat.com>

        PR target/78796
        * config/aarch64/aarch64.c (aarch64_classify_symbol): Merge large
        model checks into switch.

        * gcc.dg/tls/pr78796.c: New test.

--- gcc/config/aarch64/aarch64.c.jj     2016-08-12 18:05:00.000000000 +0200
+++ gcc/config/aarch64/aarch64.c        2016-12-13 17:13:24.372394957 +0100
@@ -9280,18 +9280,6 @@ aarch64_classify_symbol (rtx x, rtx offs
 
   if (GET_CODE (x) == SYMBOL_REF)
     {
-      if (aarch64_cmodel == AARCH64_CMODEL_LARGE)
-       {
-         /* This is alright even in PIC code as the constant
-            pool reference is always PC relative and within
-            the same translation unit.  */
-         if (nopcrelative_literal_loads
-             && CONSTANT_POOL_ADDRESS_P (x))
-           return SYMBOL_SMALL_ABSOLUTE;
-         else
-           return SYMBOL_FORCE_TO_MEM;
-       }
-
       if (aarch64_tls_symbol_p (x))
        return aarch64_classify_tls_symbol (x);
 
@@ -9332,6 +9320,16 @@ aarch64_classify_symbol (rtx x, rtx offs
                    ?  SYMBOL_SMALL_GOT_28K : SYMBOL_SMALL_GOT_4G);
          return SYMBOL_SMALL_ABSOLUTE;
 
+       case AARCH64_CMODEL_LARGE:
+         /* This is alright even in PIC code as the constant
+            pool reference is always PC relative and within
+            the same translation unit.  */
+         if (nopcrelative_literal_loads
+             && CONSTANT_POOL_ADDRESS_P (x))
+           return SYMBOL_SMALL_ABSOLUTE;
+         else
+           return SYMBOL_FORCE_TO_MEM;
+
        default:
          gcc_unreachable ();
        }
--- gcc/testsuite/gcc.dg/tls/pr78796.c.jj       2016-12-13 17:15:17.135966420 
+0100
+++ gcc/testsuite/gcc.dg/tls/pr78796.c  2016-12-13 17:15:13.939006921 +0100
@@ -0,0 +1,32 @@
+/* PR target/78796 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-additional-options "-mcmodel=large" { target aarch64-*-* } } */
+/* { dg-require-effective-target tls } */
+
+struct S { int a, b, c, d, e; };
+struct S t;
+__thread struct S s;
+
+__attribute__((used, noinline, noclone)) void
+foo (int *x, int *y)
+{
+  asm volatile ("" : : "g" (x), "g" (y) : "memory");
+  if (*x != 1 || *y != 2)
+    __builtin_abort ();
+}
+
+__attribute__((used, noinline, noclone)) void
+bar (void)
+{
+  foo (&t.c, &s.c);
+}
+
+int
+main ()
+{
+  t.c = 1;
+  s.c = 2;
+  bar ();
+  return 0;
+}

        Jakub

Reply via email to