summaryrefslogtreecommitdiff
path: root/lib/VMCore/Type.cpp
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2012-03-07 02:33:09 +0000
committerChandler Carruth <chandlerc@gmail.com>2012-03-07 02:33:09 +0000
commitf8cde7388eb96c59992bc4798ec9fca41ea1a13c (patch)
treeb69247c9ecf8783b87e7d399b441dabeb8a92070 /lib/VMCore/Type.cpp
parent344224b3a34bda62bea86c06807584ec7558e157 (diff)
downloadllvm-f8cde7388eb96c59992bc4798ec9fca41ea1a13c.tar.gz
llvm-f8cde7388eb96c59992bc4798ec9fca41ea1a13c.tar.bz2
llvm-f8cde7388eb96c59992bc4798ec9fca41ea1a13c.tar.xz
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/Type.cpp')
-rw-r--r--lib/VMCore/Type.cpp31
1 files changed, 21 insertions, 10 deletions
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");