- bfd_put_32 (info->abfd, (bfd_vma) insn,
- info->contents + urel->r_offset);
-
- /* Kill any HINT reloc that might exist for this insn. */
- xrel = (elf64_alpha_find_reloc_at_ofs
- (info->relocs, info->relend, urel->r_offset,
- R_ALPHA_HINT));
- if (xrel)
- xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
-
- info->changed_contents = TRUE;
- info->changed_relocs = TRUE;
- }
- else
- all_optimized = FALSE;
-
- /* Even if the target is not in range for a direct branch,
- if we share a GP, we can eliminate the gp reload. */
- if (optdest)
- {
- Elf_Internal_Rela *gpdisp
- = (elf64_alpha_find_reloc_at_ofs
- (info->relocs, irelend, urel->r_offset + 4,
- R_ALPHA_GPDISP));
- if (gpdisp)
- {
- bfd_byte *p_ldah = info->contents + gpdisp->r_offset;
- bfd_byte *p_lda = p_ldah + gpdisp->r_addend;
- unsigned int ldah = bfd_get_32 (info->abfd, p_ldah);
- unsigned int lda = bfd_get_32 (info->abfd, p_lda);
-
- /* Verify that the instruction is "ldah $29,0($26)".
- Consider a function that ends in a noreturn call,
- and that the next function begins with an ldgp,
- and that by accident there is no padding between.
- In that case the insn would use $27 as the base. */
- if (ldah == 0x27ba0000 && lda == 0x23bd0000)
- {
- bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah);
- bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda);
-
- gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
- info->changed_contents = TRUE;
- info->changed_relocs = TRUE;
- }
- }
- }
- }
- break;
- }
- }
-
- /* If all cases were optimized, we can reduce the use count on this
- got entry by one, possibly eliminating it. */
- if (all_optimized)
- {
- if (--info->gotent->use_count == 0)
- {
- int sz = alpha_got_entry_size (R_ALPHA_LITERAL);
- alpha_elf_tdata (info->gotobj)->total_got_size -= sz;
- if (!info->h)
- alpha_elf_tdata (info->gotobj)->local_got_size -= sz;
- }
-
- /* If the literal instruction is no longer needed (it may have been
- reused. We can eliminate it. */
- /* ??? For now, I don't want to deal with compacting the section,
- so just nop it out. */
- if (!lit_reused)
- {
- irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
- info->changed_relocs = TRUE;
-
- bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP,
- info->contents + irel->r_offset);
- info->changed_contents = TRUE;
- }
- }
-
- return TRUE;
-}
-
-static bfd_vma
-elf64_alpha_relax_opt_call (info, symval)
- struct alpha_relax_info *info;
- bfd_vma symval;
-{
- /* If the function has the same gp, and we can identify that the
- function does not use its function pointer, we can eliminate the
- address load. */
-
- /* If the symbol is marked NOPV, we are being told the function never
- needs its procedure value. */
- if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV)
- return symval;
-
- /* If the symbol is marked STD_GP, we are being told the function does
- a normal ldgp in the first two words. */
- else if ((info->other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD)
- ;
-
- /* Otherwise, we may be able to identify a GP load in the first two
- words, which we can then skip. */
- else
- {
- Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp;
- bfd_vma ofs;
-
- /* Load the relocations from the section that the target symbol is in. */
- if (info->sec == info->tsec)
- {
- tsec_relocs = info->relocs;
- tsec_relend = info->relend;
- tsec_free = NULL;
- }
- else
- {
- tsec_relocs = (_bfd_elf_link_read_relocs
- (info->abfd, info->tsec, (PTR) NULL,
- (Elf_Internal_Rela *) NULL,
- info->link_info->keep_memory));
- if (tsec_relocs == NULL)
- return 0;
- tsec_relend = tsec_relocs + info->tsec->reloc_count;
- tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
- }
-
- /* Recover the symbol's offset within the section. */
- ofs = (symval - info->tsec->output_section->vma
- - info->tsec->output_offset);
-
- /* Look for a GPDISP reloc. */
- gpdisp = (elf64_alpha_find_reloc_at_ofs
- (tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP));
-
- if (!gpdisp || gpdisp->r_addend != 4)
- {
- if (tsec_free)
- free (tsec_free);
- return 0;
- }
- if (tsec_free)
- free (tsec_free);
- }
-
- /* We've now determined that we can skip an initial gp load. Verify
- that the call and the target use the same gp. */
- if (info->link_info->hash->creator != info->tsec->owner->xvec
- || info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
- return 0;
-
- return symval + 8;
-}