Commit 2965eaa8 by Alan Modra Committed by Alan Modra

[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
parent ed2181fc
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.
......@@ -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;
})
......
......@@ -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);
......
......@@ -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")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment