[llvm-branch-commits] [cfe-tag] r90721 - /cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp

Douglas Gregor dgregor at apple.com
Sun Dec 6 13:49:26 PST 2009


Author: dgregor
Date: Sun Dec  6 15:49:26 2009
New Revision: 90721

URL: http://llvm.org/viewvc/llvm-project?rev=90721&view=rev
Log:
Merge performance improvements from 90661,90662,90663,90715,90719 to cremebrulee-23.1

Modified:
    cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp

Modified: cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp?rev=90721&r1=90720&r2=90721&view=diff

==============================================================================
--- cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/tags/cremebrulee/cremebrulee-23.1/lib/Sema/SemaCodeComplete.cpp Sun Dec  6 15:49:26 2009
@@ -45,11 +45,64 @@
     /// the result set twice.
     llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
     
+    typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
+
+    /// \brief An entry in the shadow map, which is optimized to store
+    /// a single (declaration, index) mapping (the common case) but
+    /// can also store a list of (declaration, index) mappings.
+    class ShadowMapEntry {
+      typedef llvm::SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
+
+      /// \brief Contains either the solitary NamedDecl * or a vector
+      /// of (declaration, index) pairs.
+      llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
+
+      /// \brief When the entry contains a single declaration, this is
+      /// the index associated with that entry.
+      unsigned SingleDeclIndex;
+
+    public:
+      ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
+
+      void Add(NamedDecl *ND, unsigned Index) {
+        if (DeclOrVector.isNull()) {
+          // 0 - > 1 elements: just set the single element information.
+          DeclOrVector = ND;
+          SingleDeclIndex = Index;
+          return;
+        }
+
+        if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
+          // 1 -> 2 elements: create the vector of results and push in the
+          // existing declaration.
+          DeclIndexPairVector *Vec = new DeclIndexPairVector;
+          Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
+          DeclOrVector = Vec;
+        }
+
+        // Add the new element to the end of the vector.
+        DeclOrVector.get<DeclIndexPairVector*>()->push_back(
+                                                    DeclIndexPair(ND, Index));
+      }
+
+      void Destroy() {
+        if (DeclIndexPairVector *Vec
+              = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
+          delete Vec;
+          DeclOrVector = ((NamedDecl *)0);
+        }
+      }
+
+      // Iteration.
+      class iterator;
+      iterator begin() const;
+      iterator end() const;
+    };
+
     /// \brief A mapping from declaration names to the declarations that have
     /// this name within a particular scope and their index within the list of
     /// results.
-    typedef std::multimap<DeclarationName, 
-                          std::pair<NamedDecl *, unsigned> > ShadowMap;
+    typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
     
     /// \brief The semantic analysis object for which results are being 
     /// produced.
@@ -117,6 +170,102 @@
   };  
 }
 
+class ResultBuilder::ShadowMapEntry::iterator {
+  llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
+  unsigned SingleDeclIndex;
+
+public:
+  typedef DeclIndexPair value_type;
+  typedef value_type reference;
+  typedef std::ptrdiff_t difference_type;
+  typedef std::input_iterator_tag iterator_category;
+        
+  class pointer {
+    DeclIndexPair Value;
+
+  public:
+    pointer(const DeclIndexPair &Value) : Value(Value) { }
+
+    const DeclIndexPair *operator->() const {
+      return &Value;
+    }
+  };
+        
+  iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
+
+  iterator(NamedDecl *SingleDecl, unsigned Index)
+    : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
+
+  iterator(const DeclIndexPair *Iterator)
+    : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
+
+  iterator &operator++() {
+    if (DeclOrIterator.is<NamedDecl *>()) {
+      DeclOrIterator = (NamedDecl *)0;
+      SingleDeclIndex = 0;
+      return *this;
+    }
+
+    const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
+    ++I;
+    DeclOrIterator = I;
+    return *this;
+  }
+
+  iterator operator++(int) {
+    iterator tmp(*this);
+    ++(*this);
+    return tmp;
+  }
+
+  reference operator*() const {
+    if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
+      return reference(ND, SingleDeclIndex);
+
+    return *DeclOrIterator.get<const DeclIndexPair*>();
+  }
+
+  pointer operator->() const {
+    return pointer(**this);
+  }
+
+  friend bool operator==(const iterator &X, const iterator &Y) {
+    return X.DeclOrIterator.getOpaqueValue()
+                                  == Y.DeclOrIterator.getOpaqueValue() &&
+      X.SingleDeclIndex == Y.SingleDeclIndex;
+  }
+
+  friend bool operator!=(const iterator &X, const iterator &Y) {
+    return !(X == Y);
+  }
+};
+
+namespace llvm {
+  template<>
+  struct DenseMapInfo<ResultBuilder::ShadowMapEntry> {
+    static bool isPod() { return false; }
+  };
+}
+
+ResultBuilder::ShadowMapEntry::iterator 
+ResultBuilder::ShadowMapEntry::begin() const {
+  if (DeclOrVector.isNull())
+    return iterator();
+
+  if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
+    return iterator(ND, SingleDeclIndex);
+
+  return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
+}
+
+ResultBuilder::ShadowMapEntry::iterator 
+ResultBuilder::ShadowMapEntry::end() const {
+  if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
+    return iterator();
+
+  return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
+}
+
 /// \brief Determines whether the given hidden result could be found with
 /// some extra work, e.g., by qualifying the name.
 ///
@@ -241,14 +390,18 @@
     return;
   
   ShadowMap &SMap = ShadowMaps.back();
-  ShadowMap::iterator I, IEnd;
-  for (llvm::tie(I, IEnd) = SMap.equal_range(R.Declaration->getDeclName());
-       I != IEnd; ++I) {
-    NamedDecl *ND = I->second.first;
-    unsigned Index = I->second.second;
+  ShadowMapEntry::iterator I, IEnd;
+  ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
+  if (NamePos != SMap.end()) {
+    I = NamePos->second.begin();
+    IEnd = NamePos->second.end();
+  }
+
+  for (; I != IEnd; ++I) {
+    NamedDecl *ND = I->first;
+    unsigned Index = I->second;
     if (ND->getCanonicalDecl() == CanonDecl) {
       // This is a redeclaration. Always pick the newer declaration.
-      I->second.first = R.Declaration;
       Results[Index].Declaration = R.Declaration;
       
       // Pick the best rank of the two.
@@ -265,23 +418,28 @@
   std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
   --SMEnd;
   for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
-    for (llvm::tie(I, IEnd) = SM->equal_range(R.Declaration->getDeclName());
-         I != IEnd; ++I) {
+    ShadowMapEntry::iterator I, IEnd;
+    ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
+    if (NamePos != SM->end()) {
+      I = NamePos->second.begin();
+      IEnd = NamePos->second.end();
+    }
+    for (; I != IEnd; ++I) {
       // A tag declaration does not hide a non-tag declaration.
-      if (I->second.first->getIdentifierNamespace() == Decl::IDNS_Tag &&
+      if (I->first->getIdentifierNamespace() == Decl::IDNS_Tag &&
           (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | 
                    Decl::IDNS_ObjCProtocol)))
         continue;
       
       // Protocols are in distinct namespaces from everything else.
-      if (((I->second.first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
+      if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
            || (IDNS & Decl::IDNS_ObjCProtocol)) &&
-          I->second.first->getIdentifierNamespace() != IDNS)
+          I->first->getIdentifierNamespace() != IDNS)
         continue;
       
       // The newly-added result is hidden by an entry in the shadow map.
       if (canHiddenResultBeFound(SemaRef.getLangOptions(), R.Declaration, 
-                                 I->second.first)) {
+                                 I->first)) {
         // Note that this result was hidden.
         R.Hidden = true;
         R.QualifierIsInformative = false;
@@ -327,8 +485,7 @@
     
   // Insert this result into the set of results and into the current shadow
   // map.
-  SMap.insert(std::make_pair(R.Declaration->getDeclName(),
-                             std::make_pair(R.Declaration, Results.size())));
+  SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
   Results.push_back(R);
 }
 
@@ -339,6 +496,12 @@
 
 /// \brief Exit from the current scope.
 void ResultBuilder::ExitScope() {
+  for (ShadowMap::iterator E = ShadowMaps.back().begin(),
+                        EEnd = ShadowMaps.back().end();
+       E != EEnd;
+       ++E)
+    E->second.Destroy();
+         
   ShadowMaps.pop_back();
 }
 
@@ -1064,13 +1227,54 @@
     typedef CodeCompleteConsumer::Result Result;
     
     bool isEarlierDeclarationName(DeclarationName X, DeclarationName Y) const {
-      if (!X.getObjCSelector().isNull() && !Y.getObjCSelector().isNull()) {
-        // Consider all selector kinds to be equivalent.
-      } else if (X.getNameKind() != Y.getNameKind())
+      Selector XSel = X.getObjCSelector();
+      Selector YSel = Y.getObjCSelector();
+      if (!XSel.isNull() && !YSel.isNull()) {
+        // We are comparing two selectors.
+        unsigned N = std::min(XSel.getNumArgs(), YSel.getNumArgs());
+        if (N == 0)
+          ++N;
+        for (unsigned I = 0; I != N; ++I) {
+          IdentifierInfo *XId = XSel.getIdentifierInfoForSlot(I);
+          IdentifierInfo *YId = YSel.getIdentifierInfoForSlot(I);
+          if (!XId || !YId)
+            return XId && !YId;
+          
+          switch (XId->getName().compare_lower(YId->getName())) {
+          case -1: return true;
+          case 1: return false;
+          default: break;
+          }
+        }
+    
+        return XSel.getNumArgs() < YSel.getNumArgs();
+      }
+
+      // For non-selectors, order by kind.
+      if (X.getNameKind() != Y.getNameKind())
         return X.getNameKind() < Y.getNameKind();
       
-      return llvm::LowercaseString(X.getAsString()) 
-        < llvm::LowercaseString(Y.getAsString());
+      // Order identifiers by comparison of their lowercased names.
+      if (IdentifierInfo *XId = X.getAsIdentifierInfo())
+        return XId->getName().compare_lower(
+                                     Y.getAsIdentifierInfo()->getName()) < 0;
+
+      // Order overloaded operators by the order in which they appear
+      // in our list of operators.
+      if (OverloadedOperatorKind XOp = X.getCXXOverloadedOperator())
+        return XOp < Y.getCXXOverloadedOperator();
+
+      // Order C++0x user-defined literal operators lexically by their
+      // lowercased suffixes.
+      if (IdentifierInfo *XLit = X.getCXXLiteralIdentifier())
+        return XLit->getName().compare_lower(
+                                  Y.getCXXLiteralIdentifier()->getName()) < 0;
+
+      // The only stable ordering we have is to turn the name into a
+      // string and then compare the lower-case strings. This is
+      // inefficient, but thankfully does not happen too often.
+      return llvm::StringRef(X.getAsString()).compare_lower(
+                                                 Y.getAsString()) < 0;
     }
     
     bool operator()(const Result &X, const Result &Y) const {
@@ -1088,7 +1292,7 @@
                                                    : X.Pattern->getTypedText();
         const char *YStr = (Y.Kind == Result::RK_Keyword)? Y.Keyword 
                                                    : Y.Pattern->getTypedText();
-        return strcmp(XStr, YStr) < 0;
+        return llvm::StringRef(XStr).compare_lower(YStr) < 0;
       }
       
       // Result kinds are ordered by decreasing importance.
@@ -1113,8 +1317,7 @@
                                           Y.Declaration->getDeclName());
           
         case Result::RK_Macro:
-          return llvm::LowercaseString(X.Macro->getName()) < 
-                   llvm::LowercaseString(Y.Macro->getName());
+          return X.Macro->getName().compare_lower(Y.Macro->getName()) < 0;
           
         case Result::RK_Keyword:
         case Result::RK_Pattern:





More information about the llvm-branch-commits mailing list