Simplify the handling of physreg defs and uses in RegAllocFast.

This adds extra security against using clobbered physregs, and it adds kill
markers to physreg uses.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103784 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2010-05-14 18:03:25 +00:00
parent effc8c5269
commit 4ed1082683
2 changed files with 74 additions and 111 deletions

View File

@ -135,9 +135,10 @@ namespace {
LiveRegMap::iterator i, bool isKill);
void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
unsigned VirtReg, bool isKill);
void killPhysReg(unsigned PhysReg);
void spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I,
unsigned PhysReg, bool isKill);
void usePhysReg(MachineOperand&);
void definePhysReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned PhysReg, RegState NewState);
LiveRegMap::iterator assignVirtToPhysReg(unsigned VirtReg,
unsigned PhysReg);
LiveRegMap::iterator allocVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
@ -146,8 +147,6 @@ namespace {
unsigned OpNum, unsigned VirtReg, unsigned Hint);
unsigned reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned OpNum, unsigned VirtReg, unsigned Hint);
void reservePhysReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned PhysReg);
void spillAll(MachineBasicBlock &MBB, MachineInstr *MI);
void setPhysReg(MachineOperand &MO, unsigned PhysReg);
};
@ -264,75 +263,106 @@ void RAFast::spillAll(MachineBasicBlock &MBB, MachineInstr *MI) {
spillVirtReg(MBB, MI, Dirty[i], false);
}
/// killPhysReg - Kill any virtual register aliased by PhysReg.
void RAFast::killPhysReg(unsigned PhysReg) {
// Fast path for the normal case.
switch (unsigned VirtReg = PhysRegState[PhysReg]) {
/// usePhysReg - Handle the direct use of a physical register.
/// Check that the register is not used by a virtreg.
/// Kill the physreg, marking it free.
/// This may add implicit kills to MO->getParent() and invalidate MO.
void RAFast::usePhysReg(MachineOperand &MO) {
unsigned PhysReg = MO.getReg();
assert(TargetRegisterInfo::isPhysicalRegister(PhysReg) &&
"Bad usePhysReg operand");
switch (PhysRegState[PhysReg]) {
case regDisabled:
break;
case regFree:
return;
case regReserved:
PhysRegState[PhysReg] = regFree;
// Fall through
case regFree:
UsedInInstr.set(PhysReg);
MO.setIsKill();
return;
default:
killVirtReg(VirtReg);
return;
// The physreg was allocated to a virtual register. That means to value we
// wanted has been clobbered.
llvm_unreachable("Instruction uses an allocated register");
}
// This is a disabled register, we have to check aliases.
// Maybe a superregister is reserved?
for (const unsigned *AS = TRI->getAliasSet(PhysReg);
unsigned Alias = *AS; ++AS) {
switch (unsigned VirtReg = PhysRegState[Alias]) {
switch (PhysRegState[Alias]) {
case regDisabled:
case regFree:
break;
case regReserved:
assert(TRI->isSuperRegister(PhysReg, Alias) &&
"Instruction is not using a subregister of a reserved register");
// Leave the superregister in the working set.
PhysRegState[Alias] = regFree;
UsedInInstr.set(Alias);
MO.getParent()->addRegisterKilled(Alias, TRI, true);
return;
case regFree:
if (TRI->isSuperRegister(PhysReg, Alias)) {
// Leave the superregister in the working set.
UsedInInstr.set(Alias);
MO.getParent()->addRegisterKilled(Alias, TRI, true);
return;
}
// Some other alias was in the working set - clear it.
PhysRegState[Alias] = regDisabled;
break;
default:
killVirtReg(VirtReg);
break;
llvm_unreachable("Instruction uses an alias of an allocated register");
}
}
// All aliases are disabled, bring register into working set.
PhysRegState[PhysReg] = regFree;
UsedInInstr.set(PhysReg);
MO.setIsKill();
}
/// spillPhysReg - Spill any dirty virtual registers that aliases PhysReg. If
/// isKill is set, they are also killed.
void RAFast::spillPhysReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned PhysReg, bool isKill) {
/// definePhysReg - Mark PhysReg as reserved or free after spilling any
/// virtregs. This is very similar to defineVirtReg except the physreg is
/// reserved instead of allocated.
void RAFast::definePhysReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned PhysReg, RegState NewState) {
UsedInInstr.set(PhysReg);
switch (unsigned VirtReg = PhysRegState[PhysReg]) {
case regDisabled:
break;
case regFree:
return;
case regReserved:
if (isKill)
PhysRegState[PhysReg] = regFree;
return;
default:
spillVirtReg(MBB, MI, VirtReg, isKill);
spillVirtReg(MBB, MI, VirtReg, true);
// Fall through.
case regFree:
case regReserved:
PhysRegState[PhysReg] = NewState;
return;
}
// This is a disabled register, we have to check aliases.
// This is a disabled register, disable all aliases.
PhysRegState[PhysReg] = NewState;
for (const unsigned *AS = TRI->getAliasSet(PhysReg);
unsigned Alias = *AS; ++AS) {
UsedInInstr.set(Alias);
switch (unsigned VirtReg = PhysRegState[Alias]) {
case regDisabled:
case regFree:
break;
case regReserved:
if (isKill)
PhysRegState[Alias] = regFree;
break;
default:
spillVirtReg(MBB, MI, VirtReg, isKill);
spillVirtReg(MBB, MI, VirtReg, true);
// Fall through.
case regFree:
case regReserved:
PhysRegState[Alias] = regDisabled;
if (TRI->isSuperRegister(PhysReg, Alias))
return;
break;
}
}
}
/// assignVirtToPhysReg - This method updates local state so that we know
/// that PhysReg is the proper container for VirtReg now. The physical
/// register must not be used for anything else when this is called.
@ -538,47 +568,6 @@ unsigned RAFast::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
return LR.PhysReg;
}
/// reservePhysReg - Mark PhysReg as reserved. This is very similar to
/// defineVirtReg except the physreg is reserved instead of allocated.
void RAFast::reservePhysReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned PhysReg) {
UsedInInstr.set(PhysReg);
switch (unsigned VirtReg = PhysRegState[PhysReg]) {
case regDisabled:
break;
case regFree:
PhysRegState[PhysReg] = regReserved;
return;
case regReserved:
return;
default:
spillVirtReg(MBB, MI, VirtReg, true);
PhysRegState[PhysReg] = regReserved;
return;
}
// This is a disabled register, disable all aliases.
for (const unsigned *AS = TRI->getAliasSet(PhysReg);
unsigned Alias = *AS; ++AS) {
UsedInInstr.set(Alias);
switch (unsigned VirtReg = PhysRegState[Alias]) {
case regDisabled:
case regFree:
break;
case regReserved:
// is a super register already reserved?
if (TRI->isSuperRegister(PhysReg, Alias))
return;
break;
default:
spillVirtReg(MBB, MI, VirtReg, true);
break;
}
PhysRegState[Alias] = regDisabled;
}
PhysRegState[PhysReg] = regReserved;
}
// setPhysReg - Change MO the refer the PhysReg, considering subregs.
void RAFast::setPhysReg(MachineOperand &MO, unsigned PhysReg) {
if (unsigned Idx = MO.getSubReg()) {
@ -600,9 +589,9 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
// Add live-in registers as live.
for (MachineBasicBlock::livein_iterator I = MBB.livein_begin(),
E = MBB.livein_end(); I != E; ++I)
reservePhysReg(MBB, MII, *I);
definePhysReg(MBB, MII, *I, regReserved);
SmallVector<unsigned, 8> VirtKills, PhysKills, PhysDefs;
SmallVector<unsigned, 8> VirtKills, PhysDefs;
SmallVector<MachineInstr*, 32> Coalesced;
// Otherwise, sequentially allocate each instruction in the MBB.
@ -670,7 +659,6 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
// First scan.
// Mark physreg uses and early clobbers as used.
// Collect PhysKills.
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg()) continue;
@ -678,25 +666,14 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg) ||
ReservedRegs.test(Reg)) continue;
if (MO.isUse()) {
#ifndef NDEBUG
// We are using a physreg directly. It had better not be clobbered by a
// virtreg.
assert(PhysRegState[Reg] <= regReserved && "Using clobbered physreg");
if (PhysRegState[Reg] == regDisabled)
for (const unsigned *AS = TRI->getAliasSet(Reg);
unsigned Alias = *AS; ++AS)
assert(PhysRegState[Alias] <= regReserved &&
"Physreg alias was clobbered");
#endif
PhysKills.push_back(Reg); // Any clean physreg use is a kill.
UsedInInstr.set(Reg);
usePhysReg(MO);
} else if (MO.isEarlyClobber()) {
spillPhysReg(MBB, MI, Reg, true);
UsedInInstr.set(Reg);
definePhysReg(MBB, MI, Reg, MO.isDead() ? regFree : regReserved);
PhysDefs.push_back(Reg);
}
}
// Second scan.
// Allocate virtreg uses and early clobbers.
// Collect VirtKills
@ -723,11 +700,6 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
killVirtReg(VirtKills[i]);
VirtKills.clear();
// Process physreg kills
for (unsigned i = 0, e = PhysKills.size(); i != e; ++i)
killPhysReg(PhysKills[i]);
PhysKills.clear();
MRI->addPhysRegsUsed(UsedInInstr);
// Track registers defined by instruction - early clobbers at this point.
@ -749,12 +721,8 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
if (ReservedRegs.test(Reg)) continue;
if (MO.isImplicit())
spillPhysReg(MBB, MI, Reg, true);
else
reservePhysReg(MBB, MI, Reg);
if (MO.isDead())
PhysKills.push_back(Reg);
definePhysReg(MBB, MI, Reg, (MO.isImplicit() || MO.isDead()) ?
regFree : regReserved);
continue;
}
unsigned PhysReg = defineVirtReg(MBB, MI, i, Reg, CopySrc);
@ -777,11 +745,6 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
killVirtReg(VirtKills[i]);
VirtKills.clear();
// Process physreg deads.
for (unsigned i = 0, e = PhysKills.size(); i != e; ++i)
killPhysReg(PhysKills[i]);
PhysKills.clear();
MRI->addPhysRegsUsed(UsedInInstr);
if (CopyDst && CopyDst == CopySrc && CopyDstSub == CopySrcSub) {

View File

@ -1,6 +1,6 @@
; RUN: llc < %s -march=x86 | grep "#%ebp %esi %edi 8(%edx) %eax (%ebx)"
; RUN: llc < %s -march=x86 -regalloc=local | grep "#%edi %ebp %edx 8(%ebx) %eax (%esi)"
; RUN: llc < %s -march=x86 -regalloc=fast | grep "#%ecx %ebx %edx 8(%edi) %eax (%esi)"
; RUN: llc < %s -march=x86 -regalloc=fast | grep "#%edi %ebp %edx 8(%ebx) %eax (%esi)"
; The 1st, 2nd, 3rd and 5th registers above must all be different. The registers
; referenced in the 4th and 6th operands must not be the same as the 1st or 5th