Skip to content

Commit 66251f7

Browse files
committed
RegAllocFast: Record internal state based on register units
Record internal state based on register units. This is often more efficient as there are typically fewer register units to update compared to iterating over all the aliases of a register. Original patch by Matthias Braun, but I've been rebasing and fixing it for almost 2 years and fixed a few bugs causing intermediate failures to make this patch independent of the changes in https://reviews.llvm.org/D52010.
1 parent a574edb commit 66251f7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2000
-2011
lines changed

llvm/lib/CodeGen/RegAllocFast.cpp

+87-135
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,8 @@ namespace {
106106
/// that it is alive across blocks.
107107
BitVector MayLiveAcrossBlocks;
108108

109-
/// State of a physical register.
110-
enum RegState {
111-
/// A disabled register is not available for allocation, but an alias may
112-
/// be in use. A register can only be moved out of the disabled state if
113-
/// all aliases are disabled.
114-
regDisabled,
115-
109+
/// State of a register unit.
110+
enum RegUnitState {
116111
/// A free register is not currently in use and can be allocated
117112
/// immediately without checking aliases.
118113
regFree,
@@ -126,8 +121,8 @@ namespace {
126121
/// register. In that case, LiveVirtRegs contains the inverse mapping.
127122
};
128123

129-
/// Maps each physical register to a RegState enum or a virtual register.
130-
std::vector<unsigned> PhysRegState;
124+
/// Maps each physical register to a RegUnitState enum or virtual register.
125+
std::vector<unsigned> RegUnitStates;
131126

132127
SmallVector<Register, 16> VirtDead;
133128
SmallVector<MachineInstr *, 32> Coalesced;
@@ -138,6 +133,7 @@ namespace {
138133
RegUnitSet UsedInInstr;
139134

140135
void setPhysRegState(MCPhysReg PhysReg, unsigned NewState);
136+
bool isPhysRegFree(MCPhysReg PhysReg) const;
141137

142138
/// Mark a physreg as used in this instruction.
143139
void markRegUsedInInstr(MCPhysReg PhysReg) {
@@ -189,14 +185,15 @@ namespace {
189185
bool isLastUseOfLocalReg(const MachineOperand &MO) const;
190186

191187
void addKillFlag(const LiveReg &LRI);
188+
bool verifyRegStateMapping(const LiveReg &LR) const;
192189
void killVirtReg(LiveReg &LR);
193190
void killVirtReg(Register VirtReg);
194191
void spillVirtReg(MachineBasicBlock::iterator MI, LiveReg &LR);
195192
void spillVirtReg(MachineBasicBlock::iterator MI, Register VirtReg);
196193

197194
void usePhysReg(MachineOperand &MO);
198195
void definePhysReg(MachineBasicBlock::iterator MI, MCPhysReg PhysReg,
199-
RegState NewState);
196+
unsigned NewState);
200197
unsigned calcSpillCost(MCPhysReg PhysReg) const;
201198
void assignVirtToPhysReg(LiveReg &, MCPhysReg PhysReg);
202199

@@ -229,7 +226,8 @@ namespace {
229226
bool mayLiveOut(Register VirtReg);
230227
bool mayLiveIn(Register VirtReg);
231228

232-
void dumpState();
229+
void printRegUnitState(unsigned State) const;
230+
void dumpState() const;
233231
};
234232

235233
} // end anonymous namespace
@@ -240,7 +238,16 @@ INITIALIZE_PASS(RegAllocFast, "regallocfast", "Fast Register Allocator", false,
240238
false)
241239

242240
void RegAllocFast::setPhysRegState(MCPhysReg PhysReg, unsigned NewState) {
243-
PhysRegState[PhysReg] = NewState;
241+
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI)
242+
RegUnitStates[*UI] = NewState;
243+
}
244+
245+
bool RegAllocFast::isPhysRegFree(MCPhysReg PhysReg) const {
246+
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI) {
247+
if (RegUnitStates[*UI] != regFree)
248+
return false;
249+
}
250+
return true;
244251
}
245252

246253
/// This allocates space for the specified virtual register to be held on the
@@ -384,12 +391,21 @@ void RegAllocFast::addKillFlag(const LiveReg &LR) {
384391
}
385392
}
386393

394+
bool RegAllocFast::verifyRegStateMapping(const LiveReg &LR) const {
395+
for (MCRegUnitIterator UI(LR.PhysReg, TRI); UI.isValid(); ++UI) {
396+
if (RegUnitStates[*UI] != LR.VirtReg)
397+
return false;
398+
}
399+
400+
return true;
401+
}
402+
387403
/// Mark virtreg as no longer available.
388404
void RegAllocFast::killVirtReg(LiveReg &LR) {
405+
assert(verifyRegStateMapping(LR) && "Broken RegState mapping");
389406
addKillFlag(LR);
390-
assert(PhysRegState[LR.PhysReg] == LR.VirtReg &&
391-
"Broken RegState mapping");
392-
setPhysRegState(LR.PhysReg, regFree);
407+
MCPhysReg PhysReg = LR.PhysReg;
408+
setPhysRegState(PhysReg, regFree);
393409
LR.PhysReg = 0;
394410
}
395411

@@ -416,15 +432,17 @@ void RegAllocFast::spillVirtReg(MachineBasicBlock::iterator MI,
416432

417433
/// Do the actual work of spilling.
418434
void RegAllocFast::spillVirtReg(MachineBasicBlock::iterator MI, LiveReg &LR) {
419-
assert(PhysRegState[LR.PhysReg] == LR.VirtReg && "Broken RegState mapping");
435+
assert(verifyRegStateMapping(LR) && "Broken RegState mapping");
436+
437+
MCPhysReg PhysReg = LR.PhysReg;
420438

421439
if (LR.Dirty) {
422440
// If this physreg is used by the instruction, we want to kill it on the
423441
// instruction, not on the spill.
424442
bool SpillKill = MachineBasicBlock::iterator(LR.LastUse) != MI;
425443
LR.Dirty = false;
426444

427-
spill(MI, LR.VirtReg, LR.PhysReg, SpillKill);
445+
spill(MI, LR.VirtReg, PhysReg, SpillKill);
428446

429447
if (SpillKill)
430448
LR.LastUse = nullptr; // Don't kill register again
@@ -460,53 +478,16 @@ void RegAllocFast::usePhysReg(MachineOperand &MO) {
460478
assert(PhysReg.isPhysical() && "Bad usePhysReg operand");
461479

462480
markRegUsedInInstr(PhysReg);
463-
switch (PhysRegState[PhysReg]) {
464-
case regDisabled:
465-
break;
466-
case regReserved:
467-
PhysRegState[PhysReg] = regFree;
468-
LLVM_FALLTHROUGH;
469-
case regFree:
470-
MO.setIsKill();
471-
return;
472-
default:
473-
// The physreg was allocated to a virtual register. That means the value we
474-
// wanted has been clobbered.
475-
llvm_unreachable("Instruction uses an allocated register");
476-
}
477481

478-
// Maybe a superregister is reserved?
479-
for (MCRegAliasIterator AI(PhysReg, TRI, false); AI.isValid(); ++AI) {
480-
MCPhysReg Alias = *AI;
481-
switch (PhysRegState[Alias]) {
482-
case regDisabled:
483-
break;
482+
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI) {
483+
switch (RegUnitStates[*UI]) {
484484
case regReserved:
485-
// Either PhysReg is a subregister of Alias and we mark the
486-
// whole register as free, or PhysReg is the superregister of
487-
// Alias and we mark all the aliases as disabled before freeing
488-
// PhysReg.
489-
// In the latter case, since PhysReg was disabled, this means that
490-
// its value is defined only by physical sub-registers. This check
491-
// is performed by the assert of the default case in this loop.
492-
// Note: The value of the superregister may only be partial
493-
// defined, that is why regDisabled is a valid state for aliases.
494-
assert((TRI->isSuperRegister(PhysReg, Alias) ||
495-
TRI->isSuperRegister(Alias, PhysReg)) &&
496-
"Instruction is not using a subregister of a reserved register");
485+
RegUnitStates[*UI] = regFree;
497486
LLVM_FALLTHROUGH;
498487
case regFree:
499-
if (TRI->isSuperRegister(PhysReg, Alias)) {
500-
// Leave the superregister in the working set.
501-
setPhysRegState(Alias, regFree);
502-
MO.getParent()->addRegisterKilled(Alias, TRI, true);
503-
return;
504-
}
505-
// Some other alias was in the working set - clear it.
506-
setPhysRegState(Alias, regDisabled);
507488
break;
508489
default:
509-
llvm_unreachable("Instruction uses an alias of an allocated register");
490+
llvm_unreachable("Unexpected reg unit state");
510491
}
511492
}
512493

@@ -519,38 +500,20 @@ void RegAllocFast::usePhysReg(MachineOperand &MO) {
519500
/// similar to defineVirtReg except the physreg is reserved instead of
520501
/// allocated.
521502
void RegAllocFast::definePhysReg(MachineBasicBlock::iterator MI,
522-
MCPhysReg PhysReg, RegState NewState) {
523-
markRegUsedInInstr(PhysReg);
524-
switch (Register VirtReg = PhysRegState[PhysReg]) {
525-
case regDisabled:
526-
break;
527-
default:
528-
spillVirtReg(MI, VirtReg);
529-
LLVM_FALLTHROUGH;
530-
case regFree:
531-
case regReserved:
532-
setPhysRegState(PhysReg, NewState);
533-
return;
534-
}
535-
536-
// This is a disabled register, disable all aliases.
537-
setPhysRegState(PhysReg, NewState);
538-
for (MCRegAliasIterator AI(PhysReg, TRI, false); AI.isValid(); ++AI) {
539-
MCPhysReg Alias = *AI;
540-
switch (Register VirtReg = PhysRegState[Alias]) {
541-
case regDisabled:
542-
break;
503+
MCPhysReg PhysReg, unsigned NewState) {
504+
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI) {
505+
switch (unsigned VirtReg = RegUnitStates[*UI]) {
543506
default:
544507
spillVirtReg(MI, VirtReg);
545-
LLVM_FALLTHROUGH;
508+
break;
546509
case regFree:
547510
case regReserved:
548-
setPhysRegState(Alias, regDisabled);
549-
if (TRI->isSuperRegister(PhysReg, Alias))
550-
return;
551511
break;
552512
}
553513
}
514+
515+
markRegUsedInInstr(PhysReg);
516+
setPhysRegState(PhysReg, NewState);
554517
}
555518

556519
/// Return the cost of spilling clearing out PhysReg and aliases so it is free
@@ -563,46 +526,24 @@ unsigned RegAllocFast::calcSpillCost(MCPhysReg PhysReg) const {
563526
<< " is already used in instr.\n");
564527
return spillImpossible;
565528
}
566-
switch (Register VirtReg = PhysRegState[PhysReg]) {
567-
case regDisabled:
568-
break;
569-
case regFree:
570-
return 0;
571-
case regReserved:
572-
LLVM_DEBUG(dbgs() << printReg(VirtReg, TRI) << " corresponding "
573-
<< printReg(PhysReg, TRI) << " is reserved already.\n");
574-
return spillImpossible;
575-
default: {
576-
LiveRegMap::const_iterator LRI = findLiveVirtReg(VirtReg);
577-
assert(LRI != LiveVirtRegs.end() && LRI->PhysReg &&
578-
"Missing VirtReg entry");
579-
return LRI->Dirty ? spillDirty : spillClean;
580-
}
581-
}
582529

583-
// This is a disabled register, add up cost of aliases.
584-
LLVM_DEBUG(dbgs() << printReg(PhysReg, TRI) << " is disabled.\n");
585-
unsigned Cost = 0;
586-
for (MCRegAliasIterator AI(PhysReg, TRI, false); AI.isValid(); ++AI) {
587-
MCPhysReg Alias = *AI;
588-
switch (Register VirtReg = PhysRegState[Alias]) {
589-
case regDisabled:
590-
break;
530+
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI) {
531+
switch (unsigned VirtReg = RegUnitStates[*UI]) {
591532
case regFree:
592-
++Cost;
593533
break;
594534
case regReserved:
535+
LLVM_DEBUG(dbgs() << printReg(VirtReg, TRI) << " corresponding "
536+
<< printReg(PhysReg, TRI) << " is reserved already.\n");
595537
return spillImpossible;
596538
default: {
597539
LiveRegMap::const_iterator LRI = findLiveVirtReg(VirtReg);
598540
assert(LRI != LiveVirtRegs.end() && LRI->PhysReg &&
599541
"Missing VirtReg entry");
600-
Cost += LRI->Dirty ? spillDirty : spillClean;
601-
break;
542+
return LRI->Dirty ? spillDirty : spillClean;
602543
}
603544
}
604545
}
605-
return Cost;
546+
return 0;
606547
}
607548

608549
/// This method updates local state so that we know that PhysReg is the
@@ -909,9 +850,17 @@ void RegAllocFast::handleThroughOperands(MachineInstr &MI,
909850
if (!Reg || !Reg.isPhysical())
910851
continue;
911852
markRegUsedInInstr(Reg);
912-
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
913-
if (ThroughRegs.count(PhysRegState[*AI]))
914-
definePhysReg(MI, *AI, regFree);
853+
854+
for (MCRegUnitIterator UI(Reg, TRI); UI.isValid(); ++UI) {
855+
if (!ThroughRegs.count(RegUnitStates[*UI]))
856+
continue;
857+
858+
// Need to spill any aliasing registers.
859+
for (MCRegUnitRootIterator RI(*UI, TRI); RI.isValid(); ++RI) {
860+
for (MCSuperRegIterator SI(*RI, TRI, true); SI.isValid(); ++SI) {
861+
definePhysReg(MI, *SI, regFree);
862+
}
863+
}
915864
}
916865
}
917866

@@ -975,37 +924,40 @@ void RegAllocFast::handleThroughOperands(MachineInstr &MI,
975924
}
976925

977926
#ifndef NDEBUG
978-
void RegAllocFast::dumpState() {
979-
for (unsigned Reg = 1, E = TRI->getNumRegs(); Reg != E; ++Reg) {
980-
if (PhysRegState[Reg] == regDisabled) continue;
981-
dbgs() << " " << printReg(Reg, TRI);
982-
switch(PhysRegState[Reg]) {
927+
928+
void RegAllocFast::dumpState() const {
929+
for (unsigned Unit = 1, UnitE = TRI->getNumRegUnits(); Unit != UnitE;
930+
++Unit) {
931+
switch (unsigned VirtReg = RegUnitStates[Unit]) {
983932
case regFree:
984933
break;
985934
case regReserved:
986-
dbgs() << "*";
935+
dbgs() << " " << printRegUnit(Unit, TRI) << "[P]";
987936
break;
988937
default: {
989-
dbgs() << '=' << printReg(PhysRegState[Reg]);
990-
LiveRegMap::iterator LRI = findLiveVirtReg(PhysRegState[Reg]);
991-
assert(LRI != LiveVirtRegs.end() && LRI->PhysReg &&
992-
"Missing VirtReg entry");
993-
if (LRI->Dirty)
994-
dbgs() << "*";
995-
assert(LRI->PhysReg == Reg && "Bad inverse map");
938+
dbgs() << ' ' << printRegUnit(Unit, TRI) << '=' << printReg(VirtReg);
939+
LiveRegMap::const_iterator I = findLiveVirtReg(VirtReg);
940+
assert(I != LiveVirtRegs.end() && "have LiveVirtRegs entry");
941+
if (I->Dirty)
942+
dbgs() << "[D]";
943+
assert(TRI->hasRegUnit(I->PhysReg, Unit) && "inverse mapping present");
996944
break;
997945
}
998946
}
999947
}
1000948
dbgs() << '\n';
1001949
// Check that LiveVirtRegs is the inverse.
1002-
for (LiveRegMap::iterator i = LiveVirtRegs.begin(),
1003-
e = LiveVirtRegs.end(); i != e; ++i) {
1004-
if (!i->PhysReg)
1005-
continue;
1006-
assert(i->VirtReg.isVirtual() && "Bad map key");
1007-
assert(Register::isPhysicalRegister(i->PhysReg) && "Bad map value");
1008-
assert(PhysRegState[i->PhysReg] == i->VirtReg && "Bad inverse map");
950+
for (const LiveReg &LR : LiveVirtRegs) {
951+
Register VirtReg = LR.VirtReg;
952+
assert(VirtReg.isVirtual() && "Bad map key");
953+
MCPhysReg PhysReg = LR.PhysReg;
954+
if (PhysReg != 0) {
955+
assert(Register::isPhysicalRegister(PhysReg) &&
956+
"mapped to physreg");
957+
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI) {
958+
assert(RegUnitStates[*UI] == VirtReg && "inverse map valid");
959+
}
960+
}
1009961
}
1010962
}
1011963
#endif
@@ -1247,7 +1199,7 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
12471199
this->MBB = &MBB;
12481200
LLVM_DEBUG(dbgs() << "\nAllocating " << MBB);
12491201

1250-
PhysRegState.assign(TRI->getNumRegs(), regDisabled);
1202+
RegUnitStates.assign(TRI->getNumRegUnits(), regFree);
12511203
assert(LiveVirtRegs.empty() && "Mapping not cleared from last block?");
12521204

12531205
MachineBasicBlock::iterator MII = MBB.begin();

llvm/test/CodeGen/AArch64/arm64-fast-isel-conversion-fallback.ll

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
define i32 @fptosi_wh(half %a) nounwind ssp {
55
entry:
66
; CHECK-LABEL: fptosi_wh
7-
; CHECK: fcvt s1, h0
8-
; CHECK: fcvtzs [[REG:w[0-9]+]], s1
7+
; CHECK: fcvt s0, h0
8+
; CHECK: fcvtzs [[REG:w[0-9]+]], s0
99
; CHECK: mov w0, [[REG]]
1010
%conv = fptosi half %a to i32
1111
ret i32 %conv
@@ -15,8 +15,8 @@ entry:
1515
define i32 @fptoui_swh(half %a) nounwind ssp {
1616
entry:
1717
; CHECK-LABEL: fptoui_swh
18-
; CHECK: fcvt s1, h0
19-
; CHECK: fcvtzu [[REG:w[0-9]+]], s1
18+
; CHECK: fcvt s0, h0
19+
; CHECK: fcvtzu [[REG:w[0-9]+]], s0
2020
; CHECK: mov w0, [[REG]]
2121
%conv = fptoui half %a to i32
2222
ret i32 %conv

0 commit comments

Comments
 (0)