Gold linker patch to split unlikely text into a separate segment

Sriraman Tallam via binutils binutils@sourceware.org
Thu Oct 5 18:41:00 GMT 2017


On Wed, Oct 4, 2017 at 5:12 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On 10/4/17, Sriraman Tallam <tmsriram@google.com> wrote:
>> Hi,
>>
>>      This patch adds an option to gold to create a new ELF segment for
>> code determined unlikely by the compiler.  Currently, this can be done
>> with a linker plugin but I was wondering if it is fine to have this
>> support in gold with an option for ease of use.
>>
>>      The advantages of doing this are:
>>
>> * We could only map the hot segment to huge pages to keep iTLB misses low
>> * We could munlock the unlikely segment
>>
>> Is this alright?
>>
>> ChangeLog entry:
>>
>> * options.h (text_unlikely_segment): New option.
>> * layout.cc (Layout::layout): Create new output section
>> for .text.unlikely sections with the new option.
>> (Layout::segment_precedes): Check for the new option
>> when segment flags match.
>>
>> Patch attached.
>>
>
> This is an interesting approach.  Do you have some performace
> numbers?

With function re-ordering of hot code, segment splitting and mapping
only hot code to huge pages, we see a reduction in iTLB misses
translating to performance improvements of 0.5 to 1% on some of our
benchmarks.

>
> 2 Comments:
>
> 1.  I'd prefer "-z text-unlikely-segment" with '-', instead of '_'.
> 2.  Need a testcase.

Done and patch attached.

Thanks
Sri

>
> --
> H.J.
-------------- next part --------------
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 697a40ade1..6757961e92 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,14 @@
+2017-10-04  Sriraman Tallam  <tmsriram@google.com>
+
+	* options.h (-z,text_unlikely_segment): New option.
+	* layout.cc (Layout::layout): Create new output section
+	for .text.unlikely sections with the new option.
+	(Layout::segment_precedes): Check for the new option
+	when segment flags match.
+	* testsuite/text_unlikely_segment.cc: New test source.
+	* testsuite/text_unlikely_segment.sh: New test script.
+	* testsuite/Makefile.am (text_unlikely_segment): New test.
+
 2017-09-26  Cary Coutant  <ccoutant@gmail.com>
 
 	PR gold/22213
diff --git a/gold/Makefile.in b/gold/Makefile.in
index a3c8b03bec..f5dbd2e025 100644
--- a/gold/Makefile.in
+++ b/gold/Makefile.in
@@ -87,8 +87,8 @@ subdir = .
 DIST_COMMON = NEWS README ChangeLog $(srcdir)/Makefile.in \
 	$(srcdir)/Makefile.am $(top_srcdir)/configure \
 	$(am__configure_deps) $(srcdir)/config.in \
-	$(srcdir)/../mkinstalldirs $(top_srcdir)/po/Make-in ffsll.c \
-	ftruncate.c mremap.c pread.c yyscript.h yyscript.c \
+	$(srcdir)/../mkinstalldirs $(top_srcdir)/po/Make-in mremap.c \
+	ftruncate.c ffsll.c pread.c yyscript.h yyscript.c \
 	$(srcdir)/../depcomp $(srcdir)/../ylwrap
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
diff --git a/gold/layout.cc b/gold/layout.cc
index 5f25faea55..5d0a885c52 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -1180,11 +1180,17 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
     {
       // Plugins can choose to place one or more subsets of sections in
       // unique segments and this is done by mapping these section subsets
-      // to unique output sections.  Check if this section needs to be
-      // remapped to a unique output section.
+      // to unique output sections.  All ".text.unlikely.*" sections can be
+      // moved to a unique segment with --text-unlikely-segment option.
+      // Check if this section needs to be remapped to a unique output section.
       Section_segment_map::iterator it
 	  = this->section_segment_map_.find(Const_section_id(object, shndx));
-      if (it == this->section_segment_map_.end())
+      bool text_unlikely_segment
+          = (parameters->options().text_unlikely_segment()
+             && is_prefix_of(".text.unlikely",
+                             object->section_name(shndx).c_str()));
+      if (it == this->section_segment_map_.end()
+	  && !text_unlikely_segment)
 	{
 	  os = this->choose_output_section(object, name, sh_type,
 					   shdr.get_sh_flags(), true,
@@ -1198,7 +1204,8 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
 	  elfcpp::Elf_Xword flags
 	    = this->get_output_section_flags(shdr.get_sh_flags());
 
-	  const char* os_name = it->second->name;
+	  const char* os_name = text_unlikely_segment ?
+	                        ".text.unlikely" : it->second->name;
 	  Stringpool::Key name_key;
 	  os_name = this->namepool_.add(os_name, true, &name_key);
 	  os = this->get_output_section(os_name, name_key, sh_type, flags,
@@ -1206,8 +1213,11 @@ Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
 	  if (!os->is_unique_segment())
 	    {
 	      os->set_is_unique_segment();
-	      os->set_extra_segment_flags(it->second->flags);
-	      os->set_segment_alignment(it->second->align);
+              if (!text_unlikely_segment)
+		{
+		  os->set_extra_segment_flags(it->second->flags);
+		  os->set_segment_alignment(it->second->align);
+		}
 	    }
 	}
       if (os == NULL)
@@ -3449,7 +3459,8 @@ Layout::segment_precedes(const Output_segment* seg1,
   // here if plugins want unique segments for subsets of sections.
   gold_assert(this->script_options_->saw_phdrs_clause()
 	      || parameters->options().any_section_start()
-	      || this->is_unique_segment_for_sections_specified());
+	      || this->is_unique_segment_for_sections_specified()
+	      || parameters->options().text_unlikely_segment());
   return false;
 }
 
diff --git a/gold/options.h b/gold/options.h
index 93f81b29af..8828c81016 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -1492,6 +1492,11 @@ class General_options
   DEFINE_bool_alias(textoff, text, options::DASH_Z, '\0',
 		    N_("Permit relocations in read-only segments"),
 		    NULL, true);
+  DEFINE_bool(text_unlikely_segment, options::DASH_Z, '\0', false,
+	      N_("Move .text.unlikely sections to a separate ELF segment."),
+	      N_("Do not move .text.unlikely sections to a separate "
+		 "ELF segment."));
+
 
  public:
   typedef options::Dir_list Dir_list;
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index cae47f1e09..946f88b0db 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -340,6 +340,16 @@ section_sorting_name: section_sorting_name.o gcctestdir/ld
 section_sorting_name.stdout: section_sorting_name
 	$(TEST_NM) -n --synthetic section_sorting_name > section_sorting_name.stdout
 
+check_SCRIPTS += text_unlikely_segment.sh
+check_DATA += text_unlikely_segment_readelf.stdout
+MOSTLYCLEANFILES += text_unlikely_segment
+text_unlikely_segment.o: text_unlikely_segment.cc
+	$(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $<
+text_unlikely_segment: text_unlikely_segment.o gcctestdir/ld
+	$(CXXLINK)  -Bgcctestdir/ -Wl,-z,text-unlikely-segment text_unlikely_segment.o
+text_unlikely_segment_readelf.stdout: text_unlikely_segment
+	$(TEST_READELF) -Wl $< >$@
+
 check_PROGRAMS += icf_virtual_function_folding_test
 MOSTLYCLEANFILES += icf_virtual_function_folding_test icf_virtual_function_folding_test.map
 icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc
diff --git a/gold/testsuite/text_unlikely_segment.cc b/gold/testsuite/text_unlikely_segment.cc
index e69de29bb2..f8e6dd7e66 100644
--- a/gold/testsuite/text_unlikely_segment.cc
+++ b/gold/testsuite/text_unlikely_segment.cc
@@ -0,0 +1,30 @@
+/* text_unlikey_segment.cc -- a test case for gold
+
+   Copyright (C) 2017 onwards 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.  */
+
+__attribute__((section(".text.unlikely")))
+int foo(void) {
+  return 0;
+}
+
+int main(void) {
+  return 0;
+}
diff --git a/gold/testsuite/text_unlikely_segment.sh b/gold/testsuite/text_unlikely_segment.sh
index e69de29bb2..b01fe6c715 100755
--- a/gold/testsuite/text_unlikely_segment.sh
+++ b/gold/testsuite/text_unlikely_segment.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+# plugin_final_layout.sh -- test
+
+# Copyright (C) 2011-2017 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 -z,text-unlikely-segment works as
+# intended.  File text_unlikely_segment.cc is part of this test.
+
+
+set -e
+
+# With readelf -l, an ELF Section to Segment mapping is printed as :
+##############################################
+#  Section to Segment mapping:
+#  Segment Sections...
+#  ...
+#     0x     .text.unlikely
+#  ...
+##############################################
+# Check if .text.unlikely is the only section in the segment.
+check_unique_segment()
+{
+    awk "
+BEGIN { saw_section = 0; saw_unique = 0; }
+/$2/ { saw_section = 1; }
+/[ ]*0[0-9][ ]*$2[ ]*\$/ { saw_unique = 1; }
+END {
+      if (!saw_section)
+	{
+	  printf \"Section $2 not seen in output\\n\";
+	  exit 1;
+	}
+      else if (!saw_unique)
+	{
+	  printf \"Unique segment not seen for: $2\\n\";
+	  exit 1;
+	}
+    }" $1
+}
+
+check_unique_segment text_unlikely_segment_readelf.stdout ".text.unlikely"


More information about the Binutils mailing list