VirtRegRewriter.cpp [plain text]
#define DEBUG_TYPE "virtregrewriter"
#include "VirtRegRewriter.h"
#include "VirtRegMap.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
STATISTIC(NumDSE , "Number of dead stores elided");
STATISTIC(NumDSS , "Number of dead spill slots removed");
STATISTIC(NumCommutes, "Number of instructions commuted");
STATISTIC(NumDRM , "Number of re-materializable defs elided");
STATISTIC(NumStores , "Number of stores added");
STATISTIC(NumPSpills , "Number of physical register spills");
STATISTIC(NumOmitted , "Number of reloads omitted");
STATISTIC(NumAvoided , "Number of reloads deemed unnecessary");
STATISTIC(NumCopified, "Number of available reloads turned into copies");
STATISTIC(NumReMats , "Number of re-materialization");
STATISTIC(NumLoads , "Number of loads added");
STATISTIC(NumReused , "Number of values reused");
STATISTIC(NumDCE , "Number of copies elided");
STATISTIC(NumSUnfold , "Number of stores unfolded");
STATISTIC(NumModRefUnfold, "Number of modref unfolded");
namespace {
enum RewriterName { local, trivial };
}
static cl::opt<RewriterName>
RewriterOpt("rewriter",
cl::desc("Rewriter to use (default=local)"),
cl::Prefix,
cl::values(clEnumVal(local, "local rewriter"),
clEnumVal(trivial, "trivial rewriter"),
clEnumValEnd),
cl::init(local));
static cl::opt<bool>
ScheduleSpills("schedule-spills",
cl::desc("Schedule spill code"),
cl::init(false));
VirtRegRewriter::~VirtRegRewriter() {}
static void substitutePhysReg(MachineOperand &MO, unsigned Reg,
const TargetRegisterInfo &TRI) {
if (MO.getSubReg()) {
MO.substPhysReg(Reg, TRI);
MachineInstr &MI = *MO.getParent();
if (MO.isUse() && !MO.isUndef() &&
(MO.isKill() || MI.isRegTiedToDefOperand(&MO-&MI.getOperand(0))))
MI.addRegisterKilled(Reg, &TRI, true);
} else {
MO.setReg(Reg);
}
}
namespace {
struct TrivialRewriter : public VirtRegRewriter {
bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM,
LiveIntervals* LIs) {
DEBUG(dbgs() << "********** REWRITE MACHINE CODE **********\n");
DEBUG(dbgs() << "********** Function: "
<< MF.getFunction()->getName() << '\n');
DEBUG(dbgs() << "**** Machine Instrs"
<< "(NOTE! Does not include spills and reloads!) ****\n");
DEBUG(MF.dump());
MachineRegisterInfo *mri = &MF.getRegInfo();
const TargetRegisterInfo *tri = MF.getTarget().getRegisterInfo();
bool changed = false;
for (LiveIntervals::iterator liItr = LIs->begin(), liEnd = LIs->end();
liItr != liEnd; ++liItr) {
const LiveInterval *li = liItr->second;
unsigned reg = li->reg;
if (TargetRegisterInfo::isPhysicalRegister(reg)) {
if (!li->empty())
mri->setPhysRegUsed(reg);
}
else {
if (!VRM.hasPhys(reg))
continue;
unsigned pReg = VRM.getPhys(reg);
mri->setPhysRegUsed(pReg);
SmallVector<std::pair<MachineInstr*, unsigned>, 32> reglist;
for (MachineRegisterInfo::reg_iterator I = mri->reg_begin(reg),
E = mri->reg_end(); I != E; ++I)
reglist.push_back(std::make_pair(&*I, I.getOperandNo()));
for (unsigned N=0; N != reglist.size(); ++N)
substitutePhysReg(reglist[N].first->getOperand(reglist[N].second),
pReg, *tri);
changed |= !reglist.empty();
}
}
DEBUG(dbgs() << "**** Post Machine Instrs ****\n");
DEBUG(MF.dump());
return changed;
}
};
}
namespace {
class AvailableSpills {
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
std::map<int, unsigned> SpillSlotsOrReMatsAvailable;
std::multimap<unsigned, int> PhysRegsAvailable;
void disallowClobberPhysRegOnly(unsigned PhysReg);
void ClobberPhysRegOnly(unsigned PhysReg);
public:
AvailableSpills(const TargetRegisterInfo *tri, const TargetInstrInfo *tii)
: TRI(tri), TII(tii) {
}
void clear() {
SpillSlotsOrReMatsAvailable.clear();
PhysRegsAvailable.clear();
}
const TargetRegisterInfo *getRegInfo() const { return TRI; }
unsigned getSpillSlotOrReMatPhysReg(int Slot) const {
std::map<int, unsigned>::const_iterator I =
SpillSlotsOrReMatsAvailable.find(Slot);
if (I != SpillSlotsOrReMatsAvailable.end()) {
return I->second >> 1; }
return 0;
}
void addAvailable(int SlotOrReMat, unsigned Reg, bool CanClobber = true) {
ModifyStackSlotOrReMat(SlotOrReMat);
PhysRegsAvailable.insert(std::make_pair(Reg, SlotOrReMat));
SpillSlotsOrReMatsAvailable[SlotOrReMat]= (Reg << 1) |
(unsigned)CanClobber;
if (SlotOrReMat > VirtRegMap::MAX_STACK_SLOT)
DEBUG(dbgs() << "Remembering RM#"
<< SlotOrReMat-VirtRegMap::MAX_STACK_SLOT-1);
else
DEBUG(dbgs() << "Remembering SS#" << SlotOrReMat);
DEBUG(dbgs() << " in physreg " << TRI->getName(Reg)
<< (CanClobber ? " canclobber" : "") << "\n");
}
bool canClobberPhysRegForSS(int SlotOrReMat) const {
assert(SpillSlotsOrReMatsAvailable.count(SlotOrReMat) &&
"Value not available!");
return SpillSlotsOrReMatsAvailable.find(SlotOrReMat)->second & 1;
}
bool canClobberPhysReg(unsigned PhysReg) const {
std::multimap<unsigned, int>::const_iterator I =
PhysRegsAvailable.lower_bound(PhysReg);
while (I != PhysRegsAvailable.end() && I->first == PhysReg) {
int SlotOrReMat = I->second;
I++;
if (!canClobberPhysRegForSS(SlotOrReMat))
return false;
}
return true;
}
void disallowClobberPhysReg(unsigned PhysReg);
void ClobberPhysReg(unsigned PhysReg);
void ModifyStackSlotOrReMat(int SlotOrReMat);
void ClobberSharingStackSlots(int StackSlot);
void AddAvailableRegsToLiveIn(MachineBasicBlock &MBB, BitVector &RegKills,
std::vector<MachineOperand*> &KillOps);
};
}
static MachineBasicBlock::iterator
ComputeReloadLoc(MachineBasicBlock::iterator const InsertLoc,
MachineBasicBlock::iterator const Begin,
unsigned PhysReg,
const TargetRegisterInfo *TRI,
bool DoReMat,
int SSorRMId,
const TargetInstrInfo *TII,
const MachineFunction &MF)
{
if (!ScheduleSpills)
return InsertLoc;
const TargetLowering *TL = MF.getTarget().getTargetLowering();
if (!TL->isTypeLegal(TL->getPointerTy()))
return InsertLoc;
const TargetRegisterClass *ptrRegClass =
TL->getRegClassFor(TL->getPointerTy());
if (!ptrRegClass->contains(PhysReg))
return InsertLoc;
MachineBasicBlock::iterator NewInsertLoc = InsertLoc;
while (NewInsertLoc != Begin) {
MachineBasicBlock::iterator Prev = prior(NewInsertLoc);
for (unsigned i = 0; i < Prev->getNumOperands(); ++i) {
MachineOperand &Op = Prev->getOperand(i);
if (!DoReMat && Op.isFI() && Op.getIndex() == SSorRMId)
goto stop;
}
if (Prev->findRegisterUseOperandIdx(PhysReg) != -1 ||
Prev->findRegisterDefOperand(PhysReg))
goto stop;
for (const unsigned *Alias = TRI->getAliasSet(PhysReg); *Alias; ++Alias)
if (Prev->findRegisterUseOperandIdx(*Alias) != -1 ||
Prev->findRegisterDefOperand(*Alias))
goto stop;
NewInsertLoc = Prev;
}
stop:;
if (NewInsertLoc == Begin) {
int FrameIdx;
while (InsertLoc != NewInsertLoc &&
(TII->isLoadFromStackSlot(NewInsertLoc, FrameIdx) ||
TII->isTriviallyReMaterializable(NewInsertLoc)))
++NewInsertLoc;
}
return NewInsertLoc;
}
namespace {
struct ReusedOp {
unsigned Operand;
unsigned StackSlotOrReMat;
unsigned PhysRegReused;
unsigned AssignedPhysReg;
unsigned VirtReg;
ReusedOp(unsigned o, unsigned ss, unsigned prr, unsigned apr,
unsigned vreg)
: Operand(o), StackSlotOrReMat(ss), PhysRegReused(prr),
AssignedPhysReg(apr), VirtReg(vreg) {}
};
class ReuseInfo {
MachineInstr &MI;
std::vector<ReusedOp> Reuses;
BitVector PhysRegsClobbered;
public:
ReuseInfo(MachineInstr &mi, const TargetRegisterInfo *tri) : MI(mi) {
PhysRegsClobbered.resize(tri->getNumRegs());
}
bool hasReuses() const {
return !Reuses.empty();
}
void addReuse(unsigned OpNo, unsigned StackSlotOrReMat,
unsigned PhysRegReused, unsigned AssignedPhysReg,
unsigned VirtReg) {
if (PhysRegReused == AssignedPhysReg) return;
Reuses.push_back(ReusedOp(OpNo, StackSlotOrReMat, PhysRegReused,
AssignedPhysReg, VirtReg));
}
void markClobbered(unsigned PhysReg) {
PhysRegsClobbered.set(PhysReg);
}
bool isClobbered(unsigned PhysReg) const {
return PhysRegsClobbered.test(PhysReg);
}
unsigned GetRegForReload(const TargetRegisterClass *RC, unsigned PhysReg,
MachineFunction &MF, MachineInstr *MI,
AvailableSpills &Spills,
std::vector<MachineInstr*> &MaybeDeadStores,
SmallSet<unsigned, 8> &Rejected,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps,
VirtRegMap &VRM);
unsigned GetRegForReload(unsigned VirtReg, unsigned PhysReg, MachineInstr *MI,
AvailableSpills &Spills,
std::vector<MachineInstr*> &MaybeDeadStores,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps,
VirtRegMap &VRM) {
SmallSet<unsigned, 8> Rejected;
MachineFunction &MF = *MI->getParent()->getParent();
const TargetRegisterClass* RC = MF.getRegInfo().getRegClass(VirtReg);
return GetRegForReload(RC, PhysReg, MF, MI, Spills, MaybeDeadStores,
Rejected, RegKills, KillOps, VRM);
}
};
}
static void findSinglePredSuccessor(MachineBasicBlock *MBB,
SmallVectorImpl<MachineBasicBlock *> &Succs){
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
SE = MBB->succ_end(); SI != SE; ++SI) {
MachineBasicBlock *SuccMBB = *SI;
if (SuccMBB->pred_size() == 1)
Succs.push_back(SuccMBB);
}
}
static void ResurrectConfirmedKill(unsigned Reg, const TargetRegisterInfo* TRI,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
DEBUG(dbgs() << "Resurrect " << TRI->getName(Reg) << "\n");
MachineOperand *KillOp = KillOps[Reg];
KillOp->setIsKill(false);
unsigned KReg = KillOp->getReg();
if (!RegKills[KReg])
return;
assert(KillOps[KReg]->getParent() == KillOp->getParent() &&
"invalid superreg kill flags");
KillOps[KReg] = NULL;
RegKills.reset(KReg);
for (const unsigned *SR = TRI->getSubRegisters(KReg); *SR; ++SR) {
DEBUG(dbgs() << " Resurrect subreg " << TRI->getName(*SR) << "\n");
assert(KillOps[*SR]->getParent() == KillOp->getParent() &&
"invalid subreg kill flags");
KillOps[*SR] = NULL;
RegKills.reset(*SR);
}
}
static void ResurrectKill(MachineInstr &MI, unsigned Reg,
const TargetRegisterInfo* TRI, BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
if (RegKills[Reg] && KillOps[Reg]->getParent() != &MI) {
ResurrectConfirmedKill(Reg, TRI, RegKills, KillOps);
return;
}
for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) {
unsigned SReg = *SR;
if (RegKills[SReg] && KillOps[SReg]->getParent() != &MI)
ResurrectConfirmedKill(SReg, TRI, RegKills, KillOps);
}
}
static void InvalidateKills(MachineInstr &MI,
const TargetRegisterInfo* TRI,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps,
SmallVector<unsigned, 2> *KillRegs = NULL) {
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || !MO.isUse() || !MO.isKill() || MO.isUndef())
continue;
unsigned Reg = MO.getReg();
if (TargetRegisterInfo::isVirtualRegister(Reg))
continue;
if (KillRegs)
KillRegs->push_back(Reg);
assert(Reg < KillOps.size());
if (KillOps[Reg] == &MO) {
KillOps[Reg] = NULL;
RegKills.reset(Reg);
for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) {
if (RegKills[*SR]) {
assert(KillOps[*SR] == &MO && "bad subreg kill flags");
KillOps[*SR] = NULL;
RegKills.reset(*SR);
}
}
}
else {
ResurrectKill(MI, Reg, TRI, RegKills, KillOps);
}
}
}
static bool InvalidateRegDef(MachineBasicBlock::iterator I,
MachineInstr &NewDef, unsigned Reg,
bool &HasLiveDef,
const TargetRegisterInfo *TRI) {
MachineInstr *DefMI = I;
MachineOperand *DefOp = NULL;
for (unsigned i = 0, e = DefMI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = DefMI->getOperand(i);
if (!MO.isReg() || !MO.isDef() || !MO.isKill() || MO.isUndef())
continue;
if (MO.getReg() == Reg)
DefOp = &MO;
else if (!MO.isDead())
HasLiveDef = true;
}
if (!DefOp)
return false;
bool FoundUse = false, Done = false;
MachineBasicBlock::iterator E = &NewDef;
++I; ++E;
for (; !Done && I != E; ++I) {
MachineInstr *NMI = I;
for (unsigned j = 0, ee = NMI->getNumOperands(); j != ee; ++j) {
MachineOperand &MO = NMI->getOperand(j);
if (!MO.isReg() || MO.getReg() == 0 ||
(MO.getReg() != Reg && !TRI->isSubRegister(Reg, MO.getReg())))
continue;
if (MO.isUse())
FoundUse = true;
Done = true; }
}
if (!FoundUse) {
DefOp->setIsDead();
return true;
}
return false;
}
static void UpdateKills(MachineInstr &MI, const TargetRegisterInfo* TRI,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
if (MI.isDebugValue())
return;
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || !MO.isUse() || MO.isUndef())
continue;
unsigned Reg = MO.getReg();
if (Reg == 0)
continue;
ResurrectKill(MI, Reg, TRI, RegKills, KillOps);
if (MO.isKill()) {
RegKills.set(Reg);
KillOps[Reg] = &MO;
for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) {
RegKills.set(*SR);
KillOps[*SR] = &MO;
}
}
}
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || !MO.getReg() || !MO.isDef())
continue;
unsigned Reg = MO.getReg();
RegKills.reset(Reg);
KillOps[Reg] = NULL;
for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) {
RegKills.reset(*SR);
KillOps[*SR] = NULL;
}
for (const unsigned *SR = TRI->getSuperRegisters(Reg); *SR; ++SR) {
RegKills.reset(*SR);
KillOps[*SR] = NULL;
}
}
}
static void ReMaterialize(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &MII,
unsigned DestReg, unsigned Reg,
const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI,
VirtRegMap &VRM) {
MachineInstr *ReMatDefMI = VRM.getReMaterializedMI(Reg);
#ifndef NDEBUG
const TargetInstrDesc &TID = ReMatDefMI->getDesc();
assert(TID.getNumDefs() == 1 &&
"Don't know how to remat instructions that define > 1 values!");
#endif
TII->reMaterialize(MBB, MII, DestReg, 0, ReMatDefMI, *TRI);
MachineInstr *NewMI = prior(MII);
for (unsigned i = 0, e = NewMI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = NewMI->getOperand(i);
if (!MO.isReg() || MO.getReg() == 0)
continue;
unsigned VirtReg = MO.getReg();
if (TargetRegisterInfo::isPhysicalRegister(VirtReg))
continue;
assert(MO.isUse());
unsigned Phys = VRM.getPhys(VirtReg);
assert(Phys && "Virtual register is not assigned a register?");
substitutePhysReg(MO, Phys, *TRI);
}
++NumReMats;
}
static unsigned findSuperReg(const TargetRegisterClass *RC, unsigned SubReg,
unsigned SubIdx, const TargetRegisterInfo *TRI) {
for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
I != E; ++I) {
unsigned Reg = *I;
if (TRI->getSubReg(Reg, SubIdx) == SubReg)
return Reg;
}
return 0;
}
void AvailableSpills::disallowClobberPhysRegOnly(unsigned PhysReg) {
std::multimap<unsigned, int>::iterator I =
PhysRegsAvailable.lower_bound(PhysReg);
while (I != PhysRegsAvailable.end() && I->first == PhysReg) {
int SlotOrReMat = I->second;
I++;
assert((SpillSlotsOrReMatsAvailable[SlotOrReMat] >> 1) == PhysReg &&
"Bidirectional map mismatch!");
SpillSlotsOrReMatsAvailable[SlotOrReMat] &= ~1;
DEBUG(dbgs() << "PhysReg " << TRI->getName(PhysReg)
<< " copied, it is available for use but can no longer be modified\n");
}
}
void AvailableSpills::disallowClobberPhysReg(unsigned PhysReg) {
for (const unsigned *AS = TRI->getAliasSet(PhysReg); *AS; ++AS)
disallowClobberPhysRegOnly(*AS);
disallowClobberPhysRegOnly(PhysReg);
}
void AvailableSpills::ClobberPhysRegOnly(unsigned PhysReg) {
std::multimap<unsigned, int>::iterator I =
PhysRegsAvailable.lower_bound(PhysReg);
while (I != PhysRegsAvailable.end() && I->first == PhysReg) {
int SlotOrReMat = I->second;
PhysRegsAvailable.erase(I++);
assert((SpillSlotsOrReMatsAvailable[SlotOrReMat] >> 1) == PhysReg &&
"Bidirectional map mismatch!");
SpillSlotsOrReMatsAvailable.erase(SlotOrReMat);
DEBUG(dbgs() << "PhysReg " << TRI->getName(PhysReg)
<< " clobbered, invalidating ");
if (SlotOrReMat > VirtRegMap::MAX_STACK_SLOT)
DEBUG(dbgs() << "RM#" << SlotOrReMat-VirtRegMap::MAX_STACK_SLOT-1 <<"\n");
else
DEBUG(dbgs() << "SS#" << SlotOrReMat << "\n");
}
}
void AvailableSpills::ClobberPhysReg(unsigned PhysReg) {
for (const unsigned *AS = TRI->getAliasSet(PhysReg); *AS; ++AS)
ClobberPhysRegOnly(*AS);
ClobberPhysRegOnly(PhysReg);
}
void AvailableSpills::AddAvailableRegsToLiveIn(MachineBasicBlock &MBB,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
std::set<unsigned> NotAvailable;
for (std::multimap<unsigned, int>::iterator
I = PhysRegsAvailable.begin(), E = PhysRegsAvailable.end();
I != E; ++I) {
unsigned Reg = I->first;
const TargetRegisterClass* RC = TRI->getMinimalPhysRegClass(Reg);
if (!TII->isSafeToMoveRegClassDefs(RC))
NotAvailable.insert(Reg);
else {
MBB.addLiveIn(Reg);
if (RegKills[Reg])
ResurrectConfirmedKill(Reg, TRI, RegKills, KillOps);
}
std::multimap<unsigned, int>::iterator NI = llvm::next(I);
while (NI != E && NI->first == Reg) {
++I;
++NI;
}
}
for (std::set<unsigned>::iterator I = NotAvailable.begin(),
E = NotAvailable.end(); I != E; ++I) {
ClobberPhysReg(*I);
for (const unsigned *SubRegs = TRI->getSubRegisters(*I);
*SubRegs; ++SubRegs)
ClobberPhysReg(*SubRegs);
}
}
void AvailableSpills::ModifyStackSlotOrReMat(int SlotOrReMat) {
std::map<int, unsigned>::iterator It =
SpillSlotsOrReMatsAvailable.find(SlotOrReMat);
if (It == SpillSlotsOrReMatsAvailable.end()) return;
unsigned Reg = It->second >> 1;
SpillSlotsOrReMatsAvailable.erase(It);
std::multimap<unsigned, int>::iterator I = PhysRegsAvailable.lower_bound(Reg);
for (; ; ++I) {
assert(I != PhysRegsAvailable.end() && I->first == Reg &&
"Map inverse broken!");
if (I->second == SlotOrReMat) break;
}
PhysRegsAvailable.erase(I);
}
void AvailableSpills::ClobberSharingStackSlots(int StackSlot) {
std::map<int, unsigned>::iterator It =
SpillSlotsOrReMatsAvailable.find(StackSlot);
if (It == SpillSlotsOrReMatsAvailable.end()) return;
unsigned Reg = It->second >> 1;
std::multimap<unsigned, int>::iterator I = PhysRegsAvailable.lower_bound(Reg);
while (I != PhysRegsAvailable.end() && I->first == Reg) {
std::multimap<unsigned, int>::iterator NextI = llvm::next(I);
if (I->second != StackSlot) {
DEBUG(dbgs() << "Clobbered sharing SS#" << I->second << " in "
<< PrintReg(Reg, TRI) << '\n');
SpillSlotsOrReMatsAvailable.erase(I->second);
PhysRegsAvailable.erase(I);
}
I = NextI;
}
}
unsigned ReuseInfo::GetRegForReload(const TargetRegisterClass *RC,
unsigned PhysReg,
MachineFunction &MF,
MachineInstr *MI, AvailableSpills &Spills,
std::vector<MachineInstr*> &MaybeDeadStores,
SmallSet<unsigned, 8> &Rejected,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps,
VirtRegMap &VRM) {
const TargetInstrInfo* TII = MF.getTarget().getInstrInfo();
const TargetRegisterInfo *TRI = Spills.getRegInfo();
if (Reuses.empty()) return PhysReg;
for (unsigned ro = 0, e = Reuses.size(); ro != e; ++ro) {
ReusedOp &Op = Reuses[ro];
if (Op.PhysRegReused == PhysReg &&
Rejected.count(Op.AssignedPhysReg) == 0 &&
RC->contains(Op.AssignedPhysReg)) {
unsigned NewReg = Op.AssignedPhysReg;
Rejected.insert(PhysReg);
return GetRegForReload(RC, NewReg, MF, MI, Spills, MaybeDeadStores,
Rejected, RegKills, KillOps, VRM);
} else {
unsigned PRRU = Op.PhysRegReused;
if (TRI->regsOverlap(PRRU, PhysReg)) {
MachineBasicBlock *MBB = MI->getParent();
const TargetRegisterClass *AliasRC =
MBB->getParent()->getRegInfo().getRegClass(Op.VirtReg);
ReusedOp NewOp = Op;
Reuses.erase(Reuses.begin()+ro);
unsigned RealPhysRegUsed = MI->getOperand(NewOp.Operand).getReg();
unsigned SubIdx = 0;
assert(TargetRegisterInfo::isPhysicalRegister(RealPhysRegUsed) &&
"A reuse cannot be a virtual register");
if (PRRU != RealPhysRegUsed) {
SubIdx = TRI->getSubRegIndex(PRRU, RealPhysRegUsed);
assert(SubIdx &&
"Operand physreg is not a sub-register of PhysRegUsed");
}
unsigned NewPhysReg = GetRegForReload(RC, NewOp.AssignedPhysReg,
MF, MI, Spills, MaybeDeadStores,
Rejected, RegKills, KillOps, VRM);
bool DoReMat = NewOp.StackSlotOrReMat > VirtRegMap::MAX_STACK_SLOT;
int SSorRMId = DoReMat
? VRM.getReMatId(NewOp.VirtReg) : (int) NewOp.StackSlotOrReMat;
MachineBasicBlock::iterator InsertLoc =
ComputeReloadLoc(MI, MBB->begin(), PhysReg, TRI,
DoReMat, SSorRMId, TII, MF);
if (DoReMat) {
ReMaterialize(*MBB, InsertLoc, NewPhysReg, NewOp.VirtReg, TII,
TRI, VRM);
} else {
TII->loadRegFromStackSlot(*MBB, InsertLoc, NewPhysReg,
NewOp.StackSlotOrReMat, AliasRC, TRI);
MachineInstr *LoadMI = prior(InsertLoc);
VRM.addSpillSlotUse(NewOp.StackSlotOrReMat, LoadMI);
MaybeDeadStores[NewOp.StackSlotOrReMat] = NULL;
++NumLoads;
}
Spills.ClobberPhysReg(NewPhysReg);
Spills.ClobberPhysReg(NewOp.PhysRegReused);
unsigned RReg = SubIdx ? TRI->getSubReg(NewPhysReg, SubIdx) :NewPhysReg;
MI->getOperand(NewOp.Operand).setReg(RReg);
MI->getOperand(NewOp.Operand).setSubReg(0);
Spills.addAvailable(NewOp.StackSlotOrReMat, NewPhysReg);
UpdateKills(*prior(InsertLoc), TRI, RegKills, KillOps);
DEBUG(dbgs() << '\t' << *prior(InsertLoc));
DEBUG(dbgs() << "Reuse undone!\n");
--NumReused;
return PhysReg;
}
}
}
return PhysReg;
}
static bool FoldsStackSlotModRef(MachineInstr &MI, int SS, unsigned PhysReg,
const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI,
VirtRegMap &VRM) {
if (VRM.hasEmergencySpills(&MI) || VRM.isSpillPt(&MI))
return false;
bool Found = false;
VirtRegMap::MI2VirtMapTy::const_iterator I, End;
for (tie(I, End) = VRM.getFoldedVirts(&MI); I != End; ++I) {
unsigned VirtReg = I->second.first;
VirtRegMap::ModRef MR = I->second.second;
if (MR & VirtRegMap::isModRef)
if (VRM.getStackSlot(VirtReg) == SS) {
Found= TII->getOpcodeAfterMemoryUnfold(MI.getOpcode(), true, true) != 0;
break;
}
}
if (!Found)
return false;
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || MO.getReg() == 0)
continue;
unsigned Reg = MO.getReg();
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
if (!VRM.hasPhys(Reg))
continue;
Reg = VRM.getPhys(Reg);
}
if (TRI->regsOverlap(PhysReg, Reg))
return false;
}
return true;
}
static unsigned FindFreeRegister(MachineBasicBlock::iterator MII,
MachineBasicBlock &MBB,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI,
BitVector &AllocatableRegs) {
BitVector Defs(TRI->getNumRegs());
BitVector Uses(TRI->getNumRegs());
SmallVector<unsigned, 4> LocalUses;
SmallVector<unsigned, 4> Kills;
unsigned Count = 0;
while (Count < 2) {
if (MII == MBB.begin())
break;
MachineInstr *PrevMI = prior(MII);
MII = PrevMI;
if (PrevMI->isDebugValue())
continue; ++Count;
for (unsigned i = 0, e = PrevMI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = PrevMI->getOperand(i);
if (!MO.isReg() || MO.getReg() == 0)
continue;
unsigned Reg = MO.getReg();
if (MO.isDef()) {
Defs.set(Reg);
for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS)
Defs.set(*AS);
} else {
LocalUses.push_back(Reg);
if (MO.isKill() && AllocatableRegs[Reg])
Kills.push_back(Reg);
}
}
for (unsigned i = 0, e = Kills.size(); i != e; ++i) {
unsigned Kill = Kills[i];
if (!Defs[Kill] && !Uses[Kill] &&
RC->contains(Kill))
return Kill;
}
for (unsigned i = 0, e = LocalUses.size(); i != e; ++i) {
unsigned Reg = LocalUses[i];
Uses.set(Reg);
for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS)
Uses.set(*AS);
}
}
return 0;
}
static
void AssignPhysToVirtReg(MachineInstr *MI, unsigned VirtReg, unsigned PhysReg,
const TargetRegisterInfo &TRI) {
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (MO.isReg() && MO.getReg() == VirtReg)
substitutePhysReg(MO, PhysReg, TRI);
}
}
namespace {
struct RefSorter {
bool operator()(const std::pair<MachineInstr*, int> &A,
const std::pair<MachineInstr*, int> &B) {
return A.second < B.second;
}
};
class LocalRewriter : public VirtRegRewriter {
MachineRegisterInfo *MRI;
const TargetRegisterInfo *TRI;
const TargetInstrInfo *TII;
VirtRegMap *VRM;
LiveIntervals *LIs;
BitVector AllocatableRegs;
DenseMap<MachineInstr*, unsigned> DistanceMap;
DenseMap<int, SmallVector<MachineInstr*,4> > Slot2DbgValues;
MachineBasicBlock *MBB;
public:
bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM,
LiveIntervals* LIs);
private:
void EraseInstr(MachineInstr *MI) {
VRM->RemoveMachineInstrFromMaps(MI);
LIs->RemoveMachineInstrFromMaps(MI);
MI->eraseFromParent();
}
bool OptimizeByUnfold2(unsigned VirtReg, int SS,
MachineBasicBlock::iterator &MII,
std::vector<MachineInstr*> &MaybeDeadStores,
AvailableSpills &Spills,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps);
bool OptimizeByUnfold(MachineBasicBlock::iterator &MII,
std::vector<MachineInstr*> &MaybeDeadStores,
AvailableSpills &Spills,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps);
bool CommuteToFoldReload(MachineBasicBlock::iterator &MII,
unsigned VirtReg, unsigned SrcReg, int SS,
AvailableSpills &Spills,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps,
const TargetRegisterInfo *TRI);
void SpillRegToStackSlot(MachineBasicBlock::iterator &MII,
int Idx, unsigned PhysReg, int StackSlot,
const TargetRegisterClass *RC,
bool isAvailable, MachineInstr *&LastStore,
AvailableSpills &Spills,
SmallSet<MachineInstr*, 4> &ReMatDefs,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps);
void TransferDeadness(unsigned Reg, BitVector &RegKills,
std::vector<MachineOperand*> &KillOps);
bool InsertEmergencySpills(MachineInstr *MI);
bool InsertRestores(MachineInstr *MI,
AvailableSpills &Spills,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps);
bool InsertSpills(MachineInstr *MI);
void ProcessUses(MachineInstr &MI, AvailableSpills &Spills,
std::vector<MachineInstr*> &MaybeDeadStores,
BitVector &RegKills,
ReuseInfo &ReusedOperands,
std::vector<MachineOperand*> &KillOps);
void RewriteMBB(LiveIntervals *LIs,
AvailableSpills &Spills, BitVector &RegKills,
std::vector<MachineOperand*> &KillOps);
};
}
bool LocalRewriter::runOnMachineFunction(MachineFunction &MF, VirtRegMap &vrm,
LiveIntervals* lis) {
MRI = &MF.getRegInfo();
TRI = MF.getTarget().getRegisterInfo();
TII = MF.getTarget().getInstrInfo();
VRM = &vrm;
LIs = lis;
AllocatableRegs = TRI->getAllocatableSet(MF);
DEBUG(dbgs() << "\n**** Local spiller rewriting function '"
<< MF.getFunction()->getName() << "':\n");
DEBUG(dbgs() << "**** Machine Instrs (NOTE! Does not include spills and"
" reloads!) ****\n");
DEBUG(MF.print(dbgs(), LIs->getSlotIndexes()));
AvailableSpills Spills(TRI, TII);
BitVector RegKills(TRI->getNumRegs());
std::vector<MachineOperand*> KillOps;
KillOps.resize(TRI->getNumRegs(), NULL);
SmallVector<MachineBasicBlock*, 4> SinglePredSuccs;
SmallPtrSet<MachineBasicBlock*,16> EarlyVisited;
MachineBasicBlock *Entry = MF.begin();
SmallPtrSet<MachineBasicBlock*,16> Visited;
for (df_ext_iterator<MachineBasicBlock*,
SmallPtrSet<MachineBasicBlock*,16> >
DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited);
DFI != E; ++DFI) {
MBB = *DFI;
if (!EarlyVisited.count(MBB))
RewriteMBB(LIs, Spills, RegKills, KillOps);
do {
SinglePredSuccs.clear();
findSinglePredSuccessor(MBB, SinglePredSuccs);
if (SinglePredSuccs.empty())
MBB = 0;
else {
MBB = SinglePredSuccs[0];
if (!Visited.count(MBB) && EarlyVisited.insert(MBB)) {
Spills.AddAvailableRegsToLiveIn(*MBB, RegKills, KillOps);
RewriteMBB(LIs, Spills, RegKills, KillOps);
}
}
} while (MBB);
Spills.clear();
}
DEBUG(dbgs() << "**** Post Machine Instrs ****\n");
DEBUG(MF.print(dbgs(), LIs->getSlotIndexes()));
MachineFrameInfo *MFI = MF.getFrameInfo();
int SS = VRM->getLowSpillSlot();
if (SS != VirtRegMap::NO_STACK_SLOT) {
for (int e = VRM->getHighSpillSlot(); SS <= e; ++SS) {
SmallVector<MachineInstr*, 4> &DbgValues = Slot2DbgValues[SS];
if (!VRM->isSpillSlotUsed(SS)) {
MFI->RemoveStackObject(SS);
for (unsigned j = 0, ee = DbgValues.size(); j != ee; ++j) {
MachineInstr *DVMI = DbgValues[j];
DEBUG(dbgs() << "Removing debug info referencing FI#" << SS << '\n');
EraseInstr(DVMI);
}
++NumDSS;
}
DbgValues.clear();
}
}
Slot2DbgValues.clear();
return true;
}
bool LocalRewriter::
OptimizeByUnfold2(unsigned VirtReg, int SS,
MachineBasicBlock::iterator &MII,
std::vector<MachineInstr*> &MaybeDeadStores,
AvailableSpills &Spills,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
MachineBasicBlock::iterator NextMII = llvm::next(MII);
while (NextMII != MBB->end() && NextMII->isDebugValue())
NextMII = llvm::next(NextMII);
if (NextMII == MBB->end())
return false;
if (TII->getOpcodeAfterMemoryUnfold(MII->getOpcode(), true, true) == 0)
return false;
const TargetRegisterClass* RC = MRI->getRegClass(VirtReg);
unsigned PhysReg = FindFreeRegister(MII, *MBB, RC, TRI, AllocatableRegs);
if (!PhysReg)
return false;
MachineFunction &MF = *MBB->getParent();
TRI = MF.getTarget().getRegisterInfo();
MachineInstr &MI = *MII;
if (!FoldsStackSlotModRef(MI, SS, PhysReg, TII, TRI, *VRM))
return false;
if (!FoldsStackSlotModRef(*NextMII, SS, PhysReg, TII, TRI, *VRM))
return false;
ComputeReloadLoc(MII, MBB->begin(), PhysReg, TRI, false, SS, TII, MF);
TII->loadRegFromStackSlot(*MBB, MII, PhysReg, SS, RC, TRI);
Spills.ClobberPhysReg(PhysReg);
Spills.addAvailable(SS, PhysReg);
MaybeDeadStores[SS] = NULL;
SmallVector<MachineInstr*, 4> NewMIs;
if (!TII->unfoldMemoryOperand(MF, &MI, VirtReg, false, false, NewMIs))
llvm_unreachable("Unable unfold the load / store folding instruction!");
assert(NewMIs.size() == 1);
AssignPhysToVirtReg(NewMIs[0], VirtReg, PhysReg, *TRI);
VRM->transferRestorePts(&MI, NewMIs[0]);
MII = MBB->insert(MII, NewMIs[0]);
InvalidateKills(MI, TRI, RegKills, KillOps);
EraseInstr(&MI);
++NumModRefUnfold;
do {
MachineInstr &NextMI = *NextMII;
NextMII = llvm::next(NextMII);
NewMIs.clear();
if (!TII->unfoldMemoryOperand(MF, &NextMI, VirtReg, false, false, NewMIs))
llvm_unreachable("Unable unfold the load / store folding instruction!");
assert(NewMIs.size() == 1);
AssignPhysToVirtReg(NewMIs[0], VirtReg, PhysReg, *TRI);
VRM->transferRestorePts(&NextMI, NewMIs[0]);
MBB->insert(NextMII, NewMIs[0]);
InvalidateKills(NextMI, TRI, RegKills, KillOps);
EraseInstr(&NextMI);
++NumModRefUnfold;
while (NextMII != MBB->end() && NextMII->isDebugValue())
NextMII = llvm::next(NextMII);
if (NextMII == MBB->end())
break;
} while (FoldsStackSlotModRef(*NextMII, SS, PhysReg, TII, TRI, *VRM));
TII->storeRegToStackSlot(*MBB, NextMII, PhysReg, true, SS, RC, TRI);
MachineInstr *StoreMI = prior(NextMII);
VRM->addSpillSlotUse(SS, StoreMI);
VRM->virtFolded(VirtReg, StoreMI, VirtRegMap::isMod);
return true;
}
bool LocalRewriter::
OptimizeByUnfold(MachineBasicBlock::iterator &MII,
std::vector<MachineInstr*> &MaybeDeadStores,
AvailableSpills &Spills,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
MachineFunction &MF = *MBB->getParent();
MachineInstr &MI = *MII;
unsigned UnfoldedOpc = 0;
unsigned UnfoldPR = 0;
unsigned UnfoldVR = 0;
int FoldedSS = VirtRegMap::NO_STACK_SLOT;
VirtRegMap::MI2VirtMapTy::const_iterator I, End;
for (tie(I, End) = VRM->getFoldedVirts(&MI); I != End; ) {
if (UnfoldedOpc)
return false;
UnfoldVR = I->second.first;
VirtRegMap::ModRef MR = I->second.second;
++I;
if (VRM->isAssignedReg(UnfoldVR))
continue;
FoldedSS = VRM->getStackSlot(UnfoldVR);
MachineInstr* DeadStore = MaybeDeadStores[FoldedSS];
if (DeadStore && (MR & VirtRegMap::isModRef)) {
unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(FoldedSS);
if (!PhysReg || !DeadStore->readsRegister(PhysReg))
continue;
UnfoldPR = PhysReg;
UnfoldedOpc = TII->getOpcodeAfterMemoryUnfold(MI.getOpcode(),
false, true);
}
}
if (!UnfoldedOpc) {
if (!UnfoldVR)
return false;
return OptimizeByUnfold2(UnfoldVR, FoldedSS, MII, MaybeDeadStores, Spills,
RegKills, KillOps);
}
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || MO.getReg() == 0 || !MO.isUse())
continue;
unsigned VirtReg = MO.getReg();
if (TargetRegisterInfo::isPhysicalRegister(VirtReg) || MO.getSubReg())
continue;
if (VRM->isAssignedReg(VirtReg)) {
unsigned PhysReg = VRM->getPhys(VirtReg);
if (PhysReg && TRI->regsOverlap(PhysReg, UnfoldPR))
return false;
} else if (VRM->isReMaterialized(VirtReg))
continue;
int SS = VRM->getStackSlot(VirtReg);
unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS);
if (PhysReg) {
if (TRI->regsOverlap(PhysReg, UnfoldPR))
return false;
continue;
}
if (VRM->hasPhys(VirtReg)) {
PhysReg = VRM->getPhys(VirtReg);
if (!TRI->regsOverlap(PhysReg, UnfoldPR))
continue;
}
SmallVector<MachineInstr*, 4> NewMIs;
if (TII->unfoldMemoryOperand(MF, &MI, UnfoldVR, false, false, NewMIs)) {
assert(NewMIs.size() == 1);
MachineInstr *NewMI = NewMIs.back();
MBB->insert(MII, NewMI);
NewMIs.clear();
int Idx = NewMI->findRegisterUseOperandIdx(VirtReg, false);
assert(Idx != -1);
SmallVector<unsigned, 1> Ops;
Ops.push_back(Idx);
MachineInstr *FoldedMI = TII->foldMemoryOperand(NewMI, Ops, SS);
NewMI->eraseFromParent();
if (FoldedMI) {
VRM->addSpillSlotUse(SS, FoldedMI);
if (!VRM->hasPhys(UnfoldVR))
VRM->assignVirt2Phys(UnfoldVR, UnfoldPR);
VRM->virtFolded(VirtReg, FoldedMI, VirtRegMap::isRef);
MII = FoldedMI;
InvalidateKills(MI, TRI, RegKills, KillOps);
EraseInstr(&MI);
return true;
}
}
}
return false;
}
static bool CommuteChangesDestination(MachineInstr *DefMI,
const TargetInstrDesc &TID,
unsigned SrcReg,
const TargetInstrInfo *TII,
unsigned &DstIdx) {
if (TID.getNumDefs() != 1 && TID.getNumOperands() != 3)
return false;
if (!DefMI->getOperand(1).isReg() ||
DefMI->getOperand(1).getReg() != SrcReg)
return false;
unsigned DefIdx;
if (!DefMI->isRegTiedToDefOperand(1, &DefIdx) || DefIdx != 0)
return false;
unsigned SrcIdx1, SrcIdx2;
if (!TII->findCommutedOpIndices(DefMI, SrcIdx1, SrcIdx2))
return false;
if (SrcIdx1 == 1 && SrcIdx2 == 2) {
DstIdx = 2;
return true;
}
return false;
}
bool LocalRewriter::
CommuteToFoldReload(MachineBasicBlock::iterator &MII,
unsigned VirtReg, unsigned SrcReg, int SS,
AvailableSpills &Spills,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps,
const TargetRegisterInfo *TRI) {
if (MII == MBB->begin() || !MII->killsRegister(SrcReg))
return false;
MachineInstr &MI = *MII;
MachineBasicBlock::iterator DefMII = prior(MII);
MachineInstr *DefMI = DefMII;
const TargetInstrDesc &TID = DefMI->getDesc();
unsigned NewDstIdx;
if (DefMII != MBB->begin() &&
TID.isCommutable() &&
CommuteChangesDestination(DefMI, TID, SrcReg, TII, NewDstIdx)) {
MachineOperand &NewDstMO = DefMI->getOperand(NewDstIdx);
unsigned NewReg = NewDstMO.getReg();
if (!NewDstMO.isKill() || TRI->regsOverlap(NewReg, SrcReg))
return false;
MachineInstr *ReloadMI = prior(DefMII);
int FrameIdx;
unsigned DestReg = TII->isLoadFromStackSlot(ReloadMI, FrameIdx);
if (DestReg != SrcReg || FrameIdx != SS)
return false;
int UseIdx = DefMI->findRegisterUseOperandIdx(DestReg, false);
if (UseIdx == -1)
return false;
unsigned DefIdx;
if (!MI.isRegTiedToDefOperand(UseIdx, &DefIdx))
return false;
assert(DefMI->getOperand(DefIdx).isReg() &&
DefMI->getOperand(DefIdx).getReg() == SrcReg);
MachineInstr *CommutedMI = TII->commuteInstruction(DefMI, true);
if (!CommutedMI)
return false;
MBB->insert(MII, CommutedMI);
SmallVector<unsigned, 1> Ops;
Ops.push_back(NewDstIdx);
MachineInstr *FoldedMI = TII->foldMemoryOperand(CommutedMI, Ops, SS);
CommutedMI->eraseFromParent();
if (!FoldedMI)
return false;
VRM->addSpillSlotUse(SS, FoldedMI);
VRM->virtFolded(VirtReg, FoldedMI, VirtRegMap::isRef);
const TargetRegisterClass* RC = MRI->getRegClass(VirtReg);
TII->storeRegToStackSlot(*MBB, &MI, NewReg, true, SS, RC, TRI);
MII = prior(MII);
MachineInstr *StoreMI = MII;
VRM->addSpillSlotUse(SS, StoreMI);
VRM->virtFolded(VirtReg, StoreMI, VirtRegMap::isMod);
MII = FoldedMI;
InvalidateKills(*ReloadMI, TRI, RegKills, KillOps);
EraseInstr(ReloadMI);
InvalidateKills(*DefMI, TRI, RegKills, KillOps);
EraseInstr(DefMI);
InvalidateKills(MI, TRI, RegKills, KillOps);
EraseInstr(&MI);
Spills.ClobberPhysReg(NewReg);
++NumCommutes;
return true;
}
return false;
}
void LocalRewriter::
SpillRegToStackSlot(MachineBasicBlock::iterator &MII,
int Idx, unsigned PhysReg, int StackSlot,
const TargetRegisterClass *RC,
bool isAvailable, MachineInstr *&LastStore,
AvailableSpills &Spills,
SmallSet<MachineInstr*, 4> &ReMatDefs,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
MachineBasicBlock::iterator oldNextMII = llvm::next(MII);
TII->storeRegToStackSlot(*MBB, llvm::next(MII), PhysReg, true, StackSlot, RC,
TRI);
MachineInstr *StoreMI = prior(oldNextMII);
VRM->addSpillSlotUse(StackSlot, StoreMI);
DEBUG(dbgs() << "Store:\t" << *StoreMI);
if (LastStore) {
DEBUG(dbgs() << "Removed dead store:\t" << *LastStore);
++NumDSE;
SmallVector<unsigned, 2> KillRegs;
InvalidateKills(*LastStore, TRI, RegKills, KillOps, &KillRegs);
MachineBasicBlock::iterator PrevMII = LastStore;
bool CheckDef = PrevMII != MBB->begin();
if (CheckDef)
--PrevMII;
EraseInstr(LastStore);
if (CheckDef) {
for (unsigned j = 0, ee = KillRegs.size(); j != ee; ++j) {
bool HasOtherDef = false;
if (InvalidateRegDef(PrevMII, *MII, KillRegs[j], HasOtherDef, TRI)) {
MachineInstr *DeadDef = PrevMII;
if (ReMatDefs.count(DeadDef) && !HasOtherDef) {
EraseInstr(DeadDef);
++NumDRM;
}
}
}
}
}
LastStore = prior(oldNextMII);
Spills.ModifyStackSlotOrReMat(StackSlot);
Spills.ClobberPhysReg(PhysReg);
Spills.addAvailable(StackSlot, PhysReg, isAvailable);
++NumStores;
}
static bool isSafeToDelete(MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
if (TID.mayLoad() || TID.mayStore() || TID.isTerminator() ||
TID.isCall() || TID.isBarrier() || TID.isReturn() ||
MI.isLabel() || MI.isDebugValue() ||
MI.hasUnmodeledSideEffects())
return false;
if (MI.isInlineAsm())
return false;
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || !MO.getReg())
continue;
if (MO.isDef() && !MO.isDead())
return false;
if (MO.isUse() && MO.isKill())
return false;
}
return true;
}
void LocalRewriter::
TransferDeadness(unsigned Reg, BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
SmallPtrSet<MachineInstr*, 4> Seens;
SmallVector<std::pair<MachineInstr*, int>,8> Refs;
for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(Reg),
RE = MRI->reg_end(); RI != RE; ++RI) {
MachineInstr *UDMI = &*RI;
if (UDMI->isDebugValue() || UDMI->getParent() != MBB)
continue;
DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(UDMI);
if (DI == DistanceMap.end())
continue;
if (Seens.insert(UDMI))
Refs.push_back(std::make_pair(UDMI, DI->second));
}
if (Refs.empty())
return;
std::sort(Refs.begin(), Refs.end(), RefSorter());
while (!Refs.empty()) {
MachineInstr *LastUDMI = Refs.back().first;
Refs.pop_back();
MachineOperand *LastUD = NULL;
for (unsigned i = 0, e = LastUDMI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = LastUDMI->getOperand(i);
if (!MO.isReg() || MO.getReg() != Reg)
continue;
if (!LastUD || (LastUD->isUse() && MO.isDef()))
LastUD = &MO;
if (LastUDMI->isRegTiedToDefOperand(i))
break;
}
if (LastUD->isDef()) {
if (!isSafeToDelete(*LastUDMI)) {
LastUD->setIsDead();
break;
}
EraseInstr(LastUDMI);
} else {
LastUD->setIsKill();
RegKills.set(Reg);
KillOps[Reg] = LastUD;
break;
}
}
}
bool LocalRewriter::InsertEmergencySpills(MachineInstr *MI) {
if (!VRM->hasEmergencySpills(MI))
return false;
MachineBasicBlock::iterator MII = MI;
SmallSet<int, 4> UsedSS;
std::vector<unsigned> &EmSpills = VRM->getEmergencySpills(MI);
for (unsigned i = 0, e = EmSpills.size(); i != e; ++i) {
unsigned PhysReg = EmSpills[i];
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(PhysReg);
assert(RC && "Unable to determine register class!");
int SS = VRM->getEmergencySpillSlot(RC);
if (UsedSS.count(SS))
llvm_unreachable("Need to spill more than one physical registers!");
UsedSS.insert(SS);
TII->storeRegToStackSlot(*MBB, MII, PhysReg, true, SS, RC, TRI);
MachineInstr *StoreMI = prior(MII);
VRM->addSpillSlotUse(SS, StoreMI);
MachineBasicBlock::iterator InsertLoc =
ComputeReloadLoc(llvm::next(MII), MBB->begin(), PhysReg, TRI, false, SS,
TII, *MBB->getParent());
TII->loadRegFromStackSlot(*MBB, InsertLoc, PhysReg, SS, RC, TRI);
MachineInstr *LoadMI = prior(InsertLoc);
VRM->addSpillSlotUse(SS, LoadMI);
++NumPSpills;
DistanceMap.insert(std::make_pair(LoadMI, DistanceMap.size()));
}
return true;
}
bool LocalRewriter::InsertRestores(MachineInstr *MI,
AvailableSpills &Spills,
BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
if (!VRM->isRestorePt(MI))
return false;
MachineBasicBlock::iterator MII = MI;
std::vector<unsigned> &RestoreRegs = VRM->getRestorePtRestores(MI);
for (unsigned i = 0, e = RestoreRegs.size(); i != e; ++i) {
unsigned VirtReg = RestoreRegs[e-i-1]; if (!VRM->getPreSplitReg(VirtReg))
continue; unsigned Phys = VRM->getPhys(VirtReg);
MRI->setPhysRegUsed(Phys);
bool DoReMat = VRM->isReMaterialized(VirtReg);
int SSorRMId = DoReMat
? VRM->getReMatId(VirtReg) : VRM->getStackSlot(VirtReg);
unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SSorRMId);
if (InReg == Phys) {
if (SSorRMId)
DEBUG(dbgs() << "Reusing RM#"
<< SSorRMId-VirtRegMap::MAX_STACK_SLOT-1);
else
DEBUG(dbgs() << "Reusing SS#" << SSorRMId);
DEBUG(dbgs() << " from physreg "
<< TRI->getName(InReg) << " for " << PrintReg(VirtReg)
<<" instead of reloading into physreg "
<< TRI->getName(Phys) << '\n');
++NumOmitted;
continue;
} else if (InReg && InReg != Phys) {
if (SSorRMId)
DEBUG(dbgs() << "Reusing RM#"
<< SSorRMId-VirtRegMap::MAX_STACK_SLOT-1);
else
DEBUG(dbgs() << "Reusing SS#" << SSorRMId);
DEBUG(dbgs() << " from physreg "
<< TRI->getName(InReg) << " for " << PrintReg(VirtReg)
<<" by copying it into physreg "
<< TRI->getName(Phys) << '\n');
MachineBasicBlock::iterator InsertLoc =
ComputeReloadLoc(MII, MBB->begin(), Phys, TRI, DoReMat, SSorRMId, TII,
*MBB->getParent());
MachineInstr *CopyMI = BuildMI(*MBB, InsertLoc, MI->getDebugLoc(),
TII->get(TargetOpcode::COPY), Phys)
.addReg(InReg, RegState::Kill);
Spills.ClobberPhysReg(Phys);
Spills.addAvailable(SSorRMId, Phys);
CopyMI->setAsmPrinterFlag(MachineInstr::ReloadReuse);
UpdateKills(*CopyMI, TRI, RegKills, KillOps);
DEBUG(dbgs() << '\t' << *CopyMI);
++NumCopified;
continue;
}
MachineBasicBlock::iterator InsertLoc =
ComputeReloadLoc(MII, MBB->begin(), Phys, TRI, DoReMat, SSorRMId, TII,
*MBB->getParent());
if (VRM->isReMaterialized(VirtReg)) {
ReMaterialize(*MBB, InsertLoc, Phys, VirtReg, TII, TRI, *VRM);
} else {
const TargetRegisterClass* RC = MRI->getRegClass(VirtReg);
TII->loadRegFromStackSlot(*MBB, InsertLoc, Phys, SSorRMId, RC, TRI);
MachineInstr *LoadMI = prior(InsertLoc);
VRM->addSpillSlotUse(SSorRMId, LoadMI);
++NumLoads;
DistanceMap.insert(std::make_pair(LoadMI, DistanceMap.size()));
}
Spills.ClobberPhysReg(Phys);
Spills.addAvailable(SSorRMId, Phys);
UpdateKills(*prior(InsertLoc), TRI, RegKills, KillOps);
DEBUG(dbgs() << '\t' << *prior(MII));
}
return true;
}
bool LocalRewriter::InsertSpills(MachineInstr *MI) {
if (!VRM->isSpillPt(MI))
return false;
MachineBasicBlock::iterator MII = MI;
std::vector<std::pair<unsigned,bool> > &SpillRegs =
VRM->getSpillPtSpills(MI);
for (unsigned i = 0, e = SpillRegs.size(); i != e; ++i) {
unsigned VirtReg = SpillRegs[i].first;
bool isKill = SpillRegs[i].second;
if (!VRM->getPreSplitReg(VirtReg))
continue; const TargetRegisterClass *RC = MRI->getRegClass(VirtReg);
unsigned Phys = VRM->getPhys(VirtReg);
int StackSlot = VRM->getStackSlot(VirtReg);
MachineBasicBlock::iterator oldNextMII = llvm::next(MII);
TII->storeRegToStackSlot(*MBB, llvm::next(MII), Phys, isKill, StackSlot,
RC, TRI);
MachineInstr *StoreMI = prior(oldNextMII);
VRM->addSpillSlotUse(StackSlot, StoreMI);
DEBUG(dbgs() << "Store:\t" << *StoreMI);
VRM->virtFolded(VirtReg, StoreMI, VirtRegMap::isMod);
}
return true;
}
void LocalRewriter::ProcessUses(MachineInstr &MI, AvailableSpills &Spills,
std::vector<MachineInstr*> &MaybeDeadStores,
BitVector &RegKills,
ReuseInfo &ReusedOperands,
std::vector<MachineOperand*> &KillOps) {
SmallSet<unsigned, 2> KilledMIRegs;
SmallVector<unsigned, 4> VirtUseOps;
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || MO.getReg() == 0)
continue;
unsigned VirtReg = MO.getReg();
if (TargetRegisterInfo::isPhysicalRegister(VirtReg)) {
MRI->setPhysRegUsed(VirtReg);
continue;
}
if (MO.isImplicit())
VirtUseOps.insert(VirtUseOps.begin(), i);
else
VirtUseOps.push_back(i);
if (MO.isDef() && MO.getSubReg() && MI.readsVirtualRegister(VirtReg) &&
MI.findRegisterUseOperandIdx(VirtReg) == -1) {
VirtUseOps.insert(VirtUseOps.begin(), MI.getNumOperands());
MI.addOperand(MachineOperand::CreateReg(VirtReg,
false, true)); DEBUG(dbgs() << "Partial redef: " << MI);
}
}
SmallVector<int, 2> PotentialDeadStoreSlots;
KilledMIRegs.clear();
for (unsigned j = 0, e = VirtUseOps.size(); j != e; ++j) {
unsigned i = VirtUseOps[j];
unsigned VirtReg = MI.getOperand(i).getReg();
assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
"Not a virtual register?");
unsigned SubIdx = MI.getOperand(i).getSubReg();
if (VRM->isAssignedReg(VirtReg)) {
unsigned Phys = VRM->getPhys(VirtReg);
MRI->setPhysRegUsed(Phys);
if (MI.getOperand(i).isDef())
ReusedOperands.markClobbered(Phys);
substitutePhysReg(MI.getOperand(i), Phys, *TRI);
if (VRM->isImplicitlyDefined(VirtReg))
BuildMI(*MBB, &MI, MI.getDebugLoc(),
TII->get(TargetOpcode::IMPLICIT_DEF), Phys);
continue;
}
if (!MI.getOperand(i).isUse())
continue;
bool AvoidReload = MI.getOperand(i).isUndef();
bool DoReMat = VRM->isReMaterialized(VirtReg);
int SSorRMId = DoReMat
? VRM->getReMatId(VirtReg) : VRM->getStackSlot(VirtReg);
int ReuseSlot = SSorRMId;
unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SSorRMId);
if (PhysReg && !AvoidReload && SubIdx) {
const TargetRegisterClass* RC = MRI->getRegClass(VirtReg);
if (!RC->contains(PhysReg))
PhysReg = 0;
}
if (PhysReg && !AvoidReload) {
bool CanReuse = true;
bool isTied = MI.isRegTiedToDefOperand(i);
if (isTied) {
CanReuse = !ReusedOperands.isClobbered(PhysReg) &&
Spills.canClobberPhysReg(PhysReg);
}
if (MI.isInlineAsm()) {
for (unsigned k = 0, e = MI.getNumOperands(); k != e; ++k) {
MachineOperand &MOk = MI.getOperand(k);
if (MOk.isReg() && MOk.isEarlyClobber() &&
TRI->regsOverlap(MOk.getReg(), PhysReg)) {
CanReuse = false;
DEBUG(dbgs() << "Not reusing physreg " << TRI->getName(PhysReg)
<< " for " << PrintReg(VirtReg) << ": " << MOk
<< '\n');
break;
}
}
}
if (CanReuse) {
if (ReuseSlot > VirtRegMap::MAX_STACK_SLOT)
DEBUG(dbgs() << "Reusing RM#"
<< ReuseSlot-VirtRegMap::MAX_STACK_SLOT-1);
else
DEBUG(dbgs() << "Reusing SS#" << ReuseSlot);
DEBUG(dbgs() << " from physreg "
<< TRI->getName(PhysReg) << " for " << PrintReg(VirtReg)
<< " instead of reloading into "
<< PrintReg(VRM->getPhys(VirtReg), TRI) << '\n');
unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg;
MI.getOperand(i).setReg(RReg);
MI.getOperand(i).setSubReg(0);
ReusedOperands.addReuse(i, ReuseSlot, PhysReg,
VRM->getPhys(VirtReg), VirtReg);
if (isTied)
ReusedOperands.markClobbered(PhysReg);
++NumReused;
if (MI.getOperand(i).isKill() &&
ReuseSlot <= VirtRegMap::MAX_STACK_SLOT) {
PotentialDeadStoreSlots.push_back(ReuseSlot);
}
if (!isTied && KilledMIRegs.count(VirtReg) == 0) {
MI.getOperand(i).setIsKill();
KilledMIRegs.insert(VirtReg);
}
continue;
}
unsigned DesignatedReg = VRM->getPhys(VirtReg);
assert(DesignatedReg && "Must map virtreg to physreg!");
if (ReusedOperands.hasReuses())
DesignatedReg = ReusedOperands.
GetRegForReload(VirtReg, DesignatedReg, &MI, Spills,
MaybeDeadStores, RegKills, KillOps, *VRM);
if (DesignatedReg == PhysReg) {
if (ReuseSlot > VirtRegMap::MAX_STACK_SLOT)
DEBUG(dbgs() << "Reusing RM#"
<< ReuseSlot-VirtRegMap::MAX_STACK_SLOT-1);
else
DEBUG(dbgs() << "Reusing SS#" << ReuseSlot);
DEBUG(dbgs() << " from physreg " << TRI->getName(PhysReg)
<< " for " << PrintReg(VirtReg)
<< " instead of reloading into same physreg.\n");
unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg;
MI.getOperand(i).setReg(RReg);
MI.getOperand(i).setSubReg(0);
ReusedOperands.markClobbered(RReg);
++NumReused;
continue;
}
MRI->setPhysRegUsed(DesignatedReg);
ReusedOperands.markClobbered(DesignatedReg);
MachineBasicBlock::iterator InsertLoc =
ComputeReloadLoc(&MI, MBB->begin(), PhysReg, TRI, DoReMat,
SSorRMId, TII, *MBB->getParent());
MachineInstr *CopyMI = BuildMI(*MBB, InsertLoc, MI.getDebugLoc(),
TII->get(TargetOpcode::COPY),
DesignatedReg).addReg(PhysReg);
CopyMI->setAsmPrinterFlag(MachineInstr::ReloadReuse);
UpdateKills(*CopyMI, TRI, RegKills, KillOps);
Spills.ClobberPhysReg(DesignatedReg);
Spills.addAvailable(ReuseSlot, DesignatedReg);
unsigned RReg =
SubIdx ? TRI->getSubReg(DesignatedReg, SubIdx) : DesignatedReg;
MI.getOperand(i).setReg(RReg);
MI.getOperand(i).setSubReg(0);
DEBUG(dbgs() << '\t' << *prior(InsertLoc));
++NumReused;
continue;
}
PhysReg = VRM->getPhys(VirtReg);
assert(PhysReg && "Must map virtreg to physreg!");
if (ReusedOperands.hasReuses())
PhysReg = ReusedOperands.GetRegForReload(VirtReg, PhysReg, &MI,
Spills, MaybeDeadStores, RegKills, KillOps, *VRM);
MRI->setPhysRegUsed(PhysReg);
ReusedOperands.markClobbered(PhysReg);
if (AvoidReload)
++NumAvoided;
else {
MachineBasicBlock::iterator InsertLoc =
ComputeReloadLoc(MI, MBB->begin(), PhysReg, TRI, DoReMat,
SSorRMId, TII, *MBB->getParent());
if (DoReMat) {
ReMaterialize(*MBB, InsertLoc, PhysReg, VirtReg, TII, TRI, *VRM);
} else {
const TargetRegisterClass* RC = MRI->getRegClass(VirtReg);
TII->loadRegFromStackSlot(*MBB, InsertLoc, PhysReg, SSorRMId, RC,TRI);
MachineInstr *LoadMI = prior(InsertLoc);
VRM->addSpillSlotUse(SSorRMId, LoadMI);
++NumLoads;
DistanceMap.insert(std::make_pair(LoadMI, DistanceMap.size()));
}
Spills.ClobberPhysReg(PhysReg);
if (!DoReMat)
MaybeDeadStores[SSorRMId] = NULL;
Spills.addAvailable(SSorRMId, PhysReg);
if (!MI.isRegTiedToDefOperand(i) &&
KilledMIRegs.count(VirtReg) == 0) {
MI.getOperand(i).setIsKill();
KilledMIRegs.insert(VirtReg);
}
UpdateKills(*prior(InsertLoc), TRI, RegKills, KillOps);
DEBUG(dbgs() << '\t' << *prior(InsertLoc));
}
unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg;
MI.getOperand(i).setReg(RReg);
MI.getOperand(i).setSubReg(0);
}
for (unsigned j = 0, e = PotentialDeadStoreSlots.size(); j != e; ++j) {
int PDSSlot = PotentialDeadStoreSlots[j];
MachineInstr* DeadStore = MaybeDeadStores[PDSSlot];
if (DeadStore) {
DEBUG(dbgs() << "Removed dead store:\t" << *DeadStore);
InvalidateKills(*DeadStore, TRI, RegKills, KillOps);
EraseInstr(DeadStore);
MaybeDeadStores[PDSSlot] = NULL;
++NumDSE;
}
}
}
void
LocalRewriter::RewriteMBB(LiveIntervals *LIs,
AvailableSpills &Spills, BitVector &RegKills,
std::vector<MachineOperand*> &KillOps) {
DEBUG(dbgs() << "\n**** Local spiller rewriting MBB '"
<< MBB->getName() << "':\n");
MachineFunction &MF = *MBB->getParent();
std::vector<MachineInstr*> MaybeDeadStores;
MaybeDeadStores.resize(MF.getFrameInfo()->getObjectIndexEnd(), NULL);
SmallSet<MachineInstr*, 4> ReMatDefs;
SmallSet<unsigned, 8> SpilledMIRegs;
RegKills.reset();
KillOps.clear();
KillOps.resize(TRI->getNumRegs(), NULL);
DistanceMap.clear();
for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end();
MII != E; ) {
MachineBasicBlock::iterator NextMII = llvm::next(MII);
if (OptimizeByUnfold(MII, MaybeDeadStores, Spills, RegKills, KillOps))
NextMII = llvm::next(MII);
if (InsertEmergencySpills(MII))
NextMII = llvm::next(MII);
InsertRestores(MII, Spills, RegKills, KillOps);
if (InsertSpills(MII))
NextMII = llvm::next(MII);
bool Erased = false;
bool BackTracked = false;
MachineInstr &MI = *MII;
if (MI.isDebugValue() && MI.getOperand(0).isFI())
Slot2DbgValues[MI.getOperand(0).getIndex()].push_back(&MI);
ReuseInfo ReusedOperands(MI, TRI);
ProcessUses(MI, Spills, MaybeDeadStores, RegKills, ReusedOperands, KillOps);
DEBUG(dbgs() << '\t' << MI);
SmallVector<std::pair<unsigned, VirtRegMap::ModRef>, 4> FoldedVirts;
for (std::pair<VirtRegMap::MI2VirtMapTy::const_iterator,
VirtRegMap::MI2VirtMapTy::const_iterator> FVRange =
VRM->getFoldedVirts(&MI);
FVRange.first != FVRange.second; ++FVRange.first)
FoldedVirts.push_back(FVRange.first->second);
SmallSet<int, 2> FoldedSS;
for (unsigned FVI = 0, FVE = FoldedVirts.size(); FVI != FVE; ++FVI) {
unsigned VirtReg = FoldedVirts[FVI].first;
VirtRegMap::ModRef MR = FoldedVirts[FVI].second;
DEBUG(dbgs() << "Folded " << PrintReg(VirtReg) << " MR: " << MR);
int SS = VRM->getStackSlot(VirtReg);
if (SS == VirtRegMap::NO_STACK_SLOT)
continue;
FoldedSS.insert(SS);
DEBUG(dbgs() << " - StackSlot: " << SS << "\n");
if ((MR & VirtRegMap::isRef) && !(MR & VirtRegMap::isMod)) {
int FrameIdx;
unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx);
if (DestReg && FrameIdx == SS) {
if (unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SS)) {
DEBUG(dbgs() << "Promoted Load To Copy: " << MI);
if (DestReg != InReg) {
MachineOperand *DefMO = MI.findRegisterDefOperand(DestReg);
MachineInstr *CopyMI = BuildMI(*MBB, &MI, MI.getDebugLoc(),
TII->get(TargetOpcode::COPY))
.addReg(DestReg, RegState::Define, DefMO->getSubReg())
.addReg(InReg, RegState::Kill);
NextMII = CopyMI;
NextMII->setAsmPrinterFlag(MachineInstr::ReloadReuse);
BackTracked = true;
} else {
DEBUG(dbgs() << "Removing now-noop copy: " << MI);
Spills.disallowClobberPhysReg(InReg);
}
InvalidateKills(MI, TRI, RegKills, KillOps);
EraseInstr(&MI);
Erased = true;
goto ProcessNextInst;
}
} else {
unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS);
SmallVector<MachineInstr*, 4> NewMIs;
if (PhysReg &&
TII->unfoldMemoryOperand(MF, &MI, PhysReg, false, false, NewMIs)){
MBB->insert(MII, NewMIs[0]);
InvalidateKills(MI, TRI, RegKills, KillOps);
EraseInstr(&MI);
Erased = true;
--NextMII; BackTracked = true;
goto ProcessNextInst;
}
}
}
MachineInstr* DeadStore = MaybeDeadStores[SS];
if (DeadStore) {
bool isDead = !(MR & VirtRegMap::isRef);
MachineInstr *NewStore = NULL;
if (MR & VirtRegMap::isModRef) {
unsigned PhysReg = Spills.getSpillSlotOrReMatPhysReg(SS);
SmallVector<MachineInstr*, 4> NewMIs;
if (PhysReg &&
!ReusedOperands.isClobbered(PhysReg) &&
Spills.canClobberPhysReg(PhysReg) &&
!TII->isStoreToStackSlot(&MI, SS)) { MachineOperand *KillOpnd =
DeadStore->findRegisterUseOperand(PhysReg, true);
if (KillOpnd && !KillOpnd->getSubReg() &&
TII->unfoldMemoryOperand(MF, &MI, PhysReg, false, true,NewMIs)){
MBB->insert(MII, NewMIs[0]);
NewStore = NewMIs[1];
MBB->insert(MII, NewStore);
VRM->addSpillSlotUse(SS, NewStore);
InvalidateKills(MI, TRI, RegKills, KillOps);
EraseInstr(&MI);
Erased = true;
--NextMII;
--NextMII; BackTracked = true;
isDead = true;
++NumSUnfold;
}
}
}
if (isDead) { DEBUG(dbgs() << "Removed dead store:\t" << *DeadStore);
InvalidateKills(*DeadStore, TRI, RegKills, KillOps);
EraseInstr(DeadStore);
if (!NewStore)
++NumDSE;
}
MaybeDeadStores[SS] = NULL;
if (NewStore) {
VRM->virtFolded(VirtReg, NewStore, VirtRegMap::isMod);
goto ProcessNextInst;
}
}
if (MR & VirtRegMap::isMod) {
Spills.ModifyStackSlotOrReMat(SS);
int StackSlot;
if (!(MR & VirtRegMap::isRef)) {
if (unsigned SrcReg = TII->isStoreToStackSlot(&MI, StackSlot)) {
assert(TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
"Src hasn't been allocated yet?");
if (CommuteToFoldReload(MII, VirtReg, SrcReg, StackSlot,
Spills, RegKills, KillOps, TRI)) {
NextMII = llvm::next(MII);
BackTracked = true;
goto ProcessNextInst;
}
MaybeDeadStores[StackSlot] = &MI;
Spills.addAvailable(StackSlot, SrcReg, MI.killsRegister(SrcReg));
}
}
}
}
SpilledMIRegs.clear();
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI.getOperand(i);
if (!(MO.isReg() && MO.getReg() && MO.isDef()))
continue;
unsigned VirtReg = MO.getReg();
if (!TargetRegisterInfo::isVirtualRegister(VirtReg)) {
if (MI.isIdentityCopy() && !MI.getOperand(1).isUndef() &&
MI.getNumOperands() == 2) {
++NumDCE;
DEBUG(dbgs() << "Removing now-noop copy: " << MI);
SmallVector<unsigned, 2> KillRegs;
InvalidateKills(MI, TRI, RegKills, KillOps, &KillRegs);
if (MO.isDead() && !KillRegs.empty()) {
assert(TRI->regsOverlap(KillRegs[0], MI.getOperand(0).getReg()));
TransferDeadness(MI.getOperand(1).getReg(), RegKills, KillOps);
}
EraseInstr(&MI);
Erased = true;
Spills.disallowClobberPhysReg(VirtReg);
goto ProcessNextInst;
}
Spills.ClobberPhysReg(VirtReg);
ReusedOperands.markClobbered(VirtReg);
int FrameIdx;
if (unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx)) {
assert(DestReg == VirtReg && "Unknown load situation!");
bool Folded = FoldedSS.count(FrameIdx);
Spills.addAvailable(FrameIdx, DestReg, !Folded);
goto ProcessNextInst;
}
continue;
}
unsigned SubIdx = MO.getSubReg();
bool DoReMat = VRM->isReMaterialized(VirtReg);
if (DoReMat)
ReMatDefs.insert(&MI);
int StackSlot = VRM->getStackSlot(VirtReg);
const TargetRegisterClass *RC = MRI->getRegClass(VirtReg);
unsigned PhysReg;
unsigned TiedOp;
if (MI.isRegTiedToUseOperand(i, &TiedOp)) {
PhysReg = MI.getOperand(TiedOp).getReg();
if (SubIdx) {
unsigned SuperReg = findSuperReg(RC, PhysReg, SubIdx, TRI);
assert(SuperReg && TRI->getSubReg(SuperReg, SubIdx) == PhysReg &&
"Can't find corresponding super-register!");
PhysReg = SuperReg;
}
} else {
PhysReg = VRM->getPhys(VirtReg);
if (ReusedOperands.isClobbered(PhysReg)) {
PhysReg = ReusedOperands.GetRegForReload(VirtReg, PhysReg, &MI,
Spills, MaybeDeadStores, RegKills, KillOps, *VRM);
}
}
Spills.ClobberSharingStackSlots(StackSlot);
assert(PhysReg && "VR not assigned a physical register?");
MRI->setPhysRegUsed(PhysReg);
unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg;
ReusedOperands.markClobbered(RReg);
MI.getOperand(i).setReg(RReg);
MI.getOperand(i).setSubReg(0);
if (!MO.isDead() && SpilledMIRegs.insert(VirtReg)) {
MachineInstr *&LastStore = MaybeDeadStores[StackSlot];
SpillRegToStackSlot(MII, -1, PhysReg, StackSlot, RC, true,
LastStore, Spills, ReMatDefs, RegKills, KillOps);
NextMII = llvm::next(MII);
if (MI.isIdentityCopy()) {
++NumDCE;
DEBUG(dbgs() << "Removing now-noop copy: " << MI);
InvalidateKills(MI, TRI, RegKills, KillOps);
EraseInstr(&MI);
Erased = true;
UpdateKills(*LastStore, TRI, RegKills, KillOps);
goto ProcessNextInst;
}
}
}
ProcessNextInst:
if (!Erased && !BackTracked && isSafeToDelete(MI)) {
InvalidateKills(MI, TRI, RegKills, KillOps);
EraseInstr(&MI);
Erased = true;
}
if (!Erased)
DistanceMap.insert(std::make_pair(&MI, DistanceMap.size()));
if (!Erased && !BackTracked) {
for (MachineBasicBlock::iterator II = &MI; II != NextMII; ++II)
UpdateKills(*II, TRI, RegKills, KillOps);
}
MII = NextMII;
}
}
llvm::VirtRegRewriter* llvm::createVirtRegRewriter() {
switch (RewriterOpt) {
default: llvm_unreachable("Unreachable!");
case local:
return new LocalRewriter();
case trivial:
return new TrivialRewriter();
}
}