diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2012-03-07 02:33:09 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2012-03-07 02:33:09 +0000 |
commit | f8cde7388eb96c59992bc4798ec9fca41ea1a13c (patch) | |
tree | b69247c9ecf8783b87e7d399b441dabeb8a92070 | |
parent | 344224b3a34bda62bea86c06807584ec7558e157 (diff) |
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
-rw-r--r-- | include/llvm/DerivedTypes.h | 8 | ||||
-rw-r--r-- | lib/VMCore/Type.cpp | 31 |
2 files changed, 27 insertions, 12 deletions
diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h index b9ade512cf..da5ad27b1f 100644 --- a/include/llvm/DerivedTypes.h +++ b/include/llvm/DerivedTypes.h @@ -195,9 +195,10 @@ class StructType : public CompositeType { // This is the contents of the SubClassData field. SCDB_HasBody = 1, 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 /// 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 @@ -248,6 +249,9 @@ public: /// isOpaque - Return true if this is a type with an identity that has no body /// specified yet. These prints as 'opaque' in .ll files. 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. bool hasName() const { return SymbolTableEntry != 0; } diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 0bc4f74af2..c6f35580e1 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -185,16 +185,7 @@ bool Type::isSizedDerivedType() const { if (!this->isStructTy()) return false; - // Opaque structs have no size. - 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; + return cast<StructType>(this)->isSized(); } //===----------------------------------------------------------------------===// @@ -579,6 +570,26 @@ StructType *StructType::create(StringRef Name, Type *type, ...) { 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 { assert(!isLiteral() && "Literal structs never have names"); |