Explicit instantiation declarations/definitions and optimizations

I was just thinking through the possible advice of encouraging users to use explicit template instantiation declarations/definitions to reduce object size.

It seems this may hurt performance in non-LTO builds by causing what were inlinable functions to no longer be available for inlining.

Should we consider emitting available_externally definitions of such entities (possibly under specific/higher optimization levels)?

  • David

We should, and we already do: Compiler Explorer

Do you have a case where we fail to do so? It's possible there's a bug in
this determination.

Sorry, yes, should've included my test case, which boiled down to:

template <typename T> void f() {}
extern template void f<int>(); void g() { f<int>(); }

The difference being the absence of the "inline" keyword on f's definition.
I wonder if that's the right tradeoff (I can understand using the inline
keyword to hint the inliner a little more strongly - but this seems like a
much stronger dependence on the keyword than I'd expect). Perhaps it is.

- Dave

The C++ standard doesn't permit us to instantiate f<int> in this case; per
[temp.explicit]/10,

"Except for inline functions, declarations with types deduced from their
initializer or return value (7.1.6.4), const variables of literal types,
variables of reference types, and class template specializations, explicit
instantiation declarations have the effect of suppressing the implicit
instantiation of the entity to which they refer."

So whether or not this is the right tradeoff, it's not our call to make. We
emit function definitions available_externally in (more or less) all the
cases that C++ lets us do so.

Ah, ok - that simplifies things at least. Thanks for the explanation, examples, etc.

(I wonder about as-if opportunities, but can chat about that over lunch or something, as I’m sure there aren’t any and I’ll just need to wrap my head around why)