diff options
author | Anders Carlsson <andersca@mac.com> | 2010-06-04 00:54:04 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-06-04 00:54:04 +0000 |
commit | 147a23dea1e6f247a568870b32eda1ce9a39a632 (patch) | |
tree | 623c9b67aa82d4387e6dab21bdfb90c88cc597c6 /lib/CodeGen/CGVTables.cpp | |
parent | 75f7c0f5a82689c5abe1f4c5b93bfe1fbe5feaa8 (diff) |
Use CXXRecordDecl::getFinalOverriders to get final overriders. This speeds up vtable layout by moving away from the old final overrider computation code that had O(N^2) complexity in some cases.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105447 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGVTables.cpp')
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 120 |
1 files changed, 119 insertions, 1 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 1aa9a11fc1..1a96e7f8fe 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -150,6 +150,22 @@ private: static void MergeSubobjectOffsets(const SubobjectOffsetsMapTy &NewOffsets, SubobjectOffsetsMapTy &Offsets); + /// SubobjectsToOffsetsMapTy - A mapping from a base subobject (represented + /// as a record decl and a subobject number) and its offsets in the most + /// derived class as well as the layout class. + typedef llvm::DenseMap<std::pair<const CXXRecordDecl *, unsigned>, + uint64_t> SubobjectOffsetMapTy; + + typedef llvm::DenseMap<const CXXRecordDecl *, unsigned> SubobjectCountMapTy; + + /// ComputeBaseOffsets - Compute the offsets for all base subobjects of the + /// given base. + void ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, + uint64_t OffsetInLayoutClass, + SubobjectOffsetMapTy &SubobjectOffsets, + SubobjectOffsetMapTy &SubobjectLayoutClassOffsets, + SubobjectCountMapTy &SubobjectCounts); + public: FinalOverriders(const CXXRecordDecl *MostDerivedClass, uint64_t MostDerivedClassOffset, @@ -187,13 +203,59 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass, MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass), Context(MostDerivedClass->getASTContext()), MostDerivedClassLayout(Context.getASTRecordLayout(MostDerivedClass)) { - +#if 0 // Compute the final overriders. SubobjectOffsetsMapTy Offsets; ComputeFinalOverriders(BaseSubobject(MostDerivedClass, 0), /*BaseSubobjectIsVisitedVBase=*/false, MostDerivedClassOffset, Offsets); VisitedVirtualBases.clear(); +#endif + // Compute base offsets. + SubobjectOffsetMapTy SubobjectOffsets; + SubobjectOffsetMapTy SubobjectLayoutClassOffsets; + SubobjectCountMapTy SubobjectCounts; + ComputeBaseOffsets(BaseSubobject(MostDerivedClass, 0), /*IsVirtual=*/false, + MostDerivedClassOffset, SubobjectOffsets, + SubobjectLayoutClassOffsets, SubobjectCounts); + + // Get the the final overriders. + CXXFinalOverriderMap FinalOverriders; + MostDerivedClass->getFinalOverriders(FinalOverriders); + + for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(), + E = FinalOverriders.end(); I != E; ++I) { + const CXXMethodDecl *MD = I->first; + const OverridingMethods& Methods = I->second; + + for (OverridingMethods::const_iterator I = Methods.begin(), + E = Methods.end(); I != E; ++I) { + unsigned SubobjectNumber = I->first; + assert(SubobjectOffsets.count(std::make_pair(MD->getParent(), + SubobjectNumber)) && + "Did not find subobject offset!"); + + uint64_t BaseOffset = SubobjectOffsets[std::make_pair(MD->getParent(), + SubobjectNumber)]; + + assert(I->second.size() == 1 && "Final overrider is not unique!"); + const UniqueVirtualMethod &Method = I->second.front(); + + const CXXRecordDecl *OverriderRD = Method.Method->getParent(); + assert(SubobjectLayoutClassOffsets.count( + std::make_pair(OverriderRD, Method.Subobject)) + && "Did not find subobject offset!"); + uint64_t OverriderOffset = + SubobjectLayoutClassOffsets[std::make_pair(OverriderRD, + Method.Subobject)]; + + OverriderInfo& Overrider = OverridersMap[std::make_pair(MD, BaseOffset)]; + assert(!Overrider.Method && "Overrider should not exist yet!"); + + Overrider.Offset = OverriderOffset; + Overrider.Method = Method.Method; + } + } #if DUMP_OVERRIDERS // And dump them (for now). @@ -478,6 +540,62 @@ void FinalOverriders::ComputeFinalOverriders(BaseSubobject Base, Offsets[RD].insert(Base.getBaseOffset()); } +void +FinalOverriders::ComputeBaseOffsets(BaseSubobject Base, bool IsVirtual, + uint64_t OffsetInLayoutClass, + SubobjectOffsetMapTy &SubobjectOffsets, + SubobjectOffsetMapTy &SubobjectLayoutClassOffsets, + SubobjectCountMapTy &SubobjectCounts) { + const CXXRecordDecl *RD = Base.getBase(); + + unsigned SubobjectNumber = 0; + if (!IsVirtual) + SubobjectNumber = ++SubobjectCounts[RD]; + + // Set up the subobject to offset mapping. + assert(!SubobjectOffsets.count(std::make_pair(RD, SubobjectNumber)) + && "Subobject offset already exists!"); + assert(!SubobjectLayoutClassOffsets.count(std::make_pair(RD, SubobjectNumber)) + && "Subobject offset already exists!"); + + SubobjectOffsets[std::make_pair(RD, SubobjectNumber)] = + Base.getBaseOffset(); + SubobjectLayoutClassOffsets[std::make_pair(RD, SubobjectNumber)] = + OffsetInLayoutClass; + + // Traverse our bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + uint64_t BaseOffset; + uint64_t BaseOffsetInLayoutClass; + if (I->isVirtual()) { + // Check if we've visited this virtual base before. + if (SubobjectOffsets.count(std::make_pair(BaseDecl, 0))) + continue; + + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + BaseOffset = MostDerivedClassLayout.getVBaseClassOffset(BaseDecl); + BaseOffsetInLayoutClass = + LayoutClassLayout.getVBaseClassOffset(BaseDecl); + } else { + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + uint64_t Offset = Layout.getBaseClassOffset(BaseDecl); + + BaseOffset = Base.getBaseOffset() + Offset; + BaseOffsetInLayoutClass = OffsetInLayoutClass + Offset; + } + + ComputeBaseOffsets(BaseSubobject(BaseDecl, BaseOffset), I->isVirtual(), + BaseOffsetInLayoutClass, SubobjectOffsets, + SubobjectLayoutClassOffsets, SubobjectCounts); + } +} + void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) { const CXXRecordDecl *RD = Base.getBase(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); |