From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18435 invoked by alias); 10 Apr 2007 18:03:15 -0000 Received: (qmail 18425 invoked by uid 22791); 10 Apr 2007 18:03:14 -0000 X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 10 Apr 2007 19:03:06 +0100 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.13.1/8.13.1) with ESMTP id l3AI34KD006645 for ; Tue, 10 Apr 2007 14:03:04 -0400 Received: from potter.sfbay.redhat.com (potter.sfbay.redhat.com [172.16.27.15]) by int-mx1.corp.redhat.com (8.13.1/8.13.1) with ESMTP id l3AI3313022017 for ; Tue, 10 Apr 2007 14:03:03 -0400 Received: from medalla.sfbay.redhat.com (medalla.sfbay.redhat.com [192.168.28.19]) by potter.sfbay.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id l3AI30XD018218 for ; Tue, 10 Apr 2007 14:03:02 -0400 Received: from medalla.sfbay.redhat.com (localhost.localdomain [127.0.0.1]) by medalla.sfbay.redhat.com (8.12.11.20060308/8.12.10) with ESMTP id l3AI2xVF024176 for ; Tue, 10 Apr 2007 11:02:59 -0700 Received: (from rth@localhost) by medalla.sfbay.redhat.com (8.12.11.20060308/8.12.11/Submit) id l3AI2xlB024174 for binutils@sources.redhat.com; Tue, 10 Apr 2007 11:02:59 -0700 Date: Tue, 10 Apr 2007 18:03:00 -0000 From: Richard Henderson To: binutils@sources.redhat.com Subject: speed up alpha relaxation Message-ID: <20070410180259.GA24160@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.1i X-IsSubscribed: yes Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2007-04/txt/msg00084.txt.bz2 The main barrier here is how many times we regenerate the GOT, given a large number of input files. It helps quite a bit to only regenerate these sections once per trip through all of the input files. Committed. r~ bfd/ * elf64-alpha.c (struct alpha_elf_link_hash_table): Add relax_trip. (elf64_alpha_size_got_sections): Remove unused something_changed local. (elf64_alpha_size_plt_section): Return void. (elf64_alpha_size_rela_got_section): Likewise. (elf64_alpha_relax_section): Only regenerate got+plt if the relax_trip counter has changed. include/ * bfdlink.h (struct bfd_link_info): Add relax_trip. ld/ * ldlang.c (relax_sections): Initialize and increment link_info.relax_trip. Index: bfd/elf64-alpha.c =================================================================== RCS file: /cvs/src/src/bfd/elf64-alpha.c,v retrieving revision 1.158 diff -u -p -r1.158 elf64-alpha.c --- bfd/elf64-alpha.c 26 Mar 2007 12:23:02 -0000 1.158 +++ bfd/elf64-alpha.c 10 Apr 2007 17:36:09 -0000 @@ -184,6 +184,10 @@ struct alpha_elf_link_hash_table /* The head of a list of .got subsections linked through alpha_elf_tdata(abfd)->got_link_next. */ bfd *got_list; + + /* The most recent relax pass that we've seen. The GOTs + should be regenerated if this doesn't match. */ + int relax_trip; }; /* Look up an entry in a Alpha ELF linker hash table. */ @@ -2375,7 +2379,6 @@ static bfd_boolean elf64_alpha_size_got_sections (struct bfd_link_info *info) { bfd *i, *got_list, *cur_got_obj = NULL; - int something_changed = 0; got_list = alpha_elf_hash_table (info)->got_list; @@ -2413,9 +2416,6 @@ elf64_alpha_size_got_sections (struct bf return TRUE; alpha_elf_hash_table (info)->got_list = got_list; - - /* Force got offsets to be recalculated. */ - something_changed = 1; } cur_got_obj = got_list; @@ -2429,8 +2429,6 @@ elf64_alpha_size_got_sections (struct bf alpha_elf_tdata(i)->got->size = 0; i = alpha_elf_tdata(i)->got_link_next; alpha_elf_tdata(cur_got_obj)->got_link_next = i; - - something_changed = 1; } else { @@ -2441,8 +2439,7 @@ elf64_alpha_size_got_sections (struct bf /* Once the gots have been merged, fill in the got offsets for everything therein. */ - if (1 || something_changed) - elf64_alpha_calc_got_offsets (info); + elf64_alpha_calc_got_offsets (info); return TRUE; } @@ -2477,10 +2474,10 @@ elf64_alpha_size_plt_section_1 (struct a return TRUE; } -/* Called from relax_section to rebuild the PLT in light of - potential changes in the function's status. */ +/* Called from relax_section to rebuild the PLT in light of potential changes + in the function's status. */ -static bfd_boolean +static void elf64_alpha_size_plt_section (struct bfd_link_info *info) { asection *splt, *spltrel, *sgotplt; @@ -2490,7 +2487,7 @@ elf64_alpha_size_plt_section (struct bfd dynobj = elf_hash_table(info)->dynobj; splt = bfd_get_section_by_name (dynobj, ".plt"); if (splt == NULL) - return TRUE; + return; splt->size = 0; @@ -2499,6 +2496,7 @@ elf64_alpha_size_plt_section (struct bfd /* Every plt entry requires a JMP_SLOT relocation. */ spltrel = bfd_get_section_by_name (dynobj, ".rela.plt"); + entries = 0; if (splt->size) { if (elf64_alpha_use_secureplt) @@ -2506,8 +2504,6 @@ elf64_alpha_size_plt_section (struct bfd else entries = (splt->size - OLD_PLT_HEADER_SIZE) / OLD_PLT_ENTRY_SIZE; } - else - entries = 0; spltrel->size = entries * sizeof (Elf64_External_Rela); /* When using the secureplt, we need two words somewhere in the data @@ -2518,8 +2514,6 @@ elf64_alpha_size_plt_section (struct bfd sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); sgotplt->size = entries ? 16 : 0; } - - return TRUE; } static bfd_boolean @@ -2690,7 +2684,7 @@ elf64_alpha_size_rela_got_1 (struct alph /* Set the sizes of the dynamic relocation sections. */ -static bfd_boolean +static void elf64_alpha_size_rela_got_section (struct bfd_link_info *info) { unsigned long entries; @@ -2729,15 +2723,13 @@ elf64_alpha_size_rela_got_section (struc if (!srel) { BFD_ASSERT (entries == 0); - return TRUE; + return; } srel->size = sizeof (Elf64_External_Rela) * entries; /* Now do the non-local symbols. */ alpha_elf_link_hash_traverse (alpha_elf_hash_table (info), elf64_alpha_size_rela_got_1, info); - - return TRUE; } /* Set the sizes of the dynamic sections. */ @@ -3609,7 +3601,7 @@ elf64_alpha_relax_section (bfd *abfd, as struct alpha_elf_got_entry **local_got_entries; struct alpha_relax_info info; - /* We are not currently changing any sizes, so only one pass. */ + /* There's nothing to change, yet. */ *again = FALSE; if (link_info->relocatable @@ -3618,6 +3610,22 @@ elf64_alpha_relax_section (bfd *abfd, as || sec->reloc_count == 0) return TRUE; + /* Make sure our GOT and PLT tables are up-to-date. */ + if (alpha_elf_hash_table(link_info)->relax_trip != link_info->relax_trip) + { + alpha_elf_hash_table(link_info)->relax_trip = link_info->relax_trip; + + /* This should never fail after the initial round, since the only + error is GOT overflow, and relaxation only shrinks the table. */ + if (!elf64_alpha_size_got_sections (link_info)) + abort (); + if (elf_hash_table (link_info)->dynamic_sections_created) + { + elf64_alpha_size_plt_section (link_info); + elf64_alpha_size_rela_got_section (link_info); + } + } + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; local_got_entries = alpha_elf_tdata(abfd)->local_got_entries; @@ -3827,13 +3835,6 @@ elf64_alpha_relax_section (bfd *abfd, as } } - if (!elf64_alpha_size_plt_section (link_info)) - return FALSE; - if (!elf64_alpha_size_got_sections (link_info)) - return FALSE; - if (!elf64_alpha_size_rela_got_section (link_info)) - return FALSE; - if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) { Index: include/bfdlink.h =================================================================== RCS file: /cvs/src/src/include/bfdlink.h,v retrieving revision 1.65 diff -u -p -r1.65 bfdlink.h --- include/bfdlink.h 21 Feb 2007 16:43:50 -0000 1.65 +++ include/bfdlink.h 10 Apr 2007 17:36:17 -0000 @@ -424,6 +424,11 @@ struct bfd_link_info current pass, starting from 0. */ int relax_pass; + /* Number of relaxation trips. This number is incremented every + time the relaxation pass is restarted due to a previous + relaxation returning true in *AGAIN. */ + int relax_trip; + /* Non-zero if auto-import thunks for DATA items in pei386 DLLs should be generated/linked against. Set to 1 if this feature is explicitly requested by the user, -1 if enabled by default. */ Index: ld/ldlang.c =================================================================== RCS file: /cvs/src/src/ld/ldlang.c,v retrieving revision 1.256 diff -u -p -r1.256 ldlang.c --- ld/ldlang.c 29 Mar 2007 17:16:05 -0000 1.256 +++ ld/ldlang.c 10 Apr 2007 17:36:20 -0000 @@ -5664,9 +5664,11 @@ relax_sections (void) /* Keep relaxing until bfd_relax_section gives up. */ bfd_boolean relax_again; + link_info.relax_trip = -1; do { relax_again = FALSE; + link_info.relax_trip++; /* Note: pe-dll.c does something like this also. If you find you need to change this code, you probably need to change