Take advantage of the TBAA "vtable access" annotation on loads of a global variable's vtable. This annotation marks loads as being loads of a C++ object's vtable pointer. Since we know that a vtable pointer cannot be changed to a different value after object construction, if we see a global object with an initializer that has a non-null vtable pointer, we can replace vtable loads from that object with the global initializer's vtable value.
General comment: Having a special case in TBAA for a constant after initialization value seems like the wrong factoring here. Supporting a more general extensions of !invariant.load would seem to be more generally useful.
Having said that, it doesn't look like you're adding the mechanism, just extending it. As such, my comment isn't directly relevant to the patch at hand.
Thanks for your feedback. Just to be clear, your objection is that there may be subsequent writes to @gS's vtable pointer during construction such that the value folded into @gS's initializer (i.e. the first vtable value written) is different from the value that would be loaded at the call site?
Exactly. Right now it seems like you're looking for "does the relevant field of this global have a non-zero value". For now, this coincidentally does the trick, but there's no real guarantee that it will always work.