Use a map to cache the ModuleType information, so we can do logarithmic
authorChris Lattner <sabre@nondot.org>
Mon, 3 Oct 2005 21:26:53 +0000 (21:26 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 3 Oct 2005 21:26:53 +0000 (21:26 +0000)
lookups instead of linear time lookups.  This speeds up bc parsing of a
large file from

137.834u 118.256s 4:27.96
to
132.611u 114.436s 4:08.53

with a release build.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23611 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Bytecode/Reader/Reader.cpp
lib/Bytecode/Reader/Reader.h

index 6bb06c3ce46f024867df2855111bf9904a5997fa..ba9c6ca97f61a8abfea797238f3e14efcd445697 100644 (file)
@@ -347,11 +347,25 @@ unsigned BytecodeReader::getTypeSlot(const Type *Ty) {
     return Type::FirstDerivedTyID + ModuleTypes.size() +
            (&*I - &FunctionTypes[0]);
 
-  // Check the module level types now...
-  I = std::find(ModuleTypes.begin(), ModuleTypes.end(), Ty);
-  if (I == ModuleTypes.end())
+  // If we don't have our cache yet, build it now.
+  if (ModuleTypeIDCache.empty()) {
+    unsigned N = 0;
+    ModuleTypeIDCache.reserve(ModuleTypes.size());
+    for (TypeListTy::iterator I = ModuleTypes.begin(), E = ModuleTypes.end();
+         I != E; ++I, ++N)
+      ModuleTypeIDCache.push_back(std::make_pair(*I, N));
+    
+    std::sort(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end());
+  }
+  
+  // Binary search the cache for the entry.
+  std::vector<std::pair<const Type*, unsigned> >::iterator IT =
+    std::lower_bound(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end(),
+                     std::make_pair(Ty, 0U));
+  if (IT == ModuleTypeIDCache.end() || IT->first != Ty)
     error("Didn't find type in ModuleTypes.");
-  return Type::FirstDerivedTyID + (&*I - &ModuleTypes[0]);
+    
+  return Type::FirstDerivedTyID + IT->second;
 }
 
 /// This is just like getType, but when a compaction table is in use, it is
@@ -375,11 +389,26 @@ const Type *BytecodeReader::getGlobalTableType(unsigned Slot) {
 unsigned BytecodeReader::getGlobalTableTypeSlot(const Type *Ty) {
   if (Ty->isPrimitiveType())
     return Ty->getTypeID();
-  TypeListTy::iterator I = std::find(ModuleTypes.begin(),
-                                      ModuleTypes.end(), Ty);
-  if (I == ModuleTypes.end())
+  
+  // If we don't have our cache yet, build it now.
+  if (ModuleTypeIDCache.empty()) {
+    unsigned N = 0;
+    ModuleTypeIDCache.reserve(ModuleTypes.size());
+    for (TypeListTy::iterator I = ModuleTypes.begin(), E = ModuleTypes.end();
+         I != E; ++I, ++N)
+      ModuleTypeIDCache.push_back(std::make_pair(*I, N));
+    
+    std::sort(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end());
+  }
+  
+  // Binary search the cache for the entry.
+  std::vector<std::pair<const Type*, unsigned> >::iterator IT =
+    std::lower_bound(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end(),
+                     std::make_pair(Ty, 0U));
+  if (IT == ModuleTypeIDCache.end() || IT->first != Ty)
     error("Didn't find type in ModuleTypes.");
-  return Type::FirstDerivedTyID + (&*I - &ModuleTypes[0]);
+  
+  return Type::FirstDerivedTyID + IT->second;
 }
 
 /// Retrieve a value of a given type and slot number, possibly creating
@@ -1309,6 +1338,10 @@ void BytecodeReader::ParseTypes(TypeListTy &Tab, unsigned NumEntries){
   if (Handler)
     Handler->handleTypeList(NumEntries);
 
+  // If we are about to resolve types, make sure the type cache is clear.
+  if (NumEntries)
+    ModuleTypeIDCache.clear();
+  
   // Loop through reading all of the types.  Forward types will make use of the
   // opaque types just inserted.
   //
index eec5de98493ebf6a3305541acf57dd5fe60b8d74..df0ddca7472a7e5d121837087d2f6d592af1ab9b 100644 (file)
@@ -333,6 +333,12 @@ private:
   /// @brief This vector is used to deal with forward references to types in
   /// a module.
   TypeListTy ModuleTypes;
+  
+  /// @brief This is an inverse mapping of ModuleTypes from the type to an
+  /// index.  Because refining types causes the index of this map to be
+  /// invalidated, any time we refine a type, we clear this cache and recompute
+  /// it next time we need it.  These entries are ordered by the pointer value.
+  std::vector<std::pair<const Type*, unsigned> > ModuleTypeIDCache;
 
   /// @brief This vector is used to deal with forward references to types in
   /// a function.