AVR: Sort .text.* input sections by their name.

Message ID 8f89fd03-7fa2-4c2d-a0fe-b4e99d5b2f12@gjlay.de
State New
Headers
Series AVR: Sort .text.* input sections by their name. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply

Commit Message

Georg-Johann Lay July 20, 2026, 6:44 p.m. UTC
  This patch sorts the .text.* input sections by their name
in order to increase code locality, e.g. for code from
libgcc and AVR-LibC.  For example, libgcc puts their
multiplications and helpers in .text.libgcc.mul, but
without SORT the linker may locate functions related by
their input section far apart, inserting function from
unrelated input sections in between them.

Ok for trunk?

Johann

--

AVR: Sort .text.* input sections by their name.

This patch sorts the .text.* input sections by their name
in order to increase code locality, e.g. for code from
libgcc and AVR-LibC.  For example, libgcc puts their
multiplications and helpers in .text.libgcc.mul, but
without SORT the linker may locate functions related by
their input section far apart, inserting function from
unrelated input sections in between them.

	PR ld/34415
ld/
	* scripttempl/avr.sc (text): SORT *(.text.*) input sections.
	by their name.
  

Comments

Alan Modra July 21, 2026, 5:46 a.m. UTC | #1
On Mon, Jul 20, 2026 at 08:44:51PM +0200, Georg-Johann Lay via Binutils wrote:
> This patch sorts the .text.* input sections by their name
> in order to increase code locality, e.g. for code from
> libgcc and AVR-LibC.  For example, libgcc puts their
> multiplications and helpers in .text.libgcc.mul, but
> without SORT the linker may locate functions related by
> their input section far apart, inserting function from
> unrelated input sections in between them.

While you may have found one particular case where sorting by name
helps, I suspect this is generally not a good idea.  I believe in
general you will make -ffunction-sections code locality worse by using
this patch.  Consider an object file with lots of small functions,
calls mostly within that object file.  You don't want to sort them
such that functions from other object files separate them.

> 	PR ld/34415
> ld/
> 	* scripttempl/avr.sc (text): SORT *(.text.*) input sections.
> 	by their name.
> 
> diff --git a/ld/scripttempl/avr.sc b/ld/scripttempl/avr.sc
> index b3cf421a78b..e918181700b 100644
> --- a/ld/scripttempl/avr.sc
> +++ b/ld/scripttempl/avr.sc
> @@ -248,7 +248,7 @@ cat <<EOF
>      KEEP (*(.init9))}
>      *(.text)
>      ${RELOCATING+. = ALIGN(2);
> -    *(.text.*)
> +    *(SORT(.text.*))
>      . = ALIGN(2);
>      *(.fini9)  /* _exit() starts here.  */
>      KEEP (*(.fini9))
  
Georg-Johann Lay July 21, 2026, 8:26 a.m. UTC | #2
Am 21.07.26 um 07:46 schrieb Alan Modra:
> On Mon, Jul 20, 2026 at 08:44:51PM +0200, Georg-Johann Lay via Binutils wrote:
>> This patch sorts the .text.* input sections by their name
>> in order to increase code locality, e.g. for code from
>> libgcc and AVR-LibC.  For example, libgcc puts their
>> multiplications and helpers in .text.libgcc.mul, but
>> without SORT the linker may locate functions related by
>> their input section far apart, inserting function from
>> unrelated input sections in between them.
> 
> While you may have found one particular case where sorting by name
> helps, I suspect this is generally not a good idea.  I believe in
> general you will make -ffunction-sections code locality worse by using
> this patch.  Consider an object file with lots of small functions,
> calls mostly within that object file.  You don't want to sort them
> such that functions from other object files separate them.

What really confused me is that LD my locate objects in the /same/
input section /not/ together, like with the

*(.text.*)

pattern from the current default linker scripts may result in
locations like:

0x200  funcA1  // in .text.A
0x300  funcB   // in .text.B
0x400  funcA2  // in .text.A

so that funcB separates funcA1 and funcA2.  Libs like libc and libgcc
usually have one function per object module and use sections like
.text.libgcc.mul for related stuff like mul helpers in the assumption
that stuff in the same input section will be close together.

Why aren't funcA1 and funcA2 put into one contiguous "block" of code?
The order of funvA1 and funcA2 doesn't really matter, some for the
placement of .text.A relative to .text.B.  But stuff in the /same/
input section should be put together, no?

What's the locator algorithm? As far as I know it just spits out
the stuff as it iterates over a hash table of objects?

Or does it try to minimize lengths in a dependency graph?
Like when there is a reference between fun1 and fun2 and
one between fun2 and fun3 but none between fun1 and fun3,
then minimizing web distance would be an allocation like
fun1, fun2, fun3 or fun3, fun2, fun1.  But optimizing that
would be expensive.

>> 	PR ld/34415
>> ld/
>> 	* scripttempl/avr.sc (text): SORT *(.text.*) input sections.
>> 	by their name.
>>
>> diff --git a/ld/scripttempl/avr.sc b/ld/scripttempl/avr.sc
>> index b3cf421a78b..e918181700b 100644
>> --- a/ld/scripttempl/avr.sc
>> +++ b/ld/scripttempl/avr.sc
>> @@ -248,7 +248,7 @@ cat <<EOF
>>       KEEP (*(.init9))}
>>       *(.text)
>>       ${RELOCATING+. = ALIGN(2);
>> -    *(.text.*)
>> +    *(SORT(.text.*))
>>       . = ALIGN(2);
>>       *(.fini9)  /* _exit() starts here.  */
>>       KEEP (*(.fini9))
  
Alan Modra July 21, 2026, 10:59 a.m. UTC | #3
On Tue, Jul 21, 2026 at 10:26:37AM +0200, Georg-Johann Lay wrote:
> Am 21.07.26 um 07:46 schrieb Alan Modra:
> > On Mon, Jul 20, 2026 at 08:44:51PM +0200, Georg-Johann Lay via Binutils wrote:
> > > This patch sorts the .text.* input sections by their name
> > > in order to increase code locality, e.g. for code from
> > > libgcc and AVR-LibC.  For example, libgcc puts their
> > > multiplications and helpers in .text.libgcc.mul, but
> > > without SORT the linker may locate functions related by
> > > their input section far apart, inserting function from
> > > unrelated input sections in between them.
> > 
> > While you may have found one particular case where sorting by name
> > helps, I suspect this is generally not a good idea.  I believe in
> > general you will make -ffunction-sections code locality worse by using
> > this patch.  Consider an object file with lots of small functions,
> > calls mostly within that object file.  You don't want to sort them
> > such that functions from other object files separate them.
> 
> What really confused me is that LD my locate objects in the /same/
> input section /not/ together, like with the
> 
> *(.text.*)
> 
> pattern from the current default linker scripts may result in
> locations like:
> 
> 0x200  funcA1  // in .text.A
> 0x300  funcB   // in .text.B
> 0x400  funcA2  // in .text.A
> 
> so that funcB separates funcA1 and funcA2.  Libs like libc and libgcc
> usually have one function per object module and use sections like
> .text.libgcc.mul for related stuff like mul helpers in the assumption
> that stuff in the same input section will be close together.
> 
> Why aren't funcA1 and funcA2 put into one contiguous "block" of code?
> The order of funvA1 and funcA2 doesn't really matter, some for the
> placement of .text.A relative to .text.B.  But stuff in the /same/
> input section should be put together, no?
> 
> What's the locator algorithm? As far as I know it just spits out
> the stuff as it iterates over a hash table of objects?

Conceptually the linker iterates over sections in each input file in
the order they appear in the file, with input files in the order they
appear on the command line (or are extracted from archives), placing
sections at the first input section statement match in the linker
script.  If there is no match (an orphan section) it is placed in an
output section of the same name as the input, with ld choosing a
reasonable place for that output section if it doesn't already exist.

One of the reasons you might not want to put .text.A sections together
is when compiling commonly named functions with -ffunction-sections.
For example, a static setup() function might occur in many input
files.  If all .text.setup sections were mashed together then some
would be placed far away from their callers.

> Or does it try to minimize lengths in a dependency graph?
> Like when there is a reference between fun1 and fun2 and
> one between fun2 and fun3 but none between fun1 and fun3,
> then minimizing web distance would be an allocation like
> fun1, fun2, fun3 or fun3, fun2, fun1.  But optimizing that
> would be expensive.
> 
> > > 	PR ld/34415
> > > ld/
> > > 	* scripttempl/avr.sc (text): SORT *(.text.*) input sections.
> > > 	by their name.
> > > 
> > > diff --git a/ld/scripttempl/avr.sc b/ld/scripttempl/avr.sc
> > > index b3cf421a78b..e918181700b 100644
> > > --- a/ld/scripttempl/avr.sc
> > > +++ b/ld/scripttempl/avr.sc
> > > @@ -248,7 +248,7 @@ cat <<EOF
> > >       KEEP (*(.init9))}
> > >       *(.text)
> > >       ${RELOCATING+. = ALIGN(2);
> > > -    *(.text.*)
> > > +    *(SORT(.text.*))
> > >       . = ALIGN(2);
> > >       *(.fini9)  /* _exit() starts here.  */
> > >       KEEP (*(.fini9))
  
Georg-Johann Lay July 21, 2026, 11:32 a.m. UTC | #4
Am 21.07.26 um 07:46 schrieb Alan Modra:
> On Mon, Jul 20, 2026 at 08:44:51PM +0200, Georg-Johann Lay via Binutils wrote:
>> This patch sorts the .text.* input sections by their name
>> in order to increase code locality, e.g. for code from
>> libgcc and AVR-LibC.  For example, libgcc puts their
>> multiplications and helpers in .text.libgcc.mul, but
>> without SORT the linker may locate functions related by
>> their input section far apart, inserting function from
>> unrelated input sections in between them.
> 
> While you may have found one particular case where sorting by name
> helps, I suspect this is generally not a good idea.  I believe in
> general you will make -ffunction-sections code locality worse by using
> this patch.  Consider an object file with lots of small functions,
> calls mostly within that object file.  You don't want to sort them
> such that functions from other object files separate them.

Maybe something like this would be more appropriate then?

     *(EXCLUDE_FILE(*/libgcc.a: */libm.a: */libc.a:) .text.*)
     */libgcc.a:(SORT(.text.*))
     */libc.a:(SORT(.text.*))
     */libm.a:(SORT(.text.*))

What I don't know is whether / works as a dir separator on
Window-ish hosts.  If not, maybe something like

     *(EXCLUDE_FILE(*[/\\]libgcc.a: *[/\\]libm.a: *[/\\]libc.a:) .text.*)

is the right patterns?  What I am also missing is a feature that
excludes specific input sections, like for example:

     .text.* !.text.foo.* .text.foo.bar .rodata.*

This would add .text.*, then remove .text.foo.*, and finally
add .text.foo.bar and .rodata.*.  Or am I missing some detail
in the ld docs? https://sourceware.org/binutils/docs/ld.html#Input-Section

Johann

>> 	PR ld/34415
>> ld/
>> 	* scripttempl/avr.sc (text): SORT *(.text.*) input sections.
>> 	by their name.
>>
>> diff --git a/ld/scripttempl/avr.sc b/ld/scripttempl/avr.sc
>> index b3cf421a78b..e918181700b 100644
>> --- a/ld/scripttempl/avr.sc
>> +++ b/ld/scripttempl/avr.sc
>> @@ -248,7 +248,7 @@ cat <<EOF
>>       KEEP (*(.init9))}
>>       *(.text)
>>       ${RELOCATING+. = ALIGN(2);
>> -    *(.text.*)
>> +    *(SORT(.text.*))
>>       . = ALIGN(2);
>>       *(.fini9)  /* _exit() starts here.  */
>>       KEEP (*(.fini9))
  
Alan Modra July 22, 2026, 11:54 a.m. UTC | #5
On Tue, Jul 21, 2026 at 01:32:44PM +0200, Georg-Johann Lay wrote:
> Am 21.07.26 um 07:46 schrieb Alan Modra:
> > On Mon, Jul 20, 2026 at 08:44:51PM +0200, Georg-Johann Lay via Binutils wrote:
> > > This patch sorts the .text.* input sections by their name
> > > in order to increase code locality, e.g. for code from
> > > libgcc and AVR-LibC.  For example, libgcc puts their
> > > multiplications and helpers in .text.libgcc.mul, but
> > > without SORT the linker may locate functions related by
> > > their input section far apart, inserting function from
> > > unrelated input sections in between them.
> > 
> > While you may have found one particular case where sorting by name
> > helps, I suspect this is generally not a good idea.  I believe in
> > general you will make -ffunction-sections code locality worse by using
> > this patch.  Consider an object file with lots of small functions,
> > calls mostly within that object file.  You don't want to sort them
> > such that functions from other object files separate them.
> 
> Maybe something like this would be more appropriate then?

Yes, I think thay would be better.

>     *(EXCLUDE_FILE(*/libgcc.a: */libm.a: */libc.a:) .text.*)
>     */libgcc.a:(SORT(.text.*))
>     */libc.a:(SORT(.text.*))
>     */libm.a:(SORT(.text.*))
> 
> What I don't know is whether / works as a dir separator on
> Window-ish hosts.  If not, maybe something like

Then you'll need to experiment, or look into the source.  I'm not sure
myself without doing a little digging.
  

Patch

diff --git a/ld/scripttempl/avr.sc b/ld/scripttempl/avr.sc
index b3cf421a78b..e918181700b 100644
--- a/ld/scripttempl/avr.sc
+++ b/ld/scripttempl/avr.sc
@@ -248,7 +248,7 @@  cat <<EOF
      KEEP (*(.init9))}
      *(.text)
      ${RELOCATING+. = ALIGN(2);
-    *(.text.*)
+    *(SORT(.text.*))
      . = ALIGN(2);
      *(.fini9)  /* _exit() starts here.  */
      KEEP (*(.fini9))