Patchwork AIX native TLS support [3/?]

login
register
mail settings
Submitter David Edelsohn
Date Dec. 27, 2012, 5:18 p.m.
Message ID <CAGWvnymBBWFcXiYk82By2tCojNXg0548w+YhQRrNZDcVc3eN7Q@mail.gmail.com>
Download mbox | patch
Permalink /patch/208348/
State New
Headers show

Comments

David Edelsohn - Dec. 27, 2012, 5:18 p.m.
This patch gets GCC support for native TLS on AIX working and passing
most tests.

The patch shifts the creation of the qualified symbol name from
output_toc() to rs6000_legitimize_tls_address_aix(). I was hoping that
the separate SYMBOL_REF would prevent RTL fwprop from becoming
confused about the symbols, but no such luck. The re-write still makes
things a little cleaner.

Also, private TLS data (static variables with non-zero initializers)
are not decorated with the TLS CSECT qualifier so that the AIX
assembler and linker resolve it correctly.

To prevent fwprop from breaking things, I need to prevent
rs6000_delegitimize_address from associating TLS TOC references with
the original symbol. The rs6000 port uses the constant pool to manage
the TOC.  However, for TLS symbols, the value in the TOC is not
equivalent to the symbol itself. The RTL fwprop pass thinks that it
can associate the result of a TLS access, which materializes the
symbol in a register, with the value in the constant pool and avoid
re-loading the TOC value. This does not work and passes a garbage
value to subsequent TLS calls, which produce garbage results. The two
solutions are either "hide" the TLS constant pool values by not
delegitmizing them or completely re-writing the TOC support to use a
pool separate from the constant pool.  I chose the former because TLS
is a scarce resource and its usage should be minimal anyway.

Bootstrapped on powerpc-ibm-aix7.1.0.0.

Thanks, David

        * config/rs6000/rs6000.c (rs6000_deligitimze_address): Do not
        delegitimize TLS addresses on AIX.
        (rs6000_legitimize_tls_address_aix): Append TLS symbol qualifier.
        Set SYMBOL_FLAG_LOCAL on module symbol.
        (output_toc): Do not append TLS symbol qualifier here.
        * config/rs6000/rs6000.md (tls_get_addr_internal): Add GPR 4 to
        clobbers.

Patch

Index: rs6000.c
===================================================================
--- rs6000.c    (revision 194725)
+++ rs6000.c    (working copy)
@@ -5826,6 +5826,15 @@  rs6000_delegitimize_address (rtx orig_x)
        }
 #endif
       y = XVECEXP (y, 0, 0);
+
+#ifdef HAVE_AS_TLS
+      /* Do not associate thread-local symbols with the original
+        constant pool symbol.  */
+      if (TARGET_XCOFF
+         && SYMBOL_REF_TLS_MODEL (get_pool_constant (y)) >= TLS_MODEL_REAL)
+       return orig_x;
+#endif
+
       if (offset != NULL_RTX)
        y = gen_rtx_PLUS (Pmode, y, offset);
       if (!MEM_P (orig_x))
@@ -5899,10 +5908,29 @@  rs6000_got_sym (void)
 static rtx
 rs6000_legitimize_tls_address_aix (rtx addr, enum tls_model model)
 {
-  rtx sym, mem, tocref, tlsreg, tmpreg, dest;
+  rtx sym, mem, tocref, tlsreg, tmpreg, dest, tlsaddr;
+  const char *name;
+  char *tlsname;

+  name = XSTR (addr, 0);
+  /* Append TLS CSECT qualifier, unless the symbol already is qualified
+     or the symbol will be in TLS private data section.  */
+  if (name[strlen (name) - 1] != ']'
+      && (TREE_PUBLIC (SYMBOL_REF_DECL (addr))
+         || bss_initializer_p (SYMBOL_REF_DECL (addr))))
+    {
+      tlsname = XALLOCAVEC (char, strlen (name) + 4);
+      strcpy (tlsname, name);
+      strcat (tlsname,
+             bss_initializer_p (SYMBOL_REF_DECL (addr)) ? "[UL]" : "[TL]");
+      tlsaddr = copy_rtx (addr);
+      XSTR (tlsaddr, 0) = ggc_strdup (tlsname);
+    }
+  else
+    tlsaddr = addr;
+
   /* Place addr into TOC constant pool.  */
-  sym = force_const_mem (GET_MODE (addr), addr);
+  sym = force_const_mem (GET_MODE (tlsaddr), tlsaddr);

   /* Output the TOC entry and create the MEM referencing the value.  */
   if (constant_pool_expr_p (XEXP (sym, 0))
@@ -5919,27 +5947,28 @@  rs6000_legitimize_tls_address_aix (rtx addr, enum
   if (model == TLS_MODEL_GLOBAL_DYNAMIC
       || model == TLS_MODEL_LOCAL_DYNAMIC)
     {
-      rtx module = gen_reg_rtx (Pmode);
       /* Create new TOC reference for @m symbol.  */
-      const char *name = XSTR (XVECEXP (XEXP (mem, 0), 0, 0), 0);
-      char *name2 = XALLOCAVEC (char, strlen (name) + 1);
-      strcpy (name2, "*LCM");
-      strcat (name2, name + 3);
-      tocref = create_TOC_reference (gen_rtx_SYMBOL_REF (Pmode,
-
ggc_alloc_string (name2,
-
    strlen (name2))),
-                                    NULL_RTX);
-      rtx mem2 = gen_const_mem (Pmode, tocref);
-      set_mem_alias_set (mem2, get_TOC_alias_set ());
+      name = XSTR (XVECEXP (XEXP (mem, 0), 0, 0), 0);
+      tlsname = XALLOCAVEC (char, strlen (name) + 1);
+      strcpy (tlsname, "*LCM");
+      strcat (tlsname, name + 3);
+      rtx modaddr = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (tlsname));
+      SYMBOL_REF_FLAGS (modaddr) |= SYMBOL_FLAG_LOCAL;
+      tocref = create_TOC_reference (modaddr, NULL_RTX);
+      rtx modmem = gen_const_mem (Pmode, tocref);
+      set_mem_alias_set (modmem, get_TOC_alias_set ());

-      dest = gen_reg_rtx (Pmode);
+      rtx modreg = gen_reg_rtx (Pmode);
+      emit_insn (gen_rtx_SET (VOIDmode, modreg, modmem));
+
       tmpreg = gen_reg_rtx (Pmode);
       emit_insn (gen_rtx_SET (VOIDmode, tmpreg, mem));
-      emit_insn (gen_rtx_SET (VOIDmode, module, mem2));
+
+      dest = gen_reg_rtx (Pmode);
       if (TARGET_32BIT)
-       emit_insn (gen_tls_get_addrsi (dest, module, tmpreg));
+       emit_insn (gen_tls_get_addrsi (dest, modreg, tmpreg));
       else
-       emit_insn (gen_tls_get_addrdi (dest, module, tmpreg));
+       emit_insn (gen_tls_get_addrdi (dest, modreg, tmpreg));
       return dest;
     }
   /* Obtain TLS pointer: 32 bit call or 64 bit GPR 13.  */
@@ -22320,12 +22349,6 @@  output_toc (FILE *file, rtx x, int labelno, enum m
   if (TARGET_XCOFF && GET_CODE (base) == SYMBOL_REF
       && SYMBOL_REF_TLS_MODEL (base) != 0)
     {
-      tree decl = SYMBOL_REF_DECL (base);
-      if (bss_initializer_p (decl))
-       fputs ("[UL]", file);
-      else
-       fputs ("[TL]", file);
-
       if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_LOCAL_EXEC)
        fputs ("@le", file);
       else if (SYMBOL_REF_TLS_MODEL (base) == TLS_MODEL_INITIAL_EXEC)
@@ -22340,10 +22363,7 @@  output_toc (FILE *file, rtx x, int labelno, enum m
          RS6000_OUTPUT_BASENAME (file, name);
          fputs ("[TC],", file);
          output_addr_const (file, x);
-         if (TREE_PUBLIC (SYMBOL_REF_DECL (base)))
-           fputs ("[TL]@m", file);
-         else
-           fputs ("[UL]@m", file);
+         fputs ("@m", file);
        }
     }
 #endif
Index: rs6000.md
===================================================================
--- rs6000.md   (revision 194725)
+++ rs6000.md   (working copy)
@@ -10022,6 +10022,7 @@ 
   [(set (reg:P 3)
        (unspec:P [(reg:P 3) (reg:P 4)] UNSPEC_TLSTLS))
    (clobber (reg:P 0))
+   (clobber (reg:P 4))
    (clobber (reg:P 5))
    (clobber (reg:P 11))
    (clobber (reg:CC CR0_REGNO))