[AST] Various micro-optimizations in CXXInheritance
authorBenjamin Kramer <benny.kra@googlemail.com>
Fri, 20 Jul 2018 20:13:08 +0000 (20:13 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Fri, 20 Jul 2018 20:13:08 +0000 (20:13 +0000)
1. Pack std::pair<bool, unsigned> in CXXBasePaths::ClassSubobjects.
2. Use a SmallPtrSet instead of a SmallDenseSet for CXXBasePaths::VisitedDependentRecords.
3. Reorder some members of CXXBasePaths to save 8 bytes.
4. Use a SmallSetVector instead of a SetVector in CXXBasePaths::ComputeDeclsFound to avoid some allocations.

This speeds up an -fsyntax-only on all of Boost by approx 0.15%,
mainly by speeding up CXXBasePaths::lookupInBases by
approx 10%. No functional changes.

Patch by Bruno Ricci!

Differential Revision: https://reviews.llvm.org/D49302

llvm-svn: 337607

clang/include/clang/AST/CXXInheritance.h
clang/lib/AST/CXXInheritance.cpp

index 4c031c450b1157d468a54080e45831c68be98649..2ae1d8b25823b67839884f1e26c7879732cfd866 100644 (file)
@@ -125,18 +125,36 @@ class CXXBasePaths {
   /// Paths - The actual set of paths that can be taken from the
   /// derived class to the same base class.
   std::list<CXXBasePath> Paths;
-  
+
   /// ClassSubobjects - Records the class subobjects for each class
-  /// type that we've seen. The first element in the pair says
+  /// type that we've seen. The first element IsVirtBase says
   /// whether we found a path to a virtual base for that class type,
-  /// while the element contains the number of non-virtual base
+  /// while NumberOfNonVirtBases contains the number of non-virtual base
   /// class subobjects for that class type. The key of the map is
   /// the cv-unqualified canonical type of the base class subobject.
-  llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects;
+  struct IsVirtBaseAndNumberNonVirtBases {
+    unsigned IsVirtBase : 1;
+    unsigned NumberOfNonVirtBases : 31;
+  };
+  llvm::SmallDenseMap<QualType, IsVirtBaseAndNumberNonVirtBases, 8>
+      ClassSubobjects;
 
   /// VisitedDependentRecords - Records the dependent records that have been
   /// already visited.
-  llvm::SmallDenseSet<const CXXRecordDecl *, 4> VisitedDependentRecords;
+  llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedDependentRecords;
+
+  /// DetectedVirtual - The base class that is virtual.
+  const RecordType *DetectedVirtual = nullptr;
+
+  /// ScratchPath - A BasePath that is used by Sema::lookupInBases
+  /// to help build the set of paths.
+  CXXBasePath ScratchPath;
+
+  /// Array of the declarations that have been found. This
+  /// array is constructed only if needed, e.g., to iterate over the
+  /// results within LookupResult.
+  std::unique_ptr<NamedDecl *[]> DeclsFound;
+  unsigned NumDeclsFound = 0;
 
   /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find
   /// ambiguous paths while it is looking for a path from a derived
@@ -152,20 +170,7 @@ class CXXBasePaths {
   /// if it finds a path that goes across a virtual base. The virtual class
   /// is also recorded.
   bool DetectVirtual;
-  
-  /// ScratchPath - A BasePath that is used by Sema::lookupInBases
-  /// to help build the set of paths.
-  CXXBasePath ScratchPath;
 
-  /// DetectedVirtual - The base class that is virtual.
-  const RecordType *DetectedVirtual = nullptr;
-  
-  /// Array of the declarations that have been found. This
-  /// array is constructed only if needed, e.g., to iterate over the
-  /// results within LookupResult.
-  std::unique_ptr<NamedDecl *[]> DeclsFound;
-  unsigned NumDeclsFound = 0;
-  
   void ComputeDeclsFound();
 
   bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record,
index 374ddac60b7c1e724c707651532c67b8bff21828..2825329775edd9d915c9c53e1f2be20f174d674f 100644 (file)
@@ -40,7 +40,7 @@ void CXXBasePaths::ComputeDeclsFound() {
   assert(NumDeclsFound == 0 && !DeclsFound &&
          "Already computed the set of declarations");
 
-  llvm::SetVector<NamedDecl *, SmallVector<NamedDecl *, 8>> Decls;
+  llvm::SmallSetVector<NamedDecl *, 8> Decls;
   for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path)
     Decls.insert(Path->Decls.front());
 
@@ -63,8 +63,8 @@ CXXBasePaths::decl_range CXXBasePaths::found_decls() {
 /// an unqualified, canonical class type.
 bool CXXBasePaths::isAmbiguous(CanQualType BaseType) {
   BaseType = BaseType.getUnqualifiedType();
-  std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
-  return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
+  IsVirtBaseAndNumberNonVirtBases Subobjects = ClassSubobjects[BaseType];
+  return Subobjects.NumberOfNonVirtBases + (Subobjects.IsVirtBase ? 1 : 0) > 1;
 }
 
 /// clear - Clear out all prior path information.
@@ -217,21 +217,21 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
     
     // Determine whether we need to visit this base class at all,
     // updating the count of subobjects appropriately.
-    std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
+    IsVirtBaseAndNumberNonVirtBases &Subobjects = ClassSubobjects[BaseType];
     bool VisitBase = true;
     bool SetVirtual = false;
     if (BaseSpec.isVirtual()) {
-      VisitBase = !Subobjects.first;
-      Subobjects.first = true;
+      VisitBase = !Subobjects.IsVirtBase;
+      Subobjects.IsVirtBase = true;
       if (isDetectingVirtual() && DetectedVirtual == nullptr) {
         // If this is the first virtual we find, remember it. If it turns out
         // there is no base path here, we'll reset it later.
         DetectedVirtual = BaseType->getAs<RecordType>();
         SetVirtual = true;
       }
-    } else
-      ++Subobjects.second;
-    
+    } else {
+      ++Subobjects.NumberOfNonVirtBases;
+    }
     if (isRecordingPaths()) {
       // Add this base specifier to the current path.
       CXXBasePathElement Element;
@@ -240,7 +240,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
       if (BaseSpec.isVirtual())
         Element.SubobjectNumber = 0;
       else
-        Element.SubobjectNumber = Subobjects.second;
+        Element.SubobjectNumber = Subobjects.NumberOfNonVirtBases;
       ScratchPath.push_back(Element);
 
       // Calculate the "top-down" access to this base class.