aboutsummaryrefslogtreecommitdiffstats
path: root/lib/VMCore
diff options
context:
space:
mode:
Diffstat (limited to 'lib/VMCore')
-rw-r--r--lib/VMCore/Type.cpp52
1 files changed, 29 insertions, 23 deletions
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index 9b9ca4f..d184c3a 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -749,20 +749,25 @@ public:
// The old record is now out-of-date, because one of the children has been
// updated. Remove the obsolete entry from the map.
- Map.erase(ValType::get(Ty));
+ unsigned NumErased = Map.erase(ValType::get(Ty));
+ assert(NumErased && "Element not found!");
// Remember the structural hash for the type before we start hacking on it,
// in case we need it later.
unsigned OldTypeHash = ValType::hashTypeStructure(Ty);
+ unsigned NewTypeHash;
// Find the type element we are refining... and change it now!
- for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i)
- if (Ty->ContainedTys[i] == OldType) {
- Ty->ContainedTys[i].removeUserFromConcrete();
- Ty->ContainedTys[i] = NewType;
- }
-
- unsigned TypeHash = ValType::hashTypeStructure(Ty);
+ if (OldType != NewType || !OldType->isAbstract()) {
+ for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i)
+ if (Ty->ContainedTys[i] == OldType) {
+ Ty->ContainedTys[i].removeUserFromConcrete();
+ Ty->ContainedTys[i] = NewType;
+ }
+ NewTypeHash = ValType::hashTypeStructure(Ty);
+ } else {
+ NewTypeHash = OldTypeHash;
+ }
// 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
@@ -771,11 +776,10 @@ public:
typename std::map<ValType, PATypeHolder>::iterator I;
bool Inserted;
- ValType V = ValType::get(Ty);
- tie(I, Inserted) = Map.insert(std::make_pair(V, Ty));
+ tie(I, Inserted) = Map.insert(std::make_pair(ValType::get(Ty), Ty));
if (!Inserted) {
// Refined to a different type altogether?
- RemoveFromTypesByHash(TypeHash, Ty);
+ RemoveFromTypesByHash(NewTypeHash, Ty);
// We already have this type in the table. Get rid of the newly refined
// type.
@@ -783,8 +787,9 @@ public:
Ty->refineAbstractTypeTo(NewTy);
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.
@@ -793,13 +798,16 @@ public:
tie(I, E) = TypesByHash.equal_range(OldTypeHash);
Entry = E;
for (; I != E; ++I) {
- if (I->second != Ty) {
+ if (I->second == Ty) {
+ // Remember the position of the old type if we see it in our scan.
+ Entry = I;
+ } else {
if (TypesEqual(Ty, I->second)) {
- assert(Ty->isAbstract() && "Replacing a non-abstract type?");
TypeClass *NewTy = cast<TypeClass>((Type*)I->second.get());
if (Entry == E) {
- // Find the location of Ty in the TypesByHash structure.
+ // Find the location of Ty in the TypesByHash structure if we
+ // haven't seen it already.
while (I->second != Ty) {
++I;
assert(I != E && "Structure doesn't contain type??");
@@ -811,26 +819,24 @@ public:
Ty->refineAbstractTypeTo(NewTy);
return;
}
- } else {
- // Remember the position of
- Entry = I;
}
}
-
// If there is no existing type of the same structure, we reinsert an
// updated record into the map.
Map.insert(std::make_pair(ValType::get(Ty), Ty));
}
// If the hash codes differ, update TypesByHash
- if (TypeHash != OldTypeHash) {
+ if (NewTypeHash != OldTypeHash) {
RemoveFromTypesByHash(OldTypeHash, Ty);
- TypesByHash.insert(std::make_pair(TypeHash, Ty));
+ TypesByHash.insert(std::make_pair(NewTypeHash, Ty));
}
-
+
// If the type is currently thought to be abstract, rescan all of our
- // subtypes to see if the type has just become concrete!
+ // 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();
}