Merge pull request #13205 from davezarzycki/nfc_typebase_layout_optimization
[AST] NFC: Shrink TypeKind size and optimize TypeBase layout
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 0ccd2c7..ffba716 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -72,7 +72,7 @@
enum PointerTypeKind : unsigned;
struct ValueOwnershipKind;
- enum class TypeKind {
+ enum class TypeKind : uint8_t {
#define TYPE(id, parent) id,
#define TYPE_RANGE(Id, FirstId, LastId) \
First_##Id##Type = FirstId, Last_##Id##Type = LastId,
@@ -243,6 +243,10 @@
};
using TypeMatchOptions = OptionSet<TypeMatchFlags>;
+#define NUMBITS(E, V) \
+ enum { Num##E##Bits = V }; \
+ static_assert(Num##E##Bits <= 64, "fits in a uint64_t")
+
/// TypeBase - Base class for all types in Swift.
class alignas(1 << TypeAlignInBits) TypeBase {
@@ -255,15 +259,13 @@
/// form of a non-canonical type is requested.
llvm::PointerUnion<TypeBase *, const ASTContext *> CanonicalType;
- /// Kind - The discriminator that indicates what subclass of type this is.
- const TypeKind Kind;
-
struct TypeBaseBitfields {
+ /// Kind - The discriminator that indicates what subclass of type this is.
+ const TypeKind Kind; // Naturally sized for speed (it only needs 6 bits).
+
unsigned Properties : RecursiveTypeProperties::BitWidth;
};
-
- enum { NumTypeBaseBits = RecursiveTypeProperties::BitWidth };
- static_assert(NumTypeBaseBits <= 32, "fits in an unsigned");
+ NUMBITS(TypeBase, RecursiveTypeProperties::BitWidth + sizeof(TypeKind) * 8 );
/// Returns true if the given type is a sugared type.
///
@@ -281,8 +283,7 @@
/// Whether there is an original type.
unsigned HasOriginalType : 1;
};
- enum { NumErrorTypeBits = NumTypeBaseBits + 1 };
- static_assert(NumErrorTypeBits <= 32, "fits in an unsigned");
+ NUMBITS(ErrorType, NumTypeBaseBits + 1);
struct AnyFunctionTypeBitfields {
unsigned : NumTypeBaseBits;
@@ -292,8 +293,7 @@
enum { NumExtInfoBits = 7 };
unsigned ExtInfo : NumExtInfoBits;
};
- enum { NumAnyFunctionTypeBits = NumTypeBaseBits + 7 };
- static_assert(NumAnyFunctionTypeBits <= 32, "fits in an unsigned");
+ NUMBITS(AnyFunctionType, NumTypeBaseBits + 7);
struct ArchetypeTypeBitfields {
unsigned : NumTypeBaseBits;
@@ -303,17 +303,15 @@
unsigned HasLayoutConstraint : 1;
unsigned NumProtocols : 16;
};
- enum { NumArchetypeTypeBitfields = NumTypeBaseBits + 19 };
- static_assert(NumArchetypeTypeBitfields <= 32, "fits in an unsigned");
+ NUMBITS(ArchetypeType, NumTypeBaseBits + 19);
struct TypeVariableTypeBitfields {
unsigned : NumTypeBaseBits;
/// \brief The unique number assigned to this type variable.
- unsigned ID : 32 - NumTypeBaseBits;
+ unsigned ID : 64 - NumTypeBaseBits;
};
- enum { NumTypeVariableTypeBits = NumTypeBaseBits + (32 - NumTypeBaseBits) };
- static_assert(NumTypeVariableTypeBits <= 32, "fits in an unsigned");
+ NUMBITS(TypeVariableType, 64);
struct SILFunctionTypeBitfields {
unsigned : NumTypeBaseBits;
@@ -323,8 +321,7 @@
unsigned HasErrorResult : 1;
unsigned CoroutineKind : 2;
};
- enum { NumSILFunctionTypeBits = NumTypeBaseBits + 12 };
- static_assert(NumSILFunctionTypeBits <= 32, "fits in an unsigned");
+ NUMBITS(SILFunctionType, NumTypeBaseBits + 12);
struct AnyMetatypeTypeBitfields {
unsigned : NumTypeBaseBits;
@@ -334,8 +331,7 @@
/// the value is the representation + 1
unsigned Representation : 2;
};
- enum { NumAnyMetatypeTypeBits = NumTypeBaseBits + 2 };
- static_assert(NumAnyMetatypeTypeBits <= 32, "fits in an unsigned");
+ NUMBITS(AnyMetatypeType, NumTypeBaseBits + 2);
struct ProtocolCompositionTypeBitfields {
unsigned : NumTypeBaseBits;
@@ -343,17 +339,17 @@
/// implied by any of our members.
unsigned HasExplicitAnyObject : 1;
};
- enum { NumProtocolCompositionTypeBits = NumTypeBaseBits + 1 };
- static_assert(NumProtocolCompositionTypeBits <= 32, "fits in an unsigned");
+ NUMBITS(ProtocolCompositionType, NumTypeBaseBits + 1);
+
struct TupleTypeBitfields {
unsigned : NumTypeBaseBits;
/// Whether an element of the tuple is inout.
unsigned HasInOutElement : 1;
};
- enum { NumTupleTypeBits = NumTypeBaseBits + 1 };
- static_assert(NumTupleTypeBits <= 32, "fits in an unsigned");
-
+ NUMBITS(TupleType, NumTypeBaseBits + 1);
+
+#undef NUMBITS
union {
TypeBaseBitfields TypeBaseBits;
ErrorTypeBitfields ErrorTypeBits;
@@ -369,7 +365,8 @@
protected:
TypeBase(TypeKind kind, const ASTContext *CanTypeCtx,
RecursiveTypeProperties properties)
- : CanonicalType((TypeBase*)nullptr), Kind(kind) {
+ : CanonicalType((TypeBase*)nullptr) {
+ *const_cast<TypeKind *>(&TypeBaseBits.Kind) = kind;
// If this type is canonical, switch the CanonicalType union to ASTContext.
if (CanTypeCtx)
CanonicalType = CanTypeCtx;
@@ -383,7 +380,7 @@
public:
/// getKind - Return what kind of type this is.
- TypeKind getKind() const { return Kind; }
+ TypeKind getKind() const { return TypeBaseBits.Kind; }
/// isCanonical - Return true if this is a canonical type.
bool isCanonical() const { return CanonicalType.is<const ASTContext *>(); }