diff options
author | Chad Rosier <mcrosier@apple.com> | 2013-06-27 19:38:13 +0000 |
---|---|---|
committer | Chad Rosier <mcrosier@apple.com> | 2013-06-27 19:38:13 +0000 |
commit | b7110cf5b5e4832e8ded6db7ab7577e3cfa2c462 (patch) | |
tree | 6e63e83eea514e36d93a0bf302103ac4d89247da /include | |
parent | f00e9ae990f5a836555c9d4f911c941953d14e19 (diff) | |
download | external_llvm-b7110cf5b5e4832e8ded6db7ab7577e3cfa2c462.zip external_llvm-b7110cf5b5e4832e8ded6db7ab7577e3cfa2c462.tar.gz external_llvm-b7110cf5b5e4832e8ded6db7ab7577e3cfa2c462.tar.bz2 |
Improve the compression of the tablegen DiffLists by introducing a new sort
algorithm when assigning EnumValues to the synthesized registers.
The current algorithm, LessRecord, uses the StringRef compare_numeric
function. This function compares strings, while handling embedded numbers.
For example, the R600 backend registers are sorted as follows:
T1
T1_W
T1_X
T1_XYZW
T1_Y
T1_Z
T2
T2_W
T2_X
T2_XYZW
T2_Y
T2_Z
In this example, the 'scaling factor' is dEnum/dN = 6 because T0, T1, T2
have an EnumValue offset of 6 from one another. However, in other parts
of the register bank, the scaling factors are different:
dEnum/dN = 5:
KC0_128_W
KC0_128_X
KC0_128_XYZW
KC0_128_Y
KC0_128_Z
KC0_129_W
KC0_129_X
KC0_129_XYZW
KC0_129_Y
KC0_129_Z
The diff lists do not work correctly because different kinds of registers have
different 'scaling factors'. This new algorithm, LessRecordRegister, tries to
enforce a scaling factor of 1. For example, the registers are now sorted as
follows:
T1
T2
T3
...
T0_W
T1_W
T2_W
...
T0_X
T1_X
T2_X
...
KC0_128_W
KC0_129_W
KC0_130_W
...
For the Mips and R600 I see a 19% and 6% reduction in size, respectively. I
did see a few small regressions, but the differences were on the order of a
few bytes (e.g., AArch64 was 16 bytes). I suspect there will be even
greater wins for targets with larger register files.
Patch reviewed by Jakob.
rdar://14006013
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185094 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r-- | include/llvm/TableGen/Record.h | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 76ee69d..63b72c8 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -1731,6 +1731,86 @@ struct LessRecordFieldName { } }; +struct LessRecordRegister { + static size_t min(size_t a, size_t b) { return a < b ? a : b; } + static bool ascii_isdigit(char x) { return x >= '0' && x <= '9'; } + + struct RecordParts { + SmallVector<std::pair< bool, StringRef>, 4> Parts; + + RecordParts(StringRef Rec) { + if (Rec.empty()) + return; + + size_t Len = 0; + const char *Start = Rec.data(); + const char *Curr = Start; + bool isDigitPart = ascii_isdigit(Curr[0]); + for (size_t I = 0, E = Rec.size(); I != E; ++I, ++Len) { + bool isDigit = ascii_isdigit(Curr[I]); + if (isDigit != isDigitPart) { + Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len))); + Len = 0; + Start = &Curr[I]; + isDigitPart = ascii_isdigit(Curr[I]); + } + } + // Push the last part. + Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len))); + } + + size_t size() { return Parts.size(); } + + std::pair<bool, StringRef> getPart(size_t i) { + assert (i < Parts.size() && "Invalid idx!"); + return Parts[i]; + } + }; + + bool operator()(const Record *Rec1, const Record *Rec2) const { + RecordParts LHSParts(StringRef(Rec1->getName())); + RecordParts RHSParts(StringRef(Rec2->getName())); + + size_t LHSNumParts = LHSParts.size(); + size_t RHSNumParts = RHSParts.size(); + assert (LHSNumParts && RHSNumParts && "Expected at least one part!"); + + if (LHSNumParts != RHSNumParts) + return LHSNumParts < RHSNumParts; + + // We expect the registers to be of the form [_a-zA-z]+([0-9]*[_a-zA-Z]*)*. + for (size_t I = 0, E = LHSNumParts; I < E; I+=2) { + std::pair<bool, StringRef> LHSPart = LHSParts.getPart(I); + std::pair<bool, StringRef> RHSPart = RHSParts.getPart(I); + if ((I & 1) == 0) { // Expect even part to always be alpha. + assert (LHSPart.first == false && RHSPart.first == false && + "Expected both parts to be alpha."); + if (int Res = LHSPart.second.compare(RHSPart.second)) + return Res < 0; + } + } + for (size_t I = 1, E = LHSNumParts; I < E; I+=2) { + std::pair<bool, StringRef> LHSPart = LHSParts.getPart(I); + std::pair<bool, StringRef> RHSPart = RHSParts.getPart(I); + if (I & 1) { // Expect odd part to always be numeric. + assert (LHSPart.first == true && RHSPart.first == true && + "Expected both parts to be numeric."); + if (LHSPart.second.size() != RHSPart.second.size()) + return LHSPart.second.size() < RHSPart.second.size(); + + unsigned LHSVal, RHSVal; + if (LHSPart.second.getAsInteger(10, LHSVal)) + assert("Unable to convert LHS to integer."); + if (RHSPart.second.getAsInteger(10, RHSVal)) + assert("Unable to convert RHS to integer."); + if (LHSVal != RHSVal) + return LHSVal < RHSVal; + } + } + return LHSNumParts < RHSNumParts; + } +}; + raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK); /// QualifyName - Return an Init with a qualifier prefix referring |