[PATCH] [RFC][PATCH] Minor opt to access pointers to globals via pcrel GOT entries

Bruno Cardoso Lopes bruno.cardoso at gmail.com
Fri Jan 23 10:55:18 PST 2015


Hi Rafael,

On Fri, Jan 23, 2015 at 3:00 PM, Rafael Espíndola
<rafael.espindola at gmail.com> wrote:
> On 12 January 2015 at 06:51, Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
> wrote:
>>
>> Hi rafael, grosbach,
>>
>> Global variables marked with "unnamed_addr" have the following property:
>> "...unnamed_addr indicates that the address is not significant, only the
>> content".
>>
>> One potential use of "unnamed_addr" by front-ends is to emit "unnamed_addr
>> constant" globals holding pointer initialisers to other global variables.
>> For instance, this can be used if the front-end wishes to compute and store
>> information against a location with a symbol pointer but doesn't care about
>> its address. A more concrete example follows:
>>
>> @foo = global i32 42
>> @proxy = unnamed_addr constant i32* @foo
>>
>> @delta = global i32 trunc (i64 sub (i64 ptrtoint (i32** @proxy to i64),
>>                                    i64 ptrtoint (i32* @delta to i64))
>>                           to i32)
>>
>> Here, @delta holds a data "PC"-relative offset to a pointer of @foo. The
>> darwin/x86-64 assembly output for this follows:
>>
>>  .globl  _foo
>> _foo:
>>  .long   42
>>
>>  .globl  _proxy
>> _proxy:
>>  .quad   _foo
>>
>>  .globl  _delta
>> _delta:
>>  .long   _proxy-_delta
>>
>
> It should also be required that proxy be of a discardable linkage. Using
> private seems natural for this.

Good one, will update the patch to reflect it.

>>
>> I propose a minor optimisation for such cases: given target specific
>> support, replace pc-relative accesses to such unnamed_addr global constants
>> by a PC relative access to the GOT entry of the final symbol instead.
>> Therefore, "delta" would contain a pc relative relocation to foo's GOT entry
>> and we avoid the emission of "proxy", yielding the assembly code below:
>>
>>  .globl  _foo
>> _foo:
>>  .long   42
>>
>>  .globl  _delta
>> _delta:
>>  .long   _foo at GOTPCREL+4
>>
>> There are a couple of advantages of doing this:
>> - In situations where all that’s required is that there be some way to get
>> the address of an external symbol we save space by not emitting "proxy"
>> globals. Front-ends that need to emit a great deal of data containing
>> pointers could benefit from this.
>> - As a side effect, such IR constructs combined with the proposed opt
>> opens a way to represent GOT pcrel relocations by solely using the LLVM IR,
>> which is something we currently have no way to express.
>>
>> Also, this is not MachO specific and can also benefit ELF targets. I've
>> attached a patch implementing this simple feature for x86-64/darwin but
>> mostly changes are target independent.
>
>
> The general idea makes sense. The logic is that a GOT entry is just a memory
> location holding a symbol address. If we have a GV (proxy in the above
> example) that is also just a memory location holding a symbol address, we
> can replace one with the other.
>
> Why do you have a +4 in the above example?

The "+4" offset is needed in MachO in order to correctly give the "PC"
effect on the data. For instance, exception tables on darwin are
emitted using the same pattern. I guess this is because it was
initially used only by instructions and then adjustment is done to get
the right offset inside the instruction, we need to compensate that if
using it on a data section.

> I have attached a complete example. Running llc on test.ll currently
> produces test.s. It could produce test2.s. Linking both test.s and test2.s
> with main.c produces a binary that prints 42. The advantage is that test2.o
> save a relocation and a memory location.
>
> Note that there is no +4 in test2.s.

GOTPCREL relocations work differently in ELF and don't require this hack.

> I will check the patch itself after lunch.

Thank you Rafael! :-)
Cheers,

-- 
Bruno Cardoso Lopes
http://www.brunocardoso.cc




More information about the llvm-commits mailing list