By the time working on the gdb pretty-printers for the Analyzer classes,
I observed that the MemRegion class has an inefficient memory layout.
Each and every object which's has a MemRegion as a subobject would benefit from this change.
We could spare 8 bytes for each case.
As a downside, I had to substitute the llvm::Optional, since that alone consumes 16 bytes (even if the wrapped object would consume 8 bytes :| ).
Before the patch: sizeof(MemRegion) == 48
(gdb) ptype /o class MemRegion /* offset | size */ type = class clang::ento::MemRegion : public llvm::FoldingSetBase::Node { private: /* 16 | 4 */ const clang::ento::MemRegion::Kind kind; /* XXX 4-byte hole */ /* 24 | 24 */ class llvm::Optional<clang::ento::RegionOffset> [with T = clang::ento::RegionOffset] { private: /* 24 | 24 */ class llvm::optional_detail::OptionalStorage<T, true> [with T = T] { private: /* 24 | 16 */ union { /* 1 */ char empty; /* 16 */ T value; /* total size (bytes): 16 */ }; /* 40 | 1 */ bool hasVal; /* total size (bytes): 24 */ } Storage; /* total size (bytes): 24 */ } cachedOffset; /* total size (bytes): 48 */ }
After the patch: sizeof(MemRegion) == 40
(gdb) ptype /o MemRegion /* offset | size */ type = class clang::ento::MemRegion : public llvm::FoldingSetBase::Node { private: /* 16 | 16 */ class clang::ento::RegionOffset { private: /* 16 | 8 */ const clang::ento::MemRegion *R; /* 24 | 8 */ int64_t Offset; public: static const int64_t Symbolic; /* total size (bytes): 16 */ } cachedOffset; /* 32 | 4 */ const clang::ento::MemRegion::Kind kind; /* 36 | 1 */ bool hasCachedOffset; /* total size (bytes): 40 */ }