Commit ece3bca2 by Alan Modra Committed by Alan Modra

[RS6000] Use standard call patterns for __tls_get_addr calls

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_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.

From-SVN: r266604
parent 7a24893b
2018-11-29 Alan Modra <amodra@gmail.com> 2018-11-29 Alan Modra <amodra@gmail.com>
* 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.
2018-11-29 Alan Modra <amodra@gmail.com>
* config/rs6000/darwin.md (call_indirect_nonlocal_darwin64), * config/rs6000/darwin.md (call_indirect_nonlocal_darwin64),
(call_nonlocal_darwin64, call_value_indirect_nonlocal_darwin64), (call_nonlocal_darwin64, call_value_indirect_nonlocal_darwin64),
(call_value_nonlocal_darwin64): Remove constraints from second call (call_value_nonlocal_darwin64): Remove constraints from second call
...@@ -997,6 +997,13 @@ ...@@ -997,6 +997,13 @@
(and (match_code "symbol_ref") (and (match_code "symbol_ref")
(match_test "RS6000_SYMBOL_REF_TLS_P (op)"))) (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 ;; 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. ;; to CALL. This is a SYMBOL_REF, a pseudo-register, LR or CTR.
(define_predicate "call_operand" (define_predicate "call_operand"
......
...@@ -105,8 +105,8 @@ extern int ccr_bit (rtx, int); ...@@ -105,8 +105,8 @@ extern int ccr_bit (rtx, int);
extern void rs6000_output_function_entry (FILE *, const char *); extern void rs6000_output_function_entry (FILE *, const char *);
extern void print_operand (FILE *, rtx, int); extern void print_operand (FILE *, rtx, int);
extern void print_operand_address (FILE *, rtx); extern void print_operand_address (FILE *, rtx);
extern const char *rs6000_call_template (rtx *, unsigned int, const char *); extern const char *rs6000_call_template (rtx *, unsigned int);
extern const char *rs6000_sibcall_template (rtx *, unsigned int, const char *); extern const char *rs6000_sibcall_template (rtx *, unsigned int);
extern const char *rs6000_indirect_call_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 const char *rs6000_indirect_sibcall_template (rtx *, unsigned int);
extern enum rtx_code rs6000_reverse_condition (machine_mode, 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); ...@@ -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_swdiv (rtx, rtx, rtx, bool);
extern void rs6000_emit_swsqrt (rtx, rtx, bool); extern void rs6000_emit_swsqrt (rtx, rtx, bool);
extern void output_toc (FILE *, rtx, int, machine_mode); extern void output_toc (FILE *, rtx, int, machine_mode);
extern rtx rs6000_longcall_ref (rtx);
extern void rs6000_fatal_bad_address (rtx); extern void rs6000_fatal_bad_address (rtx);
extern rtx create_TOC_reference (rtx, rtx); extern rtx create_TOC_reference (rtx, rtx);
extern void rs6000_split_multireg_move (rtx, rtx); extern void rs6000_split_multireg_move (rtx, rtx);
...@@ -198,6 +197,7 @@ extern void rs6000_split_stack_space_check (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_emit_eh_reg_restore (rtx, rtx);
extern void rs6000_call_aix (rtx, rtx, rtx, rtx); extern void rs6000_call_aix (rtx, rtx, rtx, rtx);
extern void rs6000_sibcall_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 rs6000_aix_asm_output_dwarf_table_ref (char *);
extern void get_ppc476_thunk_name (char name[32]); extern void get_ppc476_thunk_name (char name[32]);
extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins); extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins);
......
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