RDA currently uses SmallVector<int, 1> to store reaching definitions. A SmallVector<int, 1> is 24 bytes large, and X86 currently has 164 register units, which means we need 3936 bytes per block. If you have a large function with 1000 blocks, that's already 4MB.
A large fraction of these reg units will not have any reaching defs (say, those corresponding to zmm registers), and many will have just one. A TinyPtrVector serves this use-case much better, as it only needs 8 bytes per register if it has 0 or 1 reaching defs.
As the name implies, TinyPtrVector is designed to work with pointers, so we need to add some boilerplate to treat our reaching defs integers as pointers, using an appropriate encoding. We need to keep the low bit free for tagging, and make sure at least one bit is set to distinguish the null pointer.