[PATCH] RISC-V: Adjust __global_pointer$ value to reduce code size.

Palmer Dabbelt palmer@sifive.com
Tue Oct 16 01:20:00 GMT 2018


On Mon, 15 Oct 2018 17:39:06 PDT (-0700), Jim Wilson wrote:
> On Mon, Oct 15, 2018 at 4:43 PM Palmer Dabbelt <palmer@sifive.com> wrote:
>> This smells like a bug lurking somewhere.  IIRC we avoided relaxing anything
>> that points to a mergeable segment due to these sorts of constraints, are we
>> just missing something?  I would consider it a bug if users can end up with
>> incorrect relaxations, regardless of where they're targeting the GP.
>
> We avoid relaxation in mergeable and code sections.  In this case the
> problem is rodata which is neither, but immediately follows .text and
> hence variables in rodata can change address when .text shrinks.  We
> probably never tried to relax references to rodata before.  I didn't
> look at trying to handle this in relaxation itself, it was easier to
> just fix gp to avoid overlapping rodata.  We should probably look at
> the rodata problem later though.

Ah, OK.  I guess I just assemed .rodata was mergeable because I assumed strings 
ended up in there.  Either way: it seems like a bug, but only one that you just 
found when writing this patch and not one introduced by this patch.  Certainly 
it shouldn't block a merge.

>> FWIW, when drag racing linker relaxation I always ended up using an offset of
>> 0x7C0 instead of 0x800 because of that extra bit of pessimism in the linker
>> relaxations that eats a few bytes of offset.  IIRC that saves you something
>> like 3 instructions in Dhrystone's inner loop because it allows relaxing
>> against the first few bytes of .sdata.
>
> The current definition is .sdata+0x800 which makes everything .sdata
> and later relaxable.  If you used .sdata+0x7c0, then you would get the
> last 64 bytes of the .data section as relaxable.  My patch should do
> this automatically for you if .sdata+.sbss is smaller than 0x1000.
> Though if you have your own linker script you don't get any benefit
> from this unless you update your linker script.;

Ah, yes, I guess that was the point: while ".sdata+0x800" should allow relaxing 
against a symbol at ".sdata+0", in practice we have a bit of pessimism in the 
relaxation code.  I'm actually afraid I don't understand exactly where it comes 
from, but if you look at "max_alignment" and "reserve_size" in 
"_bfd_riscv_relax_section()" you'll see there's a bit -- 0x7C0 seems a bit 
conservative, I'd guess that you can relax against ".sdata+0" down to 
"__global_pointer$=.sdata+0x7F0".

It actually looks like my misunderstanding of "max_alignment" is the source of 
this auipc+addend bug you're run in to: I appear to have just blindly copied 
this alignment pessimism (IIUC, this shrinks the relaxable region by the symbol 
size, which would avoid the overflows for LUI-based sequences) from the LUI 
relaxations into the AUIPC relaxations.  Now that I actually understand the 
code (or at least, I think I understand it) that seems completely bogus for the 
AUIPC case.

Sorry!

>> I don't know if it matters any more here, as if I understand how this is all
>> working we'll end up with GP pointing quite a way before ".sdata+0x800" for
>> small programs and for big programs the extra few symbols will just be noise.
>
> For big programs there will be no extra symbols, because if
> .sdata+.bss is 0x1000 or larger we get the exact same gp value as
> before.  The smaller the program the more the benefit.  The larger the
> program the less the benefit, with the benefit dropping to zero once
> the program gets big enough.

Yes, I agree -- and I think that's why this is really splitting hairs.  This 
really only matter when drag racing Dhrystone, which isn't worth the time -- 
and also certainly shouldn't block a merge :)



More information about the Binutils mailing list