Inlining dllimport functions

Currently, Clang won’t inline a dllimport function that references a non-dllimport function. This has a big performance impact on using libc++ on Windows because even something as simple as vector::data() won’t be inlined at the max optimisation level.

Would anything break if Clang were to allow inlining of a dllimport function that references a non-dllimport function that’s also declared inline?

E.g:

inline bool f() { return false; }

__declspec(dllimport) inline bool g() { return f(); }

bool h() {
  // can we inline this without issue?
  return g();
}

I've had to do this locally for similar reasons, and so far so good.

It would cause problems if ‘f’ in turn referenced functions that were neither inline nor exported:

bool not_exported();
inline bool f() { return not_exported(); }
__declspec(dllimport) inline bool g() { return f(); }

I’m pretty sure MSVC will not inline g in this or your example, so I would suggest adjusting dllimport usage patterns to something that satisfies both compilers rather than changing clang.

Does https://reviews.llvm.org/D51340 enable this?

I’ve looked into it a bit more and it seems like the main optimisation barrier with libc++ on Windows is the extern template usage; it’s preventing a lot of trivial inlining. What about making _LIBCPP_DISABLE_EXTERN_TEMPLATE the default for Windows DLL builds?

That would be a shame. I wouldn’t want to throw away such an important code size optimization just because we can’t export the things the inline functions reference.

I understand it’s tough, though. libc++'s visibility and export macros have many consumers, many vendors, many linkage models, and basically too many cooks in the kitchen. I don’t have any brilliant suggestions for solving that.

Would it break ABI compatibility if we let Clang inline things like this? What about putting it behind a Clang-specific optimisation flag?

I’m not sure I understand this ABI compatibility concern.

I was suggesting that libc++ should export all of the class methods it needs, so that we can always emit these dllimport methods as available_externally definitions. This would be much simpler than adding new flags.

I was thinking more in the context of changing Clang.

Wouldn’t exporting some of those internal symbols get in the way of ABI stability? libc++ goes to great lengths to keep stuff like that out of the dynamic libraries.

I was thinking more in the context of changing Clang.

Wouldn’t exporting some of those internal symbols get in the way of ABI stability? libc++ goes to great lengths to keep stuff like that out of the dynamic libraries.

Yes — we don’t want to increase the ABI surface of libc++ unless necessary, because everything that is exported needs to stay the same forever.

Louis