[llvm-dev] Weak symbol/alias semantics
Teresa Johnson via llvm-dev
llvm-dev at lists.llvm.org
Wed Jan 18 11:45:59 PST 2017
I tried to enumerate all combinations of linkage types and prevailingness
among aliases, and wrote down the proposed transformations with both the
current alias form and the proposed canonical alias form. See the doc
below. In case this doesn't show up well in email (I can't seem to adjust
the column widths), here is a link to a google doc version:
https://docs.google.com/document/d/1tVrsCRPmhdPv5KZay-NkJ4fz2nJ8p-1DPYA1pyC0_HY/edit?usp=sharing
Let me know if any of this looks wrong.
Thanks!
Teresa
ThinLTO Aliases and Weak Resolution
ThinLTO has information from the linker identifying prevailing and
non-prevailing copies of weak symbols (“weak” here means
WeakAny/LinkonceAny/WeakODR/LinkonceODR LLVM linkage types). We use that
information to mark the non-prevailing copies of a weak symbol as
available_externally in the index. This is used in the backend to change
the linkage to available_externally (ODR types), or to drop to an external
declaration (Any types, with D28806). However, this cannot be done if the
symbol is either an alias or an aliasee, because available_externally
aliases are not (currently) legal in LLVM IR (this restriction could
theoretically be lifted for aliases, but an alias to an
available_externally aliasee doesn’t make much sense).
Current vs Proposed Canonical Alias forms:
1) Current alias form:
define [linkage_a] void @a() { ... }
@b = [linkage_b] alias void (), void ()* @a
2) In the proposed canonical form this becomes:
define private void @0() { ... }
@a = [linkage_a] alias void (), void ()* @0
@b = [linkage_b] alias void (), void ()* @0
Here is a table of transformed sequences, for various permutations of
linkage types and prevailingness (P=Prevailing, N=Non-prevailing). Those in
italics (first 8 rows) are already done as they are straightforward.
linkage_b (alias)
linkage_a (aliasee)
Current form
Proposed form
Notes
external OR
internal OR
private
linkonce_odr (P) OR
weak_odr (P)
linkage_a -> weak_odr
linkage_a -> weak_odr
Done
external OR
internal OR
private
linkonce (P) OR
weak (P)
linkage_a -> weak
linkage_a -> weak
Done
linkonce_odr (P) OR
weak_odr (P)
external OR
internal OR
private OR
linkage_b -> weak_odr
linkage_b -> weak_odr
Done
linkonce_odr (P) OR
weak_odr (P)
linkonce_odr (P) OR
weak_odr (P) OR
linkage_b -> weak_odr
linkage_a -> weak_odr
linkage_b -> weak_odr
inkage_a -> weak_odr
Done
linkonce_odr (P) OR
weak_odr (P)
linkonce (P) OR
weak (P)
linkage_b -> weak_odr
linkage_a -> weak
linkage_b -> weak_odr
inkage_a -> weak
Done
linkonce (P) OR
weak (P)
external OR
internal OR
private OR
linkage_b -> weak
linkage_b -> weak
Done
linkonce (P) OR
weak (P)
linkonce_odr (P) OR
weak_odr (P) OR
linkage_b -> weak
linkage_a -> weak_odr
linkage_b -> weak
linkage_a -> weak_odr
Done
linkonce (P) OR
weak (P)
linkonce (P) OR
weak (P)
linkage_b -> weak
linkage_a -> weak
linkage_b -> weak
linkage_a -> weak
Done
external OR
internal OR
private
linkonce_odr (N) OR
weak_odr (N)
linkage_a -> available_externally
@b -> RAUW @a, delete @b
1) @a = external (decl)
OR
2) linkage_a -> available_externally (copy of @0)
(no change to @b/@0)
With Proposed form and alternative 1), we lose the ability to inline @a.
With alternative 2, which requires a bit more work, we have an extra
(private) copy of def (if not completely inlined/eliminated)
external OR
internal OR
private
linkonce (N) OR
weak (N)
@a = external (decl)
@a.1 = private (def)
@b = [linkage_b] alias @a.1
@a = external (decl)
(no change to @b/@0)
linkonce_odr (N) OR
weak_odr (N)
external OR
internal OR
private
1) @b = external (decl)
OR
2) @b = available_externally (copy of @a)
(no change to @a)
1) @b = external (decl)
OR
2) linkage_b -> available_externally (copy of @0)
(no change to @a/@0)
With alternatives 1) we lose the ability to inline @b. With alternatives 2)
we retain it at the expense of a bit more work.
linkonce_odr (N) OR
weak_odr (N)
linkonce_odr (N) OR
weak_odr (N)
linkage_a -> available_externally
@b -> RAUW @a, delete @b
1) @a = external (decl)
@b = external (decl)
OR
2) linkage_a -> available_externally (copy of @0)
linkage_b -> available_externally (copy of @0)
See earlier notes about tradeoffs of alternatives 1 and 2 for Proposed form.
linkonce_odr (N) OR
weak_odr (N)
linkonce (N) OR
weak (N)
@a = external (decl)
1) @b = external (decl)
OR
2) @b = available_externally (copy of @a)
@a = external (decl)
1) @b = external (decl)
OR
2) linkage_b -> available_externally (copy of @0)
With Current form we do the transformation in a couple steps (first by
handling the non-prevailing aliasee as described earlier, then by handling
the non-prevailing ODR alias as described elsewhere above).
See earlier notes about tradeoffs between alternatives 1 and 2 for both
forms.
linkonce (N) OR
weak (N)
external OR
internal OR
private
@b = external (decl)
(no change to @a)
@b = external (decl)
(no change to @a/@0)
linkonce (N) OR
weak (N)
linkonce_odr (N) OR
weak_odr (N)
linkage_a -> available_externally
@b = external (decl)
1) @a = external (decl)
OR
2) linkage_a -> available_externally (copy of @0)
@b = external (decl)
See earlier notes about tradeoffs between alternatives 1 and 2 for Proposed
form.
linkonce (N) OR
weak (N)
linkonce (N) OR
weak (N)
@a = external (decl)
@b = external (decl)
@a = external (decl)
@b = external (decl)
If we lift the restriction on having available_externally aliases, then all
the alternatives 1 and 2 above collapse to a simple conversion of the
corresponding linkage type to available_externally.
There is only one place that ends up suboptimal (in code size) in the
Proposed form: alias is external/internal/private and aliasee is a
non-prevailing ODR. Even with alternative 2 we end up with an extra copy of
the function if we want to enable inlining. That is, unless we put in more
work to look for strong aliases to @0 and RAUW them to the newly
available_externally @a (doable, ends up with the same IR as the Current
form for this case).
On Wed, Jan 18, 2017 at 7:37 AM, Teresa Johnson <tejohnson at google.com>
wrote:
>
>
> On Wed, Jan 18, 2017 at 7:34 AM, Rafael Avila de Espindola <
> rafael.espindola at gmail.com> wrote:
>
>> Teresa Johnson <tejohnson at google.com> writes:
>> > Ok, thanks. But how does that property work the strongalias case from
>> the
>> > original email. E.g.:
>> >
>> > @f = weak global ...
>> > @strongalias = alias @f
>> >
>> > What we had concluded was that it should be transformed into the
>> following
>> > when this copy of @f is non-prevailing:
>> >
>> > @f = external global
>> > @f.llvm.1 = internal global ... // Internalized copy of original @f
>> > @strongalias = alias @fv.llvm.1
>>
>> I would use private instead of insternal, but yes, that is it.
>>
>
> Right, it should be private.
>
>
>>
>> > Maybe we are just using different terminology for the same thing, but in
>> > this case it seems as though we have broken the link between the
>> original
>> > alias @f and aliasee @strongalias? Or is the point that we haven't
>> broken
>> > the link between the value in this module of @f (copied to @f.llvm.1)
>> and
>> > @strongalias?
>>
>> Correct. The two origial symbols would still point to the save thing. It
>> is just that one of the symbols is not used and is dropped. This is the
>> case that becames simpler if the IR is required to be written as
>>
>> @data = private global....
>> @f = weak alias @data
>> @strongalias = alias @data
>>
>
> Ok thanks,
> Teresa
>
>
>>
>> Cheers,
>> Rafael
>>
>
>
>
> --
> Teresa Johnson | Software Engineer | tejohnson at google.com |
> 408-460-2413 <(408)%20460-2413>
>
--
Teresa Johnson | Software Engineer | tejohnson at google.com | 408-460-2413
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170118/911bb084/attachment-0001.html>
More information about the llvm-dev
mailing list