Take allocation hints from copy instructions to/from physregs.

This causes way more identity copies to be generated, ripe for coalescing.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103686 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2010-05-13 00:19:43 +00:00
parent 63e34f690c
commit 4bf4bafcce
3 changed files with 71 additions and 21 deletions

View File

@ -49,6 +49,7 @@ namespace {
private:
const TargetMachine *TM;
MachineFunction *MF;
MachineRegisterInfo *MRI;
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
@ -132,11 +133,11 @@ namespace {
LiveRegMap::iterator assignVirtToPhysReg(unsigned VirtReg,
unsigned PhysReg);
LiveRegMap::iterator allocVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned VirtReg);
unsigned VirtReg, unsigned Hint);
unsigned defineVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned OpNum, unsigned VirtReg);
unsigned OpNum, unsigned VirtReg, unsigned Hint);
unsigned reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned OpNum, unsigned VirtReg);
unsigned OpNum, unsigned VirtReg, unsigned Hint);
void reservePhysReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned PhysReg);
void spillAll(MachineBasicBlock &MBB, MachineInstr *MI);
@ -216,7 +217,7 @@ void RAFast::spillVirtReg(MachineBasicBlock &MBB,
LR.Dirty = false;
DEBUG(dbgs() << " Spilling register " << TRI->getName(LR.PhysReg)
<< " containing %reg" << VirtReg);
const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg);
const TargetRegisterClass *RC = MRI->getRegClass(VirtReg);
int FrameIndex = getStackSpaceFor(VirtReg, RC);
DEBUG(dbgs() << " to stack slot #" << FrameIndex << "\n");
TII->storeRegToStackSlot(MBB, MI, LR.PhysReg, spillKill,
@ -331,15 +332,52 @@ RAFast::assignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg) {
/// allocVirtReg - Allocate a physical register for VirtReg.
RAFast::LiveRegMap::iterator RAFast::allocVirtReg(MachineBasicBlock &MBB,
MachineInstr *MI,
unsigned VirtReg) {
unsigned VirtReg,
unsigned Hint) {
const unsigned spillCost = 100;
assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
"Can only allocate virtual registers");
const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg);
const TargetRegisterClass *RC = MRI->getRegClass(VirtReg);
TargetRegisterClass::iterator AOB = RC->allocation_order_begin(*MF);
TargetRegisterClass::iterator AOE = RC->allocation_order_end(*MF);
// Ignore invalid hints.
if (Hint && (!TargetRegisterInfo::isPhysicalRegister(Hint) ||
!RC->contains(Hint) || UsedInInstr.test(Hint)))
Hint = 0;
// If there is no hint, peek at the first use of this register.
if (!Hint && !MRI->use_nodbg_empty(VirtReg)) {
MachineInstr &MI = *MRI->use_nodbg_begin(VirtReg);
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
// Copy to physreg -> use physreg as hint.
if (TII->isMoveInstr(MI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
SrcReg == VirtReg && TargetRegisterInfo::isPhysicalRegister(DstReg) &&
RC->contains(DstReg) && !UsedInInstr.test(DstReg)) {
Hint = DstReg;
DEBUG(dbgs() << " %reg" << VirtReg << " gets hint from " << MI);
}
}
// Take hint when possible.
if (Hint) {
assert(RC->contains(Hint) && !UsedInInstr.test(Hint) &&
"Invalid hint should have been cleared");
switch(PhysRegState[Hint]) {
case regDisabled:
case regReserved:
break;
default:
DEBUG(dbgs() << " %reg" << VirtReg << " really wants "
<< TRI->getName(Hint) << "\n");
spillVirtReg(MBB, MI, PhysRegState[Hint], true);
// Fall through.
case regFree:
return assignVirtToPhysReg(VirtReg, Hint);
}
}
// First try to find a completely free register.
unsigned BestCost = 0, BestReg = 0;
bool hasDisabled = false;
@ -447,12 +485,12 @@ RAFast::LiveRegMap::iterator RAFast::allocVirtReg(MachineBasicBlock &MBB,
/// defineVirtReg - Allocate a register for VirtReg and mark it as dirty.
unsigned RAFast::defineVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned OpNum, unsigned VirtReg) {
unsigned OpNum, unsigned VirtReg, unsigned Hint) {
assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
"Not a virtual register");
LiveRegMap::iterator lri = LiveVirtRegs.find(VirtReg);
if (lri == LiveVirtRegs.end())
lri = allocVirtReg(MBB, MI, VirtReg);
lri = allocVirtReg(MBB, MI, VirtReg, Hint);
else
addKillFlag(lri); // Kill before redefine.
LiveReg &LR = lri->second;
@ -465,13 +503,13 @@ unsigned RAFast::defineVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
/// reloadVirtReg - Make sure VirtReg is available in a physreg and return it.
unsigned RAFast::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
unsigned OpNum, unsigned VirtReg) {
unsigned OpNum, unsigned VirtReg, unsigned Hint) {
assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
"Not a virtual register");
LiveRegMap::iterator lri = LiveVirtRegs.find(VirtReg);
if (lri == LiveVirtRegs.end()) {
lri = allocVirtReg(MBB, MI, VirtReg);
const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg);
lri = allocVirtReg(MBB, MI, VirtReg, Hint);
const TargetRegisterClass *RC = MRI->getRegClass(VirtReg);
int FrameIndex = getStackSpaceFor(VirtReg, RC);
DEBUG(dbgs() << " Reloading %reg" << VirtReg << " into "
<< TRI->getName(lri->second.PhysReg) << "\n");
@ -605,6 +643,11 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
continue;
}
// If this is a copy, we may be able to coalesce.
unsigned CopySrc, CopyDst, CopySrcSub, CopyDstSub;
if (!TII->isMoveInstr(*MI, CopySrc, CopyDst, CopySrcSub, CopyDstSub))
CopySrc = CopyDst = 0;
// Track registers used by instruction.
UsedInInstr.reset();
PhysDefs.clear();
@ -651,11 +694,14 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
unsigned Reg = MO.getReg();
if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg)) continue;
if (MO.isUse()) {
setPhysReg(MO, reloadVirtReg(MBB, MI, i, Reg));
unsigned PhysReg = reloadVirtReg(MBB, MI, i, Reg, CopyDst);
if (CopySrc == Reg)
CopySrc = PhysReg;
setPhysReg(MO, PhysReg);
if (MO.isKill())
VirtKills.push_back(Reg);
} else if (MO.isEarlyClobber()) {
unsigned PhysReg = defineVirtReg(MBB, MI, i, Reg);
unsigned PhysReg = defineVirtReg(MBB, MI, i, Reg, 0);
setPhysReg(MO, PhysReg);
PhysDefs.push_back(PhysReg);
}
@ -671,7 +717,7 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
killPhysReg(PhysKills[i]);
PhysKills.clear();
MF->getRegInfo().addPhysRegsUsed(UsedInInstr);
MRI->addPhysRegsUsed(UsedInInstr);
// Track registers defined by instruction - early clobbers at this point.
UsedInInstr.reset();
@ -702,7 +748,10 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
}
if (MO.isDead())
VirtKills.push_back(Reg);
setPhysReg(MO, defineVirtReg(MBB, MI, i, Reg));
unsigned PhysReg = defineVirtReg(MBB, MI, i, Reg, CopySrc);
if (CopyDst == Reg)
CopyDst = PhysReg;
setPhysReg(MO, PhysReg);
}
// Spill all dirty virtregs before a call, in case of an exception.
@ -721,7 +770,7 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) {
killPhysReg(PhysKills[i]);
PhysKills.clear();
MF->getRegInfo().addPhysRegsUsed(UsedInInstr);
MRI->addPhysRegsUsed(UsedInInstr);
}
// Spill all physical registers holding virtual registers now.
@ -739,6 +788,7 @@ bool RAFast::runOnMachineFunction(MachineFunction &Fn) {
DEBUG(dbgs() << "Machine Function\n");
DEBUG(Fn.dump());
MF = &Fn;
MRI = &MF->getRegInfo();
TM = &Fn.getTarget();
TRI = TM->getRegisterInfo();
TII = TM->getInstrInfo();
@ -748,7 +798,7 @@ bool RAFast::runOnMachineFunction(MachineFunction &Fn) {
// initialize the virtual->physical register map to have a 'null'
// mapping for all virtual registers
unsigned LastVirtReg = MF->getRegInfo().getLastVirtReg();
unsigned LastVirtReg = MRI->getLastVirtReg();
StackSlotForVirtReg.grow(LastVirtReg);
// Loop over all of the basic blocks, eliminating virtual register references
@ -757,7 +807,7 @@ bool RAFast::runOnMachineFunction(MachineFunction &Fn) {
AllocateBasicBlock(*MBB);
// Make sure the set of used physregs is closed under subreg operations.
MF->getRegInfo().closePhysRegsUsed(*TRI);
MRI->closePhysRegsUsed(*TRI);
StackSlotForVirtReg.clear();
return true;

View File

@ -7,8 +7,8 @@
; CHECK: subfze r4,r6
; LOCAL: subfc r6,r5,r4
; LOCAL: subfze r3,r3
; FAST: subfc r9,r8,r7
; FAST: subfze r10,r6
; FAST: subfc r3,r5,r4
; FAST: subfze r4,r6
; PR1357

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 %edi 8(%ebp) %eax (%esi)"
; RUN: llc < %s -march=x86 -regalloc=fast | grep "#%ecx %ebx %edx 8(%edi) %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