Skip to content

Commit 581b28b

Browse files
committed
[RegAllocFast] Refactor dominates algorithm for large basic block
The original brute force dominates algorithm is O(n) complexity so it is very slow for very large machine basic block which is very common with O0. This patch added InstrPosIndexes to assign index for each instruction and use it to determine dominance. The complexity is now O(1).
1 parent 1609f1c commit 581b28b

File tree

1 file changed

+78
-14
lines changed

1 file changed

+78
-14
lines changed

llvm/lib/CodeGen/RegAllocFast.cpp

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,71 @@ static RegisterRegAlloc fastRegAlloc("fast", "fast register allocator",
6262

6363
namespace {
6464

65+
/// Assign ascending index for instructions in machine basic block. The index
66+
/// can be used to determine dominance between instructions in same MBB.
67+
class InstrPosIndexes {
68+
public:
69+
void init(const MachineBasicBlock &MBB) {
70+
CurMBB = &MBB;
71+
Instr2PosIndex.clear();
72+
uint64_t LastIndex = 0;
73+
for (const MachineInstr &MI : MBB) {
74+
LastIndex += InstrDist;
75+
Instr2PosIndex[&MI] = LastIndex;
76+
}
77+
}
78+
79+
/// Set \p Index to index of \p MI. If \p MI is new inserted, it try to assign
80+
/// index without affecting existing instruction's index. Return true if all
81+
/// instructions index has been reassigned.
82+
bool getIndex(const MachineInstr &MI, uint64_t &Index) {
83+
assert(MI.getParent() == CurMBB && "MI is not in CurMBB");
84+
if (Instr2PosIndex.count(&MI)) {
85+
Index = Instr2PosIndex[&MI];
86+
return false;
87+
}
88+
89+
unsigned Distance = 1;
90+
MachineBasicBlock::const_iterator Start = MI.getIterator(),
91+
End = std::next(Start);
92+
while (Start != CurMBB->begin() &&
93+
!Instr2PosIndex.count(&*std::prev(Start))) {
94+
--Start;
95+
++Distance;
96+
}
97+
while (End != CurMBB->end() && !Instr2PosIndex.count(&*(End))) {
98+
++End;
99+
++Distance;
100+
}
101+
102+
uint64_t LastIndex =
103+
Start == CurMBB->begin() ? 0 : Instr2PosIndex.at(&*std::prev(Start));
104+
uint64_t Step = End == CurMBB->end()
105+
? static_cast<uint64_t>(InstrDist)
106+
: (Instr2PosIndex.at(&*End) - LastIndex - 1) / Distance;
107+
108+
// Reassign index for all instructions if number of new inserted
109+
// instructions exceed slot or all instructions are new.
110+
if (LLVM_UNLIKELY(!Step || (!LastIndex && Step == InstrDist))) {
111+
init(*CurMBB);
112+
Index = Instr2PosIndex.at(&MI);
113+
return true;
114+
}
115+
116+
for (auto I = Start; I != End; ++I) {
117+
LastIndex += Step;
118+
Instr2PosIndex[&*I] = LastIndex;
119+
}
120+
Index = Instr2PosIndex.at(&MI);
121+
return false;
122+
}
123+
124+
private:
125+
enum { InstrDist = 1024 };
126+
const MachineBasicBlock *CurMBB = nullptr;
127+
DenseMap<const MachineInstr *, uint64_t> Instr2PosIndex;
128+
};
129+
65130
class RegAllocFast : public MachineFunctionPass {
66131
public:
67132
static char ID;
@@ -153,6 +218,9 @@ class RegAllocFast : public MachineFunctionPass {
153218
// Register masks attached to the current instruction.
154219
SmallVector<const uint32_t *> RegMasks;
155220

221+
// Assign index for each instruction to quickly determine dominance.
222+
InstrPosIndexes PosIndexes;
223+
156224
void setPhysRegState(MCPhysReg PhysReg, unsigned NewState);
157225
bool isPhysRegFree(MCPhysReg PhysReg) const;
158226

@@ -339,18 +407,13 @@ int RegAllocFast::getStackSpaceFor(Register VirtReg) {
339407
return FrameIdx;
340408
}
341409

342-
static bool dominates(MachineBasicBlock &MBB,
343-
MachineBasicBlock::const_iterator A,
344-
MachineBasicBlock::const_iterator B) {
345-
auto MBBEnd = MBB.end();
346-
if (B == MBBEnd)
347-
return true;
348-
349-
MachineBasicBlock::const_iterator I = MBB.begin();
350-
for (; &*I != A && &*I != B; ++I)
351-
;
352-
353-
return &*I == A;
410+
static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A,
411+
const MachineInstr &B) {
412+
uint64_t IndexA, IndexB;
413+
PosIndexes.getIndex(A, IndexA);
414+
if (LLVM_UNLIKELY(PosIndexes.getIndex(B, IndexB)))
415+
PosIndexes.getIndex(A, IndexA);
416+
return IndexA < IndexB;
354417
}
355418

356419
/// Returns false if \p VirtReg is known to not live out of the current block.
@@ -371,7 +434,7 @@ bool RegAllocFast::mayLiveOut(Register VirtReg) {
371434
MayLiveAcrossBlocks.set(Register::virtReg2Index(VirtReg));
372435
return true;
373436
} else {
374-
if (!SelfLoopDef || dominates(*MBB, DefInst.getIterator(), SelfLoopDef))
437+
if (!SelfLoopDef || dominates(PosIndexes, DefInst, *SelfLoopDef))
375438
SelfLoopDef = &DefInst;
376439
}
377440
}
@@ -396,7 +459,7 @@ bool RegAllocFast::mayLiveOut(Register VirtReg) {
396459
// Try to handle some simple cases to avoid spilling and reloading every
397460
// value inside a self looping block.
398461
if (SelfLoopDef == &UseInst ||
399-
!dominates(*MBB, SelfLoopDef->getIterator(), UseInst.getIterator())) {
462+
!dominates(PosIndexes, *SelfLoopDef, UseInst)) {
400463
MayLiveAcrossBlocks.set(Register::virtReg2Index(VirtReg));
401464
return true;
402465
}
@@ -1570,6 +1633,7 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
15701633
this->MBB = &MBB;
15711634
LLVM_DEBUG(dbgs() << "\nAllocating " << MBB);
15721635

1636+
PosIndexes.init(MBB);
15731637
RegUnitStates.assign(TRI->getNumRegUnits(), regFree);
15741638
assert(LiveVirtRegs.empty() && "Mapping not cleared from last block?");
15751639

0 commit comments

Comments
 (0)