[RS6000] inline plt call sequences

Programming / Compilers / GCC - amodra [138bc75d-0d04-0410-961f-82ee72b054a4] - 29 November 2018 04:53 EST

Finally, the point of the previous patches in this series, support for inline PLT calls, keyed off -fno-plt. This emits code using new relocations that tie all insns in the sequence together, so that the linker can edit the sequence back to a direct call should the call target turn out to be local. An example of ELFv2 code to call puts is as follows:

.reloc .,R_PPC64_PLTSEQ,puts std 2,24(1) .reloc .,R_PPC64_PLT16_HA,puts addis 12,2,0 .reloc .,R_PPC64_PLT16_LO_DS,puts ld 12,0(12) .reloc .,R_PPC64_PLTSEQ,puts mtctr 12 .reloc .,R_PPC64_PLTCALL,puts bctrl ld 2,24(1)

"addis 12,2,puts@plt@ha" and "ld 12,puts@plt@l(12)" are also supported by the assembler. gcc instead uses the explicit R_PPC64_PLT16_HA and R_PPC64_PLT16_LO_DS relocs because when the call is to __tls_get_addr an extra reloc is emitted at every place where one is shown above, to specify the __tls_get_addr arg. The linker expects the extra reloc to come first. .reloc enforces that ordering.

The patch also changes code emitted for longcalls if the assembler supports the new marker relocs, so that these too can be edited. One side effect of longcalls using PLT16 relocs is that they can now be resolved lazily by ld.so.

I don't support lazy inline PLT calls for ELFv1, because ELFv1 would need barriers to reliably load both the function address and toc pointer from the PLT. ELFv1 -fno-plt uses the longcall sequence instead, which isn't edited by GNU ld.

- config.in (HAVE_AS_PLTSEQ): Add.
- config/rs6000/predicates.md (indirect_call_operand): New.
- config/rs6000/rs6000-protos.h (rs6000_pltseq_template), (rs6000_sibcall_sysv): Declare.
- config/rs6000/rs6000.c (init_cumulative_args): Set cookie CALL_LONG for -fno-plt. (print_operand ): Handle UNSPEC_PLTSEQ. (rs6000_indirect_call_template_1): Emit .reloc directives for UNSPEC_PLTSEQ calls. (rs6000_pltseq_template): New function. (rs6000_longcall_ref): Add arg parameter. Use PLT16 insns if relocs supported by assembler. Move SYMBOL_REF test to callers. (rs6000_call_aix): Adjust rs6000_longcall_ref call. Package insns in UNSPEC_PLTSEQ, preserving original func_desc. (rs6000_call_sysv): Likewise. (rs6000_sibcall_sysv): New function.
- config/rs6000/rs6000.h (HAVE_AS_PLTSEQ): Provide default.
- config/rs6000/rs6000.md (UNSPEC_PLTSEQ, UNSPEC_PLT16_HA, UNSPEC_PLT16_LO): New. (pltseq_tocsave, pltseq_plt16_ha, pltseq_plt16_lo, pltseq_mtctr): New. (call_indirect_nonlocal_sysv): Don't differentiate zero from non-zero cookie in constraints. Test explicitly for flags in length attr. Handle unspec operand 1. (call_value_indirect_nonlocal_sysv): Likewise. (call_indirect_aix, call_value_indirect_aix): Handle unspec operand 1. (call_indirect_elfv2, call_value_indirect_elfv2): Likewise. (sibcall, sibcall_value): Use rs6000_sibcall_sysv. (sibcall_indirect_nonlocal_sysv): New pattern. (sibcall_value_indirect_nonlocal_sysv): Likewise. (sibcall_nonlocal_sysv, sibcall_value_nonlocal_sysv): Remove indirect call alternatives.
- configure.ac: Check for gas plt sequence marker support.
- configure: Regenerate.

5969e425db9 [RS6000] inline plt call sequences
gcc/ChangeLog | 36 ++++
gcc/config.in | 6 +
gcc/config/rs6000/predicates.md | 18 ++
gcc/config/rs6000/rs6000-protos.h | 2 +
gcc/config/rs6000/rs6000.c | 359 ++++++++++++++++++++++++++++++++++----
gcc/config/rs6000/rs6000.h | 4 +
gcc/config/rs6000/rs6000.md | 247 +++++++++++++++++---------
gcc/configure | 48 ++++-
gcc/configure.ac | 6 +
9 files changed, 602 insertions(+), 124 deletions(-)

Upstream: gcc.gnu.org

  • Share