[llvm-commits] [llvm] r154124 - /llvm/trunk/tools/lto/LTOCodeGenerator.cpp

Duncan Sands baldrick at free.fr
Fri Apr 6 00:34:16 PDT 2012


Hi Bill,

> The internalize pass can be dangerous for LTO.

I'm kind of confused by your examples.  In your first example

> Consider the following program:
>
> $ cat main.c
> void foo(void) { }
>
> int main(int argc, char *argv[]) {
>      foo();
>      return 0;
> }
> $ cat bundle.c
> extern void foo(void);
>
> void bar(void) {
>       foo();
> }
> $ clang -o main main.c
> $ clang -o bundle.so bundle.c -bundle -bundle_loader ./main
> $ nm -m bundle.so
> 0000000000000f40 (__TEXT,__text) external _bar
>                   (undefined) external _foo (from executable)
>                   (undefined) external dyld_stub_binder (from libSystem)
> $ clang -o main main.c -O4

(^ If this is running internalize then that's a bug.  But it doesn't, right?)

> $ clang -o bundle.so bundle.c -bundle -bundle_loader ./main
> Undefined symbols for architecture x86_64:
>    "_foo", referenced from:
>        _bar in bundle-elQN6d.o
> ld: symbol(s) not found for architecture x86_64
> clang: error: linker command failed with exit code 1 (use -v to see invocation)

This looks like a bug: the linker should observe that bundle uses the symbol foo
and that main provides the symbol foo, and pass "foo" to the internalize pass in
the list of external symbols.  I think this is how the gold plugin does it. It's
not a reason to turn off internalize altogether.  Hopefully Rafael can comment.

> The linker was told that the 'foo' in 'main' was 'internal' and had no uses, so
> it was dead stripped.
>
> Another situation is something like:
>
> define void @foo() {
>    ret void
> }
>
> define void @bar() {
>    call asm volatile "call _foo" ...
>    ret void
> }
>
> The only use of 'foo' is inside of an inline ASM call. Since we don't look
> inside those for uses of functions, we don't specify this as a "use."

This is user error: the user should add a "used" attribute to foo.  This isn't
anything new: lots of people make this mistake (it's come up again and again on
the mailing list and in bugzilla).  The user should be educated here.

Ciao, Duncan.

>
> Get around this by not invoking the 'internalize' pass by default. This is an
> admitted hack for LTO correctness.
> <rdar://problem/11185386>
>
> Modified:
>      llvm/trunk/tools/lto/LTOCodeGenerator.cpp
>
> Modified: llvm/trunk/tools/lto/LTOCodeGenerator.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto/LTOCodeGenerator.cpp?rev=154124&r1=154123&r2=154124&view=diff
> ==============================================================================
> --- llvm/trunk/tools/lto/LTOCodeGenerator.cpp (original)
> +++ llvm/trunk/tools/lto/LTOCodeGenerator.cpp Thu Apr  5 16:26:44 2012
> @@ -46,10 +46,13 @@
>   #include "llvm/ADT/StringExtras.h"
>   using namespace llvm;
>
> -static cl::opt<bool>  DisableInline("disable-inlining",
> +static cl::opt<bool>  EnableInternalizing("enable-internalizing", cl::init(false),
> +  cl::desc("Internalize functions during LTO"));
> +
> +static cl::opt<bool>  DisableInline("disable-inlining", cl::init(false),
>     cl::desc("Do not run the inliner pass"));
>
> -static cl::opt<bool>  DisableGVNLoadPRE("disable-gvn-loadpre",
> +static cl::opt<bool>  DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
>     cl::desc("Do not run the GVN load PRE pass"));
>
>   const char* LTOCodeGenerator::getVersionString() {
> @@ -275,6 +278,14 @@
>   }
>
>   void LTOCodeGenerator::applyScopeRestrictions() {
> +  // Internalize only if specifically asked for. Otherwise, global symbols which
> +  // exist in the final image, but which are used outside of that image
> +  // (e.g. bundling) may be removed. This also happens when a function is used
> +  // only in inline asm. LLVM doesn't recognize that as a "use", so it could be
> +  // stripped.
> +  if (!EnableInternalizing)
> +    return;
> +
>     if (_scopeRestrictionsDone) return;
>     Module *mergedModule = _linker.getModule();
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list