New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
llvm doesn't partially remove static initializers #14049
Comments
The optimization you're suggesting isn't correct in general. For instance, given: foo bar = {bar.d, 1, 2, 3, 4}; bar.a is required to be 0. C++ only allows us to convert dynamic initialization to static if it can be done for the entirety of a variable's initializer. |
Well, no optimization is correct for a sufficiently general testcase :-) GCC does optimize this one: _GLOBAL__sub_I_x: .... bar: I noticed this in code that was implementing some sort of inheritance with function pointers. In one TU we have foo base = { function_pointer1, function_pointer2, ...}; and in another foo derived = { other_function_pointer, base.function_pointer2}; the llvm generated code initializes all of derived at runtime, the gcc one only the bits that are not known constants. |
Looks like g++ is miscompiling your code. Suppose you link that code against this: struct foo { We're back to the original situation: bar.a must be initialized by 0. C++ does not permit part of the initializer of a variable to be promoted from dynamic to static initialization, it's an all-or-nothing thing. |
And the order the fields of a struct are initialized in are also defined by the standard? May I trouble you for the standard sections? I will probably report this bug in gcc. |
That's actually irrelevant for your example. What's relevant is that the standard guarantees that x is initialized before bar.
[basic.start.init]p2 and p3 lay out the relevant rules here. In particular, note that [basic.start.init]p3 only permits the initialization for a variable to be promoted from dynamic to static, not the initialization for a sub-object of a variable. In this example, x may be initialized to 0 or to 3, but bar must be initialized to {0,1,2,3,4}. |
Thanks a lot. |
Extended Description
A small missed optimization I noticed while debugging another problem is that given
int zed();
int x = zed();
struct foo {
int a;
int b;
int c;
int d;
int e;
};
foo bar = {x, 1, 2, 3, 4};
Only the first element has to be found at runtime, but llvm still produces code to initialize the full struct:
define internal void @_GLOBAL__I_a() section ".text.startup" {
entry:
%call.i = tail call i32 @_Z3zedv() optsize
store i32 %call.i, i32* @x, align 4, !tbaa !0
store i32 %call.i, i32* getelementptr inbounds (%struct.foo* @bar, i64 0, i32 0), align 4, !tbaa !0
store i32 1, i32* getelementptr inbounds (%struct.foo* @bar, i64 0, i32 1), align 4, !tbaa !0
store i32 2, i32* getelementptr inbounds (%struct.foo* @bar, i64 0, i32 2), align 4, !tbaa !0
store i32 3, i32* getelementptr inbounds (%struct.foo* @bar, i64 0, i32 3), align 4, !tbaa !0
store i32 4, i32* getelementptr inbounds (%struct.foo* @bar, i64 0, i32 4), align 4, !tbaa !0
ret void
}
The text was updated successfully, but these errors were encountered: