[RS6000] PC-relative TLS support
authorAlan Modra <amodra@gmail.com>
Tue, 12 Nov 2019 01:11:46 +0000 (11:41 +1030)
committerAlan Modra <amodra@gcc.gnu.org>
Tue, 12 Nov 2019 01:11:46 +0000 (11:41 +1030)
Supporting TLS for -mpcrel turns out to be relatively simple.  The
existing TLSGD and TLSLD unspecs happily can have their GOT pointer
reg element replaced with zero, refelecting the fact that optimisation
of calls to __tls_get_addr when pc-rel won't use the GOT pointer.
Some other insns also can be reused, and just a few added.

* config/rs6000/predicates.md (unspec_tls): Allow const0_rtx for got
element of unspec vec.
* config/rs6000/rs6000.c (rs6000_legitimize_tls_address): Support
PC-relative TLS.
* config/rs6000/rs6000.md (UNSPEC_TLSTLS_PCREL): New unspec.
(tls_gd_pcrel, tls_ld_pcrel): New insns.
(tls_dtprel, tls_tprel): Set attr prefixed when tls_size is not 16.
(tls_got_tprel_pcrel, tls_tls_pcrel): New insns.

From-SVN: r278076

gcc/ChangeLog
gcc/config/rs6000/predicates.md
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index 4fdb911ab8bf0dc9232e94e8854c317e96cd8dc7..4a38e5459b482705af4767ab76a0f69a9aa9d489 100644 (file)
@@ -1,3 +1,14 @@
+2019-11-12  Alan Modra  <amodra@gmail.com>
+
+       * config/rs6000/predicates.md (unspec_tls): Allow const0_rtx for got
+       element of unspec vec.
+       * config/rs6000/rs6000.c (rs6000_legitimize_tls_address): Support
+       PC-relative TLS.
+       * config/rs6000/rs6000.md (UNSPEC_TLSTLS_PCREL): New unspec.
+       (tls_gd_pcrel, tls_ld_pcrel): New insns.
+       (tls_dtprel, tls_tprel): Set attr prefixed when tls_size is not 16.
+       (tls_got_tprel_pcrel, tls_tls_pcrel): New insns.
+
 2019-11-12  Alan Modra  <amodra@gmail.com>
 
        * config/rs6000/rs6000.opt (mtls-markers): Delete.
index b5c510f99f211961a83ea3a6d96667c57f0664ca..f4ecc4193ef345339cede83b500c6d90766fbffd 100644 (file)
   if (CONST_INT_P (op))
     return 1;
   if (XINT (op, 1) == UNSPEC_TLSGD)
-    return REG_P (XVECEXP (op, 0, 1));
+    return REG_P (XVECEXP (op, 0, 1)) || XVECEXP (op, 0, 1) == const0_rtx;
   if (XINT (op, 1) == UNSPEC_TLSLD)
-    return REG_P (XVECEXP (op, 0, 0));
+    return REG_P (XVECEXP (op, 0, 0)) || XVECEXP (op, 0, 0) == const0_rtx;
   return 0;
 })
 
index 892ee94032f56d1d036fb4721c46b71e2c4e3326..32101b77ea3777f95bc9e1fbf42b0131931432d2 100644 (file)
@@ -8518,7 +8518,8 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
     return rs6000_legitimize_tls_address_aix (addr, model);
 
   dest = gen_reg_rtx (Pmode);
-  if (model == TLS_MODEL_LOCAL_EXEC && rs6000_tls_size == 16)
+  if (model == TLS_MODEL_LOCAL_EXEC
+      && (rs6000_tls_size == 16 || rs6000_pcrel_p (cfun)))
     {
       rtx tlsreg;
 
@@ -8565,7 +8566,9 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
         them in the .got section.  So use a pointer to the .got section,
         not one to secondary TOC sections used by 64-bit -mminimal-toc,
         or to secondary GOT sections used by 32-bit -fPIC.  */
-      if (TARGET_64BIT)
+      if (rs6000_pcrel_p (cfun))
+       got = const0_rtx;
+      else if (TARGET_64BIT)
        got = gen_rtx_REG (Pmode, 2);
       else
        {
@@ -8628,7 +8631,7 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
          rtx uns = gen_rtx_UNSPEC (Pmode, vec, UNSPEC_TLS_GET_ADDR);
          set_unique_reg_note (get_last_insn (), REG_EQUAL, uns);
 
-         if (rs6000_tls_size == 16)
+         if (rs6000_tls_size == 16 || rs6000_pcrel_p (cfun))
            {
              if (TARGET_64BIT)
                insn = gen_tls_dtprel_64 (dest, tmp1, addr);
@@ -8669,7 +8672,14 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
          else
            insn = gen_tls_got_tprel_32 (tmp2, got, addr);
          emit_insn (insn);
-         if (TARGET_64BIT)
+         if (rs6000_pcrel_p (cfun))
+           {
+             if (TARGET_64BIT)
+               insn = gen_tls_tls_pcrel_64 (dest, tmp2, addr);
+             else
+               insn = gen_tls_tls_pcrel_32 (dest, tmp2, addr);
+           }
+         else if (TARGET_64BIT)
            insn = gen_tls_tls_64 (dest, tmp2, addr);
          else
            insn = gen_tls_tls_32 (dest, tmp2, addr);
index 0fc0f952611cdb22ddeb6de1e79df195a5226d84..cbfe38bef9477151222878744ef808ddceeba0bd 100644 (file)
@@ -86,6 +86,7 @@
    UNSPEC_TLSTPRELLO
    UNSPEC_TLSGOTTPREL
    UNSPEC_TLSTLS
+   UNSPEC_TLSTLS_PCREL
    UNSPEC_FIX_TRUNC_TF         ; fadd, rounding towards zero
    UNSPEC_STFIWX
    UNSPEC_POPCNTB
 \f
 ;; TLS support.
 
+(define_insn "*tls_gd_pcrel<bits>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+       (unspec:P [(match_operand:P 1 "rs6000_tls_symbol_ref" "")
+                  (const_int 0)]
+                 UNSPEC_TLSGD))]
+  "HAVE_AS_TLS && TARGET_ELF"
+  "la %0,%1@got@tlsgd@pcrel"
+  [(set_attr "prefixed" "yes")])
+
 (define_insn_and_split "*tls_gd<bits>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=b")
        (unspec:P [(match_operand:P 1 "rs6000_tls_symbol_ref" "")
   "HAVE_AS_TLS && TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL"
   "addi %0,%1,%2@got@tlsgd@l")
 
+(define_insn "*tls_ld_pcrel<bits>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+       (unspec:P [(const_int 0)]
+                 UNSPEC_TLSLD))]
+  "HAVE_AS_TLS && TARGET_ELF"
+  "la %0,%&@got@tlsld@pcrel"
+  [(set_attr "prefixed" "yes")])
+
 (define_insn_and_split "*tls_ld<bits>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=b")
        (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")]
                   (match_operand:P 2 "rs6000_tls_symbol_ref" "")]
                  UNSPEC_TLSDTPREL))]
   "HAVE_AS_TLS"
-  "addi %0,%1,%2@dtprel")
+  "addi %0,%1,%2@dtprel"
+  [(set (attr "prefixed")
+       (if_then_else (match_test "rs6000_tls_size == 16")
+                     (const_string "no")
+                     (const_string "yes")))])
 
 (define_insn "tls_dtprel_ha_<bits>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
                   (match_operand:P 2 "rs6000_tls_symbol_ref" "")]
                  UNSPEC_TLSTPREL))]
   "HAVE_AS_TLS"
-  "addi %0,%1,%2@tprel")
+  "addi %0,%1,%2@tprel"
+  [(set (attr "prefixed")
+       (if_then_else (match_test "rs6000_tls_size == 16")
+                     (const_string "no")
+                     (const_string "yes")))])
 
 (define_insn "tls_tprel_ha_<bits>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
   "HAVE_AS_TLS"
   "addi %0,%1,%2@tprel@l")
 
+(define_insn "*tls_got_tprel_pcrel_<bits>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=b")
+       (unspec:P [(const_int 0)
+                  (match_operand:P 1 "rs6000_tls_symbol_ref" "")]
+                 UNSPEC_TLSGOTTPREL))]
+  "HAVE_AS_TLS"
+  "<ptrload> %0,%1@got@tprel@pcrel"
+  [(set_attr "prefixed" "yes")])
+
 ;; "b" output constraint here and on tls_tls input to support linker tls
 ;; optimization.  The linker may edit the instructions emitted by a
 ;; tls_got_tprel/tls_tls pair to addis,addi.
   "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL"
   "<ptrload> %0,%2@got@tprel@l(%1)")
 
+(define_insn "tls_tls_pcrel_<bits>"
+  [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+       (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")
+                  (match_operand:P 2 "rs6000_tls_symbol_ref" "")]
+                 UNSPEC_TLSTLS_PCREL))]
+  "TARGET_ELF && HAVE_AS_TLS"
+  "add %0,%1,%2@tls@pcrel")
+
 (define_insn "tls_tls_<bits>"
   [(set (match_operand:P 0 "gpc_reg_operand" "=r")
        (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b")