[LLVMdev] Best way to clean up empty global_ctors

Nico Weber thakis at chromium.org
Wed Apr 30 17:09:24 PDT 2014


I'm not sure I understand what you mean. The unoptimized IR is

    @llvm.global_ctors = appending global [1 x { i32, void ()* }] [{
i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]

    define internal void @_GLOBAL__I_a() section
"__TEXT,__StaticInit,regular,pure_instructions" {
    entry:
      call void @__cxx_global_var_init()
      ret void
    }

    define internal void @__cxx_global_var_init() section
"__TEXT,__StaticInit,regular,pure_instructions" {
    entry:
      %0 = load i32* @_ZN3Bar18LINKER_INITIALIZEDE, align 4
      call void @_ZN3FooC1E17LinkerInitialized(%class.Foo* @foo, i32 %0)
      ret void
    }

    ; Function Attrs: ssp uwtable
    define linkonce_odr void
@_ZN3FooC1E17LinkerInitialized(%class.Foo* %this, i32) unnamed_addr #0
align 2 {
    entry:
      %this.addr = alloca %class.Foo*, align 8
      %.addr = alloca i32, align 4
      store %class.Foo* %this, %class.Foo** %this.addr, align 8
      store i32 %0, i32* %.addr, align 4
      %this1 = load %class.Foo** %this.addr
      %1 = load i32* %.addr, align 4
      call void @_ZN3FooC2E17LinkerInitialized(%class.Foo* %this1, i32 %1)
      ret void
    }

…which is quite a bit of stuff. But other passes successfully reduce this to

    @llvm.global_ctors = appending global [1 x { i32, void ()* }] [{
i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]

    ; Function Attrs: nounwind readnone
    define internal void @_GLOBAL__I_a() #1 section
"__TEXT,__StaticInit,regular,pure_instructions" {
    entry:
      ret void
    }

which is much nicer, and globalopt is able to reduce the latter bit to
an empty global_ctors list – the problem is that it runs before the IR
is optimized that much. Just doing globalopt once more (or doing just
the global_ctor bits of globalopt once more) is enough to fix the
problem. The existing machinery seems to do all that's needed, it just
needs to be used in a slightly different order as far as I understand.

On Wed, Apr 30, 2014 at 4:59 PM, Reid Kleckner <rnk at google.com> wrote:
> Can we strengthen globalopt to symbolically execute at most one direct call
> to any given function, or is that crazy talk?
>
>
> On Wed, Apr 30, 2014 at 4:48 PM, Nico Weber <thakis at chromium.org> wrote:
>>
>> Hi,
>>
>> I'd like to fix PR19590, which is about llvm.global_ctors containing
>> functions that end up being empty after optimization (which causes the
>> linker to add useless init_array entries to the output binary).
>> globalopt removes empty functions from llvm.global_ctors, but by the
>> time the function becomes empty globalopt has already run and it
>> doesn't run again.
>>
>> I'm wondering what the best fix is:
>> 1. Should globalopt run once more after all other passes have run?
>> 2. Or should the llvm.global_ctors optimization code in globalopt be
>> moved into a helper function somewhere that's called from both
>> globalopt and a new optimization pass cdtoropt that does nothing but
>> remove empty functions from llvm.global_ctors and llvm.global_dtors?
>> Then only this new pass would be added after all other passes. (This
>> new pass should run very quickly, it doesn't have to do much.)
>>
>> Thanks for any advice,
>> Nico
>> _______________________________________________
>> LLVM Developers mailing list
>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>




More information about the llvm-dev mailing list