llvm.org GIT mirror llvm / b7110cf
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 Chad Rosier 7 years ago
4 changed file(s) with 109 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
17301730 }
17311731 };
17321732
1733 struct LessRecordRegister {
1734 static size_t min(size_t a, size_t b) { return a < b ? a : b; }
1735 static bool ascii_isdigit(char x) { return x >= '0' && x <= '9'; }
1736
1737 struct RecordParts {
1738 SmallVector, 4> Parts;
1739
1740 RecordParts(StringRef Rec) {
1741 if (Rec.empty())
1742 return;
1743
1744 size_t Len = 0;
1745 const char *Start = Rec.data();
1746 const char *Curr = Start;
1747 bool isDigitPart = ascii_isdigit(Curr[0]);
1748 for (size_t I = 0, E = Rec.size(); I != E; ++I, ++Len) {
1749 bool isDigit = ascii_isdigit(Curr[I]);
1750 if (isDigit != isDigitPart) {
1751 Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len)));
1752 Len = 0;
1753 Start = &Curr[I];
1754 isDigitPart = ascii_isdigit(Curr[I]);
1755 }
1756 }
1757 // Push the last part.
1758 Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len)));
1759 }
1760
1761 size_t size() { return Parts.size(); }
1762
1763 std::pair getPart(size_t i) {
1764 assert (i < Parts.size() && "Invalid idx!");
1765 return Parts[i];
1766 }
1767 };
1768
1769 bool operator()(const Record *Rec1, const Record *Rec2) const {
1770 RecordParts LHSParts(StringRef(Rec1->getName()));
1771 RecordParts RHSParts(StringRef(Rec2->getName()));
1772
1773 size_t LHSNumParts = LHSParts.size();
1774 size_t RHSNumParts = RHSParts.size();
1775 assert (LHSNumParts && RHSNumParts && "Expected at least one part!");
1776
1777 if (LHSNumParts != RHSNumParts)
1778 return LHSNumParts < RHSNumParts;
1779
1780 // We expect the registers to be of the form [_a-zA-z]+([0-9]*[_a-zA-Z]*)*.
1781 for (size_t I = 0, E = LHSNumParts; I < E; I+=2) {
1782 std::pair LHSPart = LHSParts.getPart(I);
1783 std::pair RHSPart = RHSParts.getPart(I);
1784 if ((I & 1) == 0) { // Expect even part to always be alpha.
1785 assert (LHSPart.first == false && RHSPart.first == false &&
1786 "Expected both parts to be alpha.");
1787 if (int Res = LHSPart.second.compare(RHSPart.second))
1788 return Res < 0;
1789 }
1790 }
1791 for (size_t I = 1, E = LHSNumParts; I < E; I+=2) {
1792 std::pair LHSPart = LHSParts.getPart(I);
1793 std::pair RHSPart = RHSParts.getPart(I);
1794 if (I & 1) { // Expect odd part to always be numeric.
1795 assert (LHSPart.first == true && RHSPart.first == true &&
1796 "Expected both parts to be numeric.");
1797 if (LHSPart.second.size() != RHSPart.second.size())
1798 return LHSPart.second.size() < RHSPart.second.size();
1799
1800 unsigned LHSVal, RHSVal;
1801 if (LHSPart.second.getAsInteger(10, LHSVal))
1802 assert("Unable to convert LHS to integer.");
1803 if (RHSPart.second.getAsInteger(10, RHSVal))
1804 assert("Unable to convert RHS to integer.");
1805 if (LHSVal != RHSVal)
1806 return LHSVal < RHSVal;
1807 }
1808 }
1809 return LHSNumParts < RHSNumParts;
1810 }
1811 };
1812
17331813 raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK);
17341814
17351815 /// QualifyName - Return an Init with a qualifier prefix referring
896896 ldm r0, {r0, r2, lr}^
897897 ldm sp!, {r0-r3, pc}^
898898
899 @ CHECK: ldm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x92,0xe8]
900 @ CHECK: ldm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x92,0xe8]
901 @ CHECK: ldmib r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x92,0xe9]
902 @ CHECK: ldmda r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x12,0xe8]
903 @ CHECK: ldmdb r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x12,0xe9]
904 @ CHECK: ldm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x92,0xe8]
905
906 @ CHECK: ldm r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xb2,0xe8]
907 @ CHECK: ldmib r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xb2,0xe9]
908 @ CHECK: ldmda r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x32,0xe8]
909 @ CHECK: ldmdb r2!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x32,0xe9]
899 @ CHECK: ldm r2, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x92,0xe8]
900 @ CHECK: ldm r2, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x92,0xe8]
901 @ CHECK: ldmib r2, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x92,0xe9]
902 @ CHECK: ldmda r2, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x12,0xe8]
903 @ CHECK: ldmdb r2, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x12,0xe9]
904 @ CHECK: ldm r2, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x92,0xe8]
905
906 @ CHECK: ldm r2!, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0xb2,0xe8]
907 @ CHECK: ldmib r2!, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0xb2,0xe9]
908 @ CHECK: ldmda r2!, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x32,0xe8]
909 @ CHECK: ldmdb r2!, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x32,0xe9]
910910 @ CHECK: ldm r0, {lr, r0, r2} ^ @ encoding: [0x05,0x40,0xd0,0xe8]
911911 @ CHECK: ldm sp!, {pc, r0, r1, r2, r3} ^ @ encoding: [0x0f,0x80,0xfd,0xe8]
912912
23312331 stmda sp!, {r1,r3-r6}
23322332 stmdb r0!, {r1,r5,r7,sp}
23332333
2334 @ CHECK: stm r2, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x82,0xe8]
2334 @ CHECK: stm r2, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x82,0xe8]
23352335 @ CHECK: stm r3, {lr, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x40,0x83,0xe8]
2336 @ CHECK: stmib r4, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x84,0xe9]
2337 @ CHECK: stmda r5, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x05,0xe8]
2336 @ CHECK: stmib r4, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x84,0xe9]
2337 @ CHECK: stmda r5, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x05,0xe8]
23382338 @ CHECK: stmdb r6, {r1, r3, r4, r5, r6, r8} @ encoding: [0x7a,0x01,0x06,0xe9]
2339 @ CHECK: stmdb sp, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0x0d,0xe9]
2340
2341 @ CHECK: stm r8!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa8,0xe8]
2342 @ CHECK: stmib r9!, {r1, r3, r4, r5, r6, sp} @ encoding: [0x7a,0x20,0xa9,0xe9]
2339 @ CHECK: stmdb sp, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0x0d,0xe9]
2340
2341 @ CHECK: stm r8!, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0xa8,0xe8]
2342 @ CHECK: stmib r9!, {sp, r1, r3, r4, r5, r6} @ encoding: [0x7a,0x20,0xa9,0xe9]
23432343 @ CHECK: stmda sp!, {r1, r3, r4, r5, r6} @ encoding: [0x7a,0x00,0x2d,0xe8]
2344 @ CHECK: stmdb r0!, {r1, r5, r7, sp} @ encoding: [0xa2,0x20,0x20,0xe9]
2344 @ CHECK: stmdb r0!, {sp, r1, r5, r7} @ encoding: [0xa2,0x20,0x20,0xe9]
23452345
23462346
23472347 @------------------------------------------------------------------------------
937937
938938 // Read in the register definitions.
939939 std::vector Regs = Records.getAllDerivedDefinitions("Register");
940 std::sort(Regs.begin(), Regs.end(), LessRecord());
940 std::sort(Regs.begin(), Regs.end(), LessRecordRegister());
941941 Registers.reserve(Regs.size());
942942 // Assign the enumeration values.
943943 for (unsigned i = 0, e = Regs.size(); i != e; ++i)
946946 // Expand tuples and number the new registers.
947947 std::vector Tups =
948948 Records.getAllDerivedDefinitions("RegisterTuples");
949
950 std::vector TupRegsCopy;
949951 for (unsigned i = 0, e = Tups.size(); i != e; ++i) {
950952 const std::vector *TupRegs = Sets.expand(Tups[i]);
951 for (unsigned j = 0, je = TupRegs->size(); j != je; ++j)
952 getReg((*TupRegs)[j]);
953 TupRegsCopy.reserve(TupRegs->size());
954 TupRegsCopy.assign(TupRegs->begin(), TupRegs->end());
955 std::sort(TupRegsCopy.begin(), TupRegsCopy.end(), LessRecordRegister());
956 for (unsigned j = 0, je = TupRegsCopy.size(); j != je; ++j)
957 getReg((TupRegsCopy)[j]);
958 TupRegsCopy.clear();
953959 }
954960
955961 // Now all the registers are known. Build the object graph of explicit
308308 const std::vector &Regs,
309309 bool isCtor) {
310310 // Collect all information about dwarf register numbers
311 typedef std::map, LessRecord> DwarfRegNumsMapTy;
311 typedef std::map, LessRecordRegister> DwarfRegNumsMapTy;
312312 DwarfRegNumsMapTy DwarfRegNums;
313313
314314 // First, just pull all provided information to the map