[PATCH] PR gold/17641

Ilya Tocar tocarip.intel@gmail.com
Fri Apr 3 15:27:00 GMT 2015


Hi,

This is 64-bit version of:
https://sourceware.org/ml/binutils/2015-04/msg00023.html

Ok for trunk? 

---
 gold/ChangeLog                      | 13 ++++++
 gold/testsuite/Makefile.am          | 41 ++++++++++++++++
 gold/testsuite/x86_64_mov_to_lea.sh | 34 ++++++++++++++
 gold/testsuite/x86_64_mov_to_lea1.s | 11 +++++
 gold/x86_64.cc                      | 93 ++++++++++++++++++++++++++++++++++---
 5 files changed, 186 insertions(+), 6 deletions(-)
 create mode 100755 gold/testsuite/x86_64_mov_to_lea.sh
 create mode 100644 gold/testsuite/x86_64_mov_to_lea1.s

diff --git a/gold/ChangeLog b/gold/ChangeLog
index 6a84355..677843d 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,16 @@
+2015-04-03  Ilya Tocar  <ilya.tocar@intel.com>
+
+	PR gold/17641
+	* x86_64.cc (Target_x86_64::can_convert_mov_to_lea): New.
+	(Target_x86_64::Scan::local): Don't create GOT entry, when we
+	can convert mov to lea.
+	(Target_x86_64::Scan::global): Ditto.
+	(Target_x86_64::Relocate::relocate): Convert mov foo@GOTPCREL(%rip),
+	%reg to lea foo(%rip), %reg if possible. 
+	* testsuite/Makefile.am (x86_64_mov_to_lea): New test.
+	* testsuite/x86_64_mov_to_lea1.s: New.
+	* testsuite/x86_64_mov_to_lea.sh: Ditto.
+
 2015-04-01  Ilya Tocar  <ilya.tocar@intel.com>
 
 	PR gold/17640
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index d64547e..e389548 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -962,6 +962,47 @@ endif FN_PTRS_IN_SO_WITHOUT_PIC
 
 endif TLS
 
+if DEFAULT_TARGET_X86_64
+
+check_SCRIPTS += x86_64_mov_to_lea.sh
+check_DATA += x86_64_mov_to_lea1.stdout x86_64_mov_to_lea2.stdout \
+	x86_64_mov_to_lea3.stdout x86_64_mov_to_lea4.stdout \
+	x86_64_mov_to_lea5.stdout x86_64_mov_to_lea6.stdout
+MOSTLYCLEANFILES += x86_64_mov_to_lea1 x86_64_mov_to_lea2 \
+	x86_64_mov_to_lea3 x86_64_mov_to_lea4 x86_64_mov_to_lea5 \
+	x86_64_mov_to_lea6
+
+x86_64_mov_to_lea1.o: x86_64_mov_to_lea1.s
+	$(TEST_AS) --64 -o $@ $<
+x86_64_mov_to_lea2.o: x86_64_mov_to_lea1.s
+	$(TEST_AS) --x32 -o $@ $<
+x86_64_mov_to_lea1: x86_64_mov_to_lea1.o
+	../ld-new -Bsymbolic -shared  -melf_x86_64  -o $@ $<
+x86_64_mov_to_lea2: x86_64_mov_to_lea1.o
+	../ld-new -pie -melf_x86_64  -o $@ $<
+x86_64_mov_to_lea3: x86_64_mov_to_lea1.o
+	../ld-new -melf_x86_64  -o $@ $<
+x86_64_mov_to_lea4: x86_64_mov_to_lea2.o
+	../ld-new -Bsymbolic -shared  -melf32_x86_64  -o $@ $<
+x86_64_mov_to_lea5: x86_64_mov_to_lea2.o
+	../ld-new -pie -melf32_x86_64  -o $@ $<
+x86_64_mov_to_lea6: x86_64_mov_to_lea2.o
+	../ld-new -melf32_x86_64  -o $@ $<
+x86_64_mov_to_lea1.stdout: x86_64_mov_to_lea1
+	$(TEST_OBJDUMP) -dw $< > $@
+x86_64_mov_to_lea2.stdout: x86_64_mov_to_lea2
+	$(TEST_OBJDUMP) -dw $< > $@
+x86_64_mov_to_lea3.stdout: x86_64_mov_to_lea3
+	$(TEST_OBJDUMP) -dw $< > $@
+x86_64_mov_to_lea4.stdout: x86_64_mov_to_lea4
+	$(TEST_OBJDUMP) -dw $< > $@
+x86_64_mov_to_lea5.stdout: x86_64_mov_to_lea5
+	$(TEST_OBJDUMP) -dw $< > $@
+x86_64_mov_to_lea6.stdout: x86_64_mov_to_lea6
+	$(TEST_OBJDUMP) -dw $< > $@
+
+endif DEFAULT_TARGET_X86_64
+
 if DEFAULT_TARGET_I386
 
 check_SCRIPTS += i386_mov_to_lea.sh
diff --git a/gold/testsuite/x86_64_mov_to_lea.sh b/gold/testsuite/x86_64_mov_to_lea.sh
new file mode 100755
index 0000000..c26151b
--- /dev/null
+++ b/gold/testsuite/x86_64_mov_to_lea.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# x86_64_mov_to_lea.sh -- a test for mov2lea conversion.
+
+# Copyright (C) 2010-2015 Free Software Foundation, Inc.
+# Written by Tocar Ilya <ilya.tocar@intel.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.
+
+set -e
+
+grep -q "lea    -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea1.stdout
+grep -q "lea    -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea2.stdout
+grep -q "lea    -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea3.stdout
+grep -q "lea    -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea4.stdout
+grep -q "lea    -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea5.stdout
+grep -q "lea    -0x[a-f0-9]\+(%rip),%rax" x86_64_mov_to_lea6.stdout
+
+exit 0
diff --git a/gold/testsuite/x86_64_mov_to_lea1.s b/gold/testsuite/x86_64_mov_to_lea1.s
new file mode 100644
index 0000000..4dce487
--- /dev/null
+++ b/gold/testsuite/x86_64_mov_to_lea1.s
@@ -0,0 +1,11 @@
+	.text
+	.globl	foo
+	.type	foo, @function
+foo:
+	ret
+	.size	foo, .-foo
+	.globl	_start
+	.type	_start, @function
+_start:
+	movq	foo@GOTPCREL(%rip), %rax
+	.size	_start, .-_start
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 4543c8a..007af1d 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -865,6 +865,25 @@ class Target_x86_64 : public Sized_target<size, false>
     get_size_for_reloc(unsigned int, Relobj*);
   };
 
+  // Check if relocation against this symbol is a candidate for
+  // conversion from
+  // mov foo@GOTPCREL(%rip), %reg
+  // to lea foo(%rip), %reg.
+  static bool
+  can_convert_mov_to_lea(const Symbol* gsym)
+  {
+    gold_assert(gsym != NULL);
+    return (gsym->type() != elfcpp::STT_GNU_IFUNC
+	    && !gsym->is_undefined ()
+	    && !gsym->is_from_dynobj()
+	    && !gsym->is_preemptible()
+	    && (!parameters->options().shared()
+		|| (gsym->visibility() != elfcpp::STV_DEFAULT
+		    && gsym->visibility() != elfcpp::STV_PROTECTED)
+		|| parameters->options().Bsymbolic())
+	    && strcmp(gsym->name(), "_DYNAMIC") != 0);
+  }
+
   // Adjust TLS relocation type based on the options and whether this
   // is a local symbol.
   static tls::Tls_optimization
@@ -2458,8 +2477,27 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
     case elfcpp::R_X86_64_GOTPCREL:
     case elfcpp::R_X86_64_GOTPLT64:
       {
-	// The symbol requires a GOT entry.
+	// The symbol requires a GOT section.
 	Output_data_got<64, false>* got = target->got_section(symtab, layout);
+
+	// If the relocation symbol isn't IFUNC,
+	// and is local, then we will convert
+	// mov foo@GOTPCREL(%rip), %reg
+	// to lea foo(%rip), %reg.
+	// in Relocate::relocate.
+	if (r_type == elfcpp::R_X86_64_GOTPCREL
+	    && reloc.get_r_offset() >= 2
+	    && !is_ifunc)
+	  {
+	    section_size_type stype;
+	    const unsigned char* view = object->section_contents(data_shndx,
+								 &stype, true);
+	    if (view[reloc.get_r_offset() - 2] == 0x8b)
+	      break;
+	  }
+
+
+	// The symbol requires a GOT entry.
 	unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
 
 	// For a STT_GNU_IFUNC symbol we want the PLT offset.  That
@@ -2867,6 +2905,22 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
       {
 	// The symbol requires a GOT entry.
 	Output_data_got<64, false>* got = target->got_section(symtab, layout);
+
+	// If we convert this from
+	// mov foo@GOTPCREL(%rip), %reg
+	// to lea foo(%rip), %reg.
+	// in Relocate::relocate, then there is nothing to do here.
+	if (r_type == elfcpp::R_X86_64_GOTPCREL
+	    && reloc.get_r_offset() >= 2
+	    && Target_x86_64<size>::can_convert_mov_to_lea(gsym))
+	  {
+	    section_size_type stype;
+	    const unsigned char* view = object->section_contents(data_shndx,
+								 &stype, true);
+	    if (view[reloc.get_r_offset() - 2] == 0x8b)
+	      break;
+	  }
+
 	if (gsym->final_value_is_known())
 	  {
 	    // For a STT_GNU_IFUNC symbol we want the PLT address.
@@ -3340,7 +3394,6 @@ Target_x86_64<size>::Relocate::relocate(
     case elfcpp::R_X86_64_GOT32:
     case elfcpp::R_X86_64_GOT64:
     case elfcpp::R_X86_64_GOTPLT64:
-    case elfcpp::R_X86_64_GOTPCREL:
     case elfcpp::R_X86_64_GOTPCREL64:
       if (gsym != NULL)
 	{
@@ -3486,10 +3539,38 @@ Target_x86_64<size>::Relocate::relocate(
 
     case elfcpp::R_X86_64_GOTPCREL:
       {
-	gold_assert(have_got_offset);
-	typename elfcpp::Elf_types<size>::Elf_Addr value;
-	value = target->got_plt_section()->address() + got_offset;
-	Relocate_functions<size, false>::pcrela32(view, value, addend, address);
+      // Convert
+      // mov foo@GOTPCREL(%rip), %reg
+      // to lea foo(%rip), %reg.
+      // if possible.
+      if (rela.get_r_offset() >= 2
+	  && view[-2] == 0x8b
+	  && ((gsym == NULL && !psymval->is_ifunc_symbol())
+	      || (gsym != NULL
+		  && Target_x86_64<size>::can_convert_mov_to_lea(gsym))))
+	{
+	  view[-2] = 0x8d;
+	  Relocate_functions<size, false>::pcrela32(view, object, psymval, addend,
+						    address);
+	}
+      else
+	{
+	  if (gsym != NULL)
+	    {
+	      gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+	      got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - target->got_size();
+	    }
+	  else
+	    {
+	      unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+	      gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+	      got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+			    - target->got_size());
+	    }
+	  typename elfcpp::Elf_types<size>::Elf_Addr value;
+	  value = target->got_plt_section()->address() + got_offset;
+	  Relocate_functions<size, false>::pcrela32(view, value, addend, address);
+	}
       }
       break;
 
-- 
1.8.3.1



More information about the Binutils mailing list