From 1e03ff42433afe3a9ffad2765b537f10db3aa921 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Sat, 15 May 2010 06:09:08 +0000 Subject: [PATCH] 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 --- lib/CodeGen/RegAllocFast.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/lib/CodeGen/RegAllocFast.cpp b/lib/CodeGen/RegAllocFast.cpp index 2a66cb12d95..349bc2ccc2c 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;