From f8cde7388eb96c59992bc4798ec9fca41ea1a13c Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Wed, 7 Mar 2012 02:33:09 +0000 Subject: [PATCH] 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 --- include/llvm/DerivedTypes.h | 8 ++++++-- 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 b9ade512cfb..da5ad27b1f1 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 0bc4f74af21..c6f35580e15 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(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(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(this)->setSubclassData( + getSubclassData() | SCDB_IsSized); + return true; +} StringRef StructType::getName() const { assert(!isLiteral() && "Literal structs never have names"); -- 2.11.0