clang/library collusion

Hello,

I'm pretty much a clang newbie, looking for some advice.

I'm considering looking at a small size optimization that goes like this:
* Compiler discovers that main's argv argument is unused
* Compiler emits object with information that can be used by library and/or linker to avoid inclusion of argv-handling code

One of my colleagues suggest emitting a dummy function that just returns. The library can then put its argv-handling code in an identically-named weak function and the linker won't include it if the dummy function exists. I like this solution as it works for any library without needing any extra special technology.

As the optimization is language-specific it seems it should happen in clang rather than LLVM, perhaps by adding a function to the AST. This implies manipulating the AST after it has been constructed which, IIUC, is not an especially supported way to do things.

Is such an approach possible/sane, and would it be acceptable to upstream?

Does clang have any recognised approaches to this kind of compiler/library collusion?

Thanks in advance,

Bernie

Hello,

I'm pretty much a clang newbie, looking for some advice.

I'm considering looking at a small size optimization that goes like this:
* Compiler discovers that main's argv argument is unused
* Compiler emits object with information that can be used by library
and/or linker to avoid inclusion of argv-handling code

One of my colleagues suggest emitting a dummy function that just returns.
The library can then put its argv-handling code in an identically-named
weak function and the linker won't include it if the dummy function exists.
I like this solution as it works for any library without needing any extra
special technology.

It could be marginally better to have the library provide a weak
_Main_noargv() entry point that computes argc and argv then calls main(),
and have the compiler emit _Main_noargv as an alias to main if main doesn't
use its argc and argv. But either way, sure.

As the optimization is language-specific it seems it should happen in clang

rather than LLVM, perhaps by adding a function to the AST. This implies
manipulating the AST after it has been constructed which, IIUC, is not an
especially supported way to do things.

Is such an approach possible/sane, and would it be acceptable to upstream?

Not by manipulating the AST, no, for a couple of reasons:
1) You may not know that argc and argv are unused until you perform some
optimizations
2) It doesn't make sense to model this in the AST as it's a property of the
lowering to machine code, not a property of the source program

If you really want to do this in clang (per the above, I don't think that's
a good idea), you should do it in clang's IR generation pass rather than
modifying the AST. But I'd suggest you instead look at teaching LLVM to do
this (maybe in dead argument elimination), and from Clang just inform the
relevant LLVM pass that it can do this transformation.

Does clang have any recognised approaches to this kind of compiler/library

Isn't this more suitable to LTO DCE?

cheers,
--renato

It could be marginally better to have the library provide a weak _Main_noargv() entry point that computes argc and argv then calls main(), and have the compiler emit _Main_noargv as an alias to main if main doesn't use its argc and argv. But either way, sure.

Yes, that does feel a bit neater.

Not by manipulating the AST, no, for a couple of reasons:
1) You may not know that argc and argv are unused until you perform some optimizations
2) It doesn't make sense to model this in the AST as it's a property of the lowering to machine code, not a property of the source program

If you really want to do this in clang (per the above, I don't think that's a good idea), you should do it in clang's IR generation pass rather than modifying the AST. But I'd suggest you instead look at teaching LLVM to do this (maybe in dead argument elimination), and from Clang just inform the relevant LLVM pass that it can do this transformation.

That makes sense - I'll see if I can do it in LLVM.

Thanks for the advice.

Regards,

Bernie

Hi Renato,

IIUC, you're trying to remove args handling code by understanding
somewhere that it's not used. Clang adds it because it's the standard
way to do it, and I agree with Richard, this seems the wrong place to
add this logic.

LTO can do better DCE because it *knows* about things that you won't
need, especially true in bare metal environments, and this looks like
it could be cleared at the very end of the compilation process. Since
DCE is a big part of LTO, I though it would be the most obvious place
to add such an optimisation, if LTO is not smart enough yet to do it
(might very well be).

cheers,
--renato