mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-21 12:38:45 +00:00
Cache the sized-ness of struct types, once we reach the steady state of
"is sized". This prevents every query to isSized() from recursing over every sub-type of a struct type. This could get *very* slow for extremely deep nesting of structs, as in 177.mesa. This change is a 45% speedup for 'opt -O2' of 177.mesa.linked.bc, and likely a significant speedup for other cases as well. It even impacts -O0 cases because so many part of the code try to check whether a type is sized. Thanks for the review from Nick Lewycky and Benjamin Kramer on IRC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152197 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
344224b3a3
commit
f8cde7388e
@ -195,9 +195,10 @@ class StructType : public CompositeType {
|
|||||||
// This is the contents of the SubClassData field.
|
// This is the contents of the SubClassData field.
|
||||||
SCDB_HasBody = 1,
|
SCDB_HasBody = 1,
|
||||||
SCDB_Packed = 2,
|
SCDB_Packed = 2,
|
||||||
SCDB_IsLiteral = 4
|
SCDB_IsLiteral = 4,
|
||||||
|
SCDB_IsSized = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
/// SymbolTableEntry - For a named struct that actually has a name, this is a
|
/// SymbolTableEntry - For a named struct that actually has a name, this is a
|
||||||
/// pointer to the symbol table entry (maintained by LLVMContext) for the
|
/// pointer to the symbol table entry (maintained by LLVMContext) for the
|
||||||
/// struct. This is null if the type is an literal struct or if it is
|
/// struct. This is null if the type is an literal struct or if it is
|
||||||
@ -248,6 +249,9 @@ public:
|
|||||||
/// isOpaque - Return true if this is a type with an identity that has no body
|
/// isOpaque - Return true if this is a type with an identity that has no body
|
||||||
/// specified yet. These prints as 'opaque' in .ll files.
|
/// specified yet. These prints as 'opaque' in .ll files.
|
||||||
bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; }
|
bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; }
|
||||||
|
|
||||||
|
/// isSized - Return true if this is a sized type.
|
||||||
|
bool isSized() const;
|
||||||
|
|
||||||
/// hasName - Return true if this is a named struct that has a non-empty name.
|
/// hasName - Return true if this is a named struct that has a non-empty name.
|
||||||
bool hasName() const { return SymbolTableEntry != 0; }
|
bool hasName() const { return SymbolTableEntry != 0; }
|
||||||
|
@ -185,16 +185,7 @@ bool Type::isSizedDerivedType() const {
|
|||||||
if (!this->isStructTy())
|
if (!this->isStructTy())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Opaque structs have no size.
|
return cast<StructType>(this)->isSized();
|
||||||
if (cast<StructType>(this)->isOpaque())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Okay, our struct is sized if all of the elements are.
|
|
||||||
for (subtype_iterator I = subtype_begin(), E = subtype_end(); I != E; ++I)
|
|
||||||
if (!(*I)->isSized())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -579,6 +570,26 @@ StructType *StructType::create(StringRef Name, Type *type, ...) {
|
|||||||
return llvm::StructType::create(Ctx, StructFields, Name);
|
return llvm::StructType::create(Ctx, StructFields, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StructType::isSized() const {
|
||||||
|
if ((getSubclassData() & SCDB_IsSized) != 0)
|
||||||
|
return true;
|
||||||
|
if (isOpaque())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Okay, our struct is sized if all of the elements are, but if one of the
|
||||||
|
// elements is opaque, the struct isn't sized *yet*, but may become sized in
|
||||||
|
// the future, so just bail out without caching.
|
||||||
|
for (element_iterator I = element_begin(), E = element_end(); I != E; ++I)
|
||||||
|
if (!(*I)->isSized())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Here we cheat a bit and cast away const-ness. The goal is to memoize when
|
||||||
|
// we find a sized type, as types can only move from opaque to sized, not the
|
||||||
|
// other way.
|
||||||
|
const_cast<StructType*>(this)->setSubclassData(
|
||||||
|
getSubclassData() | SCDB_IsSized);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
StringRef StructType::getName() const {
|
StringRef StructType::getName() const {
|
||||||
assert(!isLiteral() && "Literal structs never have names");
|
assert(!isLiteral() && "Literal structs never have names");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user