Skip to content

Commit 259649a

Browse files
committed
[RDA] Avoid full reprocessing of blocks in loops (NFCI)
RDA sometimes needs to visit blocks twice, to take into account reaching defs coming in along loop back edges. Currently it handles repeated visitation the same way as usual, which means that it will scan through all instructions and their reg unit defs again. Not only is this very inefficient, it also means that all reaching defs in loops are going to be inserted twice. We can do much better than this. The only thing we need to handle is a new reaching def from a predecessor, which either needs to be prepended to the reaching definitions (if there was no reaching def from a predecessor), or needs to replace an existing predecessor reaching def, if it is more recent. Since D77508 we only store the most recent predecessor reaching def, so that's the only one that may need updating. This also has the nice side-effect that reaching definitions are now automatically sorted and unique, so drop the llvm::sort() call in favor of an assertion. Differential Revision: https://reviews.llvm.org/D77511
1 parent 76e987b commit 259649a

File tree

2 files changed

+65
-3
lines changed

2 files changed

+65
-3
lines changed

llvm/include/llvm/CodeGen/ReachingDefAnalysis.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ class ReachingDefAnalysis : public MachineFunctionPass {
207207
/// Process he given basic block.
208208
void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
209209

210+
/// Process block that is part of a loop again.
211+
void reprocessBasicBlock(MachineBasicBlock *MBB);
212+
210213
/// Update def-ages for registers defined by MI.
211214
/// Also break dependencies on partial defs and undef uses.
212215
void processDefs(MachineInstr *);

llvm/lib/CodeGen/ReachingDefAnalysis.cpp

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,65 @@ void ReachingDefAnalysis::processDefs(MachineInstr *MI) {
137137
++CurInstr;
138138
}
139139

140+
void ReachingDefAnalysis::reprocessBasicBlock(MachineBasicBlock *MBB) {
141+
unsigned MBBNumber = MBB->getNumber();
142+
assert(MBBNumber < MBBReachingDefs.size() &&
143+
"Unexpected basic block number.");
144+
145+
// Count number of non-debug instructions for end of block adjustment.
146+
int NumInsts = 0;
147+
for (const MachineInstr &MI : *MBB)
148+
if (!MI.isDebugInstr())
149+
NumInsts++;
150+
151+
// When reprocessing a block, the only thing we need to do is check whether
152+
// there is now a more recent incoming reaching definition from a predecessor.
153+
for (MachineBasicBlock *pred : MBB->predecessors()) {
154+
assert(unsigned(pred->getNumber()) < MBBOutRegsInfos.size() &&
155+
"Should have pre-allocated MBBInfos for all MBBs");
156+
const LiveRegsDefInfo &Incoming = MBBOutRegsInfos[pred->getNumber()];
157+
// Incoming may be empty for dead predecessors.
158+
if (Incoming.empty())
159+
continue;
160+
161+
for (unsigned Unit = 0; Unit != NumRegUnits; ++Unit) {
162+
int Def = Incoming[Unit];
163+
if (Def == ReachingDefDefaultVal)
164+
continue;
165+
166+
auto Start = MBBReachingDefs[MBBNumber][Unit].begin();
167+
if (Start != MBBReachingDefs[MBBNumber][Unit].end() && *Start < 0) {
168+
if (*Start >= Def)
169+
continue;
170+
171+
// Update existing reaching def from predecessor to a more recent one.
172+
*Start = Def;
173+
} else {
174+
// Insert new reaching def from predecessor.
175+
MBBReachingDefs[MBBNumber][Unit].insert(Start, Def);
176+
}
177+
178+
// Update reaching def at end of of BB. Keep in mind that these are
179+
// adjusted relative to the end of the basic block.
180+
if (MBBOutRegsInfos[MBBNumber][Unit] < Def - NumInsts)
181+
MBBOutRegsInfos[MBBNumber][Unit] = Def - NumInsts;
182+
}
183+
}
184+
}
185+
140186
void ReachingDefAnalysis::processBasicBlock(
141187
const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
142188
MachineBasicBlock *MBB = TraversedMBB.MBB;
143189
LLVM_DEBUG(dbgs() << printMBBReference(*MBB)
144190
<< (!TraversedMBB.IsDone ? ": incomplete\n"
145191
: ": all preds known\n"));
146192

193+
if (!TraversedMBB.PrimaryPass) {
194+
// Reprocess MBB that is part of a loop.
195+
reprocessBasicBlock(MBB);
196+
return;
197+
}
198+
147199
enterBasicBlock(MBB);
148200
for (MachineInstr &MI : *MBB) {
149201
if (!MI.isDebugInstr())
@@ -188,11 +240,18 @@ void ReachingDefAnalysis::traverse() {
188240
// Traverse the basic blocks.
189241
for (LoopTraversal::TraversedMBBInfo TraversedMBB : TraversedMBBOrder)
190242
processBasicBlock(TraversedMBB);
191-
// Sorting all reaching defs found for a ceartin reg unit in a given BB.
243+
#ifndef NDEBUG
244+
// Make sure reaching defs are sorted and unique.
192245
for (MBBDefsInfo &MBBDefs : MBBReachingDefs) {
193-
for (MBBRegUnitDefs &RegUnitDefs : MBBDefs)
194-
llvm::sort(RegUnitDefs);
246+
for (MBBRegUnitDefs &RegUnitDefs : MBBDefs) {
247+
int LastDef = ReachingDefDefaultVal;
248+
for (int Def : RegUnitDefs) {
249+
assert(Def > LastDef && "Defs must be sorted and unique");
250+
LastDef = Def;
251+
}
252+
}
195253
}
254+
#endif
196255
}
197256

198257
int ReachingDefAnalysis::getReachingDef(MachineInstr *MI, int PhysReg) const {

0 commit comments

Comments
 (0)