[cfe-commits] r65103 - /cfe/trunk/lib/AST/DeclBase.cpp

Chris Lattner sabre at nondot.org
Thu Feb 19 17:44:05 PST 2009


Author: lattner
Date: Thu Feb 19 19:44:05 2009
New Revision: 65103

URL: http://llvm.org/viewvc/llvm-project?rev=65103&view=rev
Log:
optimize the 'StoredDeclsMap' for the common case where there is 
exactly one decl with a specific name in a specific context.  This
avoids a bunch of malloc traffic and shrinks StoredDeclsMap to hold
one pointer instead of 3 words (for a std::vector).

This speeds up -fsyntax-only on cocoa.h with PTH by ~7.3%.

Modified:
    cfe/trunk/lib/AST/DeclBase.cpp

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=65103&r1=65102&r2=65103&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Thu Feb 19 19:44:05 2009
@@ -268,15 +268,119 @@
   }
 }
 
-// FIXME: We really want to use a DenseSet here to eliminate the
-// redundant storage of the declaration names, but (1) it doesn't give
-// us the ability to search based on DeclarationName, (2) we really
-// need something more like a DenseMultiSet, and (3) it's
-// implemented in terms of DenseMap anyway. However, this data
-// structure is really space-inefficient, so we'll have to do
-// something.
-typedef llvm::DenseMap<DeclarationName, std::vector<NamedDecl*> >
-  StoredDeclsMap;
+/// StoredDeclsList - This is an array of decls optimized a common case of only
+/// containing one entry.
+struct StoredDeclsList {
+  /// Data - If the integer is 0, then the pointer is a NamedDecl*.  If the
+  /// integer is 1, then it is a VectorTy;
+  llvm::PointerIntPair<void*, 1, bool> Data;
+  
+  /// VectorTy - When in vector form, this is what the Data pointer points to.
+  typedef llvm::SmallVector<NamedDecl*, 4> VectorTy;
+public:
+  StoredDeclsList() {}
+  StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
+    if (isVector())
+      Data.setPointer(new VectorTy(getVector()));
+  }
+  
+  ~StoredDeclsList() {
+    // If this is a vector-form, free the vector.
+    if (isVector())
+      delete &getVector();
+  }
+  
+  bool isVector() const { return Data.getInt() != 0; }
+  bool isInline() const { return Data.getInt() == 0; }
+  bool isNull() const { return Data.getPointer() == 0; }
+  
+  void setOnlyValue(NamedDecl *ND) {
+    assert(isInline() && "Not inline");
+    Data.setPointer(ND);
+  }
+
+  /// getLookupResult - Return an array of all the decls that this list
+  /// represents.
+  DeclContext::lookup_result getLookupResult() {
+    // If we have a single inline unit, return it.
+    if (isInline()) {
+      assert(!isNull() && "Empty list isn't allowed");
+      
+      // Data is a raw pointer to a NamedDecl*, return it.
+      void *Ptr = &Data;
+      return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
+    }
+    
+    // Otherwise, we have a range result.
+    VectorTy &V = getVector();
+    return DeclContext::lookup_result(&V[0], &V[0]+V.size());
+  }
+  
+  /// HandleRedeclaration - If this is a redeclaration of an existing decl,
+  /// replace the old one with D and return true.  Otherwise return false.
+  bool HandleRedeclaration(NamedDecl *D) {
+    // Most decls only have one entry in their list, special case it.
+    if (isInline()) {
+      if (!D->declarationReplaces(getInlineValue()))
+        return false;
+      setOnlyValue(D);
+      return true;
+    }
+    
+    // Determine if this declaration is actually a redeclaration.
+    VectorTy &Vec = getVector();
+    VectorTy::iterator RDI
+      = std::find_if(Vec.begin(), Vec.end(),
+                     std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
+                                  D));
+    if (RDI == Vec.end())
+      return false;
+    *RDI = D;
+    return true;
+  }
+  
+  /// AddSubsequentDecl - This is called on the second and later decl when it is
+  /// not a redeclaration to merge it into the appropriate place in our list.
+  /// 
+  void AddSubsequentDecl(NamedDecl *D) {
+    // If this is the second decl added to the list, convert this to vector
+    // form.
+    if (isInline()) {
+      NamedDecl *OldD = getInlineValue();
+      Data.setInt(1);
+      VectorTy *VT = new VectorTy();
+      VT->push_back(OldD);
+      Data.setPointer(VT);
+    }
+    
+    VectorTy &Vec = getVector();
+    if (isa<UsingDirectiveDecl>(D) ||
+        D->getIdentifierNamespace() == Decl::IDNS_Tag)
+      Vec.push_back(D);
+    else if (Vec.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
+      NamedDecl *TagD = Vec.back();
+      Vec.back() = D;
+      Vec.push_back(TagD);
+    } else
+      Vec.push_back(D);
+  }
+      
+  
+private:
+  VectorTy &getVector() const {
+    assert(isVector() && "Not in vector form");
+    return *static_cast<VectorTy*>(Data.getPointer());
+  }
+  
+  NamedDecl *getInlineValue() const {
+    assert(isInline() && "Not in inline form");
+    return (NamedDecl*)Data.getPointer();
+  }
+};
+
+
+
+typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap;
 
 DeclContext::~DeclContext() {
   unsigned Size = LookupPtr.getInt();
@@ -412,9 +516,7 @@
     StoredDeclsMap::iterator Pos = Map->find(Name);
     if (Pos == Map->end())
       return lookup_result(0, 0);
-    
-    return lookup_result(&Pos->second.front(), 
-                         &Pos->second.front() + Pos->second.size());
+    return Pos->second.getLookupResult();
   } 
 
   // We have a small array. Look into it.
@@ -559,46 +661,21 @@
   }
 
   // Insert this declaration into the map.
-  StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
-  std::vector<NamedDecl *> &DeclNameEntries = (*Map)[D->getDeclName()];
-  if (DeclNameEntries.empty()) {
-    DeclNameEntries.push_back(D);
+  StoredDeclsMap &Map = *static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
+  StoredDeclsList &DeclNameEntries = Map[D->getDeclName()];
+  if (DeclNameEntries.isNull()) {
+    DeclNameEntries.setOnlyValue(D);
     return;
   }
 
   // If it is possible that this is a redeclaration, check to see if there is
   // already a decl for which declarationReplaces returns true.  If there is
   // one, just replace it and return.
-  if (MayBeRedeclaration) {
-    // Most decls only have one entry in their list, special case it.
-    if (DeclNameEntries.size() == 1) {
-      if (D->declarationReplaces(DeclNameEntries[0])) {
-        DeclNameEntries[0] = D;
-        return;
-      }
-    } else {
-      // Determine if this declaration is actually a redeclaration.
-      std::vector<NamedDecl *>::iterator Redecl
-        = std::find_if(DeclNameEntries.begin(), DeclNameEntries.end(),
-                     std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
-                                  D));
-      if (Redecl != DeclNameEntries.end()) {
-        *Redecl = D;
-        return;
-      }
-    }
-  }
+  if (MayBeRedeclaration && DeclNameEntries.HandleRedeclaration(D))
+    return;
   
   // Put this declaration into the appropriate slot.
-  if (isa<UsingDirectiveDecl>(D) ||
-      D->getIdentifierNamespace() == Decl::IDNS_Tag)
-    DeclNameEntries.push_back(D);
-  else if (DeclNameEntries.back()->getIdentifierNamespace() == Decl::IDNS_Tag) {
-    NamedDecl *TagD = DeclNameEntries.back();
-    DeclNameEntries.back() = D;
-    DeclNameEntries.push_back(TagD);
-  } else
-    DeclNameEntries.push_back(D);
+  DeclNameEntries.AddSubsequentDecl(D);
 }
 
 /// Returns iterator range [First, Last) of UsingDirectiveDecls stored within





More information about the cfe-commits mailing list