Generating available_externally vtables for outline virtual functions
Generating available_externally vtables for optimizations purposes.
Unfortunatelly ItaniumABI doesn't guarantee that we will be able to
refer to virtual inline method by name.
But when we don't have any inline virtual methods, and key function is
not defined in this TU, we can generate that there will be vtable and
mark it as available_externally.
This is patch will help devirtualize better.
Differential Revision: http://reviews.llvm.org/D11441
llvm-svn: 243090
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 70af69b..eb85413a 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -215,6 +215,8 @@
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
+ bool canEmitAvailableExternallyVTable(const CXXRecordDecl *RD) const override;
+
void setThunkLinkage(llvm::Function *Thunk, bool ForVTable, GlobalDecl GD,
bool ReturnAdjustment) override {
// Allow inlining of thunks by emitting them with available_externally
@@ -302,6 +304,24 @@
friend class ItaniumRTTIBuilder;
void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override;
+
+ private:
+ /// Checks if function has any virtual inline function.
+ bool hasAnyVirtualInlineFunction(const CXXRecordDecl *RD) const {
+ const auto &VtableLayout =
+ CGM.getItaniumVTableContext().getVTableLayout(RD);
+
+ for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+ if (VtableComponent.getKind() !=
+ VTableComponent::Kind::CK_FunctionPointer)
+ continue;
+
+ const auto &Method = VtableComponent.getFunctionDecl();
+ if (Method->getCanonicalDecl()->isInlined())
+ return true;
+ }
+ return false;
+ }
};
class ARMCXXABI : public ItaniumCXXABI {
@@ -1481,6 +1501,19 @@
VTables.EmitVTTDefinition(VTT, CGM.getVTableLinkage(RD), RD);
}
+bool ItaniumCXXABI::canEmitAvailableExternallyVTable(
+ const CXXRecordDecl *RD) const {
+ // We don't emit available_externally vtables if we are in -fapple-kext mode
+ // because kext mode does not permit devirtualization.
+ if (CGM.getLangOpts().AppleKext)
+ return false;
+
+ // If we don't have any inline virtual functions,
+ // then we are safe to emit available_externally copy of vtable.
+ // FIXME we can still emit a copy of the vtable if we
+ // can emit definition of the inline functions.
+ return !hasAnyVirtualInlineFunction(RD);
+}
static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
llvm::Value *Ptr,
int64_t NonVirtualAdjustment,