Re: [PATCH 5/6] [RS6000] Use standard call patterns for __tls_get_addr calls

2018-11-28 Thread Alan Modra
On Wed, Nov 28, 2018 at 07:32:50AM -0600, Segher Boessenkool wrote:
> On Wed, Nov 28, 2018 at 11:37:42AM +1030, Alan Modra wrote:
> > On Tue, Nov 27, 2018 at 10:29:29AM -0600, Segher Boessenkool wrote:
> > > Looks fine.  Thank you for the cleanup!  Okay for trunk, but please do the
> > > extra testing.
> > 
> > Huh, local testing of -mno-tls-markers showed a lack of a
> > TARGET_TLS_MARKERS check in rs6000_call_template_1.  Likely this would
> > blow up on AIX.  I'll test with the following delta.
> 
> Sounds good.

For the record, this is the patch I committed.  Besides the delta
posted previously, I managed to combine the tls_gdld_aix and
tls_gdld_sysv insns into a single insn, tls_gdld_nomark.

* config/rs6000/predicates.md (unspec_tls): New.
* config/rs6000/rs6000-protos.h (rs6000_call_template),
(rs6000_sibcall_template): Update prototype.
(rs6000_longcall_ref): Delete.
(rs6000_call_sysv): Declare.
* config/rs6000/rs6000.c (edit_tls_call_insn): New function.
(global_tlsarg): New variable.
(rs6000_legitimize_tls_address): Rewrite __tls_get_addr call
handling.
(print_operand): Extract UNSPEC_TLSGD address operand.
(rs6000_call_template, rs6000_sibcall_template): Remove arg
parameter, extract from second call operand instead.
(rs6000_longcall_ref): Make static, localize vars.
(rs6000_call_aix): Rename parameter to reflect new usage.  Take
tlsarg from global_tlsarg.  Don't create unused rtl or nop insns.
(rs6000_sibcall_aix): Rename parameter to reflect new usage.  Take
tlsarg from global_tlsarg.
(rs6000_call_sysv): New function.
* config/rs6000/rs6000.md: Adjust rs6000_call_template and
rs6000_sibcall_template throughout.
(tls_gd_aix, tls_gd_sysv, tls_gd_call_aix, tls_gd_call_sysv): Delete.
(tls_ld_aix, tls_ld_sysv, tls_ld_call_aix, tls_ld_call_sysv): Delete.
(tls_gdld_nomark): New insn.
(tls_gd): Swap operand order.  Simplify mode selection.
(tls_gd_high, tls_gd_low): Swap operand order.
(tls_ld): Remove const_int 0 vector element from UNSPEC_TLSLD.
Simplify mode selection.
(tls_ld_high, tls_ld_low): Similarly adjust UNSPEC_TLSLD.
(call, call_value): Don't assert for second call operand.
Use rs6000_call_sysv.

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 5589ea19519..2c297fc45e8 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -997,6 +997,13 @@ (define_predicate "rs6000_tls_symbol_ref"
   (and (match_code "symbol_ref")
(match_test "RS6000_SYMBOL_REF_TLS_P (op)")))
 
+;; Return 1 for the UNSPEC used in TLS call operands
+(define_predicate "unspec_tls"
+  (match_code "unspec")
+{
+  return XINT (op, 1) == UNSPEC_TLSGD || XINT (op, 1) == UNSPEC_TLSLD;
+})
+
 ;; Return 1 if the operand, used inside a MEM, is a valid first argument
 ;; to CALL.  This is a SYMBOL_REF, a pseudo-register, LR or CTR.
 (define_predicate "call_operand"
diff --git a/gcc/config/rs6000/rs6000-protos.h 
b/gcc/config/rs6000/rs6000-protos.h
index f1a294a3617..dd930bb2da6 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -105,8 +105,8 @@ extern int ccr_bit (rtx, int);
 extern void rs6000_output_function_entry (FILE *, const char *);
 extern void print_operand (FILE *, rtx, int);
 extern void print_operand_address (FILE *, rtx);
-extern const char *rs6000_call_template (rtx *, unsigned int, const char *);
-extern const char *rs6000_sibcall_template (rtx *, unsigned int, const char *);
+extern const char *rs6000_call_template (rtx *, unsigned int);
+extern const char *rs6000_sibcall_template (rtx *, unsigned int);
 extern const char *rs6000_indirect_call_template (rtx *, unsigned int);
 extern const char *rs6000_indirect_sibcall_template (rtx *, unsigned int);
 extern enum rtx_code rs6000_reverse_condition (machine_mode,
@@ -130,7 +130,6 @@ extern void rs6000_expand_atomic_op (enum rtx_code, rtx, 
rtx, rtx, rtx, rtx);
 extern void rs6000_emit_swdiv (rtx, rtx, rtx, bool);
 extern void rs6000_emit_swsqrt (rtx, rtx, bool);
 extern void output_toc (FILE *, rtx, int, machine_mode);
-extern rtx rs6000_longcall_ref (rtx);
 extern void rs6000_fatal_bad_address (rtx);
 extern rtx create_TOC_reference (rtx, rtx);
 extern void rs6000_split_multireg_move (rtx, rtx);
@@ -198,6 +197,7 @@ extern void rs6000_split_stack_space_check (rtx, rtx);
 extern void rs6000_emit_eh_reg_restore (rtx, rtx);
 extern void rs6000_call_aix (rtx, rtx, rtx, rtx);
 extern void rs6000_sibcall_aix (rtx, rtx, rtx, rtx);
+extern void rs6000_call_sysv (rtx, rtx, rtx, rtx);
 extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
 extern void get_ppc476_thunk_name (char name[32]);
 extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins);
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 

Re: [PATCH 5/6] [RS6000] Use standard call patterns for __tls_get_addr calls

2018-11-28 Thread Alan Modra
On Wed, Nov 28, 2018 at 07:32:50AM -0600, Segher Boessenkool wrote:
> On Wed, Nov 28, 2018 at 11:37:42AM +1030, Alan Modra wrote:
> > On Tue, Nov 27, 2018 at 10:29:29AM -0600, Segher Boessenkool wrote:
> > > Do you think we should to deprecate -mtls-markers in GCC 9?
> > 
> > Support for the TLS marker relocs was added to binutils in 2009 (git
> > commit 727fc41e077), so yes, the option is not likely to be useful
> > nowadays.
> 
> Well, but do we gain anything if it is eventually deleted?  Simpler code?

Not much.  Unfortunately we still need to keep TARGET_TLS_MARKERS (or
replace throughout with !HAVE_AS_TLS_MARKERS) for AIX.  Deprecate AIX
perhaps?  :-)

-- 
Alan Modra
Australia Development Lab, IBM


Re: [PATCH 5/6] [RS6000] Use standard call patterns for __tls_get_addr calls

2018-11-28 Thread Segher Boessenkool
On Wed, Nov 28, 2018 at 11:37:42AM +1030, Alan Modra wrote:
> On Tue, Nov 27, 2018 at 10:29:29AM -0600, Segher Boessenkool wrote:
> > Hi!
> 
> Thanks for the review!
> 
> > > +(define_insn "*tls_gdld_aix"
> > > +  [(match_parallel 3 ""
> > 
> > A match_parallel without predicate...  Does this work?!
> 
> Yes.  In fact, rs6000/predicates.md any_parallel_operand is useless
> except as documentation.  The only thing it checks is that its operand
> is a parallel, but that has already been checked.

Right.  I grepped if there were other parallels without predicate, not
finding any, but I did not notice that half of the predicates used are
any_parallel_operand.

> >  Does this not
> > accidentally pick up the wrong things?
> 
> No.  The purpose of the predicate is to match anything beyond the
> vector of expressions.  So tls_gdld_aix* matches insns that look like:
> 
>  (set (match_operand:P 0 "gpc_reg_operand" "=b")
> (call (mem:SI (match_operand:P 1))
>   (match_operand:P 2 "unspec_tls")))
>  (match_dup 2)
>  ...
> 
> This is sufficiently different from other calls, by virtue of the
> "(match_dup 2)".

And the "unspec_tls".  Right.

> Incidentally, I think tls_gdld_aix and tls_gdld_sysv could be merged
> at the expense of complicating the length attribute expression.
> 
> > Do you think we should to deprecate -mtls-markers in GCC 9?
> 
> Support for the TLS marker relocs was added to binutils in 2009 (git
> commit 727fc41e077), so yes, the option is not likely to be useful
> nowadays.

Well, but do we gain anything if it is eventually deleted?  Simpler code?

> > Please test with -mtls-markers, too, if you can, and test on AIX.
> 
> Presumably you mean -mno-tls-markers.  -mtls-markers is the default.

Yeah, the ! case.

> > Looks fine.  Thank you for the cleanup!  Okay for trunk, but please do the
> > extra testing.
> 
> Huh, local testing of -mno-tls-markers showed a lack of a
> TARGET_TLS_MARKERS check in rs6000_call_template_1.  Likely this would
> blow up on AIX.  I'll test with the following delta.

Sounds good.


Segher


Re: [PATCH 5/6] [RS6000] Use standard call patterns for __tls_get_addr calls

2018-11-27 Thread Alan Modra
On Tue, Nov 27, 2018 at 10:29:29AM -0600, Segher Boessenkool wrote:
> Hi!

Thanks for the review!

> > +(define_insn "*tls_gdld_aix"
> > +  [(match_parallel 3 ""
> 
> A match_parallel without predicate...  Does this work?!

Yes.  In fact, rs6000/predicates.md any_parallel_operand is useless
except as documentation.  The only thing it checks is that its operand
is a parallel, but that has already been checked.

>  Does this not
> accidentally pick up the wrong things?

No.  The purpose of the predicate is to match anything beyond the
vector of expressions.  So tls_gdld_aix* matches insns that look like:

 (set (match_operand:P 0 "gpc_reg_operand" "=b")
  (call (mem:SI (match_operand:P 1))
(match_operand:P 2 "unspec_tls")))
 (match_dup 2)
 ...

This is sufficiently different from other calls, by virtue of the
"(match_dup 2)".

Incidentally, I think tls_gdld_aix and tls_gdld_sysv could be merged
at the expense of complicating the length attribute expression.

> Do you think we should to deprecate -mtls-markers in GCC 9?

Support for the TLS marker relocs was added to binutils in 2009 (git
commit 727fc41e077), so yes, the option is not likely to be useful
nowadays.

> Please test with -mtls-markers, too, if you can, and test on AIX.

Presumably you mean -mno-tls-markers.  -mtls-markers is the default.

> Looks fine.  Thank you for the cleanup!  Okay for trunk, but please do the
> extra testing.

Huh, local testing of -mno-tls-markers showed a lack of a
TARGET_TLS_MARKERS check in rs6000_call_template_1.  Likely this would
blow up on AIX.  I'll test with the following delta.

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 56ca117a0a0..5f4fcee3b33 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -8622,7 +8622,7 @@ edit_tls_call_insn (rtx arg)
 }
 
 /* Passes the tls arg value for global dynamic and local dynamic
-   emit_library_call_value in rs6000_legitimize_Tls_address to
+   emit_library_call_value in rs6000_legitimize_tls_address to
rs6000_call_aix and rs6000_call_sysv.  This is used to emit the
marker relocs put on __tls_get_addr calls.  */
 static rtx global_tlsarg;
@@ -21429,7 +21429,7 @@ rs6000_call_template_1 (rtx *operands, unsigned int 
funop, bool sibcall)
 
   char arg[12];
   arg[0] = 0;
-  if (GET_CODE (operands[funop + 1]) == UNSPEC)
+  if (TARGET_TLS_MARKERS && GET_CODE (operands[funop + 1]) == UNSPEC)
 {
   if (XINT (operands[funop + 1], 1) == UNSPEC_TLSGD)
sprintf (arg, "(%%%u@tlsgd)", funop + 1);

-- 
Alan Modra
Australia Development Lab, IBM


Re: [PATCH 5/6] [RS6000] Use standard call patterns for __tls_get_addr calls

2018-11-27 Thread Segher Boessenkool
Hi!

On Tue, Nov 13, 2018 at 11:22:43PM +1030, Alan Modra wrote:
> Version 2.
> 
> The current code handling __tls_get_addr calls for powerpc*-linux
> generates a call then overwrites the call insn with a special
> tls_{gd,ld}_{aix,sysv} pattern.  It's done that way to support
> !TARGET_TLS_MARKERS, where the arg setup insns need to be emitted
> immediately before the branch and link.  When TARGET_TLS_MARKERS, the
> arg setup insns are split from the actual call, but we then have a
> non-standard call pattern that needs to be carried through to output.
> 
> This patch changes that scheme, to instead use the standard call
> patterns for __tls_get_addr calls, except for the now rare
> !TARGET_TLS_MARKERS case.  Doing it this way should be better for
> maintenance as the !TARGET_TLS_MARKERS code can eventually disappear.
> It also makes it possible to support longcalls (and in following
> patches, inline plt calls) for __tls_get_addr without introducing yet
> more special call patterns.
> 
> __tls_get_addr calls do however need to be different to standard
> calls, because when TARGET_TLS_MARKERS the calls are decorated with an
> argument specifier, eg. "bl __tls_get_addr(thread_var@tlsgd)" that
> causes a reloc to be emitted by the assembler tying the call to its
> arg setup insns.  I chose to smuggle the arg in the currently unused
> stack size rtl.
> 
> I've also introduced rs6000_call_sysv to generate rtl for sysv calls,
> as rs6000_call_aix does for aix and elfv2 calls.  This allows
> rs6000_longcall_ref to be local to rs6000.c since the calls in the
> expanders never did anything for darwin.
> 
>   * config/rs6000/predicates.md (unspec_tls): New.
>   * config/rs6000/rs6000-protos.h (rs6000_call_template),
>   (rs6000_sibcall_template): Update prototype.
>   (rs6000_longcall_ref): Delete.
>   (rs6000_call_sysv): Declare.
>   * config/rs6000/rs6000.c (edit_tls_call_insn): New function.
>   (global_tlsarg): New variable.
>   (rs6000_legitimize_tls_address): Rewrite __tls_get_addr call
>   handling.
>   (print_operand): Extract UNSPEC_TLSGD address operand.
>   (rs6000_call_template, rs6000_sibcall_template): Remove arg
>   parameter, extract from second call operand instead.
>   (rs6000_longcall_ref): Make static, localize vars.
>   (rs6000_call_aix): Rename parameter to reflect new usage.  Take
>   tlsarg from global_tlsarg.  Don't create unused rtl or nop insns.
>   (rs6000_sibcall_aix): Rename parameter to reflect new usage.  Take
>   tlsarg from global_tlsarg.
>   (rs6000_call_sysv): New function.
>   * config/rs6000/rs6000.md: Adjust rs6000_call_template and
>   rs6000_sibcall_template throughout.
>   (tls_gd_aix, tls_gd_sysv, tls_gd_call_aix, tls_gd_call_sysv): Delete.
>   (tls_ld_aix, tls_ld_sysv, tls_ld_call_aix, tls_ld_call_sysv): Delete.
>   (tls_gdld_aix, tls_gdld_sysv): New insns, replacing above.
>   (tls_gd): Swap operand order.  Simplify mode selection.
>   (tls_gd_high, tls_gd_low): Swap operand order.
>   (tls_ld): Remove const_int 0 vector element from UNSPEC_TLSLD.
>   Simplify mode selection.
>   (tls_ld_high, tls_ld_low): Similarly adjust UNSPEC_TLSLD.
>   (call, call_value): Don't assert for second call operand.
>   Use rs6000_call_sysv.


> +/* 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
> +   marker relocs put on __tls_get_addr calls.  */
> +static rtx global_tlsarg;

Typo (s/_Tls/_tls/).

> +(define_insn "*tls_gdld_aix"
> +  [(match_parallel 3 ""

A match_parallel without predicate...  Does this work?!  Does this not
accidentally pick up the wrong things?

Do you think we should to deprecate -mtls-markers in GCC 9?

Please test with -mtls-markers, too, if you can, and test on AIX.

Looks fine.  Thank you for the cleanup!  Okay for trunk, but please do the
extra testing.


Segher


[PATCH 5/6] [RS6000] Use standard call patterns for __tls_get_addr calls

2018-11-13 Thread Alan Modra
Version 2.

The current code handling __tls_get_addr calls for powerpc*-linux
generates a call then overwrites the call insn with a special
tls_{gd,ld}_{aix,sysv} pattern.  It's done that way to support
!TARGET_TLS_MARKERS, where the arg setup insns need to be emitted
immediately before the branch and link.  When TARGET_TLS_MARKERS, the
arg setup insns are split from the actual call, but we then have a
non-standard call pattern that needs to be carried through to output.

This patch changes that scheme, to instead use the standard call
patterns for __tls_get_addr calls, except for the now rare
!TARGET_TLS_MARKERS case.  Doing it this way should be better for
maintenance as the !TARGET_TLS_MARKERS code can eventually disappear.
It also makes it possible to support longcalls (and in following
patches, inline plt calls) for __tls_get_addr without introducing yet
more special call patterns.

__tls_get_addr calls do however need to be different to standard
calls, because when TARGET_TLS_MARKERS the calls are decorated with an
argument specifier, eg. "bl __tls_get_addr(thread_var@tlsgd)" that
causes a reloc to be emitted by the assembler tying the call to its
arg setup insns.  I chose to smuggle the arg in the currently unused
stack size rtl.

I've also introduced rs6000_call_sysv to generate rtl for sysv calls,
as rs6000_call_aix does for aix and elfv2 calls.  This allows
rs6000_longcall_ref to be local to rs6000.c since the calls in the
expanders never did anything for darwin.

* config/rs6000/predicates.md (unspec_tls): New.
* config/rs6000/rs6000-protos.h (rs6000_call_template),
(rs6000_sibcall_template): Update prototype.
(rs6000_longcall_ref): Delete.
(rs6000_call_sysv): Declare.
* config/rs6000/rs6000.c (edit_tls_call_insn): New function.
(global_tlsarg): New variable.
(rs6000_legitimize_tls_address): Rewrite __tls_get_addr call
handling.
(print_operand): Extract UNSPEC_TLSGD address operand.
(rs6000_call_template, rs6000_sibcall_template): Remove arg
parameter, extract from second call operand instead.
(rs6000_longcall_ref): Make static, localize vars.
(rs6000_call_aix): Rename parameter to reflect new usage.  Take
tlsarg from global_tlsarg.  Don't create unused rtl or nop insns.
(rs6000_sibcall_aix): Rename parameter to reflect new usage.  Take
tlsarg from global_tlsarg.
(rs6000_call_sysv): New function.
* config/rs6000/rs6000.md: Adjust rs6000_call_template and
rs6000_sibcall_template throughout.
(tls_gd_aix, tls_gd_sysv, tls_gd_call_aix, tls_gd_call_sysv): Delete.
(tls_ld_aix, tls_ld_sysv, tls_ld_call_aix, tls_ld_call_sysv): Delete.
(tls_gdld_aix, tls_gdld_sysv): New insns, replacing above.
(tls_gd): Swap operand order.  Simplify mode selection.
(tls_gd_high, tls_gd_low): Swap operand order.
(tls_ld): Remove const_int 0 vector element from UNSPEC_TLSLD.
Simplify mode selection.
(tls_ld_high, tls_ld_low): Similarly adjust UNSPEC_TLSLD.
(call, call_value): Don't assert for second call operand.
Use rs6000_call_sysv.

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index b80c278d742..7e45d2f0371 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1039,6 +1039,13 @@ (define_predicate "rs6000_tls_symbol_ref"
   (and (match_code "symbol_ref")
(match_test "RS6000_SYMBOL_REF_TLS_P (op)")))
 
+;; Return 1 for the UNSPEC used in TLS call operands
+(define_predicate "unspec_tls"
+  (match_code "unspec")
+{
+  return XINT (op, 1) == UNSPEC_TLSGD || XINT (op, 1) == UNSPEC_TLSLD;
+})
+
 ;; Return 1 if the operand, used inside a MEM, is a valid first argument
 ;; to CALL.  This is a SYMBOL_REF, a pseudo-register, LR or CTR.
 (define_predicate "call_operand"
diff --git a/gcc/config/rs6000/rs6000-protos.h 
b/gcc/config/rs6000/rs6000-protos.h
index 967f65e2d94..3fd89dc20db 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -111,8 +111,8 @@ extern int ccr_bit (rtx, int);
 extern void rs6000_output_function_entry (FILE *, const char *);
 extern void print_operand (FILE *, rtx, int);
 extern void print_operand_address (FILE *, rtx);
-extern const char *rs6000_call_template (rtx *, unsigned int, const char *);
-extern const char *rs6000_sibcall_template (rtx *, unsigned int, const char *);
+extern const char *rs6000_call_template (rtx *, unsigned int);
+extern const char *rs6000_sibcall_template (rtx *, unsigned int);
 extern const char *rs6000_indirect_call_template (rtx *, unsigned int);
 extern const char *rs6000_indirect_sibcall_template (rtx *, unsigned int);
 extern enum rtx_code rs6000_reverse_condition (machine_mode,
@@ -136,7 +136,6 @@ extern void rs6000_expand_atomic_op (enum rtx_code, rtx, 
rtx, rtx, rtx, rtx);
 extern void rs6000_emit_swdiv (rtx, rtx, rtx, bool);
 

[PATCH 5/6] [RS6000] Use standard call patterns for __tls_get_addr calls

2018-11-06 Thread Alan Modra
The current code handling __tls_get_addr calls for powerpc*-linux
generates a call then overwrites the call insn with a special
tls_{gd,ld}_{aix,sysv} pattern.  It's done that way to support
!TARGET_TLS_MARKERS, where the arg setup insns need to be emitted
immediately before the branch and link.  When TARGET_TLS_MARKERS, the
arg setup insns are split from the actual call, but we then have a
non-standard call pattern that needs to be carried through to output.

This patch changes that scheme, to instead use the standard call
patterns for __tls_get_addr calls, except for the now rare
!TARGET_TLS_MARKERS case.  Doing it this way should be better for
maintenance as the !TARGET_TLS_MARKERS code can eventually disappear.
It also makes it possible to support longcalls (and in following
patches, inline plt calls) for __tls_get_addr without introducing yet
more special call patterns.

__tls_get_addr calls do however need to be different to standard
calls, because when TARGET_TLS_MARKERS the calls are decorated with an
argument specifier, eg. "bl __tls_get_addr(thread_var@tlsgd)" that
causes a reloc to be emitted by the assembler tying the call to its
arg setup insns.  I chose to smuggle the arg in the currently unused
stack size rtl.

I've also introduced rs6000_call_sysv to generate rtl for sysv calls,
as rs6000_call_aix does for aix and elfv2 calls.  This allows
rs6000_longcall_ref to be local to rs6000.c since the calls in the
expanders never did anything for darwin.

* config/rs6000/predicates.md (unspec_tls): New.
* config/rs6000/rs6000-protos.h (rs6000_output_call): Update proto.
(rs6000_longcall_ref): Delete.
(rs6000_call_sysv): Declare.
* config/rs6000/rs6000.c (edit_tls_call_insn): New function.
(global_tlsarg): New variable.
(rs6000_legitimize_tls_address): Rewrite __tls_get_addr call
handling.
(print_operand): Extract UNSPEC_TLSGD address operand.
(rs6000_output_call): Remove arg parameter, extract from second
call operand instead.
(rs6000_longcall_ref): Make static, localize vars.
(rs6000_call_aix): Rename parameter to reflect new usage.  Take
tlsarg from global_tlsarg.  Don't create unused rtl or nop insns.
(rs6000_sibcall_aix): Rename parameter to reflect new usage.  Take
tlsarg from global_tlsarg.
(rs6000_call_sysv): New function.
* config/rs6000/rs6000.md: Adjust rs6000_output_call throughout.
(tls_sysv_suffix): Delete.
(tls_gd_aix, tls_gd_sysv, tls_gd_call_aix, tls_gd_call_sysv): Delete.
(tls_ld_aix, tls_ld_sysv, tls_ld_call_aix, tls_ld_call_sysv): Delete.
(tls_gdld_aix, tls_gdld_sysv): New insns, replacing above.
(tls_gd): Swap operand order.  Simplify mode selection.
(tls_gd_high, tls_gd_low): Swap operand order.
(tls_ld): Remove const_int 0 vector element from UNSPEC_TLSLD.
Simplify mode selection.
(tls_ld_high, tls_ld_low): Similarly adjust UNSPEC_TLSLD.
(call, call_value): Don't assert for second call operand.
Use rs6000_call_sysv.

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 40b0114a64f..8f13c1457e4 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1039,6 +1039,13 @@ (define_predicate "rs6000_tls_symbol_ref"
   (and (match_code "symbol_ref")
(match_test "RS6000_SYMBOL_REF_TLS_P (op)")))
 
+;; Return 1 for the UNSPEC used in TLS call operands
+(define_predicate "unspec_tls"
+  (match_code "unspec")
+{
+  return XINT (op, 1) == UNSPEC_TLSGD || XINT (op, 1) == UNSPEC_TLSLD;
+})
+
 ;; Return 1 if the operand, used inside a MEM, is a valid first argument
 ;; to CALL.  This is a SYMBOL_REF, a pseudo-register, LR or CTR.
 (define_predicate "call_operand"
diff --git a/gcc/config/rs6000/rs6000-protos.h 
b/gcc/config/rs6000/rs6000-protos.h
index 493cfe6ba2b..9e84c692a9b 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -111,7 +111,7 @@ extern int ccr_bit (rtx, int);
 extern void rs6000_output_function_entry (FILE *, const char *);
 extern void print_operand (FILE *, rtx, int);
 extern void print_operand_address (FILE *, rtx);
-extern const char *rs6000_output_call (rtx *, unsigned int, bool, const char 
*);
+extern const char *rs6000_output_call (rtx *, unsigned int, bool);
 extern const char *rs6000_output_indirect_call (rtx *, unsigned int, bool);
 extern enum rtx_code rs6000_reverse_condition (machine_mode,
   enum rtx_code);
@@ -134,7 +134,6 @@ extern void rs6000_expand_atomic_op (enum rtx_code, rtx, 
rtx, rtx, rtx, rtx);
 extern void rs6000_emit_swdiv (rtx, rtx, rtx, bool);
 extern void rs6000_emit_swsqrt (rtx, rtx, bool);
 extern void output_toc (FILE *, rtx, int, machine_mode);
-extern rtx rs6000_longcall_ref (rtx);
 extern void rs6000_fatal_bad_address (rtx);
 extern rtx create_TOC_reference (rtx,