Group text sections with prefixes .text.unlikely,.text.hot and .text.startup

by default.


2012-12-18  Sriraman Tallam  <tmsriram@google.com>

	* layout.cc (Layout::is_section_name_prefix_grouped): New function.
	* layout.h (Layout::is_section_name_prefix_grouped): New function.
	* output.cc (Output_section::add_input_section): Check if section
	name contains special prefix.  Keep input sections to sort such
	sections.
	(Output_section::Input_section_sort_section_order_index_compare
	 ::operator()): Group sections according to prefixes.
	* (Output_section::sort_attached_input_sections): Add condition
	to Input_section_entry constructor call.
	* testsuite/Makefile.am (text_section_grouping): New test.
	* testsuite/Makefile.in: Regenerate.
	* testsuite/text_section_grouping.cc: New file.
	* testsuite/text_section_grouping.sh: New file.
This commit is contained in:
Sriraman Tallam 2012-12-19 02:55:15 +00:00
parent e0e51b2391
commit 28f2a4ac6f
8 changed files with 265 additions and 7 deletions

View File

@ -1,3 +1,19 @@
2012-12-18 Sriraman Tallam <tmsriram@google.com>
* layout.cc (Layout::is_section_name_prefix_grouped): New function.
* layout.h (Layout::is_section_name_prefix_grouped): New function.
* output.cc (Output_section::add_input_section): Check if section
name contains special prefix. Keep input sections to sort such
sections.
(Output_section::Input_section_sort_section_order_index_compare
::operator()): Group sections according to prefixes.
* (Output_section::sort_attached_input_sections): Add condition
to Input_section_entry constructor call.
* testsuite/Makefile.am (text_section_grouping): New test.
* testsuite/Makefile.in: Regenerate.
* testsuite/text_section_grouping.cc: New file.
* testsuite/text_section_grouping.sh: New file.
2012-12-17 Nick Clifton <nickc@redhat.com>
* Makefile.am: Add copyright notice.

View File

@ -2409,6 +2409,20 @@ Layout::relaxation_loop_body(
return off;
}
// By default, gold groups input sections with certain prefixes. This
// function returns true if this section name NAME contains such a prefix.
bool
Layout::is_section_name_prefix_grouped(const char *name)
{
if (is_prefix_of(".text.unlikely", name)
|| is_prefix_of(".text.startup", name)
|| is_prefix_of(".text.hot", name))
return true;
return false;
}
// Search the list of patterns and find the postion of the given section
// name in the output section. If the section name matches a glob
// pattern and a non-glob name, then the non-glob position takes

View File

@ -552,6 +552,11 @@ class Layout
// Maps section SECN to SEGMENT s.
void
insert_section_segment_map(Const_section_id secn, Unique_segment_info *s);
// By default, gold groups input sections with certain prefixes. This
// function returns true if this section name NAME contains such a prefix.
bool
is_section_name_prefix_grouped(const char *name);
bool
is_section_ordering_specified()

View File

@ -2478,6 +2478,19 @@ Output_section::add_input_section(Layout* layout,
}
}
// The GNU linker groups input sections whose names match .text.unlikely.*.
// This is used to get better code layout. We are compatible.
// Additionally, it could also be beneficial to group .text.hot.*,
// .text.startup.* prefixed input sections. Function
// "is_section_name_prefix_grouped" in layout.cc determines the input
// section prefixes that must be grouped.
if (!have_sections_script
&& !parameters->options().relocatable()
&& !this->input_section_order_specified()
&& !this->must_sort_attached_input_sections()
&& layout->is_section_name_prefix_grouped(secname))
this->set_input_section_order_specified();
// We need to keep track of this section if we are already keeping
// track of sections, or if we are relaxing. Also, if this is a
// section which requires sorting, or which may require sorting in
@ -2491,7 +2504,8 @@ Output_section::add_input_section(Layout* layout,
|| this->must_sort_attached_input_sections()
|| parameters->options().user_set_Map()
|| parameters->target().may_relax()
|| layout->is_section_ordering_specified())
|| layout->is_section_ordering_specified()
|| this->input_section_order_specified())
{
Input_section isecn(object, shndx, input_section_size, addralign);
/* If section ordering is requested by specifying a ordering file,
@ -3484,7 +3498,9 @@ Output_section::Input_section_sort_init_fini_compare::operator()(
// Return true if S1 should come before S2. Sections that do not match
// any pattern in the section ordering file are placed ahead of the sections
// that match some pattern.
// that match some pattern. This function is also used to group text according
// to their prefix. The following prefixes are recognized: ".text.startup",
// ".text.hot", and ".text.unlikely".
bool
Output_section::Input_section_sort_section_order_index_compare::operator()(
@ -3494,11 +3510,59 @@ Output_section::Input_section_sort_section_order_index_compare::operator()(
unsigned int s1_secn_index = s1.input_section().section_order_index();
unsigned int s2_secn_index = s2.input_section().section_order_index();
// Keep input order if section ordering cannot determine order.
if (s1_secn_index == s2_secn_index)
return s1.index() < s2.index();
// If section ordering is specified, it takes precedence.
if (s1_secn_index != s2_secn_index)
return s1_secn_index < s2_secn_index;
return s1_secn_index < s2_secn_index;
// Sort all the sections with no names to the end.
if (!s1.section_has_name() || !s2.section_has_name())
{
if (s1.section_has_name())
return true;
if (s2.section_has_name())
return false;
return s1.index() < s2.index();
}
// If it is a text section use the following order:
// .text.unlikely, .text.startup, .text.hot. The prefixes
// must match those in function is_section_name_prefix_grouped
// in layout.cc
const char* section_prefix [] =
{
".text.unlikely",
".text.startup",
".text.hot"
};
const unsigned int num_prefixes
= sizeof(section_prefix) / sizeof(const char*);
unsigned int s1_group_index = num_prefixes;
unsigned int s2_group_index = num_prefixes;
unsigned int flag_done = 0;
for (unsigned int i = 0; i < num_prefixes && flag_done < 2; i++)
{
if (s1_group_index == num_prefixes
&& is_prefix_of(section_prefix[i], s1.section_name().c_str()))
{
s1_group_index = i;
flag_done++;
}
if (s2_group_index == num_prefixes
&& is_prefix_of(section_prefix[i], s2.section_name().c_str()))
{
s2_group_index = i;
flag_done++;
}
}
if (s1_group_index == s2_group_index)
return s1.index() < s2.index();
else
return s1_group_index < s2_group_index;
}
// This updates the section order index of input sections according to the
@ -3559,7 +3623,8 @@ Output_section::sort_attached_input_sections()
p != this->input_sections_.end();
++p, ++i)
sort_list.push_back(Input_section_sort_entry(*p, i,
this->must_sort_attached_input_sections()));
(this->must_sort_attached_input_sections()
|| this->input_section_order_specified())));
// Sort the input sections.
if (this->must_sort_attached_input_sections())

View File

@ -250,6 +250,16 @@ final_layout: final_layout.o final_layout_sequence.txt gcctestdir/ld
final_layout.stdout: final_layout
$(TEST_NM) -n --synthetic final_layout > final_layout.stdout
check_SCRIPTS += text_section_grouping.sh
check_DATA += text_section_grouping.stdout
MOSTLYCLEANFILES += text_section_grouping
text_section_grouping.o: text_section_grouping.cc
$(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $<
text_section_grouping: text_section_grouping.o gcctestdir/ld
$(CXXLINK) -Bgcctestdir/ text_section_grouping.o
text_section_grouping.stdout: text_section_grouping
$(TEST_NM) -n --synthetic text_section_grouping > text_section_grouping.stdout
check_PROGRAMS += icf_virtual_function_folding_test
MOSTLYCLEANFILES += icf_virtual_function_folding_test
icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc

View File

@ -81,6 +81,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_grouping.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_sht_rel_addend_test.sh \
@ -111,6 +112,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_1.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_2.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_grouping.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_sht_rel_addend_test.stdout \
@ -122,6 +124,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_test icf_keep_unique_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test icf_safe_so_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ text_section_grouping \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout_sequence.txt \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_virtual_function_folding_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test \
@ -3701,6 +3704,8 @@ icf_safe_so_test.sh.log: icf_safe_so_test.sh
@p='icf_safe_so_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
final_layout.sh.log: final_layout.sh
@p='final_layout.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
text_section_grouping.sh.log: text_section_grouping.sh
@p='text_section_grouping.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
icf_preemptible_functions_test.sh.log: icf_preemptible_functions_test.sh
@p='icf_preemptible_functions_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
icf_string_merge_test.sh.log: icf_string_merge_test.sh
@ -4348,6 +4353,12 @@ uninstall-am:
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--section-ordering-file,final_layout_sequence.txt final_layout.o
@GCC_TRUE@@NATIVE_LINKER_TRUE@final_layout.stdout: final_layout
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -n --synthetic final_layout > final_layout.stdout
@GCC_TRUE@@NATIVE_LINKER_TRUE@text_section_grouping.o: text_section_grouping.cc
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $<
@GCC_TRUE@@NATIVE_LINKER_TRUE@text_section_grouping: text_section_grouping.o gcctestdir/ld
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ text_section_grouping.o
@GCC_TRUE@@NATIVE_LINKER_TRUE@text_section_grouping.stdout: text_section_grouping
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -n --synthetic text_section_grouping > text_section_grouping.stdout
@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIE -g -o $@ $<
@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test: icf_virtual_function_folding_test.o gcctestdir/ld

View File

@ -0,0 +1,72 @@
// text_section_grouping.cc -- a test case for gold
// Copyright 2012 Free Software Foundation, Inc.
// Written by Sriraman Tallam <tmsriram@google.com>.
// This file is part of gold.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.
// The goal of this program is to verify if .text sections are grouped
// according to prefix. .text.unlikely, .text.startup and .text.hot should
// be grouped and placed together.
extern "C"
__attribute__ ((section(".text.hot.foo")))
int hot_foo()
{
return 1;
}
extern "C"
__attribute__ ((section(".text.startup.foo")))
int startup_foo()
{
return 1;
}
extern "C"
__attribute__ ((section(".text.unlikely.foo")))
int unlikely_foo()
{
return 1;
}
extern "C"
__attribute__ ((section(".text.hot.bar")))
int hot_bar()
{
return 1;
}
extern "C"
__attribute__ ((section(".text.startup.bar")))
int startup_bar()
{
return 1;
}
extern "C"
__attribute__ ((section(".text.unlikely.bar")))
int unlikely_bar()
{
return 1;
}
int main()
{
return 1;
}

View File

@ -0,0 +1,65 @@
#!/bin/sh
# text_section_grouping.sh -- test
# Copyright 2012 Free Software Foundation, Inc.
# Written by Sriraman Tallam <tmsriram@google.com>.
# This file is part of gold.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
# MA 02110-1301, USA.
# The goal of this program is to verify if .text sections are grouped
# according to prefix. .text.unlikely, .text.startup and .text.hot should
# be grouped and placed together.
set -e
check()
{
awk "
BEGIN { saw1 = 0; saw2 = 0; err = 0; }
/.*$2\$/ { saw1 = 1; }
/.*$3\$/ {
saw2 = 1;
if (!saw1)
{
printf \"layout of $2 and $3 is not right\\n\";
err = 1;
exit 1;
}
}
END {
if (!saw1 && !err)
{
printf \"did not see $2\\n\";
exit 1;
}
if (!saw2 && !err)
{
printf \"did not see $3\\n\";
exit 1;
}
}" $1
}
# addr (unlikely_*) < addr (startup_*) < addr (hot_*)
check text_section_grouping.stdout "unlikely_foo" "startup_foo"
check text_section_grouping.stdout "startup_foo" "hot_foo"
check text_section_grouping.stdout "unlikely_bar" "startup_bar"
check text_section_grouping.stdout "startup_bar" "hot_bar"
check text_section_grouping.stdout "unlikely_foo" "startup_bar"
check text_section_grouping.stdout "startup_foo" "hot_bar"