public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Add support for sparc GOTDATA optimizations in Gold.
@ 2012-04-11 22:29 David Miller
  2012-04-17  0:16 ` Ian Lance Taylor
  0 siblings, 1 reply; 3+ messages in thread
From: David Miller @ 2012-04-11 22:29 UTC (permalink / raw)
  To: binutils


Basically, this mirrors the logic in the BFD linker which
already supports this transformation.

For a PIC transformation of the form:

	sethi	%gdop_hix22(symbol), %g1
	xor	%g1, %gdop_lox10(symbol), %g1
	ld	[%l7 + %g1], %o0

into:

	sethi	%hi(~(symbol - got_base)), %g1
	xor	%g1, %lo(((symbol - got_base)&0x3ff)|0x1c00), %g1
	add	%l7, %g1, %o0

and also eliminates the GOT slot.  The funny arithmatic and the use of
'xor' is so that on 64-bit arbitrary 32-bit negative offsets can work
and are properly sign extended.

gold/

	* sparc.cc (Target_sparc::got_address): New function.
	(Sparc_relocate_functions::gdop_hix22): New function.
	(Sparc_relocate_functions::gdop_lox10): New function.
	(Target_sparc::Scan::local): Do not emit a GOT entry for GOTDATA
	relocs.
	(Target_sparc::Scan::local): Likewise if the global symbol is not
	preemptible and is not IFUNC.
	(Target_sparc::Relocate::relocate): Perform GOTDATA code
	transformations for local and non-preemptible non-IFUNC global
	symbols.
---
 gold/sparc.cc |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 102 insertions(+), 1 deletion(-)

diff --git a/gold/sparc.cc b/gold/sparc.cc
index d1e83eb..a513a00 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -185,6 +185,15 @@ class Target_sparc : public Sized_target<size, big_endian>
     return this->got_size() / (size / 8);
   }
 
+  // Return the address of the GOT.
+  uint64_t
+  got_address() const
+  {
+    if (this->got_ == NULL)
+      return 0;
+    return this->got_->address();
+  }
+
   // Return the number of entries in the PLT.
   unsigned int
   plt_entry_count() const;
@@ -1065,6 +1074,28 @@ public:
     elfcpp::Swap<32, true>::writeval(wv, val | reloc);
   }
 
+  // R_SPARC_GOTDATA_OP_HIX22: @gdopoff(Symbol + Addend) >> 10
+  static inline void
+  gdop_hix22(unsigned char* view,
+	     typename elfcpp::Elf_types<size>::Elf_Addr value,
+	     typename elfcpp::Elf_types<size>::Elf_Addr addend)
+  {
+    typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
+    Valtype* wv = reinterpret_cast<Valtype*>(view);
+    Valtype val = elfcpp::Swap<32, true>::readval(wv);
+    int32_t reloc = (value + addend);
+
+    val &= ~0x3fffff;
+
+    if (reloc < 0)
+      reloc ^= ~(Valtype)0;
+    reloc >>= 10;
+
+    reloc &= 0x3fffff;
+
+    elfcpp::Swap<32, true>::writeval(wv, val | reloc);
+  }
+
   // R_SPARC_HIX22: ((Symbol + Addend) ^ 0xffffffffffffffff) >> 10
   static inline void
   hix22(unsigned char* view,
@@ -1106,6 +1137,26 @@ public:
     elfcpp::Swap<32, true>::writeval(wv, val | reloc);
   }
 
+  // R_SPARC_GOTDATA_OP_LOX10: (@gdopoff(Symbol + Addend) & 0x3ff) | 0x1c00
+  static inline void
+  gdop_lox10(unsigned char* view,
+	     typename elfcpp::Elf_types<size>::Elf_Addr value,
+	     typename elfcpp::Elf_types<size>::Elf_Addr addend)
+  {
+    typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
+    Valtype* wv = reinterpret_cast<Valtype*>(view);
+    Valtype val = elfcpp::Swap<32, true>::readval(wv);
+    int32_t reloc = (value + addend);
+
+    if (reloc < 0)
+      reloc = (reloc & 0x3ff) | 0x1c00;
+    else
+      reloc = (reloc & 0x3ff);
+
+    val &= ~0x1fff;
+    elfcpp::Swap<32, true>::writeval(wv, val | reloc);
+  }
+
   // R_SPARC_LOX10: ((Symbol + Addend) & 0x3ff) | 0x1c00
   static inline void
   lox10(unsigned char* view,
@@ -2266,6 +2317,10 @@ Target_sparc<size, big_endian>::Scan::local(
     case elfcpp::R_SPARC_GOTDATA_OP:
     case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
     case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+      // We will optimize this into a GOT relative relocation
+      // and code transform the GOT load into an addition.
+      break;
+
     case elfcpp::R_SPARC_GOT10:
     case elfcpp::R_SPARC_GOT13:
     case elfcpp::R_SPARC_GOT22:
@@ -2695,6 +2750,15 @@ Target_sparc<size, big_endian>::Scan::global(
     case elfcpp::R_SPARC_GOTDATA_OP:
     case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
     case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+      if (gsym->is_defined()
+          && !gsym->is_from_dynobj()
+          && !gsym->is_preemptible()
+	  && !is_ifunc)
+	{
+	  // We will optimize this into a GOT relative relocation
+	  // and code transform the GOT load into an addition.
+	  break;
+	}
     case elfcpp::R_SPARC_GOT10:
     case elfcpp::R_SPARC_GOT13:
     case elfcpp::R_SPARC_GOT22:
@@ -3076,6 +3140,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
 			typename elfcpp::Elf_types<size>::Elf_Addr address,
 			section_size_type view_size)
 {
+  bool orig_is_ifunc = psymval->is_ifunc_symbol();
   r_type &= 0xff;
 
   if (this->ignore_gd_add_)
@@ -3108,7 +3173,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
 
       psymval = &symval;
     }
-  else if (gsym == NULL && psymval->is_ifunc_symbol())
+  else if (gsym == NULL && orig_is_ifunc)
     {
       unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
       if (object->local_has_plt_offset(r_sym))
@@ -3125,11 +3190,24 @@ Target_sparc<size, big_endian>::Relocate::relocate(
   // pointer points to the beginning, not the end, of the table.
   // So we just use the plain offset.
   unsigned int got_offset = 0;
+  bool gdop_valid = false;
   switch (r_type)
     {
     case elfcpp::R_SPARC_GOTDATA_OP:
     case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
     case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+      // If this is local, we did not create a GOT entry because we
+      // intend to transform this into a GOT relative relocation.
+      if (gsym == NULL
+	  || (gsym->is_defined()
+	      && !gsym->is_from_dynobj()
+	      && !gsym->is_preemptible()
+	      && !orig_is_ifunc))
+	{
+	  got_offset = psymval->value(object, 0) - target->got_address();
+	  gdop_valid = true;
+	  break;
+	}
     case elfcpp::R_SPARC_GOT10:
     case elfcpp::R_SPARC_GOT13:
     case elfcpp::R_SPARC_GOT22:
@@ -3248,14 +3326,37 @@ Target_sparc<size, big_endian>::Relocate::relocate(
       break;
 
     case elfcpp::R_SPARC_GOTDATA_OP:
+      if (gdop_valid)
+	{
+	  typedef typename elfcpp::Swap<32, true>::Valtype Insntype;
+	  Insntype* wv = reinterpret_cast<Insntype*>(view);
+	  Insntype val;
+
+	  // {ld,ldx} [%rs1 + %rs2], %rd --> add %rs1, %rs2, %rd
+	  val = elfcpp::Swap<32, true>::readval(wv);
+	  val = 0x80000000 | (val & 0x3e07c01f);
+	  elfcpp::Swap<32, true>::writeval(wv, val);
+	}
       break;
 
     case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+      if (gdop_valid)
+	{
+	  Reloc::gdop_lox10(view, got_offset, addend);
+	  break;
+	}
+      /* Fall through.  */
     case elfcpp::R_SPARC_GOT13:
       Reloc::rela32_13(view, got_offset, addend);
       break;
 
     case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
+      if (gdop_valid)
+	{
+	  Reloc::gdop_hix22(view, got_offset, addend);
+	  break;
+	}
+      /* Fall through.  */
     case elfcpp::R_SPARC_GOT22:
       Reloc::hi22(view, got_offset, addend);
       break;
-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Add support for sparc GOTDATA optimizations in Gold.
  2012-04-11 22:29 [PATCH] Add support for sparc GOTDATA optimizations in Gold David Miller
@ 2012-04-17  0:16 ` Ian Lance Taylor
  2012-04-17  2:33   ` David Miller
  0 siblings, 1 reply; 3+ messages in thread
From: Ian Lance Taylor @ 2012-04-17  0:16 UTC (permalink / raw)
  To: David Miller; +Cc: binutils

David Miller <davem@davemloft.net> writes:

> gold/
>
> 	* sparc.cc (Target_sparc::got_address): New function.
> 	(Sparc_relocate_functions::gdop_hix22): New function.
> 	(Sparc_relocate_functions::gdop_lox10): New function.
> 	(Target_sparc::Scan::local): Do not emit a GOT entry for GOTDATA
> 	relocs.
> 	(Target_sparc::Scan::local): Likewise if the global symbol is not
> 	preemptible and is not IFUNC.
> 	(Target_sparc::Relocate::relocate): Perform GOTDATA code
> 	transformations for local and non-preemptible non-IFUNC global
> 	symbols.

> +  // R_SPARC_GOTDATA_OP_HIX22: @gdopoff(Symbol + Addend) >> 10
> +  static inline void
> +  gdop_hix22(unsigned char* view,
> +	     typename elfcpp::Elf_types<size>::Elf_Addr value,
> +	     typename elfcpp::Elf_types<size>::Elf_Addr addend)
> +  {
> +    typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
> +    Valtype* wv = reinterpret_cast<Valtype*>(view);
> +    Valtype val = elfcpp::Swap<32, true>::readval(wv);
> +    int32_t reloc = (value + addend);
> +
> +    val &= ~0x3fffff;
> +
> +    if (reloc < 0)
> +      reloc ^= ~(Valtype)0;
> +    reloc >>= 10;
> +
> +    reloc &= 0x3fffff;
> +
> +    elfcpp::Swap<32, true>::writeval(wv, val | reloc);
> +  }

I think I would change the line setting reloc to
    int32_t reloc = static_cast<int32_t>(value + addend);
to make clear that you are intentionally dropping some bits for the
64-bit target.

The line
    reloc ^= ~(Valtype)0;
should probably be
    reloc ^= ~static_cast<int32_t>(0);
or perhaps even, for extreme clarity,
    reloc = static_cast<int32_t>(static_cast<uint32_t>(reloc) 
                                 ^ static_cast<uint32_t>(0));
to avoid bit operations on signed types.

This is OK with changes along those lines.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Add support for sparc GOTDATA optimizations in Gold.
  2012-04-17  0:16 ` Ian Lance Taylor
@ 2012-04-17  2:33   ` David Miller
  0 siblings, 0 replies; 3+ messages in thread
From: David Miller @ 2012-04-17  2:33 UTC (permalink / raw)
  To: iant; +Cc: binutils

From: Ian Lance Taylor <iant@google.com>
Date: Mon, 16 Apr 2012 17:15:35 -0700

> I think I would change the line setting reloc to
>     int32_t reloc = static_cast<int32_t>(value + addend);
> to make clear that you are intentionally dropping some bits for the
> 64-bit target.
> 
> The line
>     reloc ^= ~(Valtype)0;
> should probably be
>     reloc ^= ~static_cast<int32_t>(0);
> or perhaps even, for extreme clarity,
>     reloc = static_cast<int32_t>(static_cast<uint32_t>(reloc) 
>                                  ^ static_cast<uint32_t>(0));
> to avoid bit operations on signed types.
> 
> This is OK with changes along those lines.

Ok, I choose the medium level of clarity :-)

Thanks.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-04-17  2:30 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-11 22:29 [PATCH] Add support for sparc GOTDATA optimizations in Gold David Miller
2012-04-17  0:16 ` Ian Lance Taylor
2012-04-17  2:33   ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).