[PATCH] D103495: [static initializers] Don't put ordered dynamic initializers of static variables into global_ctors

Reid Kleckner via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 2 11:50:35 PDT 2021


rnk added subscribers: aeubanks, hans, rsmith.
rnk added a comment.

+ at rsmith @hans @aeubanks

I think this would be an unfortunate code size and startup time regression for Itanium C++ inline variables. The existing code was written under the assumption that vague linkage (GVA_DiscardableODR) implies no initialization ordering, but I think you've found a valid counterexample.

> specifically when init_array is not used

Can you elaborate on why that is? Here's what I remember, and what I guess is happening. ELF has two initializer schemes: .init_array and .ctors. They are essentially equivalent, they are both arrays of function pointers, but one is called in reverse order and the other is called in forward order. The compiler knows which scheme is in use and it is controlled by -fuse-init-array.

The LLVM IR langref says that llvm.global_ctors are called in ascending priority order, and the order between initializers is not defined. That's not very helpful and often doesn't reflect reality. I wonder if we could do two things, perhaps separately:

1. emit llvm.global_ctors so that they are called in order of appearance in the IR array (is this not already true?)
2. define the order of initialization in LangRef

With the first change in place, we can be confident that so long as all includers of the `StaticsClass` in the test emit both initializers in the correct order, no matter which initializers prevail, they will be called in the correct order. Of course, this could break users relying on the existing ordering, nevermind that it is explicitly documented as undefined.

The second change is only a documentation change, but I would like to find a way to justify what LLVM does in GlobalOpt. GlobalOpt can effectively fold a dynamic initializer to constant memory in certain cases. That can only ever have the effect of making an initializer run earlier. As long as no initializers depend on observing uninitialized globals, that should be safe. The guarantee that we want to provide is that, for each initializer, all initializers prior to it in the global_ctors array will have run when it runs. Initializers that appear later may run earlier. Hopefully that covers both the usual way that .init_array sections are linked together and the way globalopt optimizes dynamic initialization.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103495/new/

https://reviews.llvm.org/D103495



More information about the cfe-commits mailing list