Skip to content

Commit ab0d01a

Browse files
authored
[MC] Cache MCRegAliasIterator (#93510)
AMDGPU has a lot of registers, almost 9000. Many of those registers have aliases. For instance, SGPR0 has a ton of aliases due to the presence of register tuples. It's even worse if you query the aliases of a register tuple itself. A large register tuple can have hundreds of aliases because it may include 16 registers, and each of those registers have their own tuples as well. The current implementation of MCRegAliasIterator is not good at this. In some extreme cases it can iterate, 7000 more times than necessary, just giving duplicates over and over again and using a lot of expensive iterators. This patch implements a cache system for MCRegAliasIterator. It does the expensive part only once and then saves it for us so the next iterations on that register's aliases are just a map lookup. Furthermore, the cached data is uniqued (and sorted). Thus, this speeds up code by both speeding up the iterator itself, but also by minimizing the number of loop iterations users of the iterator do.
1 parent 88e42c6 commit ab0d01a

File tree

3 files changed

+111
-53
lines changed

3 files changed

+111
-53
lines changed

llvm/include/llvm/MC/MCRegisterInfo.h

Lines changed: 19 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ class MCRegisterInfo {
187187
DenseMap<MCRegister, int> L2SEHRegs; // LLVM to SEH regs mapping
188188
DenseMap<MCRegister, int> L2CVRegs; // LLVM to CV regs mapping
189189

190+
mutable std::vector<std::vector<MCPhysReg>> RegAliasesCache;
191+
ArrayRef<MCPhysReg> getCachedAliasesOf(MCPhysReg R) const;
192+
190193
/// Iterator class that can traverse the differentially encoded values in
191194
/// DiffLists. Don't use this class directly, use one of the adaptors below.
192195
class DiffListIterator
@@ -263,6 +266,7 @@ class MCRegisterInfo {
263266
friend class MCRegUnitIterator;
264267
friend class MCRegUnitMaskIterator;
265268
friend class MCRegUnitRootIterator;
269+
friend class MCRegAliasIterator;
266270

267271
/// Initialize MCRegisterInfo, called by TableGen
268272
/// auto-generated routines. *DO NOT USE*.
@@ -298,6 +302,8 @@ class MCRegisterInfo {
298302
EHDwarf2LRegsSize = 0;
299303
Dwarf2LRegs = nullptr;
300304
Dwarf2LRegsSize = 0;
305+
306+
RegAliasesCache.resize(NumRegs);
301307
}
302308

303309
/// Used to initialize LLVM register to Dwarf
@@ -723,63 +729,30 @@ class MCRegUnitRootIterator {
723729
}
724730
};
725731

726-
/// MCRegAliasIterator enumerates all registers aliasing Reg. If IncludeSelf is
727-
/// set, Reg itself is included in the list. This iterator does not guarantee
728-
/// any ordering or that entries are unique.
732+
/// MCRegAliasIterator enumerates all registers aliasing Reg.
729733
class MCRegAliasIterator {
730734
private:
731-
MCRegister Reg;
732-
const MCRegisterInfo *MCRI;
733-
bool IncludeSelf;
734-
735-
MCRegUnitIterator RI;
736-
MCRegUnitRootIterator RRI;
737-
MCSuperRegIterator SI;
735+
const MCPhysReg *It = nullptr;
736+
const MCPhysReg *End = nullptr;
738737

739738
public:
740739
MCRegAliasIterator(MCRegister Reg, const MCRegisterInfo *MCRI,
741-
bool IncludeSelf)
742-
: Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) {
743-
// Initialize the iterators.
744-
for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) {
745-
for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) {
746-
for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) {
747-
if (!(!IncludeSelf && Reg == *SI))
748-
return;
749-
}
750-
}
751-
}
752-
}
753-
754-
bool isValid() const { return RI.isValid(); }
755-
756-
MCRegister operator*() const {
757-
assert(SI.isValid() && "Cannot dereference an invalid iterator.");
758-
return *SI;
740+
bool IncludeSelf) {
741+
ArrayRef<MCPhysReg> Cache = MCRI->getCachedAliasesOf(Reg);
742+
assert(Cache.back() == Reg);
743+
It = Cache.begin();
744+
End = Cache.end();
745+
if (!IncludeSelf)
746+
--End;
759747
}
760748

761-
void advance() {
762-
// Assuming SI is valid.
763-
++SI;
764-
if (SI.isValid()) return;
765-
766-
++RRI;
767-
if (RRI.isValid()) {
768-
SI = MCSuperRegIterator(*RRI, MCRI, true);
769-
return;
770-
}
749+
bool isValid() const { return It != End; }
771750

772-
++RI;
773-
if (RI.isValid()) {
774-
RRI = MCRegUnitRootIterator(*RI, MCRI);
775-
SI = MCSuperRegIterator(*RRI, MCRI, true);
776-
}
777-
}
751+
MCRegister operator*() const { return *It; }
778752

779753
MCRegAliasIterator &operator++() {
780754
assert(isValid() && "Cannot move off the end of the list.");
781-
do advance();
782-
while (!IncludeSelf && isValid() && *SI == Reg);
755+
++It;
783756
return *this;
784757
}
785758
};

llvm/lib/MC/MCRegisterInfo.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,90 @@
2020

2121
using namespace llvm;
2222

23+
namespace {
24+
/// MCRegAliasIterator enumerates all registers aliasing Reg. This iterator
25+
/// does not guarantee any ordering or that entries are unique.
26+
class MCRegAliasIteratorImpl {
27+
private:
28+
MCRegister Reg;
29+
const MCRegisterInfo *MCRI;
30+
31+
MCRegUnitIterator RI;
32+
MCRegUnitRootIterator RRI;
33+
MCSuperRegIterator SI;
34+
35+
public:
36+
MCRegAliasIteratorImpl(MCRegister Reg, const MCRegisterInfo *MCRI)
37+
: Reg(Reg), MCRI(MCRI) {
38+
39+
// Initialize the iterators.
40+
for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) {
41+
for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) {
42+
for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) {
43+
if (Reg != *SI)
44+
return;
45+
}
46+
}
47+
}
48+
}
49+
50+
bool isValid() const { return RI.isValid(); }
51+
52+
MCRegister operator*() const {
53+
assert(SI.isValid() && "Cannot dereference an invalid iterator.");
54+
return *SI;
55+
}
56+
57+
void advance() {
58+
// Assuming SI is valid.
59+
++SI;
60+
if (SI.isValid())
61+
return;
62+
63+
++RRI;
64+
if (RRI.isValid()) {
65+
SI = MCSuperRegIterator(*RRI, MCRI, true);
66+
return;
67+
}
68+
69+
++RI;
70+
if (RI.isValid()) {
71+
RRI = MCRegUnitRootIterator(*RI, MCRI);
72+
SI = MCSuperRegIterator(*RRI, MCRI, true);
73+
}
74+
}
75+
76+
MCRegAliasIteratorImpl &operator++() {
77+
assert(isValid() && "Cannot move off the end of the list.");
78+
do
79+
advance();
80+
while (isValid() && *SI == Reg);
81+
return *this;
82+
}
83+
};
84+
} // namespace
85+
86+
ArrayRef<MCPhysReg> MCRegisterInfo::getCachedAliasesOf(MCPhysReg R) const {
87+
auto &Aliases = RegAliasesCache[R];
88+
if (!Aliases.empty())
89+
return Aliases;
90+
91+
for (MCRegAliasIteratorImpl It(R, this); It.isValid(); ++It)
92+
Aliases.push_back(*It);
93+
94+
sort(Aliases);
95+
Aliases.erase(unique(Aliases), Aliases.end());
96+
assert(none_of(Aliases, [&](auto &Cur) { return R == Cur; }) &&
97+
"MCRegAliasIteratorImpl includes Self!");
98+
99+
// Always put "self" at the end, so the iterator can choose to ignore it.
100+
// For registers without aliases, it also serves as a sentinel value that
101+
// tells us to not recompute the alias set.
102+
Aliases.push_back(R);
103+
Aliases.shrink_to_fit();
104+
return Aliases;
105+
}
106+
23107
MCRegister
24108
MCRegisterInfo::getMatchingSuperReg(MCRegister Reg, unsigned SubIdx,
25109
const MCRegisterClass *RC) const {

llvm/test/CodeGen/ARM/constant-island-movwt.mir

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -898,13 +898,14 @@ body: |
898898
# CHECK-NEXT: CONSTPOOL_ENTRY 1, %const.0, 4
899899
# CHECK-NEXT: {{^ $}}
900900
# CHECK-NEXT: bb.2.entry (align 2):
901-
# CHECK-NEXT: liveins: $d13, $s27, $r10, $r9, $r8, $s26, $d12, $s25, $s24,
902-
# CHECK-SAME: $d15, $s30, $s31, $d14, $s28, $s29, $lr, $r0, $d21,
903-
# CHECK-SAME: $r3, $q10, $d20, $d17, $r2, $d25, $q11, $d22, $d23,
904-
# CHECK-SAME: $r1, $q8, $d16, $s3, $q14, $d28, $d29, $d19, $s17,
905-
# CHECK-SAME: $d8, $s16, $r6, $r7, $r4, $q12, $q9, $d18, $s0, $q15,
906-
# CHECK-SAME: $d30, $d31, $r12, $s1, $d0, $d24, $s2, $d1, $q0, $s6,
907-
# CHECK-SAME: $d3, $d2, $s4, $q1, $s7, $s5, $d9, $s18, $s19, $q4
901+
# CHECK-NEXT: liveins: $s26, $s27, $r10, $r9, $r8, $d13, $s24, $s25,
902+
# CHECK-SAME: $d12, $d15, $s30, $s31, $d14, $s28, $s29, $lr,
903+
# CHECK-SAME: $d21, $q10, $r7, $r0, $d20, $d17, $r2, $q12,
904+
# CHECK-SAME: $q11, $d22, $d23, $r1, $q8, $d16, $d30, $q14,
905+
# CHECK-SAME: $d28, $d29, $d19, $s17, $r4, $d8, $r6, $r3,
906+
# CHECK-SAME: $s16, $d25, $q9, $d18, $s0, $d31, $s3, $q15,
907+
# CHECK-SAME: $r12, $d0, $s1, $d24, $d1, $s2, $q0, $s5, $d2,
908+
# CHECK-SAME: $q1, $s4, $s7, $d3, $s6, $d9, $s18, $s19, $q4
908909
# CHECK-NEXT: {{^ $}}
909910
# CHECK-NEXT: $r5 = t2MOVi16 target-flags(arm-lo16) @.str.84, 14 /* CC::al */, $noreg
910911
# CHECK-NEXT: $r5 = t2MOVTi16 $r5, target-flags(arm-hi16) @.str.84, 14 /* CC::al */, $noreg

0 commit comments

Comments
 (0)