On 2010-06-16, JMGross <[email protected]> wrote:
> I had this happen long time ago when I included the different object
> files or libraries in the wrong order with GCC under linux. After
> reordering them so that their contend had already been referenced,
> all was well. I think I had similar problems (immediately solved)
> with mspgcc.
Those problems were with the --gc-sections feature?
It sounds to me like you were linking libraries before you linked the
object files that referenced the routines in the library. That's a
different, unrelated issue.
> If these compiler flags allow treating different functions in the
> same files to be kept or discarded depending of whether they are
> used, it's obvious that they need to be be considered unused when
> they haven't been referenced yet.
The garbage collection algorithm used by the linker shouldn't depend
what order you link the object files. If you've got examples where it
seems to matter, please post it because that's a bug and needs to be
fixed.
> (It would be pretty useless to have such a feature if it could be
> inhibited by circular references of dead code.)
True, but that doesn't mean that the object files have to be a
partially ordered set. Nodes are not discarded based on a
reference-count -- they're discarded based on a reachability.
> Unless the linker has been greatly improved since then, the problem
> should be there. Maybe I'm wrong.
You seem to be assuming a single-pass linker. It works in two passes.
First it reads all of the object files. Then it starts at all of the
nodes (symbols) marked as "keep" and traverses the reference graph
marking all reachable nodes.
When it's done traversing the graph, it discards any nodes that
haven't been reached from the initial set of "keep" nodes.
Are you sure you're not thinking about the requirement that libraries
be paritially ordered with respect to referencing objects?
> About the reduced effectiveness of the optimization, this one is
> obvious. If the linker is allowed to include or discard parts of a
> compilation unit depending of their usage, the compiler may not do
> any optimization that crosses the boundary between functions.
I'm afraid that's not at all obvious to me.
Example: A C file contains two functions: foo() and bar(). foo() is
called by various external functions. bar() is called only by foo().
The compiler can inline bar() without causing any problems.
> Else either common code may disappear when not linked or a reference
> is generated that will keep the normally unused other function from
> being excluded from the build.
Sorry, you've lost me. I'm not saying it doesn't happen, but I can't
visualize it. Do you have an example?
> Or the common part is referenced by both with a branch (instead of a
> relative jump), making the code less efficient.
IIRC, the linker will convert "long" branches into short/relative
jumps at link time. At least it does that for all the other targets I
use...
> Also, some addressing modes cannot be used under such a setup.
I don't understand why. Can you provide an actual example?
> Optimizations INSIDE a function are not touched, of course. Only
> those across functions (e.g. identical exit code). The common
> subexpression elimination was a bad example. (I was a bit in haste
> when I wrote this, it was at the end of my office hours)
Some things like optmizing addressing modes for far/short destinations
have to be done at link time instead of compile time, but I don't see
how that hurts anything.
--
Grant Edwards grant.b.edwards Yow! This ASEXUAL PIG
at really BOILS my BLOOD
gmail.com ... He's so ... so
... URGENT!!