[LLVMdev] [ARM] [PIC] optimizing the loading of hidden global variable

Nick Kledzik kledzik at apple.com
Fri Mar 14 09:35:16 PDT 2014


On Mar 14, 2014, at 9:03 AM, Rafael Espíndola <rafael.espindola at gmail.com> wrote:

> 
> On ARM, that is not the case. We produce
> 
>        ldr     r0, .LCPI0_0
>        add     r4, pc, r0 // r4 is the equivalent of ebx in the x86 case.
>        ldr       r0, .LCPI0_1 // r0 is the constant that is an
> immediate in x86.
>        add     r0, r0, r4 // that is the add that is folded in x86
> ...
> .LCPI0_0:
>        .long   _GLOBAL_OFFSET_TABLE_-(.LPC0_0+8)
> .LCPI0_1:
>        .long   g0(GOTOFF)
> 
> For ARM, codegen already keeps tracks of offset so it can implement
> the constant islands, so it should be able to see that the two globals
> are close enough that offset between them fits an immediate.
> 
> Nick, will this work on MachO or can ld64 move _g0, _g1 and _g2 too far apart?
When this is compiled, you only know that g0, g1, and g2 will be in the same
linkage unit.  You don’t know if they will come from the same translation unit.
You don’t know how big the overall __DATA segment will be, so yes it is
quite possible g0, g1, and g2 will be more that 64KB apart.

Also, 32-bit arm for mach-o does not use a GOT.   The compiler does create
GOT-like slots call non-lazy-pointers for accessing symbols defined outside
the translation unit.  Given that the arrays are declared hidden, that means
they will be defined in the linkage unit.  So, ideally the non-lazy-pointer indirection
could be removed and have the code directly access the array.  The problem
is mach-o has no relocation for pointer diffs where one of the pointers is 
undefined.  Currently, the only solution is to get the optimal (not use non-lazy-
pointer) is to build with LTO.

-Nick

> 
> BTW, what will gcc produce for
> 
> void init(void *);
> extern int g0[100] __attribute__((visibility("hidden")));
> extern int g1[100] __attribute__((visibility("hidden")));
> extern int g2[100] __attribute__((visibility("hidden")));
> void foo() {
>  init(&g0);
>  init(&g1);
>  init(&g2);
> }
> 
> Cheers,
> Rafael





More information about the llvm-dev mailing list