RegisterScavenging.cpp [plain text]
#define DEBUG_TYPE "reg-scavenging"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;
void RegScavenger::setUsed(unsigned Reg) {
RegsAvailable.reset(Reg);
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
unsigned SubReg = *SubRegs; ++SubRegs)
RegsAvailable.reset(SubReg);
}
bool RegScavenger::isAliasUsed(unsigned Reg) const {
if (isUsed(Reg))
return true;
for (const unsigned *R = TRI->getAliasSet(Reg); *R; ++R)
if (isUsed(*R))
return true;
return false;
}
void RegScavenger::initRegState() {
ScavengedReg = 0;
ScavengedRC = NULL;
ScavengeRestore = NULL;
RegsAvailable.set();
if (!MBB)
return;
for (MachineBasicBlock::livein_iterator I = MBB->livein_begin(),
E = MBB->livein_end(); I != E; ++I)
setUsed(*I);
BitVector PR = MBB->getParent()->getFrameInfo()->getPristineRegs(MBB);
for (int I = PR.find_first(); I>0; I = PR.find_next(I))
setUsed(I);
}
void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
MachineFunction &MF = *mbb->getParent();
const TargetMachine &TM = MF.getTarget();
TII = TM.getInstrInfo();
TRI = TM.getRegisterInfo();
MRI = &MF.getRegInfo();
assert((NumPhysRegs == 0 || NumPhysRegs == TRI->getNumRegs()) &&
"Target changed?");
if (!MBB) {
NumPhysRegs = TRI->getNumRegs();
RegsAvailable.resize(NumPhysRegs);
KillRegs.resize(NumPhysRegs);
DefRegs.resize(NumPhysRegs);
ReservedRegs = TRI->getReservedRegs(MF);
CalleeSavedRegs.resize(NumPhysRegs);
const unsigned *CSRegs = TRI->getCalleeSavedRegs(&MF);
if (CSRegs != NULL)
for (unsigned i = 0; CSRegs[i]; ++i)
CalleeSavedRegs.set(CSRegs[i]);
}
MBB = mbb;
initRegState();
Tracking = false;
}
void RegScavenger::addRegWithSubRegs(BitVector &BV, unsigned Reg) {
BV.set(Reg);
for (const unsigned *R = TRI->getSubRegisters(Reg); *R; R++)
BV.set(*R);
}
void RegScavenger::forward() {
if (!Tracking) {
MBBI = MBB->begin();
Tracking = true;
} else {
assert(MBBI != MBB->end() && "Already past the end of the basic block!");
MBBI = llvm::next(MBBI);
}
assert(MBBI != MBB->end() && "Already at the end of the basic block!");
MachineInstr *MI = MBBI;
if (MI == ScavengeRestore) {
ScavengedReg = 0;
ScavengedRC = NULL;
ScavengeRestore = NULL;
}
if (MI->isDebugValue())
return;
bool isPred = TII->isPredicated(MI);
KillRegs.reset();
DefRegs.reset();
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (MO.isRegMask())
(isPred ? DefRegs : KillRegs).setBitsNotInMask(MO.getRegMask());
if (!MO.isReg())
continue;
unsigned Reg = MO.getReg();
if (!Reg || isReserved(Reg))
continue;
if (MO.isUse()) {
if (MO.isUndef())
continue;
if (!isPred && MO.isKill())
addRegWithSubRegs(KillRegs, Reg);
} else {
assert(MO.isDef());
if (!isPred && MO.isDead())
addRegWithSubRegs(KillRegs, Reg);
else
addRegWithSubRegs(DefRegs, Reg);
}
}
#ifndef NDEBUG
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg())
continue;
unsigned Reg = MO.getReg();
if (!Reg || isReserved(Reg))
continue;
if (MO.isUse()) {
if (MO.isUndef())
continue;
if (!isUsed(Reg)) {
bool SubUsed = false;
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
unsigned SubReg = *SubRegs; ++SubRegs)
if (isUsed(SubReg)) {
SubUsed = true;
break;
}
if (!SubUsed) {
MBB->getParent()->verify(NULL, "In Register Scavenger");
llvm_unreachable("Using an undefined register!");
}
(void)SubUsed;
}
} else {
assert(MO.isDef());
#if 0
assert((KillRegs.test(Reg) || isUnused(Reg) ||
isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) &&
"Re-defining a live register!");
#endif
}
}
#endif // NDEBUG
setUnused(KillRegs);
setUsed(DefRegs);
}
void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) {
used = RegsAvailable;
used.flip();
if (includeReserved)
used |= ReservedRegs;
else
used.reset(ReservedRegs);
}
unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RC) const {
for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
I != E; ++I)
if (!isAliasUsed(*I)) {
DEBUG(dbgs() << "Scavenger found unused reg: " << TRI->getName(*I) <<
"\n");
return *I;
}
return 0;
}
BitVector RegScavenger::getRegsAvailable(const TargetRegisterClass *RC) {
BitVector Mask(TRI->getNumRegs());
for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
I != E; ++I)
if (!isAliasUsed(*I))
Mask.set(*I);
return Mask;
}
unsigned RegScavenger::findSurvivorReg(MachineBasicBlock::iterator StartMI,
BitVector &Candidates,
unsigned InstrLimit,
MachineBasicBlock::iterator &UseMI) {
int Survivor = Candidates.find_first();
assert(Survivor > 0 && "No candidates for scavenging");
MachineBasicBlock::iterator ME = MBB->getFirstTerminator();
assert(StartMI != ME && "MI already at terminator");
MachineBasicBlock::iterator RestorePointMI = StartMI;
MachineBasicBlock::iterator MI = StartMI;
bool inVirtLiveRange = false;
for (++MI; InstrLimit > 0 && MI != ME; ++MI, --InstrLimit) {
if (MI->isDebugValue()) {
++InstrLimit; continue;
}
bool isVirtKillInsn = false;
bool isVirtDefInsn = false;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (MO.isRegMask())
Candidates.clearBitsNotInMask(MO.getRegMask());
if (!MO.isReg() || MO.isUndef() || !MO.getReg())
continue;
if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
if (MO.isDef())
isVirtDefInsn = true;
else if (MO.isKill())
isVirtKillInsn = true;
continue;
}
Candidates.reset(MO.getReg());
for (const unsigned *R = TRI->getAliasSet(MO.getReg()); *R; R++)
Candidates.reset(*R);
}
if (!inVirtLiveRange) RestorePointMI = MI;
if (isVirtKillInsn) inVirtLiveRange = false;
if (isVirtDefInsn) inVirtLiveRange = true;
if (Candidates.test(Survivor))
continue;
if (Candidates.none())
break;
Survivor = Candidates.find_first();
}
if (MI == ME) RestorePointMI = ME;
assert (RestorePointMI != StartMI &&
"No available scavenger restore location!");
UseMI = RestorePointMI;
return Survivor;
}
unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC,
MachineBasicBlock::iterator I,
int SPAdj) {
BitVector Candidates =
TRI->getAllocatableSet(*I->getParent()->getParent(), RC);
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
MachineOperand &MO = I->getOperand(i);
if (MO.isReg() && MO.getReg() != 0 &&
!TargetRegisterInfo::isVirtualRegister(MO.getReg()))
Candidates.reset(MO.getReg());
}
BitVector Available = getRegsAvailable(RC);
Available &= Candidates;
if (Available.any())
Candidates = Available;
MachineBasicBlock::iterator UseMI;
unsigned SReg = findSurvivorReg(I, Candidates, 25, UseMI);
if (!isAliasUsed(SReg)) {
DEBUG(dbgs() << "Scavenged register: " << TRI->getName(SReg) << "\n");
return SReg;
}
assert(ScavengedReg == 0 &&
"Scavenger slot is live, unable to scavenge another register!");
ScavengedReg = SReg;
if (!TRI->saveScavengerRegister(*MBB, I, UseMI, RC, SReg)) {
assert(ScavengingFrameIndex >= 0 &&
"Cannot scavenge register without an emergency spill slot!");
TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC,TRI);
MachineBasicBlock::iterator II = prior(I);
TRI->eliminateFrameIndex(II, SPAdj, this);
TII->loadRegFromStackSlot(*MBB, UseMI, SReg, ScavengingFrameIndex, RC, TRI);
II = prior(UseMI);
TRI->eliminateFrameIndex(II, SPAdj, this);
}
ScavengeRestore = prior(UseMI);
ScavengedRC = RC;
DEBUG(dbgs() << "Scavenged register (with spill): " << TRI->getName(SReg) <<
"\n");
return SReg;
}