Re: PC-relative TLS support

2019-11-11 Thread Alan Modra
On Mon, Nov 11, 2019 at 05:56:47AM -0600, Segher Boessenkool wrote:
> On Wed, Aug 21, 2019 at 09:55:28PM +0930, Alan Modra wrote:
> > This patch removes !TARGET_TLS_MARKERS support.  -mtls-markers (and
> > -mno-tls-markers) disappear as valid options too, because I figure
> > they haven't been used too much except by people testing the
> > compiler.
> 
> Okay.
> 
> > (rs6000_call_template_1): Delete TARGET_TLS_MARKERS test and
> > allow other UNSPECs besides UNSPEC_TLSGD and UNSPEC_TLSLD.
> 
> Why is that?  Should we allow the other code that can happen and keep
> the gcc_unreachable?  Or do we know that no other code can happen here
> ever, and the extra documentation isn't useful?

The code in question is just printing the @tlsgd or @tlsld arg.  I
don't see any point in asserting that no other UNSPEC could ever be
used in a call operand.  Other places dealing with UNSPEC_TLSGD
and UNSPEC_TLSLD don't check, and if another UNSPEC is invented for
some fancy future call insn it's quite unlikely to want to output
anything here.

(I don't think I found such an UNSPEC already extant..)

> > --- a/gcc/config/rs6000/rs6000.md
> > +++ b/gcc/config/rs6000/rs6000.md
> > @@ -9413,7 +9413,7 @@ (define_insn_and_split "*tls_gd"
> > (unspec:P [(match_operand:P 1 "rs6000_tls_symbol_ref" "")
> >(match_operand:P 2 "gpc_reg_operand" "b")]
> >   UNSPEC_TLSGD))]
> > -  "HAVE_AS_TLS && TARGET_TLS_MARKERS"
> > +  "HAVE_AS_TLS && !TARGET_XCOFF"
> 
> Should that be TARGET_ELF instead?

Either should work.  So, yes, probably better with TARGET_ELF.

-- 
Alan Modra
Australia Development Lab, IBM


Re: PC-relative TLS support

2019-11-11 Thread Segher Boessenkool
On Wed, Aug 21, 2019 at 09:55:28PM +0930, Alan Modra wrote:
> This patch removes !TARGET_TLS_MARKERS support.  -mtls-markers (and
> -mno-tls-markers) disappear as valid options too, because I figure
> they haven't been used too much except by people testing the
> compiler.

Okay.

>   (rs6000_call_template_1): Delete TARGET_TLS_MARKERS test and
>   allow other UNSPECs besides UNSPEC_TLSGD and UNSPEC_TLSLD.

Why is that?  Should we allow the other code that can happen and keep
the gcc_unreachable?  Or do we know that no other code can happen here
ever, and the extra documentation isn't useful?

> --- a/gcc/config/rs6000/rs6000.md
> +++ b/gcc/config/rs6000/rs6000.md
> @@ -9413,7 +9413,7 @@ (define_insn_and_split "*tls_gd"
>   (unspec:P [(match_operand:P 1 "rs6000_tls_symbol_ref" "")
>  (match_operand:P 2 "gpc_reg_operand" "b")]
> UNSPEC_TLSGD))]
> -  "HAVE_AS_TLS && TARGET_TLS_MARKERS"
> +  "HAVE_AS_TLS && !TARGET_XCOFF"

Should that be TARGET_ELF instead?

Okay for trunk with those two things looked at.  Thanks!


Segher


Re: PC-relative TLS support

2019-11-11 Thread Segher Boessenkool
Hi Alan,

On Mon, Nov 11, 2019 at 05:46:01PM +1030, Alan Modra wrote:
> On Wed, Aug 21, 2019 at 09:55:28PM +0930, Alan Modra wrote:
> > On Mon, Aug 19, 2019 at 07:45:19AM -0500, Segher Boessenkool wrote:
> > > But if you think we can remove the !TARGET_TLS_MARKERS everywhere it
> > > is relevant at all, now is the time, patches very welcome, it would be
> > > a nice cleanup :-)  Needs testing everywhere of course, but now is
> > > stage 1 :-)
> > 
> > This patch removes !TARGET_TLS_MARKERS support.  -mtls-markers (and
> > -mno-tls-markers) disappear as valid options too, because I figure
> > they haven't been used too much except by people testing the
> > compiler.  Bootstrapped and regression tested powerpc64le-linux and
> > powerpc-ibm-aix7.1.3.0 (on gcc111).  I believe powerpc*-darwin doesn't
> > support TLS.

Excellent :-)

> > Requiring an 8 year old binutils-2.20 shouldn't be that onerous.

Right.  Your binutils should be about the same vintage as your GCC, or
various things will not work anyway.  And building binutils is easy and
cheap anyway, compared to building GCC.

> I should have pinged this before now,

And I shouldn't have dropped it :-)

> and really I think the following
> additional patch makes more sense than any sort of sorry message.
> Mostly people will be running the assembler anyway so will discover
> quickly that their assembler is too old.

Yeah, that's fine.  Almost no one would ever hit that anwyay.

I'll reply to the rest as reply to the original mail.


Segher


Re: PC-relative TLS support

2019-11-10 Thread Alan Modra
On Wed, Aug 21, 2019 at 09:55:28PM +0930, Alan Modra wrote:
> On Mon, Aug 19, 2019 at 07:45:19AM -0500, Segher Boessenkool wrote:
> > But if you think we can remove the !TARGET_TLS_MARKERS everywhere it
> > is relevant at all, now is the time, patches very welcome, it would be
> > a nice cleanup :-)  Needs testing everywhere of course, but now is
> > stage 1 :-)
> 
> This patch removes !TARGET_TLS_MARKERS support.  -mtls-markers (and
> -mno-tls-markers) disappear as valid options too, because I figure
> they haven't been used too much except by people testing the
> compiler.  Bootstrapped and regression tested powerpc64le-linux and
> powerpc-ibm-aix7.1.3.0 (on gcc111).  I believe powerpc*-darwin doesn't
> support TLS.
> 
> Requiring an 8 year old binutils-2.20 shouldn't be that onerous.
> 
> Note that this patch doesn't remove the configure test to set
> HAVE_AS_TLS_MARKERS.  I was wondering whether I ought to hook that
> into a "sorry, your assembler is too old" error?

https://gcc.gnu.org/ml/gcc-patches/2019-08/msg01487.html

I should have pinged this before now, and really I think the following
additional patch makes more sense than any sort of sorry message.
Mostly people will be running the assembler anyway so will discover
quickly that their assembler is too old.

* configure.ac (HAVE_AS_TLS_MARKERS): Delete test.
* configure: Regenerate.
* config.in: Regenerate.

diff --git a/gcc/configure.ac b/gcc/configure.ac
index 5f32fd4d5e4..44d816630e9 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -4811,12 +4811,6 @@ LCF0:
   [AC_DEFINE(HAVE_AS_GNU_ATTRIBUTE, 1,
  [Define if your assembler supports .gnu_attribute.])])
 
-gcc_GAS_CHECK_FEATURE([tls marker support],
-  gcc_cv_as_powerpc_tls_markers, [2,20,0],,
-  [ bl __tls_get_addr(x@tlsgd)],,
-  [AC_DEFINE(HAVE_AS_TLS_MARKERS, 1,
- [Define if your assembler supports arg info for __tls_get_addr.])])
-
 gcc_GAS_CHECK_FEATURE([prologue entry point marker support],
   gcc_cv_as_powerpc_entry_markers, [2,26,0],-a64 --fatal-warnings,
   [ .reloc .,R_PPC64_ENTRY; nop],,

>   * config/rs6000/rs6000-protos.h (rs6000_output_tlsargs): Delete.
>   * config/rs6000/rs6000.c (rs6000_output_tlsargs): Delete.
>   (rs6000_legitimize_tls_address): Remove !TARGET_TLS_MARKERS code.
>   (rs6000_call_template_1): Delete TARGET_TLS_MARKERS test and
>   allow other UNSPECs besides UNSPEC_TLSGD and UNSPEC_TLSLD.
>   (rs6000_indirect_call_template_1): Likewise.
>   (rs6000_pltseq_template): Likewise.
>   (rs6000_opt_vars): Remove "tls-markers" entry.
>   * config/rs6000/rs6000.h (TARGET_TLS_MARKERS): Don't define.
>   (IS_NOMARK_TLSGETADDR): Likewise.
>   * config/rs6000/rs6000.md (tls_gd): Replace TARGET_TLS_MARKERS
>   with !TARGET_XCOFF.
>   (tls_gd_high, tls_gd_low): Likewise.
>   (tls_ld, tls_ld_high, tls_ld_low): Likewise.
>   (pltseq_plt_pcrel): Likewise.
>   (call_value_local32): Remove IS_NOMARK_TLSGETADDR predicate test.
>   (call_value_local64): Likewise.
>   (call_value_indirect_nonlocal_sysv): Remove IS_NOMARK_TLSGETADDR
>   output and length attribute sub-expression.
>   (call_value_nonlocal_sysv),
>   (call_value_nonlocal_sysv_secure),
>   (call_value_local_aix, call_value_nonlocal_aix),
>   (call_value_indirect_aix, call_value_indirect_elfv2),
>   (call_value_indirect_pcrel): Likewise.
>   * config/rs6000/rs6000.opt (mtls-markers): Delete.
>   * doc/install.texi (powerpc-*-*): Require binutils-2.20.

-- 
Alan Modra
Australia Development Lab, IBM


Re: PC-relative TLS support

2019-08-21 Thread Alan Modra
On Mon, Aug 19, 2019 at 07:45:19AM -0500, Segher Boessenkool wrote:
> But if you think we can remove the !TARGET_TLS_MARKERS everywhere it
> is relevant at all, now is the time, patches very welcome, it would be
> a nice cleanup :-)  Needs testing everywhere of course, but now is
> stage 1 :-)

This patch removes !TARGET_TLS_MARKERS support.  -mtls-markers (and
-mno-tls-markers) disappear as valid options too, because I figure
they haven't been used too much except by people testing the
compiler.  Bootstrapped and regression tested powerpc64le-linux and
powerpc-ibm-aix7.1.3.0 (on gcc111).  I believe powerpc*-darwin doesn't
support TLS.

Requiring an 8 year old binutils-2.20 shouldn't be that onerous.

Note that this patch doesn't remove the configure test to set
HAVE_AS_TLS_MARKERS.  I was wondering whether I ought to hook that
into a "sorry, your assembler is too old" error?

* config/rs6000/rs6000-protos.h (rs6000_output_tlsargs): Delete.
* config/rs6000/rs6000.c (rs6000_output_tlsargs): Delete.
(rs6000_legitimize_tls_address): Remove !TARGET_TLS_MARKERS code.
(rs6000_call_template_1): Delete TARGET_TLS_MARKERS test and
allow other UNSPECs besides UNSPEC_TLSGD and UNSPEC_TLSLD.
(rs6000_indirect_call_template_1): Likewise.
(rs6000_pltseq_template): Likewise.
(rs6000_opt_vars): Remove "tls-markers" entry.
* config/rs6000/rs6000.h (TARGET_TLS_MARKERS): Don't define.
(IS_NOMARK_TLSGETADDR): Likewise.
* config/rs6000/rs6000.md (tls_gd): Replace TARGET_TLS_MARKERS
with !TARGET_XCOFF.
(tls_gd_high, tls_gd_low): Likewise.
(tls_ld, tls_ld_high, tls_ld_low): Likewise.
(pltseq_plt_pcrel): Likewise.
(call_value_local32): Remove IS_NOMARK_TLSGETADDR predicate test.
(call_value_local64): Likewise.
(call_value_indirect_nonlocal_sysv): Remove IS_NOMARK_TLSGETADDR
output and length attribute sub-expression.
(call_value_nonlocal_sysv),
(call_value_nonlocal_sysv_secure),
(call_value_local_aix, call_value_nonlocal_aix),
(call_value_indirect_aix, call_value_indirect_elfv2),
(call_value_indirect_pcrel): Likewise.
* config/rs6000/rs6000.opt (mtls-markers): Delete.
* doc/install.texi (powerpc-*-*): Require binutils-2.20.

diff --git a/gcc/config/rs6000/rs6000-protos.h 
b/gcc/config/rs6000/rs6000-protos.h
index 06e40d94b17..88b5b7cec55 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -139,7 +139,6 @@ extern bool valid_sf_si_move (rtx, rtx, machine_mode);
 extern void rs6000_emit_move (rtx, rtx, machine_mode);
 extern bool rs6000_legitimate_offset_address_p (machine_mode, rtx,
bool, bool);
-extern void rs6000_output_tlsargs (rtx *);
 extern rtx rs6000_find_base_term (rtx);
 extern rtx rs6000_return_addr (int, rtx);
 extern void rs6000_output_symbol_ref (FILE*, rtx);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index e792116fb40..5e2b08c3c72 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -8329,41 +8329,6 @@ rs6000_legitimize_tls_address_aix (rtx addr, enum 
tls_model model)
   return dest;
 }
 
-/* Output arg setup instructions for a !TARGET_TLS_MARKERS
-   __tls_get_addr call.  */
-
-void
-rs6000_output_tlsargs (rtx *operands)
-{
-  /* Set up operands for output_asm_insn, without modifying OPERANDS.  */
-  rtx op[3];
-
-  /* The set dest of the call, ie. r3, which is also the first arg reg.  */
-  op[0] = operands[0];
-  /* The TLS symbol from global_tlsarg stashed as CALL operand 2.  */
-  op[1] = XVECEXP (operands[2], 0, 0);
-  if (XINT (operands[2], 1) == UNSPEC_TLSGD)
-{
-  /* The GOT register.  */
-  op[2] = XVECEXP (operands[2], 0, 1);
-  if (TARGET_CMODEL != CMODEL_SMALL)
-   output_asm_insn ("addis %0,%2,%1@got@tlsgd@ha\n\t"
-"addi %0,%0,%1@got@tlsgd@l", op);
-  else
-   output_asm_insn ("addi %0,%2,%1@got@tlsgd", op);
-}
-  else if (XINT (operands[2], 1) == UNSPEC_TLSLD)
-{
-  if (TARGET_CMODEL != CMODEL_SMALL)
-   output_asm_insn ("addis %0,%1,%&@got@tlsld@ha\n\t"
-"addi %0,%0,%&@got@tlsld@l", op);
-  else
-   output_asm_insn ("addi %0,%1,%&@got@tlsld", op);
-}
-  else
-gcc_unreachable ();
-}
-
 /* Passes the tls arg value for global dynamic and local dynamic
emit_library_call_value in rs6000_legitimize_tls_address to
rs6000_call_aix and rs6000_call_sysv.  This is used to emit the
@@ -8465,16 +8430,10 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model 
model)
  rtx arg = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, addr, got),
UNSPEC_TLSGD);
  tga = rs6000_tls_get_addr ();
+ rtx argreg = gen_rtx_REG (Pmode, 3);
+ emit_insn (gen_rtx_SET (argreg, arg));
  global_tlsarg = arg;
- if (

Re: PC-relative TLS support

2019-08-19 Thread Segher Boessenkool
On Fri, Aug 16, 2019 at 11:29:30AM +0930, Alan Modra wrote:
> On Thu, Aug 15, 2019 at 01:24:07PM -0500, Segher Boessenkool wrote:
> > On Thu, Aug 15, 2019 at 01:35:10PM +0930, Alan Modra wrote:
> > > Supporting TLS for -mpcrel turns out to be relatively simple, in part
> > > due to deciding that !TARGET_TLS_MARKERS with -mpcrel is silly.  No
> > > assembler that I know of supporting prefix insns lacks TLS marker
> > > support.
> > 
> > Will this stay that way?  (Or do we not care, not now anyway?)
> 
> I'd say we leave that problem to someone who wants pcrel without tls
> markers.  It's not hard to do, just extend rs6000_output_tlsargs and
> adjust IS_NOMARK_TLSGETADDR length attribute expressions.

Okay, so the latter option :-)

> > > Also, at some point powerpc gcc ought to remove
> > > !TARGET_TLS_MARKERS generally and simplify all the occurrences of
> > > IS_NOMARK_TLSGETADDR in rs6000.md rather than complicating them.
> > 
> > The last time this came up (a year ago) the conclusion was that we first
> > would have to remove AIX support.
> 
> Hmm, I wonder has that changed?  A quick look at the source says the
> AIX TLS support uses completely different patterns and shouldn't care.

https://gcc.gnu.org/ml/gcc-patches/2018-11/msg02259.html

But if you think we can remove the !TARGET_TLS_MARKERS everywhere it
is relevant at all, now is the time, patches very welcome, it would be
a nice cleanup :-)  Needs testing everywhere of course, but now is
stage 1 :-)


Segher


Re: PC-relative TLS support

2019-08-15 Thread Alan Modra
On Thu, Aug 15, 2019 at 01:24:07PM -0500, Segher Boessenkool wrote:
> Hi!
> 
> On Thu, Aug 15, 2019 at 01:35:10PM +0930, Alan Modra wrote:
> > Supporting TLS for -mpcrel turns out to be relatively simple, in part
> > due to deciding that !TARGET_TLS_MARKERS with -mpcrel is silly.  No
> > assembler that I know of supporting prefix insns lacks TLS marker
> > support.
> 
> Will this stay that way?  (Or do we not care, not now anyway?)

I'd say we leave that problem to someone who wants pcrel without tls
markers.  It's not hard to do, just extend rs6000_output_tlsargs and
adjust IS_NOMARK_TLSGETADDR length attribute expressions.

> > Also, at some point powerpc gcc ought to remove
> > !TARGET_TLS_MARKERS generally and simplify all the occurrences of
> > IS_NOMARK_TLSGETADDR in rs6000.md rather than complicating them.
> 
> The last time this came up (a year ago) the conclusion was that we first
> would have to remove AIX support.

Hmm, I wonder has that changed?  A quick look at the source says the
AIX TLS support uses completely different patterns and shouldn't care.

> (Changelog has whitespace damage, I guess that is just from how you
> mailed this?  Please fix when applying it).

Fixed.  (It wasn't the mailer..)

-- 
Alan Modra
Australia Development Lab, IBM


Re: PC-relative TLS support

2019-08-15 Thread Segher Boessenkool
Hi!

On Thu, Aug 15, 2019 at 01:35:10PM +0930, Alan Modra wrote:
> Supporting TLS for -mpcrel turns out to be relatively simple, in part
> due to deciding that !TARGET_TLS_MARKERS with -mpcrel is silly.  No
> assembler that I know of supporting prefix insns lacks TLS marker
> support.

Will this stay that way?  (Or do we not care, not now anyway?)

> Also, at some point powerpc gcc ought to remove
> !TARGET_TLS_MARKERS generally and simplify all the occurrences of
> IS_NOMARK_TLSGETADDR in rs6000.md rather than complicating them.

The last time this came up (a year ago) the conclusion was that we first
would have to remove AIX support.

> * config/rs6000/predicates.md (unspec_tls): Allow const0_rtx for got
>   element of unspec vec.
> * config/rs6000/rs6000.c (rs6000_option_override_internal): Disable
>   -mpcrel if -mno-tls-markers.
>   (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.

(Changelog has whitespace damage, I guess that is just from how you
mailed this?  Please fix when applying it).

The patch is fine when its prerequisites are in.  Thanks,


Segher


PC-relative TLS support

2019-08-14 Thread Alan Modra
Supporting TLS for -mpcrel turns out to be relatively simple, in part
due to deciding that !TARGET_TLS_MARKERS with -mpcrel is silly.  No
assembler that I know of supporting prefix insns lacks TLS marker
support.  Also, at some point powerpc gcc ought to remove
!TARGET_TLS_MARKERS generally and simplify all the occurrences of
IS_NOMARK_TLSGETADDR in rs6000.md rather than complicating them.

Mike, the rs6000_option_override_internal hunk is new compared to
the patch you had from me.

* config/rs6000/predicates.md (unspec_tls): Allow const0_rtx for got
element of unspec vec.
* config/rs6000/rs6000.c (rs6000_option_override_internal): Disable
-mpcrel if -mno-tls-markers.
(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.

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index fba87946ec7..4ea588e1027 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -995,9 +995,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 6aca0ce5bf3..c04206ab139 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -4216,6 +4216,16 @@ rs6000_option_override_internal (bool global_init_p)
| OPTION_MASK_PCREL_OPT);
 }
 
+  /* -mpcrel requires tls marker support.  */
+  if (TARGET_PCREL && !TARGET_TLS_MARKERS)
+{
+  if ((rs6000_isa_flags_explicit & OPTION_MASK_PCREL) != 0)
+   error ("%qs requires %qs", "-mpcrel", "-mtls-markers");
+
+  rs6000_isa_flags &= ~(OPTION_MASK_PCREL
+   | OPTION_MASK_PCREL_OPT);
+}
+
   /* Check -mfuture debug switches.  */
   if (!TARGET_PCREL && TARGET_PCREL_OPT)
 {
@@ -8613,7 +8623,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;
 
@@ -8660,7 +8671,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
{
@@ -8735,7 +8748,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);
@@ -8776,7 +8789,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 0e7d90e5357..6e32d8fdff1 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -88,6 +88,7 @@
UNSPEC_TLSTPRELLO
UNSPEC_TLSGOTTPREL
UNSPEC_TLSTLS
+   UNSPEC_TLSTLS_PCREL
UNSPEC_FIX_TRUNC_TF ; fadd, rounding towards zero
UNSPEC_STFIWX
UNSPEC_POPCNTB
@@ -9514,6 +9515,15 @@
 
 ;; TLS support.
 
+(define_insn "*tls_gd_pcrel"
+  [(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_TLS_MARKERS"
+  "la %0,%1@got@tlsgd@pcrel"
+  [(set_attr "prefixed" "yes")])
+
 (define_insn_and_s