forked from OSchip/llvm-project
Eliminate the branching in QualType::getTypePtr() by providing a
common base for ExtQuals and Type that stores the underlying type pointer. This results in a 2% performance win for -emit-llvm on a typical C file, with 1% memory growth in the AST. Note that there is an API change in this optimization: QualType::getTypePtr() can no longer be invoked on a NULL QualType. If the QualType might be NULL, use QualType::getTypePtrOrNull(). I've audited all uses of getTypePtr() in the code base and changed the appropriate uses over to getTypePtrOrNull(). A future optimization opportunity would be to distinguish between cast/dyn_cast and cast_or_null/dyn_cast_or_null; for the former, we could use getTypePtr() rather than getTypePtrOrNull(), to take another branch out of the cast/dyn_cast implementation. llvm-svn: 121489
This commit is contained in:
parent
924a8f3573
commit
0cdc832077
|
@ -66,7 +66,16 @@ public:
|
|||
|
||||
/// \brief Retrieve the underlying type pointer, which refers to a
|
||||
/// canonical type.
|
||||
T *getTypePtr() const { return cast_or_null<T>(Stored.getTypePtr()); }
|
||||
///
|
||||
/// The underlying pointer must not be NULL.
|
||||
T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); }
|
||||
|
||||
/// \brief Retrieve the underlying type pointer, which refers to a
|
||||
/// canonical type, or NULL.
|
||||
///
|
||||
T *getTypePtrOrNull() const {
|
||||
return cast_or_null<T>(Stored.getTypePtrOrNull());
|
||||
}
|
||||
|
||||
/// \brief Implicit conversion to a qualified type.
|
||||
operator QualType() const { return Stored; }
|
||||
|
@ -225,7 +234,7 @@ public:
|
|||
/// @code
|
||||
/// if (CanQual<PointerType> Ptr = T->getAs<PointerType>()) { ... }
|
||||
/// @endcode
|
||||
operator const T*() const { return this->Stored.getTypePtr(); }
|
||||
operator const T*() const { return this->Stored.getTypePtrOrNull(); }
|
||||
|
||||
/// \brief Try to convert the given canonical type to a specific structural
|
||||
/// type.
|
||||
|
@ -338,7 +347,7 @@ template<typename T>
|
|||
struct simplify_type<const ::clang::CanQual<T> > {
|
||||
typedef T* SimpleType;
|
||||
static SimpleType getSimplifiedValue(const ::clang::CanQual<T> &Val) {
|
||||
return Val.getTypePtr();
|
||||
return Val.getTypePtrOrNull();
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
|
|
|
@ -2259,7 +2259,7 @@ public:
|
|||
}
|
||||
|
||||
/// \brief Set the underlying integer type.
|
||||
void setIntegerType(QualType T) { IntegerType = T.getTypePtr(); }
|
||||
void setIntegerType(QualType T) { IntegerType = T.getTypePtrOrNull(); }
|
||||
|
||||
/// \brief Set the underlying integer type source info.
|
||||
void setIntegerTypeSourceInfo(TypeSourceInfo* TInfo) { IntegerType = TInfo; }
|
||||
|
|
|
@ -910,7 +910,7 @@ class TemplateTypeParmDecl : public TypeDecl {
|
|||
bool Typename, QualType Type, bool ParameterPack)
|
||||
: TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename),
|
||||
InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() {
|
||||
TypeForDecl = Type.getTypePtr();
|
||||
TypeForDecl = Type.getTypePtrOrNull();
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
@ -326,7 +326,24 @@ private:
|
|||
static const uint32_t AddressSpaceShift = 5;
|
||||
};
|
||||
|
||||
|
||||
/// \brief Base class that is common to both the \c ExtQuals and \c Type
|
||||
/// classes, which allows \c QualType to access the common fields between the
|
||||
/// two.
|
||||
///
|
||||
class ExtQualsTypeCommonBase {
|
||||
protected:
|
||||
ExtQualsTypeCommonBase(const Type *BaseType) : BaseType(BaseType) { }
|
||||
|
||||
/// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or
|
||||
/// a self-referential pointer (for \c Type).
|
||||
///
|
||||
/// This pointer allows an efficient mapping from a QualType to its
|
||||
/// underlying type pointer.
|
||||
const Type *BaseType;
|
||||
|
||||
friend class QualType;
|
||||
};
|
||||
|
||||
/// ExtQuals - We can encode up to four bits in the low bits of a
|
||||
/// type pointer, but there are many more type qualifiers that we want
|
||||
/// to be able to apply to an arbitrary type. Therefore we have this
|
||||
|
@ -337,7 +354,7 @@ private:
|
|||
/// in three low bits on the QualType pointer; a fourth bit records whether
|
||||
/// the pointer is an ExtQuals node. The extended qualifiers (address spaces,
|
||||
/// Objective-C GC attributes) are much more rare.
|
||||
class ExtQuals : public llvm::FoldingSetNode {
|
||||
class ExtQuals : public ExtQualsTypeCommonBase, public llvm::FoldingSetNode {
|
||||
// NOTE: changing the fast qualifiers should be straightforward as
|
||||
// long as you don't make 'const' non-fast.
|
||||
// 1. Qualifiers:
|
||||
|
@ -351,15 +368,13 @@ class ExtQuals : public llvm::FoldingSetNode {
|
|||
// 3. ASTContext:
|
||||
// a) Update get{Volatile,Restrict}Type.
|
||||
|
||||
/// BaseType - the underlying type that this qualifies
|
||||
const Type *BaseType;
|
||||
|
||||
/// Quals - the immutable set of qualifiers applied by this
|
||||
/// node; always contains extended qualifiers.
|
||||
Qualifiers Quals;
|
||||
|
||||
public:
|
||||
ExtQuals(const Type *Base, Qualifiers Quals) : BaseType(Base), Quals(Quals)
|
||||
ExtQuals(const Type *Base, Qualifiers Quals)
|
||||
: ExtQualsTypeCommonBase(Base), Quals(Quals)
|
||||
{
|
||||
assert(Quals.hasNonFastQualifiers()
|
||||
&& "ExtQuals created with no fast qualifiers");
|
||||
|
@ -444,10 +459,25 @@ public:
|
|||
/// Retrieves a pointer to the underlying (unqualified) type.
|
||||
/// This should really return a const Type, but it's not worth
|
||||
/// changing all the users right now.
|
||||
///
|
||||
/// This function requires that the type not be NULL. If the type might be
|
||||
/// NULL, use the (slightly less efficient) \c getTypePtrOrNull().
|
||||
Type *getTypePtr() const {
|
||||
if (hasLocalNonFastQualifiers())
|
||||
return const_cast<Type*>(getExtQualsUnsafe()->getBaseType());
|
||||
return const_cast<Type*>(getTypePtrUnsafe());
|
||||
assert(!isNull() && "Cannot retrieve a NULL type pointer");
|
||||
uintptr_t CommonPtrVal
|
||||
= reinterpret_cast<uintptr_t>(Value.getOpaqueValue());
|
||||
CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1);
|
||||
ExtQualsTypeCommonBase *CommonPtr
|
||||
= reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal);
|
||||
return const_cast<Type *>(CommonPtr->BaseType);
|
||||
}
|
||||
|
||||
Type *getTypePtrOrNull() const {
|
||||
uintptr_t TypePtrPtrVal
|
||||
= reinterpret_cast<uintptr_t>(Value.getOpaqueValue());
|
||||
TypePtrPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1);
|
||||
Type **TypePtrPtr = reinterpret_cast<Type**>(TypePtrPtrVal);
|
||||
return TypePtrPtr? *TypePtrPtr : 0;
|
||||
}
|
||||
|
||||
/// Divides a QualType into its unqualified type and a set of local
|
||||
|
@ -741,7 +771,7 @@ namespace llvm {
|
|||
template<> struct simplify_type<const ::clang::QualType> {
|
||||
typedef ::clang::Type* SimpleType;
|
||||
static SimpleType getSimplifiedValue(const ::clang::QualType &Val) {
|
||||
return Val.getTypePtr();
|
||||
return Val.getTypePtrOrNull();
|
||||
}
|
||||
};
|
||||
template<> struct simplify_type< ::clang::QualType>
|
||||
|
@ -790,7 +820,7 @@ namespace clang {
|
|||
///
|
||||
/// Types, once created, are immutable.
|
||||
///
|
||||
class Type {
|
||||
class Type : public ExtQualsTypeCommonBase {
|
||||
public:
|
||||
enum TypeClass {
|
||||
#define TYPE(Class, Base) Class,
|
||||
|
@ -981,7 +1011,8 @@ protected:
|
|||
// silence VC++ warning C4355: 'this' : used in base member initializer list
|
||||
Type *this_() { return this; }
|
||||
Type(TypeClass tc, QualType Canonical, bool Dependent, bool VariablyModified)
|
||||
: CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical) {
|
||||
: ExtQualsTypeCommonBase(this),
|
||||
CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical) {
|
||||
TypeBits.TC = tc;
|
||||
TypeBits.Dependent = Dependent;
|
||||
TypeBits.VariablyModified = VariablyModified;
|
||||
|
|
|
@ -359,7 +359,7 @@ public:
|
|||
|
||||
QualType getDesugaredValueType(ASTContext &Context) const {
|
||||
QualType T = getValueType();
|
||||
return T.getTypePtr() ? T.getDesugaredType(Context) : T;
|
||||
return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
|
||||
}
|
||||
|
||||
QualType getDesugaredLocationType(ASTContext &Context) const {
|
||||
|
|
|
@ -2772,6 +2772,9 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
|
|||
}
|
||||
QualType PointeeType = GetType(Record[0]);
|
||||
QualType ClassType = GetType(Record[1]);
|
||||
if (PointeeType.isNull() || ClassType.isNull())
|
||||
return QualType();
|
||||
|
||||
return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
|
||||
}
|
||||
|
||||
|
@ -4368,7 +4371,10 @@ ASTReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
|
|||
|
||||
case NestedNameSpecifier::TypeSpec:
|
||||
case NestedNameSpecifier::TypeSpecWithTemplate: {
|
||||
Type *T = GetType(Record[Idx++]).getTypePtr();
|
||||
Type *T = GetType(Record[Idx++]).getTypePtrOrNull();
|
||||
if (!T)
|
||||
return 0;
|
||||
|
||||
bool Template = Record[Idx++];
|
||||
NNS = NestedNameSpecifier::Create(*Context, Prev, Template, T);
|
||||
break;
|
||||
|
|
|
@ -167,7 +167,7 @@ void ASTDeclReader::Visit(Decl *D) {
|
|||
|
||||
if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
|
||||
// if we have a fully initialized TypeDecl, we can safely read its type now.
|
||||
TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtr());
|
||||
TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtrOrNull());
|
||||
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
// FunctionDecl's body was written last after all other Stmts/Exprs.
|
||||
if (Record[Idx++])
|
||||
|
@ -443,7 +443,7 @@ void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
|
|||
|
||||
void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
|
||||
VisitObjCContainerDecl(ID);
|
||||
ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
|
||||
ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtrOrNull());
|
||||
ID->setSuperClass(cast_or_null<ObjCInterfaceDecl>
|
||||
(Reader.GetDecl(Record[Idx++])));
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
|
|||
}
|
||||
|
||||
static CXTypeKind GetTypeKind(QualType T) {
|
||||
Type *TP = T.getTypePtr();
|
||||
Type *TP = T.getTypePtrOrNull();
|
||||
if (!TP)
|
||||
return CXType_Invalid;
|
||||
|
||||
|
@ -186,7 +186,7 @@ CXType clang_getCanonicalType(CXType CT) {
|
|||
|
||||
CXType clang_getPointeeType(CXType CT) {
|
||||
QualType T = GetQualType(CT);
|
||||
Type *TP = T.getTypePtr();
|
||||
Type *TP = T.getTypePtrOrNull();
|
||||
|
||||
if (!TP)
|
||||
return MakeCXType(QualType(), GetTU(CT));
|
||||
|
@ -217,7 +217,7 @@ CXCursor clang_getTypeDeclaration(CXType CT) {
|
|||
return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
|
||||
|
||||
QualType T = GetQualType(CT);
|
||||
Type *TP = T.getTypePtr();
|
||||
Type *TP = T.getTypePtrOrNull();
|
||||
|
||||
if (!TP)
|
||||
return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
|
||||
|
@ -254,7 +254,7 @@ try_again:
|
|||
// FIXME: Template type parameters!
|
||||
|
||||
case Type::Elaborated:
|
||||
TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtr();
|
||||
TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
|
||||
goto try_again;
|
||||
|
||||
default:
|
||||
|
@ -324,7 +324,7 @@ unsigned clang_equalTypes(CXType A, CXType B) {
|
|||
|
||||
CXType clang_getResultType(CXType X) {
|
||||
QualType T = GetQualType(X);
|
||||
if (!T.getTypePtr())
|
||||
if (!T.getTypePtrOrNull())
|
||||
return MakeCXType(QualType(), GetTU(X));
|
||||
|
||||
if (const FunctionType *FD = T->getAs<FunctionType>())
|
||||
|
@ -347,7 +347,7 @@ CXType clang_getCursorResultType(CXCursor C) {
|
|||
|
||||
unsigned clang_isPODType(CXType X) {
|
||||
QualType T = GetQualType(X);
|
||||
if (!T.getTypePtr())
|
||||
if (!T.getTypePtrOrNull())
|
||||
return 0;
|
||||
return T->isPODType() ? 1 : 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue