The main purpose of this is to address the TODO in SmallBitVector to store
the large mode in a single allocation. I made some other optimisations and
fixed a few bugs while I was at it.
Behaviour changes:
- operator== now returns false when sizes are not equal
- Hashing
- Fixed bug where BitVectors with equal contents but different capacities would get different hashes
- Fixed bug where SmallBitVector would hash differently in small and large modes
- Allow empty BitVectors and SmallBitVectors to be used as DenseMap keys
- BitVector::getData now returns only in-use words
Internal changes:
- SmallBitVector Large-mode now lives in a single allocation
- sizeof(BitVector) is now 16, previously 24
- BitVector(unsigned, bool) no longer allocates when s==0
- Most uses of Bits now call getActiveBits, returning only the BitWords currently in use.
- set_unused_bits now only affects bits in the top used word. Unused BitWords are now uninitialised, which should make many operations faster on very over-allocated vectors. This change should be safe because of the above change - accessing the uninitialised data should trip a bounds check. See commit f93a82f08f29163c342f320b88710b8eb0beb804 which introduced this behaviour
- grow no longer initialises data
- Re-implemented the two-vector operations in SmallBitVector to improve performance in the mixed small/large case
- SmallBitVector::getSmallBits now masks out size bits only. setSmallSize already ensures that unused data bits are zero.
Also included a bug-fix to RegScavenger, which started tripping an assert that I added. This
change should probably go in on its own but I don't know how to write a test exercising that
code, or who might be able to help me.
clang-format: please reformat the code