From 4a421c53cf609d68fe956c2e7270d34c0ab8500f Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 30 Apr 2019 16:33:25 +0930 Subject: [PATCH] PowerPC GOT_PCREL34 optimisation bfd/ * elf64-ppc.c (ppc64_elf_check_relocs): Set has_gotrel for R_PPC64_GOT_PCREL34. (xlate_pcrel_opt): New function. (ppc64_elf_edit_toc): Handle R_PPC64_GOT_PCREL34. (ppc64_elf_relocate_section): Edit GOT indirect to GOT relative for R_PPC64_GOT_PCREL34. Implement R_PPC64_PCREL_OPT optimisation. ld/ * testsuite/ld-powerpc/pcrelopt.s, * testsuite/ld-powerpc/pcrelopt.d, * testsuite/ld-powerpc/pcrelopt.sec: New test. * testsuite/ld-powerpc/powerpc.exp: Run it. --- bfd/ChangeLog | 9 ++ bfd/elf64-ppc.c | 223 +++++++++++++++++++++++++-- ld/ChangeLog | 7 + ld/testsuite/ld-powerpc/pcrelopt.d | 89 +++++++++++ ld/testsuite/ld-powerpc/pcrelopt.s | 119 ++++++++++++++ ld/testsuite/ld-powerpc/pcrelopt.sec | 6 + ld/testsuite/ld-powerpc/powerpc.exp | 4 + 7 files changed, 444 insertions(+), 13 deletions(-) create mode 100644 ld/testsuite/ld-powerpc/pcrelopt.d create mode 100644 ld/testsuite/ld-powerpc/pcrelopt.s create mode 100644 ld/testsuite/ld-powerpc/pcrelopt.sec diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9091df02942..0e21664e91d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2019-05-24 Alan Modra + + * elf64-ppc.c (ppc64_elf_check_relocs): Set has_gotrel for + R_PPC64_GOT_PCREL34. + (xlate_pcrel_opt): New function. + (ppc64_elf_edit_toc): Handle R_PPC64_GOT_PCREL34. + (ppc64_elf_relocate_section): Edit GOT indirect to GOT relative + for R_PPC64_GOT_PCREL34. Implement R_PPC64_PCREL_OPT optimisation. + 2019-05-24 Alan Modra * reloc.c (BFD_RELOC_PPC64_D34, BFD_RELOC_PPC64_D34_LO), diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index ad47bed372d..75189b6967f 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -4567,6 +4567,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_GOT16_DS: case R_PPC64_GOT16_HA: case R_PPC64_GOT16_LO_DS: + case R_PPC64_GOT_PCREL34: ppc64_elf_tdata (abfd)->has_gotrel = 1; ppc64_elf_section_data (sec)->has_gotrel = 1; /* Fall through. */ @@ -4574,7 +4575,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_PPC64_GOT16: case R_PPC64_GOT16_HI: case R_PPC64_GOT16_LO: - case R_PPC64_GOT_PCREL34: dogot: /* This symbol requires a global offset table entry. */ sec->has_toc_reloc = 1; @@ -8141,6 +8141,114 @@ ok_lo_toc_insn (unsigned int insn, enum elf_ppc64_reloc_type r_type) && (insn & 1) == 0)); } +/* PCREL_OPT in one instance flags to the linker that a pair of insns: + pld ra,symbol@got@pcrel + load/store rt,0(ra) + or + paddi ra,symbol@pcrel + load/store rt,0(ra) + may be translated to + pload/pstore rt,symbol@pcrel + nop. + This function returns true if the optimization is possible, placing + the prefix insn in *PINSN1 and a NOP in *PINSN2. + + On entry to this function, the linker has already determined that + the pld can be replaced with paddi: *PINSN1 is that paddi insn, + while *PINSN2 is the second instruction. */ + +static bfd_boolean +xlate_pcrel_opt (uint64_t *pinsn1, uint64_t *pinsn2) +{ + uint32_t insn2 = *pinsn2 >> 32; + uint64_t i1new; + + /* Check that regs match. */ + if (((insn2 >> 16) & 31) != ((*pinsn1 >> 21) & 31)) + return FALSE; + + switch ((insn2 >> 26) & 63) + { + default: + return FALSE; + + case 32: /* lwz */ + case 34: /* lbz */ + case 36: /* stw */ + case 38: /* stb */ + case 40: /* lhz */ + case 42: /* lha */ + case 44: /* sth */ + case 48: /* lfs */ + case 50: /* lfd */ + case 52: /* stfs */ + case 54: /* stfd */ + /* These are the PMLS cases, where we just need to tack a prefix + on the insn. Check that the D field is zero. */ + if ((insn2 & 0xffff) != 0) + return FALSE; + i1new = ((1ULL << 58) | (2ULL << 56) | (1ULL << 52) + | (insn2 & ((63ULL << 26) | (31ULL << 21)))); + break; + + case 58: /* lwa, ld */ + if ((insn2 & 0xfffd) != 0) + return FALSE; + i1new = ((1ULL << 58) | (1ULL << 52) + | (insn2 & 2 ? 41ULL << 26 : 57ULL << 26) + | (insn2 & (31ULL << 21))); + break; + + case 57: /* lxsd, lxssp */ + if ((insn2 & 0xfffc) != 0 || (insn2 & 3) < 2) + return FALSE; + i1new = ((1ULL << 58) | (1ULL << 52) + | ((40ULL | (insn2 & 3)) << 26) + | (insn2 & (31ULL << 21))); + break; + + case 61: /* stxsd, stxssp, lxv, stxv */ + if ((insn2 & 3) == 0) + return FALSE; + else if ((insn2 & 3) >= 2) + { + if ((insn2 & 0xfffc) != 0) + return FALSE; + i1new = ((1ULL << 58) | (1ULL << 52) + | ((44ULL | (insn2 & 3)) << 26) + | (insn2 & (31ULL << 21))); + } + else + { + if ((insn2 & 0xfff0) != 0) + return FALSE; + i1new = ((1ULL << 58) | (1ULL << 52) + | ((50ULL | (insn2 & 4) | ((insn2 & 8) >> 3)) << 26) + | (insn2 & (31ULL << 21))); + } + break; + + case 56: /* lq */ + if ((insn2 & 0xffff) != 0) + return FALSE; + i1new = ((1ULL << 58) | (1ULL << 52) + | (insn2 & ((63ULL << 26) | (31ULL << 21)))); + break; + + case 62: /* std, stq */ + if ((insn2 & 0xfffd) != 0) + return FALSE; + i1new = ((1ULL << 58) | (1ULL << 52) + | ((insn2 & 2) == 0 ? 61ULL << 26 : 60ULL << 26) + | (insn2 & (31ULL << 21))); + break; + } + + *pinsn1 = i1new; + *pinsn2 = (uint64_t) NOP << 32; + return TRUE; +} + /* Examine all relocs referencing .toc sections in order to remove unused .toc entries. */ @@ -8797,8 +8905,8 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) } /* Look for cases where we can change an indirect GOT access to - a GOT relative access, possibly reducing the number of GOT - entries. */ + a GOT relative or PC relative access, possibly reducing the + number of GOT entries. */ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) { asection *sec; @@ -8849,8 +8957,8 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) asection *sym_sec; struct elf_link_hash_entry *h; struct got_entry *ent; - bfd_vma val; - unsigned char buf[4]; + bfd_vma sym_addend, val, pc; + unsigned char buf[8]; unsigned int insn; r_type = ELF64_R_TYPE (rel->r_info); @@ -8862,6 +8970,11 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) case R_PPC64_GOT16_DS: case R_PPC64_GOT16_HA: case R_PPC64_GOT16_LO_DS: + sym_addend = rel->r_addend; + break; + + case R_PPC64_GOT_PCREL34: + sym_addend = 0; break; } @@ -8877,7 +8990,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) val = h->root.u.def.value; else val = sym->st_value; - val += rel->r_addend; + val += sym_addend; val += sym_sec->output_section->vma + sym_sec->output_offset; switch (r_type) @@ -8919,6 +9032,22 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) if ((insn & (0x3f << 26 | 0x3)) != 58u << 26 /* ld */) continue; break; + + case R_PPC64_GOT_PCREL34: + pc = rel->r_offset; + pc += sec->output_section->vma + sec->output_offset; + if (val - pc + (1ULL << 33) >= 1ULL << 34) + continue; + if (!bfd_get_section_contents (ibfd, sec, buf, + rel->r_offset & ~3, 8)) + goto got_error_ret; + insn = bfd_get_32 (ibfd, buf); + if ((insn & (-1u << 18)) != ((1u << 26) | (1u << 20))) + continue; + insn = bfd_get_32 (ibfd, buf + 4); + if ((insn & (0x3f << 26)) != 57u << 26) + continue; + break; } if (h != NULL) @@ -8929,7 +9058,7 @@ ppc64_elf_edit_toc (struct bfd_link_info *info) ent = local_got_ents[r_symndx]; } for (; ent != NULL; ent = ent->next) - if (ent->addend == rel->r_addend + if (ent->addend == sym_addend && ent->owner == ibfd && ent->tls_type == 0) break; @@ -13772,6 +13901,8 @@ ppc64_elf_relocate_section (bfd *output_bfd, Elf_Internal_Rela orig_rel; reloc_howto_type *howto; struct reloc_howto_struct alt_howto; + uint64_t pinsn; + bfd_vma offset; again: orig_rel = *rel; @@ -14134,7 +14265,6 @@ ppc64_elf_relocate_section (bfd *output_bfd, if ((tls_mask & TLS_TLS) != 0 && (tls_mask & TLS_LD) == 0) { unsigned int insn1, insn2; - bfd_vma offset; tls_ldgd_opt: offset = (bfd_vma) -1; @@ -14236,9 +14366,9 @@ ppc64_elf_relocate_section (bfd *output_bfd, && rel + 1 < relend) { unsigned int insn2; - bfd_vma offset = rel->r_offset; enum elf_ppc64_reloc_type r_type1 = ELF64_R_TYPE (rel[1].r_info); + offset = rel->r_offset; if (is_plt_seq_reloc (r_type1)) { bfd_put_32 (output_bfd, NOP, contents + offset); @@ -14285,9 +14415,9 @@ ppc64_elf_relocate_section (bfd *output_bfd, && rel + 1 < relend) { unsigned int insn2; - bfd_vma offset = rel->r_offset; enum elf_ppc64_reloc_type r_type1 = ELF64_R_TYPE (rel[1].r_info); + offset = rel->r_offset; if (is_plt_seq_reloc (r_type1)) { bfd_put_32 (output_bfd, NOP, contents + offset); @@ -14431,7 +14561,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, && relocation + 0x80008000 <= 0xffffffff) { unsigned int insn1, insn2; - bfd_vma offset = rel->r_offset - d_offset; + offset = rel->r_offset - d_offset; insn1 = bfd_get_32 (input_bfd, contents + offset); insn2 = bfd_get_32 (input_bfd, contents + offset + 4); if ((insn1 & 0xffff0000) == ADDIS_R2_R12 @@ -14823,6 +14953,74 @@ ppc64_elf_relocate_section (bfd *output_bfd, } } break; + + case R_PPC64_GOT_PCREL34: + from = (rel->r_offset + + input_section->output_section->vma + + input_section->output_offset); + if (relocation - from + (1ULL << 33) < 1ULL << 34 + && SYMBOL_REFERENCES_LOCAL (info, &h->elf)) + { + offset = rel->r_offset; + pinsn = bfd_get_32 (input_bfd, contents + offset); + pinsn <<= 32; + pinsn |= bfd_get_32 (input_bfd, contents + offset + 4); + if ((pinsn & ((-1ULL << 50) | (63ULL << 26))) + == ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */)) + { + /* Replace with paddi. */ + pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26); + r_type = R_PPC64_PCREL34; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + bfd_put_32 (input_bfd, pinsn >> 32, contents + offset); + bfd_put_32 (input_bfd, pinsn, contents + offset + 4); + goto pcrelopt; + } + } + break; + + case R_PPC64_PCREL34: + if (SYMBOL_REFERENCES_LOCAL (info, &h->elf)) + { + offset = rel->r_offset; + pinsn = bfd_get_32 (input_bfd, contents + offset); + pinsn <<= 32; + pinsn |= bfd_get_32 (input_bfd, contents + offset + 4); + if ((pinsn & ((-1ULL << 50) | (63ULL << 26))) + == ((1ULL << 58) | (2ULL << 56) | (1ULL << 52) + | (14ULL << 26) /* paddi */)) + { + pcrelopt: + if (rel + 1 < relend + && rel[1].r_offset == offset + && rel[1].r_info == ELF64_R_INFO (0, R_PPC64_PCREL_OPT)) + { + bfd_vma off2 = rel[1].r_addend; + if (off2 == 0) + /* zero means next insn. */ + off2 = 8; + off2 += offset; + if (off2 + 4 <= input_section->size) + { + uint64_t pinsn2; + pinsn2 = bfd_get_32 (input_bfd, contents + off2); + pinsn2 <<= 32; + if ((pinsn2 & (63ULL << 58)) == 1ULL << 58) + break; + if (xlate_pcrel_opt (&pinsn, &pinsn2)) + { + bfd_put_32 (input_bfd, pinsn >> 32, + contents + offset); + bfd_put_32 (input_bfd, pinsn, + contents + offset + 4); + bfd_put_32 (input_bfd, pinsn2 >> 32, + contents + off2); + } + } + } + } + } + break; } /* Set `addend'. */ @@ -14847,6 +15045,7 @@ ppc64_elf_relocate_section (bfd *output_bfd, case R_PPC64_GNU_VTINHERIT: case R_PPC64_GNU_VTENTRY: case R_PPC64_ENTRY: + case R_PPC64_PCREL_OPT: goto copy_reloc; /* GOT16 relocations. Like an ADDR16 using the symbol's @@ -15882,8 +16081,6 @@ ppc64_elf_relocate_section (bfd *output_bfd, r = bfd_reloc_outofrange; else { - uint64_t pinsn; - relocation += addend; if (howto->pc_relative) relocation -= (rel->r_offset diff --git a/ld/ChangeLog b/ld/ChangeLog index 0965cd79b5f..be42aba3070 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +2019-05-24 Alan Modra + + * testsuite/ld-powerpc/pcrelopt.s, + * testsuite/ld-powerpc/pcrelopt.d, + * testsuite/ld-powerpc/pcrelopt.sec: New test. + * testsuite/ld-powerpc/powerpc.exp: Run it. + 2019-05-23 Jose E. Marchesi * Makefile.am (ALL_64_EMULATION_SOURCES): Add eelf64bpf.c. diff --git a/ld/testsuite/ld-powerpc/pcrelopt.d b/ld/testsuite/ld-powerpc/pcrelopt.d new file mode 100644 index 00000000000..18fdb95abff --- /dev/null +++ b/ld/testsuite/ld-powerpc/pcrelopt.d @@ -0,0 +1,89 @@ + +.*: file format .* + +Disassembly of section \.text: + +0+10000200 <_start>: +.*: (06 10 00 01|01 00 10 06) plbz r3,66320 +.*: (88 60 03 10|10 03 60 88) +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) plhz r4,66308 +.*: (a0 80 03 04|04 03 80 a0) +.*: (60 00 00 00|00 00 00 60) nop +.*: (60 00 00 00|00 00 00 60) nop +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) plha r3,66288 +.*: (a8 60 02 f0|f0 02 60 a8) +.*: (40 82 ff f4|f4 ff 82 40) bne .* +.*: (06 10 00 01|01 00 10 06) plwz r3,66276 +.*: (80 60 02 e4|e4 02 60 80) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) plwa r3,66264 +.*: (a4 60 02 d8|d8 02 60 a4) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) pld r3,66252 +.*: (e4 60 02 cc|cc 02 60 e4) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) plq r14,66240 +.*: (e1 c0 02 c0|c0 02 c0 e1) +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) plfs f1,66228 +.*: (c0 20 02 b4|b4 02 20 c0) +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) plfd f1,66216 +.*: (c8 20 02 a8|a8 02 20 c8) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) plxsd v30,66204 +.*: (ab c0 02 9c|9c 02 c0 ab) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) plxssp v31,66192 +.*: (af e0 02 90|90 02 e0 af) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) plxv vs63,66180 +.*: (cf e0 02 84|84 02 e0 cf) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) plxv vs0,66168 +.*: (c8 00 02 78|78 02 00 c8) +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) pstb r3,66156 +.*: (98 60 02 6c|6c 02 60 98) +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) psth r3,66144 +.*: (b0 60 02 60|60 02 60 b0) +.*: (60 00 00 00|00 00 00 60) nop +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) pstw r3,66128 +.*: (90 60 02 50|50 02 60 90) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) pstd r3,66116 +.*: (f4 60 02 44|44 02 60 f4) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) pstq r14,66104 +.*: (f1 c0 02 38|38 02 c0 f1) +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) pstfd f1,66092 +.*: (d8 20 02 2c|2c 02 20 d8) +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) pstfs f2,66080 +.*: (d0 40 02 20|20 02 40 d0) +.*: (60 00 00 00|00 00 00 60) nop +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) pstxsd v30,66064 +.*: (bb c0 02 10|10 02 c0 bb) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) pstxssp v31,66052 +.*: (bf e0 02 04|04 02 e0 bf) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) pstxv vs63,66040 +.*: (df e0 01 f8|f8 01 e0 df) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) pstxv vs0,66028 +.*: (d8 00 01 ec|ec 01 00 d8) +.*: (60 00 00 00|00 00 00 60) nop +.*: (04 10 00 01|01 00 10 04) pld r9,66008 +.*: (e5 20 01 d8|d8 01 20 e5) +.*: (e8 09 00 00|00 00 09 e8) ld r0,0\(r9\) +.*: (60 00 00 00|00 00 00 60) nop +.*: (06 10 00 01|01 00 10 06) pla r7,66000 +.*: (38 e0 01 d0|d0 01 e0 38) +.*: (88 c7 00 00|00 00 c7 88) lbz r6,0\(r7\) diff --git a/ld/testsuite/ld-powerpc/pcrelopt.s b/ld/testsuite/ld-powerpc/pcrelopt.s new file mode 100644 index 00000000000..78b0f51f733 --- /dev/null +++ b/ld/testsuite/ld-powerpc/pcrelopt.s @@ -0,0 +1,119 @@ + .text + .globl _start +_start: +# original PCREL_OPT definition, with second insn immediately after first + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0 + lbz 3,0(9) + +# but we now allow an offset to the second insn + pld 22,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) + nop +0: lhz 4,0(22) + +# in fact, it can even be before the "first" insn +0: lha 3,0(9) + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0b-(.-8) + bne 0b + +# and of course, other local labels work + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,.L1-(.-8) +.L1: lwz 3,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: lwa 3,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: ld 3,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: lq 14,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: lfs 1,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: lfd 1,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: lxsd 30,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: lxssp 31,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: lxv 63,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: lxv 0,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: stb 3,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: sth 3,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: stw 3,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: std 3,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: stq 14,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: stfd 1,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: stfs 2,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: stxsd 30,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: stxssp 31,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: stxv 63,0(9) + + pld 9,sym@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: stxv 0,0(9) + +# This should not optimize + .extern i + .type i,@object + pld 9,i@got@pcrel + .reloc .-8,R_PPC64_PCREL_OPT,0f-(.-8) +0: ld 0,0(9) + +# and this should edit from GOT indirect to GOT relative +# ie. change the pld to paddi, leaving the lbz as is. + pld 7,sym@got@pcrel + lbz 6,0(7) + + .data +sym: .space 32 diff --git a/ld/testsuite/ld-powerpc/pcrelopt.sec b/ld/testsuite/ld-powerpc/pcrelopt.sec new file mode 100644 index 00000000000..1dcd3a7362c --- /dev/null +++ b/ld/testsuite/ld-powerpc/pcrelopt.sec @@ -0,0 +1,6 @@ +# check for just one GOT entry +#... +.* \.rela\.dyn +RELA +[0-9a-f]+ [0-9a-f]+ 000018 .* +#... +.* \.got +PROGBITS +[0-9a-f]+ [0-9a-f]+ 000010 .* +#pass diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp index a2dcfdce898..658f319739e 100644 --- a/ld/testsuite/ld-powerpc/powerpc.exp +++ b/ld/testsuite/ld-powerpc/powerpc.exp @@ -260,6 +260,10 @@ set ppc64elftests { {"notoc ext" "" "" "-a64" {ext.s} {} ""} {"notoc" "-melf64ppc --no-plt-localentry -T ext.lnk" "" "-a64" {notoc.s} {{objdump -d notoc.d} {readelf {-wf -W} notoc.wf}} "notoc"} + {"pcrelopt" "-melf64ppc --hash-style=gnu" "tmpdir/symtocbase.so" + "-a64 -mfuture" {pcrelopt.s} + {{objdump {-d -Mfuture} pcrelopt.d} + {readelf {-S --wide} pcrelopt.sec}} "pcrelopt" } } set ppceabitests { -- 2.30.2