mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-12 15:30:56 +00:00
Separate the type-became-concrete case from the type-is-resolved case, the
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
This commit is contained in:
parent
ea2fdf9380
commit
66cafb33bc
@ -736,14 +736,34 @@ public:
|
|||||||
/// The specified iterator tells us what the type USED to look like.
|
/// The specified iterator tells us what the type USED to look like.
|
||||||
void finishRefinement(TypeClass *Ty, const DerivedType *OldType,
|
void finishRefinement(TypeClass *Ty, const DerivedType *OldType,
|
||||||
const Type *NewType) {
|
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
|
#ifdef DEBUG_MERGE_TYPES
|
||||||
std::cerr << "refineAbstractTy(" << (void*)OldType << "[" << *OldType
|
std::cerr << "refineAbstractTy(" << (void*)OldType << "[" << *OldType
|
||||||
<< "], " << (void*)NewType << " [" << *NewType << "])\n";
|
<< "], " << (void*)NewType << " [" << *NewType << "])\n";
|
||||||
#endif
|
#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
|
// Make a temporary type holder for the type so that it doesn't disappear on
|
||||||
// us when we erase the entry from the map.
|
// us when we erase the entry from the map.
|
||||||
@ -759,31 +779,23 @@ public:
|
|||||||
unsigned OldTypeHash = ValType::hashTypeStructure(Ty);
|
unsigned OldTypeHash = ValType::hashTypeStructure(Ty);
|
||||||
|
|
||||||
// Find the type element we are refining... and change it now!
|
// 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)
|
for (unsigned i = 0, e = Ty->ContainedTys.size(); i != e; ++i)
|
||||||
if (Ty->ContainedTys[i] == OldType)
|
if (Ty->ContainedTys[i] == OldType)
|
||||||
Ty->ContainedTys[i] = NewType;
|
Ty->ContainedTys[i] = NewType;
|
||||||
}
|
|
||||||
unsigned NewTypeHash = ValType::hashTypeStructure(Ty);
|
unsigned NewTypeHash = ValType::hashTypeStructure(Ty);
|
||||||
|
|
||||||
// If there are no cycles going through this node, we can do a simple,
|
// 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
|
// efficient lookup in the map, instead of an inefficient nasty linear
|
||||||
// lookup.
|
// lookup.
|
||||||
if (!Ty->isAbstract() || !TypeHasCycleThroughItself(Ty)) {
|
if (!TypeHasCycleThroughItself(Ty)) {
|
||||||
typename std::map<ValType, PATypeHolder>::iterator I;
|
typename std::map<ValType, PATypeHolder>::iterator I;
|
||||||
bool Inserted;
|
bool Inserted;
|
||||||
|
|
||||||
tie(I, Inserted) = Map.insert(std::make_pair(ValType::get(Ty), Ty));
|
tie(I, Inserted) = Map.insert(std::make_pair(ValType::get(Ty), Ty));
|
||||||
if (!Inserted) {
|
if (!Inserted) {
|
||||||
|
assert(OldType != NewType);
|
||||||
// Refined to a different type altogether?
|
// 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
|
// We already have this type in the table. Get rid of the newly refined
|
||||||
// type.
|
// type.
|
||||||
@ -792,8 +804,6 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
// 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
|
// structurally identical to the newly refined type. If so, this type
|
||||||
// gets refined to the pre-existing type.
|
// gets refined to the pre-existing type.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user