summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorPiotr Padlewski <prazek@google.com>2015-07-24 04:04:49 +0000
committerPiotr Padlewski <prazek@google.com>2015-07-24 04:04:49 +0000
commita68a78751fb0d4eb7eb047365a66ea9becbc6a28 (patch)
treea0e518429cfb8bba71d662ba042c65ee702eccf1 /clang/lib
parent5d8e569926773bea0e55d00a644c17ca202c29cc (diff)
downloadbcm5719-llvm-a68a78751fb0d4eb7eb047365a66ea9becbc6a28.tar.gz
bcm5719-llvm-a68a78751fb0d4eb7eb047365a66ea9becbc6a28.zip
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
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CGCXXABI.h3
-rw-r--r--clang/lib/CodeGen/CGVTables.cpp42
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp33
-rw-r--r--clang/lib/CodeGen/MicrosoftCXXABI.cpp4
4 files changed, 70 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index 436b96a615e..5ef409ecdee 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -218,6 +218,9 @@ public:
virtual void emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) = 0;
virtual llvm::GlobalVariable *getThrowInfo(QualType T) { return nullptr; }
+ virtual bool canEmitAvailableExternallyVTable(
+ const CXXRecordDecl *RD) const = 0;
+
virtual void emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) = 0;
virtual llvm::CallInst *
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 7321dbfe340..c6d7e0632c7 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -679,6 +679,12 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
return VTable;
}
+static bool shouldEmitAvailableExternallyVTable(const CodeGenModule &CGM,
+ const CXXRecordDecl *RD) {
+ return CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ CGM.getCXXABI().canEmitAvailableExternallyVTable(RD);
+}
+
/// Compute the required linkage of the v-table for the given class.
///
/// Note that we only call this at the end of the translation unit.
@@ -700,7 +706,12 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
switch (keyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared:
case TSK_ExplicitSpecialization:
- assert(def && "Should not have been asked to emit this");
+ assert((def || CodeGenOpts.OptimizationLevel > 0) &&
+ "Shouldn't query vtable linkage without key function or "
+ "optimizations");
+ if (!def && CodeGenOpts.OptimizationLevel > 0)
+ return llvm::GlobalVariable::AvailableExternallyLinkage;
+
if (keyFunction->isInlined())
return !Context.getLangOpts().AppleKext ?
llvm::GlobalVariable::LinkOnceODRLinkage :
@@ -742,16 +753,18 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
}
switch (RD->getTemplateSpecializationKind()) {
- case TSK_Undeclared:
- case TSK_ExplicitSpecialization:
- case TSK_ImplicitInstantiation:
- return DiscardableODRLinkage;
-
- case TSK_ExplicitInstantiationDeclaration:
- return llvm::GlobalVariable::ExternalLinkage;
-
- case TSK_ExplicitInstantiationDefinition:
- return NonDiscardableODRLinkage;
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ case TSK_ImplicitInstantiation:
+ return DiscardableODRLinkage;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ return shouldEmitAvailableExternallyVTable(*this, RD)
+ ? llvm::GlobalVariable::AvailableExternallyLinkage
+ : llvm::GlobalVariable::ExternalLinkage;
+
+ case TSK_ExplicitInstantiationDefinition:
+ return NonDiscardableODRLinkage;
}
llvm_unreachable("Invalid TemplateSpecializationKind!");
@@ -819,7 +832,12 @@ bool CodeGenVTables::isVTableExternal(const CXXRecordDecl *RD) {
/// we define that v-table?
static bool shouldEmitVTableAtEndOfTranslationUnit(CodeGenModule &CGM,
const CXXRecordDecl *RD) {
- return !CGM.getVTables().isVTableExternal(RD);
+ // If vtable is internal then it has to be done
+ if (!CGM.getVTables().isVTableExternal(RD))
+ return true;
+
+ // If it's external then maybe we will need it as available_externally
+ return shouldEmitAvailableExternallyVTable(CGM, RD);
}
/// Given that at some point we emitted a reference to one or more
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 70af69b7645..eb85413a5de 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -215,6 +215,8 @@ public:
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 @@ public:
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 @@ void ItaniumCXXABI::emitVirtualInheritanceTables(const CXXRecordDecl *RD) {
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,
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index f864213566a..613d29a63cd 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -106,6 +106,10 @@ public:
QualType DestTy) override;
bool EmitBadCastCall(CodeGenFunction &CGF) override;
+ bool canEmitAvailableExternallyVTable(
+ const CXXRecordDecl *RD) const override {
+ return false;
+ }
llvm::Value *
GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
OpenPOWER on IntegriCloud