Skip to content

Commit 48be81e

Browse files
authored
[NFC] [Serializer] Pack information in serializer (#69287)
Previously, the boolean values will occupy spaces that can contain integers. It wastes the spaces especially if the boolean values are serialized consecutively. The patch tries to pack such consecutive boolean values (and enum values) so that we can save more spaces and so the times. Before the patch, we need 4.478s (in my machine) to build the std module (https://libcxx.llvm.org/Modules.html) with 28712 bytes for size of the BMI. After the patch, the time becomes to 4.374s and the size becomes to 27388 bytes for the size of the BMI. This is intended to be a NFC patch. This patch doesn't optimize all such cases. We can do it later after we have consensus on this.
1 parent 03110dd commit 48be81e

File tree

7 files changed

+471
-357
lines changed

7 files changed

+471
-357
lines changed

clang/include/clang/AST/DeclBase.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ class alignas(8) Decl {
211211
/// The kind of ownership a declaration has, for visibility purposes.
212212
/// This enumeration is designed such that higher values represent higher
213213
/// levels of name hiding.
214-
enum class ModuleOwnershipKind : unsigned {
214+
enum class ModuleOwnershipKind : unsigned char {
215215
/// This declaration is not owned by a module.
216216
Unowned,
217217

clang/include/clang/Serialization/ASTReader.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,6 +2407,53 @@ class ASTReader
24072407
bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; }
24082408
};
24092409

2410+
/// A simple helper class to unpack an integer to bits and consuming
2411+
/// the bits in order.
2412+
class BitsUnpacker {
2413+
constexpr static uint32_t BitsIndexUpbound = 32;
2414+
2415+
public:
2416+
BitsUnpacker(uint32_t V) { updateValue(V); }
2417+
BitsUnpacker(const BitsUnpacker &) = delete;
2418+
BitsUnpacker(BitsUnpacker &&) = delete;
2419+
BitsUnpacker operator=(const BitsUnpacker &) = delete;
2420+
BitsUnpacker operator=(BitsUnpacker &&) = delete;
2421+
~BitsUnpacker() {
2422+
#ifndef NDEBUG
2423+
while (isValid())
2424+
assert(!getNextBit() && "There are unprocessed bits!");
2425+
#endif
2426+
}
2427+
2428+
void updateValue(uint32_t V) {
2429+
Value = V;
2430+
CurrentBitsIndex = 0;
2431+
}
2432+
2433+
bool getNextBit() {
2434+
assert(isValid());
2435+
return Value & (1 << CurrentBitsIndex++);
2436+
}
2437+
2438+
uint32_t getNextBits(uint32_t Width) {
2439+
assert(isValid());
2440+
assert(Width < BitsIndexUpbound);
2441+
uint32_t Ret = (Value >> CurrentBitsIndex) & ((1 << Width) - 1);
2442+
CurrentBitsIndex += Width;
2443+
return Ret;
2444+
}
2445+
2446+
bool canGetNextNBits(uint32_t Width) const {
2447+
return CurrentBitsIndex + Width < BitsIndexUpbound;
2448+
}
2449+
2450+
private:
2451+
bool isValid() const { return CurrentBitsIndex < BitsIndexUpbound; }
2452+
2453+
uint32_t Value;
2454+
uint32_t CurrentBitsIndex = ~0;
2455+
};
2456+
24102457
} // namespace clang
24112458

24122459
#endif // LLVM_CLANG_SERIALIZATION_ASTREADER_H

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,59 @@ class PCHGenerator : public SemaConsumer {
830830
bool hasEmittedPCH() const { return Buffer->IsComplete; }
831831
};
832832

833+
/// A simple helper class to pack several bits in order into (a) 32 bit
834+
/// integer(s).
835+
class BitsPacker {
836+
constexpr static uint32_t BitIndexUpbound = 32u;
837+
838+
public:
839+
BitsPacker() = default;
840+
BitsPacker(const BitsPacker &) = delete;
841+
BitsPacker(BitsPacker &&) = delete;
842+
BitsPacker operator=(const BitsPacker &) = delete;
843+
BitsPacker operator=(BitsPacker &&) = delete;
844+
~BitsPacker() {
845+
assert(!hasUnconsumedValues() && "There are unprocessed bits!");
846+
}
847+
848+
void addBit(bool Value) { addBits(Value, 1); }
849+
void addBits(uint32_t Value, uint32_t BitsWidth) {
850+
assert(BitsWidth < BitIndexUpbound);
851+
assert((Value < (1u << BitsWidth)) && "Passing narrower bit width!");
852+
853+
if (CurrentBitIndex + BitsWidth >= BitIndexUpbound) {
854+
Values.push_back(0);
855+
CurrentBitIndex = 0;
856+
}
857+
858+
assert(CurrentBitIndex < BitIndexUpbound);
859+
Values.back() |= Value << CurrentBitIndex;
860+
CurrentBitIndex += BitsWidth;
861+
}
862+
863+
bool hasUnconsumedValues() const {
864+
return ConsumingValueIndex < Values.size();
865+
}
866+
uint32_t getNextValue() {
867+
assert(hasUnconsumedValues());
868+
return Values[ConsumingValueIndex++];
869+
}
870+
871+
// We can convert the packer to an uint32_t if there is only one values.
872+
operator uint32_t() {
873+
assert(Values.size() == 1);
874+
return getNextValue();
875+
}
876+
877+
private:
878+
SmallVector<uint64_t, 4> Values;
879+
uint16_t ConsumingValueIndex = 0;
880+
// Initialize CurrentBitIndex with an invalid value
881+
// to make it easier to update Values. See the implementation
882+
// of `addBits` to see the details.
883+
uint16_t CurrentBitIndex = BitIndexUpbound;
884+
};
885+
833886
} // namespace clang
834887

835888
#endif // LLVM_CLANG_SERIALIZATION_ASTWRITER_H

0 commit comments

Comments
 (0)