mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-28 07:05:03 +00:00
Change Type::isAbstract to have better comments, a more correct name
(PromoteAbstractToConcrete), and to use a set to avoid recomputation. In particular, this set eliminates the potentially exponential cases from this little recursive algorithm. On a particularly nasty testcase, llvm-dis on the .bc file went from 34 minutes (which is when I killed it, it still hadn't finished) to 0.57s. Remember kids, exponential algorithms are bad. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16772 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
df00115aa4
commit
b5c16705fd
@ -443,19 +443,26 @@ void DerivedType::dropAllTypeUses() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// isTypeAbstract - This is a recursive function that walks a type hierarchy
|
// PromoteAbstractToConcrete - This is a recursive function that walks a type
|
||||||
// calculating whether or not a type is abstract. Worst case it will have to do
|
// graph calculating whether or not a type is abstract.
|
||||||
// a lot of traversing if you have some whacko opaque types, but in most cases,
|
|
||||||
// it will do some simple stuff when it hits non-abstract types that aren't
|
|
||||||
// recursive.
|
|
||||||
//
|
//
|
||||||
bool Type::isTypeAbstract() {
|
// This method returns true if the type is found to still be abstract.
|
||||||
|
//
|
||||||
|
bool Type::PromoteAbstractToConcrete(void *Ptr) {
|
||||||
if (!isAbstract()) // Base case for the recursion
|
if (!isAbstract()) // Base case for the recursion
|
||||||
return false; // Primitive = leaf type
|
return false; // Primitive = leaf type
|
||||||
|
|
||||||
if (isa<OpaqueType>(this)) // Base case for the recursion
|
if (isa<OpaqueType>(this)) // Base case for the recursion
|
||||||
return true; // This whole type is abstract!
|
return true; // This whole type is abstract!
|
||||||
|
|
||||||
|
/// KnownAbstractTypes - This set contains all of the types that we know for
|
||||||
|
/// sure are abstract. Once we discover that a type really is abstract, we
|
||||||
|
/// remember this so we don't have to do potentially exponential amounts of
|
||||||
|
/// checking in some cases.
|
||||||
|
std::set<Type*> &KnownAbstractTypes = *(std::set<Type*>*)Ptr;
|
||||||
|
if (KnownAbstractTypes.count(this))
|
||||||
|
return true; // We already know this type is abstract!
|
||||||
|
|
||||||
// We have to guard against recursion. To do this, we temporarily mark this
|
// We have to guard against recursion. To do this, we temporarily mark this
|
||||||
// type as concrete, so that if we get back to here recursively we will think
|
// type as concrete, so that if we get back to here recursively we will think
|
||||||
// it's not abstract, and thus not scan it again.
|
// it's not abstract, and thus not scan it again.
|
||||||
@ -465,15 +472,14 @@ bool Type::isTypeAbstract() {
|
|||||||
// one!
|
// one!
|
||||||
for (Type::subtype_iterator I = subtype_begin(), E = subtype_end();
|
for (Type::subtype_iterator I = subtype_begin(), E = subtype_end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
if (const_cast<Type*>(I->get())->isTypeAbstract()) {
|
if (const_cast<Type*>(I->get())->PromoteAbstractToConcrete(Ptr)) {
|
||||||
|
KnownAbstractTypes.insert(this);
|
||||||
setAbstract(true); // Restore the abstract bit.
|
setAbstract(true); // Restore the abstract bit.
|
||||||
return true; // This type is abstract if subtype is abstract!
|
return true; // This type is abstract if subtype is abstract!
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the abstract bit.
|
// Nothing looks abstract here.
|
||||||
setAbstract(true);
|
setAbstract(false);
|
||||||
|
|
||||||
// Nothing looks abstract here...
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,7 +731,8 @@ public:
|
|||||||
// 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!
|
||||||
if (Ty->isAbstract()) {
|
if (Ty->isAbstract()) {
|
||||||
Ty->setAbstract(Ty->isTypeAbstract());
|
std::set<Type*> KnownAbstractTypes;
|
||||||
|
Ty->PromoteAbstractToConcrete(&KnownAbstractTypes);
|
||||||
|
|
||||||
// If the type just became concrete, notify all users!
|
// If the type just became concrete, notify all users!
|
||||||
if (!Ty->isAbstract())
|
if (!Ty->isAbstract())
|
||||||
|
Loading…
Reference in New Issue
Block a user