aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorChad Rosier <mcrosier@apple.com>2013-06-27 19:38:13 +0000
committerChad Rosier <mcrosier@apple.com>2013-06-27 19:38:13 +0000
commitb7110cf5b5e4832e8ded6db7ab7577e3cfa2c462 (patch)
tree6e63e83eea514e36d93a0bf302103ac4d89247da /include
parentf00e9ae990f5a836555c9d4f911c941953d14e19 (diff)
downloadexternal_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.h80
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