avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] [RFT] [PATCH] New linker optimizations.


From: Björn Haase
Subject: [avr-libc-dev] [RFT] [PATCH] New linker optimizations.
Date: Sat, 15 Oct 2005 16:44:51 +0200
User-agent: KMail/1.7.1

Hi,

The following patch adds support for linker relaxation for the avr port. The 
most important issue is to make the linker choose the shorter variant of the 
two call/jump alternatives if the displacement is sufficiently small.

This small change alone results in 1.5 - 3 per cent code size reduction for
the applications I have checked so far. E.g. about 500 bytes reduction for an 
application of about 13k. The patch changes gas, bfd and ld.

The patch is against binutils head. I think that it has no serious bugs, but 
it needs testing.

In order to test, first step is to 
1.) check that the patched new gas variant does not have bugs. I.e. one would 
have first make sure that when re-compiling/re-assembling everything without 
special linker options the application still works.
2.) Then one could switch on the --relax option of the linker. (When using gcc 
to link use -Wl,--relax).
3.) The jumps turn out to be more local if one uses gcc with the switch 
--ffunction-sections. When using this switch linker relaxation helps more.
4.) The full monty of the optimizations with the patch would then be 
--ffunction-sections -Wl,--relax -Wl,--gc-sections, where the linker also 
removes unused functions and variables from the application.

Possibly one might want to re-compile avr-libc after the tests: Only the files 
assembled and compiled with the new binutils will benefit from the new 
optimizations.

Yours,

Bjoern

P.S.: 
Here is my mail to the binutils mailing list summing up the changes I have 
made.


Hi,

this is the second revision for my suggestions concerning linker relaxation
support for avr.

It incorporates the following changes:

GAS:

In order to make relaxation work, we need to make gas preserve more
relocs than it used to preserve. The issue is that all the relative 
instruction
offsets no longer must be calculated at assembly time but at linke time.
For this purpose the patch disables the fixups for all of the program-space
relative relocs by setting linkrelax to the value 1.

Because there was no way to find out from the object file itself if it is
suitable for relaxing or not, I have introduced a new flag bit in the 
e_flag portion of the elf header. Bits 0-3 have the same meaning. After the
change bit #7 is used for signalizing: "This elf object file is suitable for
linker relaxation since it preserves the local symbols." (new define symbol
EF_AVR_LINKRELAX_PREPARED).

In order to be able to leave the fixup for the higher two bytes of 32 bit 
values
to the linker, I have changed the present workaround. Before my change gas
internally made use of negated BFD enum values for these higher bytes.
I replaced this by adding proper new relocs to bfd and the elf files
(BFD_RELOC_AVR_MS8_LDI and R_AVR_MS8_LDI as well as the negated variants)
for the most significant byte of 32 bit values.


BFD:

I first had to implement a couple of changes in bfd for supporting the new 
relocs for the most significant bytes.

Three functions for implementing linker relaxation support are now new.
Before the relaxation machine starts, it is checked that the bfd
has the EF_AVR_LINKRELAX_PREPARED flag set in the elf header so that we could
safely continue to link old object files.

In the ".jumptables" and ".vectors" sections only a reduced relaxation
machine runs: Jumps and Calls are replaced by the shorter variants
without changing the relative addresses.

In elf32-avr.c I then have introduced a new global variable determinating
the wrap-around value of the avr program memory space. This value is
presently not valid but if it is filled one day with the correct value,
the relaxation machine will make use of the wrap-around shortcuts for jumps.
Possibly one could add later on target-specific options for filling
this variable with the target hardware's values.

LD:

In order to fix the --gc-sections bug I have added the required KEEP() 
statements in the linker script for avr.

Yours,

Bjoern.

P.S.: FYI, here is the mail to the binutils mailing list.


Hi,

this is the second revision for my suggestions concerning linker relaxation
support for avr.

It incorporates the following changes:

GAS:

In order to make relaxation work, we need to make gas preserve more
relocs than it used to preserve. The issue is that all the relative 
instruction offsets no longer must be calculated at assembly time but at 
linke time.
For this purpose the patch disables the fixups for all of the program-space
relative relocs by setting linkrelax to the value 1.

Because there was no way to find out from the object file itself if it is
suitable for relaxing or not, I have introduced a new flag bit in the 
e_flag portion of the elf header. Bits 0-3 have the same meaning. After the
change bit #7 is used for signalizing: "This elf object file is suitable for
linker relaxation since it preserves the local symbols." (new define symbol
EF_AVR_LINKRELAX_PREPARED).

In order to be able to leave the fixup for the higher two bytes of 32 bit 
values
to the linker, I have changed the present workaround. Before my change gas
internally made use of negated BFD enum values for these higher bytes.
I replaced this by adding proper new relocs to bfd and the elf files
(BFD_RELOC_AVR_MS8_LDI and R_AVR_MS8_LDI as well as the negated variants)
for the most significant byte of 32 bit values.


BFD:

I first had to implement a couple of changes in bfd for supporting the new 
relocs for the most significant bytes.

Three functions for implementing linker relaxation support are now new.
Before the relaxation machine starts, it is checked that the bfd
has the EF_AVR_LINKRELAX_PREPARED flag set in the elf header so that we could
safely continue to link old object files.

In the ".jumptables" and ".vectors" sections only a reduced relaxation
machine runs: Jumps and Calls are replaced by the shorter variants
without changing the relative addresses.

In elf32-avr.c I then have introduced a new global variable determinating
the wrap-around value of the avr program memory space. This value is
presently not valid but if it is filled one day with the correct value,
the relaxation machine will make use of the wrap-around shortcuts for jumps.
Possibly one could add later on target-specific options for filling
this variable with the target hardware's values.

LD:

In order to fix the --gc-sections bug I have added the required KEEP() 
statements in the linker script for avr.

Yours,

Bjoern.


2005-10-15  Bjoern Haase  <address@hidden>

        * include/elf/avr.h: 

        R_AVR_MS8_LDI,R_AVR_MS8_LDI_NEG: Add.
        EF_AVR_LINKRELAX_PREPARED: Add.

        * bfd/elf32-avr.c:

        avr_reloc_map: 
        insert BFD_RELOC_AVR_MS8_LDI and R_AVR_MS8_LDI
        bfd_elf_avr_final_write_processing: 
        set EF_AVR_LINKRELAX_PREPARED in e_flags field.
        elf32_avr_relax_section: add.
        elf32_avr_relax_delete_bytes: add.
        elf32_avr_get_relocated_section_contents: add.
        avr_pc_wrap_around: add.
        avr_relative_distance_considering_wrap_around: add.
        avr_final_link_relocate: Handle negative int8t_t immediate for R_AVR_LDI
        
        * gas/config/tc-avr.c: 

        md_apply_fix, exp_mod: 
        Use BFD_RELOC_HH8_LDI and BFD_RELOC_MS8_LDI for hlo8() and hhi8()
        md_begin: 
        include inttypes.h, set linkrelax variable to 1, add cast to (intptr_t)
        avr_ldi_expression: use cast to (intptr_t) instead of (int)
        
        * gas/config/tc-avr.h:
        TC_LINKRELAX_FIXUP, TC_VALIDATE_FIX, tc_fix_adjustable: add.
        
        * bfd/bfd-in2.h: Add BFD_RELOC_AVR_MS8_LDI and BFD_RELOC_AVR_LDI_NEG
        * bfd/libbfd.h: Ditto.
        * bfd/reloc.c: Ditto.

        * ld/scripttempl/avr.sc:
        add *(.jumptables) *(.lowtext), add KEEP() directives

Attachment: relax_avr_rev2.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]