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 /lib/VMCore | |
parent | 344224b3a34bda62bea86c06807584ec7558e157 (diff) | |
download | external_llvm-f8cde7388eb96c59992bc4798ec9fca41ea1a13c.zip external_llvm-f8cde7388eb96c59992bc4798ec9fca41ea1a13c.tar.gz external_llvm-f8cde7388eb96c59992bc4798ec9fca41ea1a13c.tar.bz2 |
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
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/Type.cpp | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 0bc4f74..c6f3558 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"); |