There is a bug in IRGen where the calling convention of initialization functions for thread-local static members of c++ template classes isn't set. This caused InstCombine to remove a call to an initialization function because of the mismatch in the calling conventions between the initialization function and the call.
For example, when the following piece of code (this is in test/CodeGenCXX/cxx11-thread-local.cpp) is compiled,
int g(); template<typename T> struct V { static thread_local int m; }; template<typename T> thread_local int V<T>::m = g(); int e = V<int>::m;
IRGen generates the following IR:
@_ZTHN1VIiE1mE = linkonce_odr alias void (), void ()* @__cxx_global_var_init.9 define weak_odr hidden cxx_fast_tlscc i32* @_ZTWN1VIiE1mE() #2 { call cxx_fast_tlscc void @_ZTHN1VIiE1mE() ; this calls @__cxx_global_var_init.9 ret i32* @_ZN1VIiE1mE } ; this function is missing the calling convention "cxx_fast_tlscc". define internal void @__cxx_global_var_init.9() #0 section "__TEXT,__StaticInit,regular,pure_instructions" { ... }
To fix the bug, this patch sets the calling convention of the initialization functions to 'cxx_fast_tlscc'. Alternatively, I could remove 'cxx_fast_tlscc' from the call instruction, but I suppose we don't want to do so for performance reasons.
rdar://problem/40447463