aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/RegAllocFast.cpp
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2010-05-15 06:09:08 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2010-05-15 06:09:08 +0000
commit1e03ff42433afe3a9ffad2765b537f10db3aa921 (patch)
treebbd694c24cc292cecf29a0b69c4af72795996569 /lib/CodeGen/RegAllocFast.cpp
parent54b78dca4e98f15e1723368fabda6cdf81f73956 (diff)
Calculate liveness on the fly for local registers.
When working top-down in a basic block, substituting physregs for virtregs, the use-def chains are kept up to date. That means we can recognize a virtreg kill by the use-def chain becoming empty. This makes the fast allocator independent of incoming kill flags. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103866 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/RegAllocFast.cpp')
-rw-r--r--lib/CodeGen/RegAllocFast.cpp31
1 files changed, 31 insertions, 0 deletions
diff --git a/lib/CodeGen/RegAllocFast.cpp b/lib/CodeGen/RegAllocFast.cpp
index 2a66cb12d9..349bc2ccc2 100644
--- a/lib/CodeGen/RegAllocFast.cpp
+++ b/lib/CodeGen/RegAllocFast.cpp
@@ -132,6 +132,8 @@ namespace {
bool runOnMachineFunction(MachineFunction &Fn);
void AllocateBasicBlock(MachineBasicBlock &MBB);
int getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC);
+ bool isLastUseOfLocalReg(MachineOperand&);
+
void addKillFlag(LiveRegMap::iterator i);
void killVirtReg(LiveRegMap::iterator i);
void killVirtReg(unsigned VirtReg);
@@ -174,6 +176,26 @@ int RAFast::getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC) {
return FrameIdx;
}
+/// isLastUseOfLocalReg - Return true if MO is the only remaining reference to
+/// its virtual register, and it is guaranteed to be a block-local register.
+///
+bool RAFast::isLastUseOfLocalReg(MachineOperand &MO) {
+ // Check for non-debug uses or defs following MO.
+ // This is the most likely way to fail - fast path it.
+ MachineOperand *i = &MO;
+ while ((i = i->getNextOperandForReg()))
+ if (!i->isDebug())
+ return false;
+
+ // If the register has ever been spilled or reloaded, we conservatively assume
+ // it is a global register used in multiple blocks.
+ if (StackSlotForVirtReg[MO.getReg()] != -1)
+ return false;
+
+ // Check that the use/def chain has exactly one operand - MO.
+ return &MRI->reg_nodbg_begin(MO.getReg()).getOperand() == &MO;
+}
+
/// addKillFlag - Set kill flags on last use of a virtual register.
void RAFast::addKillFlag(LiveRegMap::iterator lri) {
assert(lri != LiveVirtRegs.end() && "Killing unmapped virtual register");
@@ -566,6 +588,15 @@ unsigned RAFast::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
TII->loadRegFromStackSlot(MBB, MI, lri->second.PhysReg, FrameIndex, RC,
TRI);
++NumLoads;
+ } else if (lri->second.Dirty) {
+ MachineOperand &MO = MI->getOperand(OpNum);
+ if (isLastUseOfLocalReg(MO)) {
+ DEBUG(dbgs() << "Killing last use: " << MO << "\n");
+ MO.setIsKill();
+ } else if (MO.isKill()) {
+ DEBUG(dbgs() << "Clearing dubious kill: " << MO << "\n");
+ MO.setIsKill(false);
+ }
}
LiveReg &LR = lri->second;
LR.LastUse = MI;