summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-11-12 11:41:46 +1030
committerAlan Modra <amodra@gcc.gnu.org>2019-11-12 11:41:46 +1030
commit2965eaa89d843a1c260291376020d71127c05741 (patch)
tree3b8930ad957500ac4c6b16dd73b76b30f93a3643
parented2181fc2a3ff3a0f65110c906093d5ce0d8e048 (diff)
[RS6000] PC-relative TLS support
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
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/rs6000/predicates.md4
-rw-r--r--gcc/config/rs6000/rs6000.c18
-rw-r--r--gcc/config/rs6000/rs6000.md47
4 files changed, 72 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4fdb911ab8b..4a38e5459b4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,16 @@
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.
* config/rs6000/rs6000.h (TARGET_TLS_MARKERS): Don't define.
(IS_NOMARK_TLSGETADDR): Likewise.
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index b5c510f99f2..f4ecc4193ef 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -986,9 +986,9 @@
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;
})
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 892ee94032f..32101b77ea3 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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);
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 0fc0f952611..cbfe38bef94 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -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
@@ -9495,6 +9496,15 @@
;; 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" "")
@@ -9535,6 +9545,14 @@
"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")]
@@ -9578,7 +9596,11 @@
(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")
@@ -9642,7 +9664,11 @@
(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")
@@ -9660,6 +9686,15 @@
"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.
@@ -9703,6 +9738,14 @@
"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")