forked from OSchip/llvm-project
*** Significantly speed up type resultion
This change speeds up type resolution by checking to see if a type is recursive, and if it's not, using a more efficient algorithm. This dramatically reduces bytecode loading time of kc++, reducing time-to-jit kc++ --version to 17s from 33s llvm-svn: 10088
This commit is contained in:
parent
c39fcfff0d
commit
1a02ca932c
|
@ -14,6 +14,7 @@
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/SymbolTable.h"
|
#include "llvm/SymbolTable.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
|
#include "Support/DepthFirstIterator.h"
|
||||||
#include "Support/StringExtras.h"
|
#include "Support/StringExtras.h"
|
||||||
#include "Support/STLExtras.h"
|
#include "Support/STLExtras.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -495,7 +496,6 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2,
|
||||||
std::map<const Type *, const Type *> &EqTypes) {
|
std::map<const Type *, const Type *> &EqTypes) {
|
||||||
if (Ty == Ty2) return true;
|
if (Ty == Ty2) return true;
|
||||||
if (Ty->getPrimitiveID() != Ty2->getPrimitiveID()) return false;
|
if (Ty->getPrimitiveID() != Ty2->getPrimitiveID()) return false;
|
||||||
if (Ty->isPrimitiveType()) return true;
|
|
||||||
if (isa<OpaqueType>(Ty))
|
if (isa<OpaqueType>(Ty))
|
||||||
return false; // Two unequal opaque types are never equal
|
return false; // Two unequal opaque types are never equal
|
||||||
|
|
||||||
|
@ -595,9 +595,46 @@ public:
|
||||||
// updated. Remove the obsolete entry from the map.
|
// updated. Remove the obsolete entry from the map.
|
||||||
Map.erase(TyIt);
|
Map.erase(TyIt);
|
||||||
|
|
||||||
|
// Determine whether there is a cycle through the type graph which passes
|
||||||
|
// back through this type. Other cycles are ok,
|
||||||
|
bool HasTypeCycle = false;
|
||||||
|
{
|
||||||
|
std::set<const Type*> VisitedTypes;
|
||||||
|
for (Type::subtype_iterator I = Ty->subtype_begin(),
|
||||||
|
E = Ty->subtype_end(); I != E; ++I) {
|
||||||
|
for (df_ext_iterator<const Type *, std::set<const Type*> >
|
||||||
|
DFI = df_ext_begin(*I, VisitedTypes),
|
||||||
|
E = df_ext_end(*I, VisitedTypes); DFI != E; ++DFI)
|
||||||
|
if (*DFI == Ty) {
|
||||||
|
HasTypeCycle = true;
|
||||||
|
goto FoundCycle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FoundCycle:
|
||||||
|
|
||||||
|
ValType Key = ValType::get(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 (!HasTypeCycle) {
|
||||||
|
iterator I = Map.find(ValType::get(Ty));
|
||||||
|
if (I != Map.end()) {
|
||||||
|
// We already have this type in the table. Get rid of the newly refined
|
||||||
|
// type.
|
||||||
|
assert(Ty->isAbstract() && "Replacing a non-abstract type?");
|
||||||
|
TypeClass *NewTy = I->second;
|
||||||
|
|
||||||
|
// Refined to a different type altogether?
|
||||||
|
Ty->refineAbstractTypeTo(NewTy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
// Now we check to see if there is an existing entry in the table which is
|
// 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
|
// structurally identical to the newly refined type. If so, this type
|
||||||
// refined to the pre-existing type.
|
// gets refined to the pre-existing type.
|
||||||
//
|
//
|
||||||
for (iterator I = Map.begin(), E = Map.end(); I != E; ++I)
|
for (iterator I = Map.begin(), E = Map.end(); I != E; ++I)
|
||||||
if (TypesEqual(Ty, I->second)) {
|
if (TypesEqual(Ty, I->second)) {
|
||||||
|
@ -608,10 +645,11 @@ public:
|
||||||
Ty->refineAbstractTypeTo(NewTy);
|
Ty->refineAbstractTypeTo(NewTy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If there is no existing type of the same structure, we reinsert an
|
// If there is no existing type of the same structure, we reinsert an
|
||||||
// updated record into the map.
|
// updated record into the map.
|
||||||
Map.insert(std::make_pair(ValType::get(Ty), Ty));
|
Map.insert(std::make_pair(Key, Ty));
|
||||||
|
|
||||||
// If the type is currently thought to be abstract, rescan all of our
|
// 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!
|
||||||
|
|
Loading…
Reference in New Issue