Re: [whopr] Design/implementation alternatives for the driver and WPA

2008-06-04 Thread Nick Kledzik


On Jun 4, 2008, at 12:44 PM, Ian Lance Taylor wrote:

Chris Lattner <[EMAIL PROTECTED]> writes:


* The return value of lto_module_get_symbol_attributes is not
defined.


Ah, sorry about that.  Most of the details are actually in the public
header.  The result of this function is a 'lto_symbol_attributes'
bitmask.  This should be more useful and revealing:
http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/lto.h?revision=HEAD&view=markup


From an ELF perspective, this doesn't seem to have a way to indicate a
common symbol, and it doesn't provide the symbol's type.

The current lto interface does return whether a  symbol is
REGULAR, TENTATIVE, WEAK_DEF, or UNDEFINED.  There is also
CODE vs DATA which could be used to indicate STT_FUNC vs STT_OBJECT.



 It also
doesn't have a way to indicate section groups.

(How do section groups work in Mach-O?  Example is a C++ template
function with a static constant array which winds up in the .rodata
section.  Section groups permit discarding the array when we discard
the function code.)
Neither mach-o or llvm have group comdat.   We just rely on dead code  
stripping.

If the temple function was coalesced away, there would no longer be
a reference to that static const array, so it would get dead stripped.

Dead stripping is an important pass in LTO.



* Interfaces like lto_module_get_symbol_name and
lto_codegen_add_must_preserve_symbol are inefficient when dealing
with large symbol tables.


The intended model is for the linker to query the LTO plugin for its
symbol list and build up its own linker-specific hash table.  This  
way

you don't need to force the linker to use the plugin's data structure
or the plugin to use the linker data structure.  We converged on this
approach after trying it the other way.

Does this make sense, do you have a better idea?


In gcc's LTO approach, I think the linker will already have access to
the symbol table anyhow.  But my actual point here is that requiring a
function call for every symbol is inefficient.  These functions should
take an array and a count.  There can be hundreds of thousands of
entries in a symbol table, and the interface should scale accordingly.

I see you have your gold hat on here!  The current interface is
simple and clean.  If it does turn out that repeated calls to  
lto_module_get_symbol*

are really a bottleneck, we could add a "bulk" function.



The LLVM
interface does not do that.


Yes it does, the linker fully handles symbol resolution in our model.


Suppose the linker is invoked on a
sequence of object files, some with with LTO information, some
without, all interspersed.  Suppose some symbols are defined in
multiple .o files, through the use of common symbols, weak symbols,
and/or section groups.  The LLVM interface simply passes each object
file to the plugin.


No, the native linker handles all the native .o files.


The result is that the plugin is required to do
symbol resolution itself.  This 1) loses one of the benefits of  
having

the linker around; 2) will yield incorrect results when some non-LTO
object is linked in between LTO objects but redefines some earlier
weak symbol.


In the LLVM LTO model, the plugin only needs to know about its .o
files, and the linker uses this information to reason about symbol
merging etc.  The Mac OS X linker can even do dead code stripping
across Macho .o files and LLVM .bc files.


To be clear, when I said object file here, I meant any input file.
You may have understood that.

In ELF you have to think about symbol overriding.  Let's say you link
a.o b.o c.o.  a.o has a reference to symbol S.  b.o has a strong
definition.  c.o has a weak definition.  a.o and c.o have LTO
information, b.o does not.  ELF requires that a.o call the symbol from
b.o, not the symbol from c.o.  I don't see how to make that work with
the LLVM interface.
This does work.  There are two parts to it.  First the linker's master  
symbol

table sees the strong definition of S in b.o and the weak in c.o and
decides to use the strong one from b.o.  Second (because of that) the  
linker

calls  lto_codegen_add_must_preserve_symbol("S"). The LTO engine then
sees it has a weak global function S and it cannot inline those.  Put  
together

the LTO engine does generate a copy of S, but the linker throws it away
and uses the one from b.o.

-Nick



Re: [whopr] Design/implementation alternatives for the driver and WPA

2008-06-04 Thread Nick Kledzik


On Jun 4, 2008, at 1:45 PM, Ian Lance Taylor wrote:


The result is that the plugin is required to do
symbol resolution itself.  This 1) loses one of the benefits of
having
the linker around; 2) will yield incorrect results when some non- 
LTO

object is linked in between LTO objects but redefines some earlier
weak symbol.


In the LLVM LTO model, the plugin only needs to know about its .o
files, and the linker uses this information to reason about symbol
merging etc.  The Mac OS X linker can even do dead code stripping
across Macho .o files and LLVM .bc files.


To be clear, when I said object file here, I meant any input file.
You may have understood that.

In ELF you have to think about symbol overriding.  Let's say you  
link

a.o b.o c.o.  a.o has a reference to symbol S.  b.o has a strong
definition.  c.o has a weak definition.  a.o and c.o have LTO
information, b.o does not.  ELF requires that a.o call the symbol  
from
b.o, not the symbol from c.o.  I don't see how to make that work  
with

the LLVM interface.
This does work.  There are two parts to it.  First the linker's  
master

symbol
table sees the strong definition of S in b.o and the weak in c.o and
decides to use the strong one from b.o.  Second (because of that) the
linker
calls  lto_codegen_add_must_preserve_symbol("S"). The LTO engine then
sees it has a weak global function S and it cannot inline those.  Put
together
the LTO engine does generate a copy of S, but the linker throws it  
away

and uses the one from b.o.


OK, for that case.  But are you asserting that this works in all
cases?  Should I come up with other examples of mixing LTO objects
with non-LTO objects using different types of symbols?
I don't claim our current implementation is bug free, but the lto  
interface

matches the Apple linker internal model, so we don't expect and have
not encountered any problems mixing mach-o and llvm bitcode files.

-Nick



Re: [whopr] Design/implementation alternatives for the driver and WPA

2008-06-04 Thread Nick Kledzik


On Jun 4, 2008, at 5:00 PM, Ian Lance Taylor wrote:

Nick Kledzik <[EMAIL PROTECTED]> writes:


I don't claim our current implementation is bug free, but the lto
interface
matches the Apple linker internal model, so we don't expect and have
not encountered any problems mixing mach-o and llvm bitcode files.


Hmmm, OK, how about this example:

a.o: contains LTO information, refers to S
b.o: no LTO information, defines S
c.o: contains LTO information, defines S at version V, S/V is not  
hidden


In the absence of b.o, the reference to S in a.o will be resolved
against the definition of S in c.o.  In the presence of b.o, the
reference to S in a.o will be resolved against the definition of S in
b.o.

I suppose we could refuse to inline versioned symbols, but that
doesn't seem desirable since it is normally fine.



As Chris mentioned earlier today, the Apple tool chain does not  
support versioned symbols.
But if versioned symbols are a naming convention (that is everything  
is encoded in
the symbol name), then this would work the same as your previous  
example.  Namely,
the linker would coalesce away S in c.o, which in turns tell the LTO  
engine that it
can't inline/optimize away c.o's S and after LTO is done, the linker  
throws away

the LTO generated S and uses b.o's S instead.

-Nick


On Jun 4, 2008, at 9:29 AM, Chris Lattner wrote:
When I look at the LLVM interface as described on that web page, I  
see

these issues, all fixable:
* No support for symbol versioning.


Very true.  I think it would great to work from a common model that  
can be extended to support both compilers.  Having a unified  
interface would be very useful, and we are happy to evolve the  
interface to suit more general needs.




Re: [whopr] Design/implementation alternatives for the driver and WPA

2008-06-04 Thread Nick Kledzik


On Jun 4, 2008, at 5:39 PM, Ian Lance Taylor wrote:

Nick Kledzik <[EMAIL PROTECTED]> writes:


On Jun 4, 2008, at 5:00 PM, Ian Lance Taylor wrote:

Nick Kledzik <[EMAIL PROTECTED]> writes:


I don't claim our current implementation is bug free, but the lto
interface
matches the Apple linker internal model, so we don't expect and  
have

not encountered any problems mixing mach-o and llvm bitcode files.


Hmmm, OK, how about this example:

a.o: contains LTO information, refers to S
b.o: no LTO information, defines S
c.o: contains LTO information, defines S at version V, S/V is not
hidden

In the absence of b.o, the reference to S in a.o will be resolved
against the definition of S in c.o.  In the presence of b.o, the
reference to S in a.o will be resolved against the definition of S  
in

b.o.

I suppose we could refuse to inline versioned symbols, but that
doesn't seem desirable since it is normally fine.



As Chris mentioned earlier today, the Apple tool chain does not
support versioned symbols.
But if versioned symbols are a naming convention (that is everything
is encoded in
the symbol name), then this would work the same as your previous
example.  Namely,
the linker would coalesce away S in c.o, which in turns tell the LTO
engine that it
can't inline/optimize away c.o's S and after LTO is done, the linker
throws away
the LTO generated S and uses b.o's S instead.


Versioned symbols are not a naming convention, but they aren't all
that different from one.  Basically every symbol may have an optional
version, and when a symbol has a version the version may be hidden or
not.  A symbol definition with a hidden version may only be matched by
a symbol reference with that exact version.  A symbol definition with
a non-hidden version definition may be matched by a symbol reference
with the same name without a version.  This is most interesting in the
dynamic linker, of course.

How does the linker inform the plugin that the plugin is not permitted
to use c.o's S?
In the previous case where S was weak, the call to  
lto_codegen_add_must_preserve_symbol("S")

caused the LTO engine to know it could not inline S (because it was
a weak definition and used outside the LTO usage sphere). And then
after LTO was done, the linker threw away the LTO produced S and used
the one from c.o instead.

In this case S is a regular symbol.  So the previous trick won't  
work.  Probably
the best solution would be to add a new  lto_ API to tell the LTO  
engine to
ignore a definition is already has.  It would make more sense to use  
this

new API in the weak case too.

-Nick



Re: [whopr] Design/implementation alternatives for the driver and WPA

2008-06-05 Thread Nick Kledzik


On Jun 5, 2008, at 10:43 AM, Ian Lance Taylor wrote:

Chris Lattner <[EMAIL PROTECTED]> writes:


LLVM LTO handles this by marking symbols "internal" (aka static, aka
not TREE_PUBLIC, whatever) when the symbol is not visible outside the
LTO scope.  This allows the optimizers to go crazy and hack away at
the symbols, but only when safe.


How does the linker do this?  Are you saying that when generating a
shared library, the linker calls lto_codegen_add_must_preserve_symbol
for every externally visible symbol?

Yes.


How does the linker tell LTO that a symbol may be inlined, but must
also be externally visible?

The linker just tells LTO which symbols must remain.  The LTO engine
is free to inline anything that would improve codegen, with the  
exception

that any weak definition that must remain (preserved) cannot be inlined.

-Nick