Separate the type-became-concrete case from the type-is-resolved case, the
authorChris Lattner <sabre@nondot.org>
Sun, 13 Nov 2005 01:27:50 +0000 (01:27 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 13 Nov 2005 01:27:50 +0000 (01:27 +0000)
former of which takes much less work than the later.  This speeds up linking
eon from 3.749 to 3.637s with a release build (about 3%).

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

lib/VMCore/Type.cpp

index c60702754b1764839f52f2e359b62f8c2163f62c..3336226be0f5e9e40f98b92b9985036bafe57c81 100644 (file)
@@ -736,15 +736,35 @@ public:
   /// The specified iterator tells us what the type USED to look like.
   void finishRefinement(TypeClass *Ty, const DerivedType *OldType,
                         const Type *NewType) {
-    // Either NewTy == OldTy (in which case the specified type just became
-    // concrete) or they are different an the Ty is thought to be abstract.
-    assert((Ty->isAbstract() || OldType == NewType) &&
-           "Refining a non-abstract type!");
 #ifdef DEBUG_MERGE_TYPES
     std::cerr << "refineAbstractTy(" << (void*)OldType << "[" << *OldType
-              << "], " << (void*)NewType << " [" << *NewType << "])\n";
+    << "], " << (void*)NewType << " [" << *NewType << "])\n";
 #endif
+    // If NewTy == OldTy, then the type just became concrete.  In this case, we
+    // don't need to change the current type, we just need to drop uses of the
+    // type and potentially mark Ty as concrete now too.
+    if (OldType == NewType) {
+      // If the element just became concrete, remove 'ty' from the abstract
+      // type user list for the type.  Do this for as many times as Ty uses
+      // OldType.
+      for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i)
+        if (Ty->ContainedTys[i] == OldType)
+          OldType->removeAbstractTypeUser(Ty);
 
+      // If the type is currently thought to be abstract, rescan all of our
+      // subtypes to see if the type has just become concrete!  Note that this
+      // may send out notifications to AbstractTypeUsers that types become
+      // concrete.
+      if (Ty->isAbstract())
+        Ty->PromoteAbstractToConcrete();
+      return;
+    }
+    
+    
+    // Otherwise, we are changing one subelement type into another.  Clearly the
+    // OldType must have been abstract, making us abstract.
+    assert(Ty->isAbstract() && "Refining a non-abstract type!");
+    
     // Make a temporary type holder for the type so that it doesn't disappear on
     // us when we erase the entry from the map.
     PATypeHolder TyHolder = Ty;
@@ -759,31 +779,23 @@ public:
     unsigned OldTypeHash = ValType::hashTypeStructure(Ty);
 
     // Find the type element we are refining... and change it now!
-    if (!OldType->isAbstract()) {
-      // If the element just became concrete, remove 'ty' from the abstract
-      // type user list for the type.
-      for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i)
-        if (Ty->ContainedTys[i] == OldType)
-          OldType->removeAbstractTypeUser(Ty);
-    } else {
-      assert(OldType != NewType && "Unknown case!");
-      for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i)
-        if (Ty->ContainedTys[i] == OldType)
-          Ty->ContainedTys[i] = NewType;
-    }
+    for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i)
+      if (Ty->ContainedTys[i] == OldType)
+        Ty->ContainedTys[i] = NewType;
     unsigned NewTypeHash = ValType::hashTypeStructure(Ty);
     
     // If there are no cycles going through this node, we can do a simple,
     // efficient lookup in the map, instead of an inefficient nasty linear
     // lookup.
-    if (!Ty->isAbstract() || !TypeHasCycleThroughItself(Ty)) {
+    if (!TypeHasCycleThroughItself(Ty)) {
       typename std::map<ValType, PATypeHolder>::iterator I;
       bool Inserted;
 
       tie(I, Inserted) = Map.insert(std::make_pair(ValType::get(Ty), Ty));
       if (!Inserted) {
+        assert(OldType != NewType);
         // Refined to a different type altogether?
-        RemoveFromTypesByHash(NewTypeHash, Ty);
+        RemoveFromTypesByHash(OldTypeHash, Ty);
 
         // We already have this type in the table.  Get rid of the newly refined
         // type.
@@ -792,8 +804,6 @@ public:
         return;
       }
     } else {
-      assert(Ty->isAbstract() && "Potentially replacing a non-abstract type?");
-
       // Now we check to see if there is an existing entry in the table which is
       // structurally identical to the newly refined type.  If so, this type
       // gets refined to the pre-existing type.