STATISTIC(NumReused, "Number of values reused");
STATISTIC(NumDSE , "Number of dead stores elided");
STATISTIC(NumDCE , "Number of copies elided");
+STATISTIC(NumDSS , "Number of dead spill slots removed");
namespace {
enum SpillerName { simple, local };
: TII(*mf.getTarget().getInstrInfo()), MF(mf),
Virt2PhysMap(NO_PHYS_REG), Virt2StackSlotMap(NO_STACK_SLOT),
Virt2ReMatIdMap(NO_STACK_SLOT), Virt2SplitMap(0),
- Virt2SplitKillMap(0), ReMatMap(NULL), ReMatId(MAX_STACK_SLOT+1) {
+ Virt2SplitKillMap(0), ReMatMap(NULL), ReMatId(MAX_STACK_SLOT+1),
+ LowSpillSlot(NO_STACK_SLOT), HighSpillSlot(NO_STACK_SLOT) {
+ SpillSlotToUsesMap.resize(8);
grow();
}
assert(Virt2StackSlotMap[virtReg] == NO_STACK_SLOT &&
"attempt to assign stack slot to already spilled register");
const TargetRegisterClass* RC = MF.getRegInfo().getRegClass(virtReg);
- int frameIndex = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
- RC->getAlignment());
- Virt2StackSlotMap[virtReg] = frameIndex;
+ int SS = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
+ RC->getAlignment());
+ if (LowSpillSlot == NO_STACK_SLOT)
+ LowSpillSlot = SS;
+ if (HighSpillSlot == NO_STACK_SLOT || SS > HighSpillSlot)
+ HighSpillSlot = SS;
+ unsigned Idx = SS-LowSpillSlot;
+ while (Idx >= SpillSlotToUsesMap.size())
+ SpillSlotToUsesMap.resize(SpillSlotToUsesMap.size()*2);
+ Virt2StackSlotMap[virtReg] = SS;
++NumSpills;
- return frameIndex;
+ return SS;
}
-void VirtRegMap::assignVirt2StackSlot(unsigned virtReg, int frameIndex) {
+void VirtRegMap::assignVirt2StackSlot(unsigned virtReg, int SS) {
assert(TargetRegisterInfo::isVirtualRegister(virtReg));
assert(Virt2StackSlotMap[virtReg] == NO_STACK_SLOT &&
"attempt to assign stack slot to already spilled register");
- assert((frameIndex >= 0 ||
- (frameIndex >= MF.getFrameInfo()->getObjectIndexBegin())) &&
+ assert((SS >= 0 ||
+ (SS >= MF.getFrameInfo()->getObjectIndexBegin())) &&
"illegal fixed frame index");
- Virt2StackSlotMap[virtReg] = frameIndex;
+ Virt2StackSlotMap[virtReg] = SS;
}
int VirtRegMap::assignVirtReMatId(unsigned virtReg) {
Virt2ReMatIdMap[virtReg] = id;
}
+void VirtRegMap::addSpillSlotUse(int FI, MachineInstr *MI) {
+ if (!MF.getFrameInfo()->isFixedObjectIndex(FI)) {
+ assert(FI >= 0 && "Spill slot index should not be negative!");
+ SpillSlotToUsesMap[FI-LowSpillSlot].insert(MI);
+ }
+}
+
void VirtRegMap::virtFolded(unsigned VirtReg, MachineInstr *OldMI,
MachineInstr *NewMI, ModRef MRInfo) {
// Move previous memory references folded to new instruction.
MI2VirtMap.insert(IP, std::make_pair(MI, std::make_pair(VirtReg, MRInfo)));
}
+void VirtRegMap::RemoveMachineInstrFromMaps(MachineInstr *MI) {
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand &MO = MI->getOperand(i);
+ if (!MO.isFrameIndex())
+ continue;
+ int FI = MO.getIndex();
+ if (MF.getFrameInfo()->isFixedObjectIndex(FI))
+ continue;
+ SpillSlotToUsesMap[FI-LowSpillSlot].erase(MI);
+ }
+ MI2VirtMap.erase(MI);
+ SpillPt2VirtMap.erase(MI);
+ RestorePt2VirtMap.erase(MI);
+}
+
void VirtRegMap::print(std::ostream &OS) const {
const TargetRegisterInfo* TRI = MF.getTarget().getRegisterInfo();
std::find(LoadedRegs.begin(), LoadedRegs.end(), VirtReg)
== LoadedRegs.end()) {
TII.loadRegFromStackSlot(MBB, &MI, PhysReg, StackSlot, RC);
+ MachineInstr *LoadMI = prior(MII);
+ VRM.addSpillSlotUse(StackSlot, LoadMI);
LoadedRegs.push_back(VirtReg);
++NumLoads;
- DOUT << '\t' << *prior(MII);
+ DOUT << '\t' << *LoadMI;
}
if (MO.isDef()) {
TII.storeRegToStackSlot(MBB, next(MII), PhysReg, true,
StackSlot, RC);
+ MachineInstr *StoreMI = next(MII);
+ VRM.addSpillSlotUse(StackSlot, StoreMI);
++NumStores;
}
}
MBB != E; ++MBB)
RewriteMBB(*MBB, VRM);
+ // Mark unused spill slots.
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ int SS = VRM.getLowSpillSlot();
+ if (SS != VirtRegMap::NO_STACK_SLOT)
+ for (int e = VRM.getHighSpillSlot(); SS <= e; ++SS)
+ if (!VRM.isSpillSlotUsed(SS)) {
+ MFI->RemoveStackObject(SS);
+ ++NumDSS;
+ }
+
DOUT << "**** Post Machine Instrs ****\n";
DEBUG(MF.dump());
} else {
TII->loadRegFromStackSlot(*MBB, MII, NewPhysReg,
NewOp.StackSlotOrReMat, AliasRC);
+ MachineInstr *LoadMI = prior(MII);
+ VRM.addSpillSlotUse(NewOp.StackSlotOrReMat, LoadMI);
// Any stores to this stack slot are not dead anymore.
MaybeDeadStores[NewOp.StackSlotOrReMat] = NULL;
++NumLoads;
std::vector<MachineOperand*> &KillOps,
VirtRegMap &VRM) {
TII->storeRegToStackSlot(MBB, next(MII), PhysReg, true, StackSlot, RC);
- DOUT << "Store:\t" << *next(MII);
+ MachineInstr *StoreMI = next(MII);
+ VRM.addSpillSlotUse(StackSlot, StoreMI);
+ DOUT << "Store:\t" << *StoreMI;
// If there is a dead store to this stack slot, nuke it now.
if (LastStore) {
bool CheckDef = PrevMII != MBB.begin();
if (CheckDef)
--PrevMII;
- MBB.erase(LastStore);
VRM.RemoveMachineInstrFromMaps(LastStore);
+ MBB.erase(LastStore);
if (CheckDef) {
// Look at defs of killed registers on the store. Mark the defs
// as dead since the store has been deleted and they aren't
if (ReMatDefs.count(DeadDef) && !HasOtherDef) {
// FIXME: This assumes a remat def does not have side
// effects.
- MBB.erase(DeadDef);
VRM.RemoveMachineInstrFromMaps(DeadDef);
+ MBB.erase(DeadDef);
++NumDRM;
}
}
ReMaterialize(MBB, MII, Phys, VirtReg, TRI, VRM);
} else {
const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg);
- TII->loadRegFromStackSlot(MBB, &MI, Phys, VRM.getStackSlot(VirtReg),
- RC);
+ int SS = VRM.getStackSlot(VirtReg);
+ TII->loadRegFromStackSlot(MBB, &MI, Phys, SS, RC);
+ MachineInstr *LoadMI = prior(MII);
+ VRM.addSpillSlotUse(SS, LoadMI);
++NumLoads;
}
// This invalidates Phys.
int StackSlot = VRM.getStackSlot(VirtReg);
TII->storeRegToStackSlot(MBB, next(MII), Phys, isKill, StackSlot, RC);
MachineInstr *StoreMI = next(MII);
+ VRM.addSpillSlotUse(StackSlot, StoreMI);
DOUT << "Store:\t" << StoreMI;
VRM.virtFolded(VirtReg, StoreMI, VirtRegMap::isMod);
}
} else {
const TargetRegisterClass* RC = RegInfo->getRegClass(VirtReg);
TII->loadRegFromStackSlot(MBB, &MI, PhysReg, SSorRMId, RC);
+ MachineInstr *LoadMI = prior(MII);
+ VRM.addSpillSlotUse(SSorRMId, LoadMI);
++NumLoads;
}
// This invalidates PhysReg.
if (TII->isMoveInstr(MI, Src, Dst) && Src == Dst) {
++NumDCE;
DOUT << "Removing now-noop copy: " << MI;
+ VRM.RemoveMachineInstrFromMaps(&MI);
MBB.erase(&MI);
Erased = true;
- VRM.RemoveMachineInstrFromMaps(&MI);
Spills.disallowClobberPhysReg(VirtReg);
goto ProcessNextInst;
}
if (TII->isMoveInstr(MI, Src, Dst) && Src == Dst) {
++NumDCE;
DOUT << "Removing now-noop copy: " << MI;
+ VRM.RemoveMachineInstrFromMaps(&MI);
MBB.erase(&MI);
Erased = true;
- VRM.RemoveMachineInstrFromMaps(&MI);
UpdateKills(*LastStore, RegKills, KillOps);
goto ProcessNextInst;
}
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Streams.h"
#include <map>
/// conflicts with stack slot numbers.
int ReMatId;
+ /// LowSpillSlot, HighSpillSlot - Lowest and highest spill slot indexes.
+ int LowSpillSlot, HighSpillSlot;
+
+ /// SpillSlotToUsesMap - Records uses for each register spill slot.
+ SmallVector<SmallPtrSet<MachineInstr*, 4>, 8> SpillSlotToUsesMap;
+
VirtRegMap(const VirtRegMap&); // DO NOT IMPLEMENT
void operator=(const VirtRegMap&); // DO NOT IMPLEMENT
RestorePt2VirtMap.erase(I);
}
+ /// @brief Return lowest spill slot index.
+ int getLowSpillSlot() const {
+ return LowSpillSlot;
+ }
+
+ /// @brief Return highest spill slot index.
+ int getHighSpillSlot() const {
+ return HighSpillSlot;
+ }
+
+ /// @brief Records a spill slot use.
+ void addSpillSlotUse(int FrameIndex, MachineInstr *MI);
+
+ /// @brief Returns true if spill slot has been used.
+ bool isSpillSlotUsed(int FrameIndex) const {
+ assert(FrameIndex >= 0 && "Spill slot index should not be negative!");
+ return !SpillSlotToUsesMap[FrameIndex-LowSpillSlot].empty();
+ }
+
/// @brief Updates information about the specified virtual register's value
/// folded into newMI machine instruction.
void virtFolded(unsigned VirtReg, MachineInstr *OldMI, MachineInstr *NewMI,
/// RemoveMachineInstrFromMaps - MI is being erased, remove it from the
/// the folded instruction map and spill point map.
- void RemoveMachineInstrFromMaps(MachineInstr *MI) {
- MI2VirtMap.erase(MI);
- SpillPt2VirtMap.erase(MI);
- RestorePt2VirtMap.erase(MI);
- }
+ void RemoveMachineInstrFromMaps(MachineInstr *MI);
void print(std::ostream &OS) const;
void print(std::ostream *OS) const { if (OS) print(*OS); }