Newer
Older
Dan Gohman
committed
unsigned ImpUse = getReMatImplicitUse(li, MI);
if (ImpUse) {
const LiveInterval &ImpLi = getInterval(ImpUse);
for (MachineRegisterInfo::use_iterator ri = mri_->use_begin(li.reg),
re = mri_->use_end(); ri != re; ++ri) {
MachineInstr *UseMI = &*ri;
unsigned UseIdx = getInstructionIndex(UseMI);
if (li.FindLiveRangeContaining(UseIdx)->valno != ValNo)
continue;
if (!isValNoAvailableAt(ImpLi, MI, UseIdx))
return false;
}
// If a register operand of the re-materialized instruction is going to
// be spilled next, then it's not legal to re-materialize this instruction.
for (unsigned i = 0, e = SpillIs.size(); i != e; ++i)
if (ImpUse == SpillIs[i]->reg)
return false;
Dan Gohman
committed
}
return true;
Evan Cheng
committed
}
Evan Cheng
committed
/// isReMaterializable - Returns true if the definition MI of the specified
/// val# of the specified interval is re-materializable.
bool LiveIntervals::isReMaterializable(const LiveInterval &li,
const VNInfo *ValNo, MachineInstr *MI) {
SmallVector<LiveInterval*, 4> Dummy1;
bool Dummy2;
return isReMaterializable(li, ValNo, MI, Dummy1, Dummy2);
}
Evan Cheng
committed
/// isReMaterializable - Returns true if every definition of MI of every
/// val# of the specified interval is re-materializable.
bool LiveIntervals::isReMaterializable(const LiveInterval &li,
SmallVectorImpl<LiveInterval*> &SpillIs,
bool &isLoad) {
Evan Cheng
committed
isLoad = false;
for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end();
i != e; ++i) {
const VNInfo *VNI = *i;
unsigned DefIdx = VNI->def;
if (DefIdx == ~1U)
continue; // Dead val#.
// Is the def for the val# rematerializable?
if (DefIdx == ~0u)
return false;
MachineInstr *ReMatDefMI = getInstructionFromIndex(DefIdx);
bool DefIsLoad = false;
Evan Cheng
committed
if (!ReMatDefMI ||
!isReMaterializable(li, VNI, ReMatDefMI, SpillIs, DefIsLoad))
Evan Cheng
committed
isLoad |= DefIsLoad;
/// FilterFoldedOps - Filter out two-address use operands. Return
/// true if it finds any issue with the operands that ought to prevent
/// folding.
static bool FilterFoldedOps(MachineInstr *MI,
SmallVector<unsigned, 2> &Ops,
unsigned &MRInfo,
SmallVector<unsigned, 2> &FoldOps) {
const TargetInstrDesc &TID = MI->getDesc();
MRInfo = 0;
for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
unsigned OpIdx = Ops[i];
Evan Cheng
committed
MachineOperand &MO = MI->getOperand(OpIdx);
// FIXME: fold subreg use.
Evan Cheng
committed
if (MO.getSubReg())
return true;
Evan Cheng
committed
if (MO.isDef())
MRInfo |= (unsigned)VirtRegMap::isMod;
else {
// Filter out two-address use operand(s).
Evan Cheng
committed
if (!MO.isImplicit() &&
TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) {
MRInfo = VirtRegMap::isModRef;
continue;
}
MRInfo |= (unsigned)VirtRegMap::isRef;
}
FoldOps.push_back(OpIdx);
Evan Cheng
committed
}
return false;
}
/// tryFoldMemoryOperand - Attempts to fold either a spill / restore from
/// slot / to reg or any rematerialized load into ith operand of specified
/// MI. If it is successul, MI is updated with the newly created MI and
/// returns true.
bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI,
VirtRegMap &vrm, MachineInstr *DefMI,
unsigned InstrIdx,
SmallVector<unsigned, 2> &Ops,
bool isSS, int Slot, unsigned Reg) {
// If it is an implicit def instruction, just delete it.
if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
RemoveMachineInstrFromMaps(MI);
vrm.RemoveMachineInstrFromMaps(MI);
MI->eraseFromParent();
++numFolds;
return true;
}
// Filter the list of operand indexes that are to be folded. Abort if
// any operand will prevent folding.
unsigned MRInfo = 0;
SmallVector<unsigned, 2> FoldOps;
if (FilterFoldedOps(MI, Ops, MRInfo, FoldOps))
return false;
Evan Cheng
committed
Evan Cheng
committed
// The only time it's safe to fold into a two address instruction is when
// it's folding reload and spill from / into a spill stack slot.
if (DefMI && (MRInfo & VirtRegMap::isMod))
Evan Cheng
committed
return false;
MachineInstr *fmi = isSS ? tii_->foldMemoryOperand(*mf_, MI, FoldOps, Slot)
: tii_->foldMemoryOperand(*mf_, MI, FoldOps, DefMI);
// Remember this instruction uses the spill slot.
if (isSS) vrm.addSpillSlotUse(Slot, fmi);
// Attempt to fold the memory reference into the instruction. If
// we can do this, we don't need to insert spill code.
MachineBasicBlock &MBB = *MI->getParent();
if (isSS && !mf_->getFrameInfo()->isImmutableObjectIndex(Slot))
vrm.virtFolded(Reg, MI, fmi, (VirtRegMap::ModRef)MRInfo);
vrm.transferRestorePts(MI, fmi);
vrm.transferEmergencySpills(MI, fmi);
Evan Cheng
committed
i2miMap_[InstrIdx /InstrSlots::NUM] = fmi;
mi2iMap_[fmi] = InstrIdx;
++numFolds;
Evan Cheng
committed
/// canFoldMemoryOperand - Returns true if the specified load / store
/// folding is possible.
bool LiveIntervals::canFoldMemoryOperand(MachineInstr *MI,
SmallVector<unsigned, 2> &Ops,
// Filter the list of operand indexes that are to be folded. Abort if
// any operand will prevent folding.
unsigned MRInfo = 0;
Evan Cheng
committed
SmallVector<unsigned, 2> FoldOps;
if (FilterFoldedOps(MI, Ops, MRInfo, FoldOps))
return false;
Evan Cheng
committed
// It's only legal to remat for a use, not a def.
if (ReMat && (MRInfo & VirtRegMap::isMod))
return false;
Evan Cheng
committed
Evan Cheng
committed
return tii_->canFoldMemoryOperand(MI, FoldOps);
}
bool LiveIntervals::intervalIsInOneMBB(const LiveInterval &li) const {
SmallPtrSet<MachineBasicBlock*, 4> MBBs;
for (LiveInterval::Ranges::const_iterator
I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) {
std::vector<IdxMBBPair>::const_iterator II =
std::lower_bound(Idx2MBBMap.begin(), Idx2MBBMap.end(), I->start);
if (II == Idx2MBBMap.end())
continue;
if (I->end > II->first) // crossing a MBB.
return false;
MBBs.insert(II->second);
if (MBBs.size() > 1)
return false;
}
return true;
}
Evan Cheng
committed
/// rewriteImplicitOps - Rewrite implicit use operands of MI (i.e. uses of
/// interval on to-be re-materialized operands of MI) with new register.
void LiveIntervals::rewriteImplicitOps(const LiveInterval &li,
MachineInstr *MI, unsigned NewVReg,
VirtRegMap &vrm) {
// There is an implicit use. That means one of the other operand is
// being remat'ed and the remat'ed instruction has li.reg as an
// use operand. Make sure we rewrite that as well.
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg())
Evan Cheng
committed
continue;
unsigned Reg = MO.getReg();
if (Reg == 0 || TargetRegisterInfo::isPhysicalRegister(Reg))
continue;
if (!vrm.isReMaterialized(Reg))
continue;
MachineInstr *ReMatMI = vrm.getReMaterializedMI(Reg);
MachineOperand *UseMO = ReMatMI->findRegisterUseOperand(li.reg);
if (UseMO)
UseMO->setReg(NewVReg);
Evan Cheng
committed
}
}
/// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper functions
/// for addIntervalsForSpills to rewrite uses / defs for the given live range.
Evan Cheng
committed
bool LiveIntervals::
Evan Cheng
committed
rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI,
bool TrySplit, unsigned index, unsigned end, MachineInstr *MI,
MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI,
unsigned Slot, int LdSlot,
bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete,
Evan Cheng
committed
VirtRegMap &vrm,
const TargetRegisterClass* rc,
SmallVector<int, 4> &ReMatIds,
unsigned &NewVReg, unsigned ImpUse, bool &HasDef, bool &HasUse,
DenseMap<unsigned,unsigned> &MBBVRegsMap,
std::vector<LiveInterval*> &NewLIs, float &SSWeight) {
MachineBasicBlock *MBB = MI->getParent();
unsigned loopDepth = loopInfo->getLoopDepth(MBB);
Evan Cheng
committed
bool CanFold = false;
RestartInstruction:
for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
MachineOperand& mop = MI->getOperand(i);
if (!mop.isReg())
continue;
unsigned Reg = mop.getReg();
unsigned RegI = Reg;
if (Reg == 0 || TargetRegisterInfo::isPhysicalRegister(Reg))
continue;
if (Reg != li.reg)
continue;
bool TryFold = !DefIsReMat;
bool FoldSS = true; // Default behavior unless it's a remat.
int FoldSlot = Slot;
if (DefIsReMat) {
// If this is the rematerializable definition MI itself and
// all of its uses are rematerialized, simply delete it.
Evan Cheng
committed
DOUT << "\t\t\t\tErasing re-materlizable def: ";
DOUT << MI << '\n';
MI->eraseFromParent();
break;
}
// If def for this use can't be rematerialized, then try folding.
// If def is rematerializable and it's a load, also try folding.
TryFold = !ReMatDefMI || (ReMatDefMI && (MI == ReMatOrigDefMI || isLoad));
if (isLoad) {
// Try fold loads (from stack slot, constant pool, etc.) into uses.
FoldSS = isLoadSS;
FoldSlot = LdSlot;
}
}
// Scan all of the operands of this instruction rewriting operands
// to use NewVReg instead of li.reg as appropriate. We do this for
// two reasons:
//
// 1. If the instr reads the same spilled vreg multiple times, we
// want to reuse the NewVReg.
// 2. If the instr is a two-addr instruction, we are required to
// keep the src/dst regs pinned.
//
// Keep track of whether we replace a use and/or def so that we can
// create the spill interval with the appropriate range.
Evan Cheng
committed
SmallVector<unsigned, 2> Ops;
Ops.push_back(i);
for (unsigned j = i+1, e = MI->getNumOperands(); j != e; ++j) {
const MachineOperand &MOj = MI->getOperand(j);
if (!MOj.isReg())
unsigned RegJ = MOj.getReg();
if (RegJ == 0 || TargetRegisterInfo::isPhysicalRegister(RegJ))
Ops.push_back(j);
HasUse |= MOj.isUse();
HasDef |= MOj.isDef();
Evan Cheng
committed
if (HasUse && !li.liveAt(getUseIndex(index)))
// Must be defined by an implicit def. It should not be spilled. Note,
// this is for correctness reason. e.g.
// 8 %reg1024<def> = IMPLICIT_DEF
// 12 %reg1024<def> = INSERT_SUBREG %reg1024<kill>, %reg1025, 2
// The live range [12, 14) are not part of the r1024 live interval since
// it's defined by an implicit def. It will not conflicts with live
// interval of r1025. Now suppose both registers are spilled, you can
Evan Cheng
committed
// the INSERT_SUBREG and both target registers that would overlap.
HasUse = false;
// Update stack slot spill weight if we are splitting.
float Weight = getSpillWeight(HasDef, HasUse, loopDepth);
if (!TrySplit)
SSWeight += Weight;
// Create a new virtual register for the spill interval.
// Create the new register now so we can map the fold instruction
// to the new register so when it is unfolded we get the correct
// answer.
bool CreatedNewVReg = false;
if (NewVReg == 0) {
NewVReg = mri_->createVirtualRegister(rc);
vrm.grow();
CreatedNewVReg = true;
}
if (!TryFold)
CanFold = false;
else {
Evan Cheng
committed
// Do not fold load / store here if we are splitting. We'll find an
// optimal point to insert a load / store later.
if (!TrySplit) {
if (tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index,
Evan Cheng
committed
// Folding the load/store can completely change the instruction in
// unpredictable ways, rescan it from the beginning.
if (FoldSS) {
// We need to give the new vreg the same stack slot as the
// spilled interval.
vrm.assignVirt2StackSlot(NewVReg, FoldSlot);
}
Evan Cheng
committed
HasUse = false;
HasDef = false;
CanFold = false;
if (isRemoved(MI)) {
SSWeight -= Weight;
Evan Cheng
committed
break;
Evan Cheng
committed
goto RestartInstruction;
}
} else {
// We'll try to fold it later if it's profitable.
CanFold = canFoldMemoryOperand(MI, Ops, DefIsReMat);
Evan Cheng
committed
}
Evan Cheng
committed
mop.setReg(NewVReg);
Evan Cheng
committed
if (mop.isImplicit())
rewriteImplicitOps(li, MI, NewVReg, vrm);
Evan Cheng
committed
// Reuse NewVReg for other reads.
Evan Cheng
committed
for (unsigned j = 0, e = Ops.size(); j != e; ++j) {
MachineOperand &mopj = MI->getOperand(Ops[j]);
mopj.setReg(NewVReg);
if (mopj.isImplicit())
rewriteImplicitOps(li, MI, NewVReg, vrm);
}
Evan Cheng
committed
if (CreatedNewVReg) {
if (DefIsReMat) {
vrm.setVirtIsReMaterialized(NewVReg, ReMatDefMI/*, CanDelete*/);
Evan Cheng
committed
if (ReMatIds[VNI->id] == VirtRegMap::MAX_STACK_SLOT) {
Evan Cheng
committed
ReMatIds[VNI->id] = vrm.assignVirtReMatId(NewVReg);
Evan Cheng
committed
vrm.assignVirtReMatId(NewVReg, ReMatIds[VNI->id]);
}
if (!CanDelete || (HasUse && HasDef)) {
// If this is a two-addr instruction then its use operands are
// rematerializable but its def is not. It should be assigned a
// stack slot.
vrm.assignVirt2StackSlot(NewVReg, Slot);
}
} else {
vrm.assignVirt2StackSlot(NewVReg, Slot);
}
} else if (HasUse && HasDef &&
vrm.getStackSlot(NewVReg) == VirtRegMap::NO_STACK_SLOT) {
// If this interval hasn't been assigned a stack slot (because earlier
// def is a deleted remat def), do it now.
assert(Slot != VirtRegMap::NO_STACK_SLOT);
vrm.assignVirt2StackSlot(NewVReg, Slot);
// Re-matting an instruction with virtual register use. Add the
// register as an implicit use on the use MI.
if (DefIsReMat && ImpUse)
MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true));
// create a new register interval for this spill / remat.
LiveInterval &nI = getOrCreateInterval(NewVReg);
if (CreatedNewVReg) {
NewLIs.push_back(&nI);
MBBVRegsMap.insert(std::make_pair(MI->getParent()->getNumber(), NewVReg));
if (TrySplit)
vrm.setIsSplitFromReg(NewVReg, li.reg);
}
if (CreatedNewVReg) {
LiveRange LR(getLoadIndex(index), getUseIndex(index)+1,
nI.getNextValue(~0U, 0, VNInfoAllocator));
DOUT << " +" << LR;
nI.addRange(LR);
} else {
// Extend the split live interval to this def / use.
unsigned End = getUseIndex(index)+1;
LiveRange LR(nI.ranges[nI.ranges.size()-1].end, End,
nI.getValNumInfo(nI.getNumValNums()-1));
DOUT << " +" << LR;
nI.addRange(LR);
}
}
if (HasDef) {
LiveRange LR(getDefIndex(index), getStoreIndex(index),
nI.getNextValue(~0U, 0, VNInfoAllocator));
DOUT << " +" << LR;
nI.addRange(LR);
}
Evan Cheng
committed
return CanFold;
bool LiveIntervals::anyKillInMBBAfterIdx(const LiveInterval &li,
const VNInfo *VNI,
MachineBasicBlock *MBB, unsigned Idx) const {
for (unsigned j = 0, ee = VNI->kills.size(); j != ee; ++j) {
unsigned KillIdx = VNI->kills[j];
if (KillIdx > Idx && KillIdx < End)
return true;
/// RewriteInfo - Keep track of machine instrs that will be rewritten
/// during spilling.
namespace {
struct RewriteInfo {
unsigned Index;
MachineInstr *MI;
bool HasUse;
bool HasDef;
RewriteInfo(unsigned i, MachineInstr *mi, bool u, bool d)
: Index(i), MI(mi), HasUse(u), HasDef(d) {}
};
struct RewriteInfoCompare {
bool operator()(const RewriteInfo &LHS, const RewriteInfo &RHS) const {
return LHS.Index < RHS.Index;
}
};
}
rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit,
MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI,
unsigned Slot, int LdSlot,
bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete,
Evan Cheng
committed
VirtRegMap &vrm,
const TargetRegisterClass* rc,
SmallVector<int, 4> &ReMatIds,
DenseMap<unsigned, std::vector<SRInfo> > &SpillIdxes,
BitVector &RestoreMBBs,
DenseMap<unsigned, std::vector<SRInfo> > &RestoreIdxes,
DenseMap<unsigned,unsigned> &MBBVRegsMap,
std::vector<LiveInterval*> &NewLIs, float &SSWeight) {
Evan Cheng
committed
bool AllCanFold = true;
unsigned start = getBaseIndex(I->start);
unsigned end = getBaseIndex(I->end-1) + InstrSlots::NUM;
// First collect all the def / use in this live range that will be rewritten.
Evan Cheng
committed
// Make sure they are sorted according to instruction index.
std::vector<RewriteInfo> RewriteMIs;
Evan Cheng
committed
for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(li.reg),
re = mri_->reg_end(); ri != re; ) {
MachineInstr *MI = &*ri;
MachineOperand &O = ri.getOperand();
++ri;
Evan Cheng
committed
assert(!O.isImplicit() && "Spilling register that's used as implicit use?");
unsigned index = getInstructionIndex(MI);
if (index < start || index >= end)
continue;
Evan Cheng
committed
if (O.isUse() && !li.liveAt(getUseIndex(index)))
// Must be defined by an implicit def. It should not be spilled. Note,
// this is for correctness reason. e.g.
// 8 %reg1024<def> = IMPLICIT_DEF
// 12 %reg1024<def> = INSERT_SUBREG %reg1024<kill>, %reg1025, 2
// The live range [12, 14) are not part of the r1024 live interval since
// it's defined by an implicit def. It will not conflicts with live
// interval of r1025. Now suppose both registers are spilled, you can
Evan Cheng
committed
// the INSERT_SUBREG and both target registers that would overlap.
continue;
RewriteMIs.push_back(RewriteInfo(index, MI, O.isUse(), O.isDef()));
}
std::sort(RewriteMIs.begin(), RewriteMIs.end(), RewriteInfoCompare());
unsigned ImpUse = DefIsReMat ? getReMatImplicitUse(li, ReMatDefMI) : 0;
// Now rewrite the defs and uses.
for (unsigned i = 0, e = RewriteMIs.size(); i != e; ) {
RewriteInfo &rwi = RewriteMIs[i];
++i;
unsigned index = rwi.Index;
bool MIHasUse = rwi.HasUse;
bool MIHasDef = rwi.HasDef;
MachineInstr *MI = rwi.MI;
// If MI def and/or use the same register multiple times, then there
// are multiple entries.
while (i != e && RewriteMIs[i].MI == MI) {
assert(RewriteMIs[i].Index == index);
bool isUse = RewriteMIs[i].HasUse;
if (isUse) ++NumUses;
MIHasUse |= isUse;
MIHasDef |= RewriteMIs[i].HasDef;
++i;
}
if (ImpUse && MI != ReMatDefMI) {
// Re-matting an instruction with virtual register use. Update the
Evan Cheng
committed
// register interval's spill weight to HUGE_VALF to prevent it from
// being spilled.
Evan Cheng
committed
ImpLi.weight = HUGE_VALF;
unsigned MBBId = MBB->getNumber();
Evan Cheng
committed
unsigned ThisVReg = 0;
DenseMap<unsigned,unsigned>::iterator NVI = MBBVRegsMap.find(MBBId);
if (NVI != MBBVRegsMap.end()) {
Evan Cheng
committed
ThisVReg = NVI->second;
// One common case:
// x = use
// ...
// ...
// def = ...
// = use
// It's better to start a new interval to avoid artifically
// extend the new interval.
if (MIHasDef && !MIHasUse) {
MBBVRegsMap.erase(MBB->getNumber());
Evan Cheng
committed
ThisVReg = 0;
}
}
Evan Cheng
committed
bool IsNew = ThisVReg == 0;
if (IsNew) {
// This ends the previous live interval. If all of its def / use
// can be folded, give it a low spill weight.
if (NewVReg && TrySplit && AllCanFold) {
LiveInterval &nI = getOrCreateInterval(NewVReg);
nI.weight /= 10.0F;
}
AllCanFold = true;
}
NewVReg = ThisVReg;
Evan Cheng
committed
bool CanFold = rewriteInstructionForSpills(li, I->valno, TrySplit,
index, end, MI, ReMatOrigDefMI, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
CanDelete, vrm, rc, ReMatIds, loopInfo, NewVReg,
ImpUse, HasDef, HasUse, MBBVRegsMap, NewLIs, SSWeight);
Evan Cheng
committed
AllCanFold &= CanFold;
// Update weight of spill interval.
LiveInterval &nI = getOrCreateInterval(NewVReg);
// The spill weight is now infinity as it cannot be spilled again.
nI.weight = HUGE_VALF;
continue;
}
// Keep track of the last def and first use in each MBB.
if (HasDef) {
if (MI != ReMatOrigDefMI || !CanDelete) {
bool HasKill = false;
if (!HasUse)
HasKill = anyKillInMBBAfterIdx(li, I->valno, MBB, getDefIndex(index));
else {
// If this is a two-address code, then this index starts a new VNInfo.
const VNInfo *VNI = li.findDefinedVNInfo(getDefIndex(index));
if (VNI)
HasKill = anyKillInMBBAfterIdx(li, VNI, MBB, getDefIndex(index));
DenseMap<unsigned, std::vector<SRInfo> >::iterator SII =
SpillIdxes.find(MBBId);
if (!HasKill) {
if (SII == SpillIdxes.end()) {
std::vector<SRInfo> S;
S.push_back(SRInfo(index, NewVReg, true));
SpillIdxes.insert(std::make_pair(MBBId, S));
} else if (SII->second.back().vreg != NewVReg) {
SII->second.push_back(SRInfo(index, NewVReg, true));
} else if ((int)index > SII->second.back().index) {
// If there is an earlier def and this is a two-address
// instruction, then it's not possible to fold the store (which
// would also fold the load).
SRInfo &Info = SII->second.back();
Info.index = index;
Info.canFold = !HasUse;
SpillMBBs.set(MBBId);
} else if (SII != SpillIdxes.end() &&
SII->second.back().vreg == NewVReg &&
(int)index > SII->second.back().index) {
// There is an earlier def that's not killed (must be two-address).
// The spill is no longer needed.
SII->second.pop_back();
if (SII->second.empty()) {
SpillIdxes.erase(MBBId);
SpillMBBs.reset(MBBId);
}
if (HasUse) {
DenseMap<unsigned, std::vector<SRInfo> >::iterator SII =
SpillIdxes.find(MBBId);
if (SII != SpillIdxes.end() &&
SII->second.back().vreg == NewVReg &&
(int)index > SII->second.back().index)
// Use(s) following the last def, it's not safe to fold the spill.
SII->second.back().canFold = false;
DenseMap<unsigned, std::vector<SRInfo> >::iterator RII =
RestoreIdxes.find(MBBId);
if (RII != RestoreIdxes.end() && RII->second.back().vreg == NewVReg)
// If we are splitting live intervals, only fold if it's the first
// use and there isn't another use later in the MBB.
RII->second.back().canFold = false;
else if (IsNew) {
// Only need a reload if there isn't an earlier def / use.
if (RII == RestoreIdxes.end()) {
std::vector<SRInfo> Infos;
Infos.push_back(SRInfo(index, NewVReg, true));
RestoreIdxes.insert(std::make_pair(MBBId, Infos));
} else {
RII->second.push_back(SRInfo(index, NewVReg, true));
}
RestoreMBBs.set(MBBId);
}
// Update spill weight.
unsigned loopDepth = loopInfo->getLoopDepth(MBB);
nI.weight += getSpillWeight(HasDef, HasUse, loopDepth);
Evan Cheng
committed
if (NewVReg && TrySplit && AllCanFold) {
// If all of its def / use can be folded, give it a low spill weight.
LiveInterval &nI = getOrCreateInterval(NewVReg);
nI.weight /= 10.0F;
}
bool LiveIntervals::alsoFoldARestore(int Id, int index, unsigned vr,
BitVector &RestoreMBBs,
DenseMap<unsigned,std::vector<SRInfo> > &RestoreIdxes) {
if (!RestoreMBBs[Id])
return false;
std::vector<SRInfo> &Restores = RestoreIdxes[Id];
for (unsigned i = 0, e = Restores.size(); i != e; ++i)
if (Restores[i].index == index &&
Restores[i].vreg == vr &&
Restores[i].canFold)
return true;
return false;
}
void LiveIntervals::eraseRestoreInfo(int Id, int index, unsigned vr,
BitVector &RestoreMBBs,
DenseMap<unsigned,std::vector<SRInfo> > &RestoreIdxes) {
if (!RestoreMBBs[Id])
return;
std::vector<SRInfo> &Restores = RestoreIdxes[Id];
for (unsigned i = 0, e = Restores.size(); i != e; ++i)
if (Restores[i].index == index && Restores[i].vreg)
Restores[i].index = -1;
}
Evan Cheng
committed
/// handleSpilledImpDefs - Remove IMPLICIT_DEF instructions which are being
/// spilled and create empty intervals for their uses.
void
LiveIntervals::handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm,
const TargetRegisterClass* rc,
std::vector<LiveInterval*> &NewLIs) {
for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(li.reg),
re = mri_->reg_end(); ri != re; ) {
Evan Cheng
committed
MachineOperand &O = ri.getOperand();
MachineInstr *MI = &*ri;
++ri;
Evan Cheng
committed
if (O.isDef()) {
assert(MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF &&
"Register def was not rewritten?");
RemoveMachineInstrFromMaps(MI);
vrm.RemoveMachineInstrFromMaps(MI);
MI->eraseFromParent();
} else {
// This must be an use of an implicit_def so it's not part of the live
// interval. Create a new empty live interval for it.
// FIXME: Can we simply erase some of the instructions? e.g. Stores?
unsigned NewVReg = mri_->createVirtualRegister(rc);
vrm.grow();
vrm.setIsImplicitlyDefined(NewVReg);
NewLIs.push_back(&getOrCreateInterval(NewVReg));
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (MO.isReg() && MO.getReg() == li.reg)
Evan Cheng
committed
MO.setReg(NewVReg);
}
}
}
}
Owen Anderson
committed
namespace {
struct LISorter {
bool operator()(LiveInterval* A, LiveInterval* B) {
return A->beginNumber() < B->beginNumber();
}
};
}
Owen Anderson
committed
std::vector<LiveInterval*> LiveIntervals::
addIntervalsForSpillsFast(const LiveInterval &li,
const MachineLoopInfo *loopInfo,
VirtRegMap &vrm, float& SSWeight) {
Owen Anderson
committed
std::vector<LiveInterval*> added;
assert(li.weight != HUGE_VALF &&
"attempt to spill already spilled interval!");
DOUT << "\t\t\t\tadding intervals for spills for interval: ";
DEBUG(li.dump());
DOUT << '\n';
const TargetRegisterClass* rc = mri_->getRegClass(li.reg);
Owen Anderson
committed
MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(li.reg);
while (RI != mri_->reg_end()) {
MachineInstr* MI = &*RI;
Owen Anderson
committed
Owen Anderson
committed
SmallVector<unsigned, 2> Indices;
bool HasUse = false;
bool HasDef = false;
Owen Anderson
committed
Owen Anderson
committed
for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
MachineOperand& mop = MI->getOperand(i);
if (!mop.isReg() || mop.getReg() != li.reg) continue;
Owen Anderson
committed
HasUse |= MI->getOperand(i).isUse();
HasDef |= MI->getOperand(i).isDef();
Indices.push_back(i);
Owen Anderson
committed
}
Owen Anderson
committed
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
if (!tryFoldMemoryOperand(MI, vrm, NULL, getInstructionIndex(MI),
Indices, true, slot, li.reg)) {
unsigned NewVReg = mri_->createVirtualRegister(rc);
vrm.grow();
vrm.assignVirt2StackSlot(NewVReg, slot);
// create a new register for this spill
LiveInterval &nI = getOrCreateInterval(NewVReg);
// the spill weight is now infinity as it
// cannot be spilled again
nI.weight = HUGE_VALF;
// Rewrite register operands to use the new vreg.
for (SmallVectorImpl<unsigned>::iterator I = Indices.begin(),
E = Indices.end(); I != E; ++I) {
MI->getOperand(*I).setReg(NewVReg);
if (MI->getOperand(*I).isUse())
MI->getOperand(*I).setIsKill(true);
}
// Fill in the new live interval.
unsigned index = getInstructionIndex(MI);
if (HasUse) {
LiveRange LR(getLoadIndex(index), getUseIndex(index),
nI.getNextValue(~0U, 0, getVNInfoAllocator()));
DOUT << " +" << LR;
nI.addRange(LR);
vrm.addRestorePoint(NewVReg, MI);
}
if (HasDef) {
LiveRange LR(getDefIndex(index), getStoreIndex(index),
nI.getNextValue(~0U, 0, getVNInfoAllocator()));
DOUT << " +" << LR;
nI.addRange(LR);
vrm.addSpillPoint(NewVReg, true, MI);
}
Owen Anderson
committed
Owen Anderson
committed
DOUT << "\t\t\t\tadded new interval: ";
DEBUG(nI.dump());
DOUT << '\n';
unsigned loopDepth = loopInfo->getLoopDepth(MI->getParent());
if (HasUse) {
if (HasDef)
SSWeight += getSpillWeight(true, true, loopDepth);
else
SSWeight += getSpillWeight(false, true, loopDepth);
} else
SSWeight += getSpillWeight(true, false, loopDepth);
}
Owen Anderson
committed
RI = mri_->reg_begin(li.reg);
Owen Anderson
committed
}
Owen Anderson
committed
// Clients expect the new intervals to be returned in sorted order.
Owen Anderson
committed
std::sort(added.begin(), added.end(), LISorter());
Owen Anderson
committed
return added;
}
SmallVectorImpl<LiveInterval*> &SpillIs,
const MachineLoopInfo *loopInfo, VirtRegMap &vrm,
float &SSWeight) {
if (EnableFastSpilling)
return addIntervalsForSpillsFast(li, loopInfo, vrm, SSWeight);
assert(li.weight != HUGE_VALF &&
"attempt to spill already spilled interval!");
DOUT << "\t\t\t\tadding intervals for spills for interval: ";
// Spill slot weight.
SSWeight = 0.0f;
DenseMap<unsigned, std::vector<SRInfo> > SpillIdxes;
BitVector RestoreMBBs(mf_->getNumBlockIDs());
DenseMap<unsigned, std::vector<SRInfo> > RestoreIdxes;
DenseMap<unsigned,unsigned> MBBVRegsMap;
Evan Cheng
committed
const TargetRegisterClass* rc = mri_->getRegClass(li.reg);
unsigned NumValNums = li.getNumValNums();
SmallVector<MachineInstr*, 4> ReMatDefs;
ReMatDefs.resize(NumValNums, NULL);
SmallVector<MachineInstr*, 4> ReMatOrigDefs;
ReMatOrigDefs.resize(NumValNums, NULL);
SmallVector<int, 4> ReMatIds;
ReMatIds.resize(NumValNums, VirtRegMap::MAX_STACK_SLOT);
BitVector ReMatDelete(NumValNums);
unsigned Slot = VirtRegMap::MAX_STACK_SLOT;
// Spilling a split live interval. It cannot be split any further. Also,
// it's also guaranteed to be a single val# / range interval.
if (vrm.getPreSplitReg(li.reg)) {
vrm.setIsSplitFromReg(li.reg, 0);
// Unset the split kill marker on the last use.
unsigned KillIdx = vrm.getKillPoint(li.reg);
if (KillIdx) {
MachineInstr *KillMI = getInstructionFromIndex(KillIdx);
assert(KillMI && "Last use disappeared?");
int KillOp = KillMI->findRegisterUseOperandIdx(li.reg, true);
assert(KillOp != -1 && "Last use disappeared?");
KillMI->getOperand(KillOp).setIsKill(false);
Evan Cheng
committed
vrm.removeKillPoint(li.reg);
bool DefIsReMat = vrm.isReMaterialized(li.reg);
Slot = vrm.getStackSlot(li.reg);
assert(Slot != VirtRegMap::MAX_STACK_SLOT);
MachineInstr *ReMatDefMI = DefIsReMat ?
vrm.getReMaterializedMI(li.reg) : NULL;
int LdSlot = 0;
bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot);
bool isLoad = isLoadSS ||
(DefIsReMat && (ReMatDefMI->getDesc().canFoldAsLoad()));
bool IsFirstRange = true;
for (LiveInterval::Ranges::const_iterator
I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) {
// If this is a split live interval with multiple ranges, it means there
// are two-address instructions that re-defined the value. Only the
// first def can be rematerialized!
if (IsFirstRange) {
// Note ReMatOrigDefMI has already been deleted.
rewriteInstructionsForSpills(li, false, I, NULL, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
Evan Cheng
committed
false, vrm, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs, SSWeight);
} else {
rewriteInstructionsForSpills(li, false, I, NULL, 0,
Slot, 0, false, false, false,
Evan Cheng
committed
false, vrm, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs, SSWeight);
SSWeight = 0.0f; // Already accounted for when split.
Evan Cheng
committed
handleSpilledImpDefs(li, vrm, rc, NewLIs);
return NewLIs;
}
bool TrySplit = SplitAtBB && !intervalIsInOneMBB(li);
if (SplitLimit != -1 && (int)numSplits >= SplitLimit)
TrySplit = false;
if (TrySplit)
++numSplits;
bool NeedStackSlot = false;
for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end();
i != e; ++i) {
const VNInfo *VNI = *i;
unsigned VN = VNI->id;
unsigned DefIdx = VNI->def;
if (DefIdx == ~1U)
continue; // Dead val#.
// Is the def for the val# rematerializable?
MachineInstr *ReMatDefMI = (DefIdx == ~0u)
? 0 : getInstructionFromIndex(DefIdx);
Evan Cheng
committed
bool dummy;
if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI, SpillIs, dummy)) {
// Original def may be modified so we have to make a copy here.
MachineInstr *Clone = mf_->CloneMachineInstr(ReMatDefMI);
ClonedMIs.push_back(Clone);
ReMatDefs[VN] = Clone;
if (VNI->hasPHIKill) {
// A kill is a phi node, not all of its uses can be rematerialized.
CanDelete = false;
// Need a stack slot if there is any live range where uses cannot be
// rematerialized.
NeedStackSlot = true;
}
if (CanDelete)
ReMatDelete.set(VN);
} else {
// Need a stack slot if there is any live range where uses cannot be
// rematerialized.
NeedStackSlot = true;
}
}
// One stack slot per live interval.
if (NeedStackSlot && vrm.getPreSplitReg(li.reg) == 0)
Slot = vrm.assignVirt2StackSlot(li.reg);
// Create new intervals and rewrite defs and uses.
for (LiveInterval::Ranges::const_iterator
I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) {
MachineInstr *ReMatDefMI = ReMatDefs[I->valno->id];
MachineInstr *ReMatOrigDefMI = ReMatOrigDefs[I->valno->id];
bool DefIsReMat = ReMatDefMI != NULL;
bool CanDelete = ReMatDelete[I->valno->id];
int LdSlot = 0;
bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot);
(DefIsReMat && ReMatDefMI->getDesc().canFoldAsLoad());
rewriteInstructionsForSpills(li, TrySplit, I, ReMatOrigDefMI, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
Evan Cheng
committed
CanDelete, vrm, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs, SSWeight);
// Insert spills / restores if we are splitting.
if (!TrySplit) {
Evan Cheng
committed
handleSpilledImpDefs(li, vrm, rc, NewLIs);