Skip to content

Commit a21387c

Browse files
committed
Revert "RegAllocFast: Record internal state based on register units"
This seems to have caused incorrect register allocation in some cases, breaking tests in the Zig standard library (PR47278). As discussed on the bug, revert back to green for now. > 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. This reverts commit 66251f7, and follow-ups 931a68f and 0671a4c. It also adjust some test expectations.
1 parent 6c1f2a3 commit a21387c

Some content is hidden

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

47 files changed

+2155
-2153
lines changed

llvm/lib/CodeGen/RegAllocFast.cpp

Lines changed: 135 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,13 @@ namespace {
106106
/// that it is alive across blocks.
107107
BitVector MayLiveAcrossBlocks;
108108

109-
/// State of a register unit.
110-
enum RegUnitState {
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+
111116
/// A free register is not currently in use and can be allocated
112117
/// immediately without checking aliases.
113118
regFree,
@@ -121,8 +126,8 @@ namespace {
121126
/// register. In that case, LiveVirtRegs contains the inverse mapping.
122127
};
123128

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

127132
SmallVector<Register, 16> VirtDead;
128133
SmallVector<MachineInstr *, 32> Coalesced;
@@ -184,18 +189,14 @@ namespace {
184189
bool isLastUseOfLocalReg(const MachineOperand &MO) const;
185190

186191
void addKillFlag(const LiveReg &LRI);
187-
#ifndef NDEBUG
188-
bool verifyRegStateMapping(const LiveReg &LR) const;
189-
#endif
190-
191192
void killVirtReg(LiveReg &LR);
192193
void killVirtReg(Register VirtReg);
193194
void spillVirtReg(MachineBasicBlock::iterator MI, LiveReg &LR);
194195
void spillVirtReg(MachineBasicBlock::iterator MI, Register VirtReg);
195196

196197
void usePhysReg(MachineOperand &MO);
197198
void definePhysReg(MachineBasicBlock::iterator MI, MCPhysReg PhysReg,
198-
unsigned NewState);
199+
RegState NewState);
199200
unsigned calcSpillCost(MCPhysReg PhysReg) const;
200201
void assignVirtToPhysReg(LiveReg &, MCPhysReg PhysReg);
201202

@@ -228,7 +229,7 @@ namespace {
228229
bool mayLiveOut(Register VirtReg);
229230
bool mayLiveIn(Register VirtReg);
230231

231-
void dumpState() const;
232+
void dumpState();
232233
};
233234

234235
} // end anonymous namespace
@@ -239,8 +240,7 @@ INITIALIZE_PASS(RegAllocFast, "regallocfast", "Fast Register Allocator", false,
239240
false)
240241

241242
void RegAllocFast::setPhysRegState(MCPhysReg PhysReg, unsigned NewState) {
242-
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI)
243-
RegUnitStates[*UI] = NewState;
243+
PhysRegState[PhysReg] = NewState;
244244
}
245245

246246
/// This allocates space for the specified virtual register to be held on the
@@ -384,23 +384,12 @@ void RegAllocFast::addKillFlag(const LiveReg &LR) {
384384
}
385385
}
386386

387-
#ifndef NDEBUG
388-
bool RegAllocFast::verifyRegStateMapping(const LiveReg &LR) const {
389-
for (MCRegUnitIterator UI(LR.PhysReg, TRI); UI.isValid(); ++UI) {
390-
if (RegUnitStates[*UI] != LR.VirtReg)
391-
return false;
392-
}
393-
394-
return true;
395-
}
396-
#endif
397-
398387
/// Mark virtreg as no longer available.
399388
void RegAllocFast::killVirtReg(LiveReg &LR) {
400-
assert(verifyRegStateMapping(LR) && "Broken RegState mapping");
401389
addKillFlag(LR);
402-
MCPhysReg PhysReg = LR.PhysReg;
403-
setPhysRegState(PhysReg, regFree);
390+
assert(PhysRegState[LR.PhysReg] == LR.VirtReg &&
391+
"Broken RegState mapping");
392+
setPhysRegState(LR.PhysReg, regFree);
404393
LR.PhysReg = 0;
405394
}
406395

@@ -427,17 +416,15 @@ void RegAllocFast::spillVirtReg(MachineBasicBlock::iterator MI,
427416

428417
/// Do the actual work of spilling.
429418
void RegAllocFast::spillVirtReg(MachineBasicBlock::iterator MI, LiveReg &LR) {
430-
assert(verifyRegStateMapping(LR) && "Broken RegState mapping");
431-
432-
MCPhysReg PhysReg = LR.PhysReg;
419+
assert(PhysRegState[LR.PhysReg] == LR.VirtReg && "Broken RegState mapping");
433420

434421
if (LR.Dirty) {
435422
// If this physreg is used by the instruction, we want to kill it on the
436423
// instruction, not on the spill.
437424
bool SpillKill = MachineBasicBlock::iterator(LR.LastUse) != MI;
438425
LR.Dirty = false;
439426

440-
spill(MI, LR.VirtReg, PhysReg, SpillKill);
427+
spill(MI, LR.VirtReg, LR.PhysReg, SpillKill);
441428

442429
if (SpillKill)
443430
LR.LastUse = nullptr; // Don't kill register again
@@ -473,16 +460,53 @@ void RegAllocFast::usePhysReg(MachineOperand &MO) {
473460
assert(PhysReg.isPhysical() && "Bad usePhysReg operand");
474461

475462
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+
}
476477

477-
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI) {
478-
switch (RegUnitStates[*UI]) {
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;
479484
case regReserved:
480-
RegUnitStates[*UI] = regFree;
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");
481497
LLVM_FALLTHROUGH;
482498
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);
483507
break;
484508
default:
485-
llvm_unreachable("Unexpected reg unit state");
509+
llvm_unreachable("Instruction uses an alias of an allocated register");
486510
}
487511
}
488512

@@ -495,20 +519,38 @@ void RegAllocFast::usePhysReg(MachineOperand &MO) {
495519
/// similar to defineVirtReg except the physreg is reserved instead of
496520
/// allocated.
497521
void RegAllocFast::definePhysReg(MachineBasicBlock::iterator MI,
498-
MCPhysReg PhysReg, unsigned NewState) {
499-
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI) {
500-
switch (unsigned VirtReg = RegUnitStates[*UI]) {
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;
501543
default:
502544
spillVirtReg(MI, VirtReg);
503-
break;
545+
LLVM_FALLTHROUGH;
504546
case regFree:
505547
case regReserved:
548+
setPhysRegState(Alias, regDisabled);
549+
if (TRI->isSuperRegister(PhysReg, Alias))
550+
return;
506551
break;
507552
}
508553
}
509-
510-
markRegUsedInInstr(PhysReg);
511-
setPhysRegState(PhysReg, NewState);
512554
}
513555

514556
/// Return the cost of spilling clearing out PhysReg and aliases so it is free
@@ -521,24 +563,46 @@ unsigned RegAllocFast::calcSpillCost(MCPhysReg PhysReg) const {
521563
<< " is already used in instr.\n");
522564
return spillImpossible;
523565
}
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+
}
524582

525-
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI) {
526-
switch (unsigned VirtReg = RegUnitStates[*UI]) {
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;
527591
case regFree:
592+
++Cost;
528593
break;
529594
case regReserved:
530-
LLVM_DEBUG(dbgs() << printReg(VirtReg, TRI) << " corresponding "
531-
<< printReg(PhysReg, TRI) << " is reserved already.\n");
532595
return spillImpossible;
533596
default: {
534597
LiveRegMap::const_iterator LRI = findLiveVirtReg(VirtReg);
535598
assert(LRI != LiveVirtRegs.end() && LRI->PhysReg &&
536599
"Missing VirtReg entry");
537-
return LRI->Dirty ? spillDirty : spillClean;
600+
Cost += LRI->Dirty ? spillDirty : spillClean;
601+
break;
538602
}
539603
}
540604
}
541-
return 0;
605+
return Cost;
542606
}
543607

544608
/// This method updates local state so that we know that PhysReg is the
@@ -845,17 +909,9 @@ void RegAllocFast::handleThroughOperands(MachineInstr &MI,
845909
if (!Reg || !Reg.isPhysical())
846910
continue;
847911
markRegUsedInInstr(Reg);
848-
849-
for (MCRegUnitIterator UI(Reg, TRI); UI.isValid(); ++UI) {
850-
if (!ThroughRegs.count(RegUnitStates[*UI]))
851-
continue;
852-
853-
// Need to spill any aliasing registers.
854-
for (MCRegUnitRootIterator RI(*UI, TRI); RI.isValid(); ++RI) {
855-
for (MCSuperRegIterator SI(*RI, TRI, true); SI.isValid(); ++SI) {
856-
definePhysReg(MI, *SI, regFree);
857-
}
858-
}
912+
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
913+
if (ThroughRegs.count(PhysRegState[*AI]))
914+
definePhysReg(MI, *AI, regFree);
859915
}
860916
}
861917

@@ -919,40 +975,37 @@ void RegAllocFast::handleThroughOperands(MachineInstr &MI,
919975
}
920976

921977
#ifndef NDEBUG
922-
923-
void RegAllocFast::dumpState() const {
924-
for (unsigned Unit = 1, UnitE = TRI->getNumRegUnits(); Unit != UnitE;
925-
++Unit) {
926-
switch (unsigned VirtReg = RegUnitStates[Unit]) {
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]) {
927983
case regFree:
928984
break;
929985
case regReserved:
930-
dbgs() << " " << printRegUnit(Unit, TRI) << "[P]";
986+
dbgs() << "*";
931987
break;
932988
default: {
933-
dbgs() << ' ' << printRegUnit(Unit, TRI) << '=' << printReg(VirtReg);
934-
LiveRegMap::const_iterator I = findLiveVirtReg(VirtReg);
935-
assert(I != LiveVirtRegs.end() && "have LiveVirtRegs entry");
936-
if (I->Dirty)
937-
dbgs() << "[D]";
938-
assert(TRI->hasRegUnit(I->PhysReg, Unit) && "inverse mapping present");
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");
939996
break;
940997
}
941998
}
942999
}
9431000
dbgs() << '\n';
9441001
// Check that LiveVirtRegs is the inverse.
945-
for (const LiveReg &LR : LiveVirtRegs) {
946-
Register VirtReg = LR.VirtReg;
947-
assert(VirtReg.isVirtual() && "Bad map key");
948-
MCPhysReg PhysReg = LR.PhysReg;
949-
if (PhysReg != 0) {
950-
assert(Register::isPhysicalRegister(PhysReg) &&
951-
"mapped to physreg");
952-
for (MCRegUnitIterator UI(PhysReg, TRI); UI.isValid(); ++UI) {
953-
assert(RegUnitStates[*UI] == VirtReg && "inverse map valid");
954-
}
955-
}
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");
9561009
}
9571010
}
9581011
#endif
@@ -1194,7 +1247,7 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
11941247
this->MBB = &MBB;
11951248
LLVM_DEBUG(dbgs() << "\nAllocating " << MBB);
11961249

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

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

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

Lines changed: 4 additions & 4 deletions
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 s0, h0
8-
; CHECK: fcvtzs [[REG:w[0-9]+]], s0
7+
; CHECK: fcvt s1, h0
8+
; CHECK: fcvtzs [[REG:w[0-9]+]], s1
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 s0, h0
19-
; CHECK: fcvtzu [[REG:w[0-9]+]], s0
18+
; CHECK: fcvt s1, h0
19+
; CHECK: fcvtzu [[REG:w[0-9]+]], s1
2020
; CHECK: mov w0, [[REG]]
2121
%conv = fptoui half %a to i32
2222
ret i32 %conv

0 commit comments

Comments
 (0)