Newer
Older
handleLiveInRegister(MBB, MIIndex, getOrCreateInterval(*AS),
true);
Owen Anderson
committed
// Skip over empty initial indices.
while (MIIndex / InstrSlots::NUM < i2miMap_.size() &&
getInstructionFromIndex(MIIndex) == 0)
MIIndex += InstrSlots::NUM;
for (; MI != miEnd; ++MI) {
DOUT << MIIndex << "\t" << *MI;
for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
MachineOperand &MO = MI->getOperand(i);
// handle register defs - build intervals
if (MO.isReg() && MO.getReg() && MO.isDef()) {
Evan Cheng
committed
handleRegisterDef(MBB, MI, MIIndex, MO, i);
// Skip over the empty slots after each instruction.
unsigned Slots = MI->getDesc().getNumDefs();
if (Slots == 0)
Slots = 1;
MIIndex += InstrSlots::NUM * Slots;
Owen Anderson
committed
// Skip over empty indices.
while (MIIndex / InstrSlots::NUM < i2miMap_.size() &&
getInstructionFromIndex(MIIndex) == 0)
MIIndex += InstrSlots::NUM;
Alkis Evlogimenos
committed
}
Alkis Evlogimenos
committed
}
Alkis Evlogimenos
committed
bool LiveIntervals::findLiveInMBBs(unsigned Start, unsigned End,
SmallVectorImpl<MachineBasicBlock*> &MBBs) const {
std::vector<IdxMBBPair>::const_iterator I =
std::lower_bound(Idx2MBBMap.begin(), Idx2MBBMap.end(), Start);
bool ResVal = false;
while (I != Idx2MBBMap.end()) {
if (I->first >= End)
break;
MBBs.push_back(I->second);
ResVal = true;
++I;
}
return ResVal;
}
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
bool LiveIntervals::findReachableMBBs(unsigned Start, unsigned End,
SmallVectorImpl<MachineBasicBlock*> &MBBs) const {
std::vector<IdxMBBPair>::const_iterator I =
std::lower_bound(Idx2MBBMap.begin(), Idx2MBBMap.end(), Start);
bool ResVal = false;
while (I != Idx2MBBMap.end()) {
if (I->first > End)
break;
MachineBasicBlock *MBB = I->second;
if (getMBBEndIdx(MBB) > End)
break;
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
SE = MBB->succ_end(); SI != SE; ++SI)
MBBs.push_back(*SI);
ResVal = true;
++I;
}
return ResVal;
}
Owen Anderson
committed
LiveInterval* LiveIntervals::createInterval(unsigned reg) {
float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ? HUGE_VALF : 0.0F;
Owen Anderson
committed
return new LiveInterval(reg, Weight);
/// dupInterval - Duplicate a live interval. The caller is responsible for
/// managing the allocated memory.
LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) {
LiveInterval *NewLI = createInterval(li->reg);
NewLI->Copy(*li, mri_, getVNInfoAllocator());
return NewLI;
}
Evan Cheng
committed
/// getVNInfoSourceReg - Helper function that parses the specified VNInfo
/// copy field and returns the source register that defines it.
unsigned LiveIntervals::getVNInfoSourceReg(const VNInfo *VNI) const {
if (!VNI->copy)
return 0;
Evan Cheng
committed
if (VNI->copy->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) {
// If it's extracting out of a physical register, return the sub-register.
unsigned Reg = VNI->copy->getOperand(1).getReg();
if (TargetRegisterInfo::isPhysicalRegister(Reg))
Reg = tri_->getSubReg(Reg, VNI->copy->getOperand(2).getImm());
return Reg;
} else if (VNI->copy->getOpcode() == TargetInstrInfo::INSERT_SUBREG ||
VNI->copy->getOpcode() == TargetInstrInfo::SUBREG_TO_REG)
Evan Cheng
committed
return VNI->copy->getOperand(2).getReg();
Evan Cheng
committed
Evan Cheng
committed
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (tii_->isMoveInstr(*VNI->copy, SrcReg, DstReg, SrcSubReg, DstSubReg))
Evan Cheng
committed
return SrcReg;
llvm_unreachable("Unrecognized copy instruction!");
Evan Cheng
committed
return 0;
}
//===----------------------------------------------------------------------===//
// Register allocator hooks.
//
Evan Cheng
committed
/// getReMatImplicitUse - If the remat definition MI has one (for now, we only
/// allow one) virtual register operand, then its uses are implicitly using
/// the register. Returns the virtual register.
unsigned LiveIntervals::getReMatImplicitUse(const LiveInterval &li,
MachineInstr *MI) const {
unsigned RegOp = 0;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (!MO.isReg() || !MO.isUse())
Evan Cheng
committed
continue;
unsigned Reg = MO.getReg();
if (Reg == 0 || Reg == li.reg)
continue;
if (TargetRegisterInfo::isPhysicalRegister(Reg) &&
!allocatableRegs_[Reg])
continue;
Evan Cheng
committed
// FIXME: For now, only remat MI with at most one register operand.
assert(!RegOp &&
"Can't rematerialize instruction with multiple register operand!");
RegOp = MO.getReg();
Dan Gohman
committed
#ifndef NDEBUG
Evan Cheng
committed
break;
Dan Gohman
committed
#endif
Evan Cheng
committed
}
return RegOp;
}
/// isValNoAvailableAt - Return true if the val# of the specified interval
/// which reaches the given instruction also reaches the specified use index.
bool LiveIntervals::isValNoAvailableAt(const LiveInterval &li, MachineInstr *MI,
unsigned UseIdx) const {
unsigned Index = getInstructionIndex(MI);
VNInfo *ValNo = li.FindLiveRangeContaining(Index)->valno;
LiveInterval::const_iterator UI = li.FindLiveRangeContaining(UseIdx);
return UI != li.end() && UI->valno == ValNo;
}
/// isReMaterializable - Returns true if the definition MI of the specified
/// val# of the specified interval is re-materializable.
bool LiveIntervals::isReMaterializable(const LiveInterval &li,
Evan Cheng
committed
const VNInfo *ValNo, MachineInstr *MI,
SmallVectorImpl<LiveInterval*> &SpillIs,
Evan Cheng
committed
bool &isLoad) {
if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
Evan Cheng
committed
return true;
int FrameIdx = 0;
if (tii_->isLoadFromStackSlot(MI, FrameIdx) &&
Evan Cheng
committed
mf_->getFrameInfo()->isImmutableObjectIndex(FrameIdx))
// FIXME: Let target specific isReallyTriviallyReMaterializable determines
// this but remember this is not safe to fold into a two-address
// instruction.
Evan Cheng
committed
// This is a load from fixed stack slot. It can be rematerialized.
return true;
Dan Gohman
committed
// If the target-specific rules don't identify an instruction as
// being trivially rematerializable, use some target-independent
// rules.
if (!MI->getDesc().isRematerializable() ||
!tii_->isTriviallyReMaterializable(MI)) {
if (!EnableAggressiveRemat)
return false;
Dan Gohman
committed
// If the instruction accesses memory but the memoperands have been lost,
Dan Gohman
committed
// we can't analyze it.
const TargetInstrDesc &TID = MI->getDesc();
Dan Gohman
committed
if ((TID.mayLoad() || TID.mayStore()) && MI->memoperands_empty())
return false;
// Avoid instructions obviously unsafe for remat.
if (TID.hasUnmodeledSideEffects() || TID.isNotDuplicable())
return false;
// If the instruction accesses memory and the memory could be non-constant,
// assume the instruction is not rematerializable.
for (std::list<MachineMemOperand>::const_iterator
I = MI->memoperands_begin(), E = MI->memoperands_end(); I != E; ++I){
Dan Gohman
committed
const MachineMemOperand &MMO = *I;
if (MMO.isVolatile() || MMO.isStore())
return false;
const Value *V = MMO.getValue();
if (!V)
return false;
if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(V)) {
if (!PSV->isConstant(mf_->getFrameInfo()))
return false;
} else if (!aa_->pointsToConstantMemory(V))
return false;
}
// If any of the registers accessed are non-constant, conservatively assume
// the instruction is not rematerializable.
unsigned ImpUse = 0;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (MO.isReg()) {
Dan Gohman
committed
unsigned Reg = MO.getReg();
if (Reg == 0)
Evan Cheng
committed
continue;
Dan Gohman
committed
if (TargetRegisterInfo::isPhysicalRegister(Reg))
return false;
// Only allow one def, and that in the first operand.
if (MO.isDef() != (i == 0))
Evan Cheng
committed
return false;
Dan Gohman
committed
// Only allow constant-valued registers.
bool IsLiveIn = mri_->isLiveIn(Reg);
MachineRegisterInfo::def_iterator I = mri_->def_begin(Reg),
E = mri_->def_end();
// For the def, it should be the only def of that register.
Dan Gohman
committed
if (MO.isDef() && (next(I) != E || IsLiveIn))
return false;
if (MO.isUse()) {
// Only allow one use other register use, as that's all the
// remat mechanisms support currently.
if (Reg != li.reg) {
if (ImpUse == 0)
ImpUse = Reg;
else if (Reg != ImpUse)
return false;
}
// For the use, there should be only one associated def.
Dan Gohman
committed
if (I != E && (next(I) != E || IsLiveIn))
return false;
}
Evan Cheng
committed
}
}
Evan Cheng
committed
}
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;
Evan Cheng
committed
continue; // Dead val#.
// Is the def for the val# rematerializable?
Evan Cheng
committed
return false;
MachineInstr *ReMatDefMI = getInstructionFromIndex(VNI->def);
Evan Cheng
committed
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) {
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).
if (MI->isRegTiedToDefOperand(OpIdx)) {
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,
Evan Cheng
committed
std::vector<LiveInterval*> &NewLIs) {
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;
// 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;
Evan Cheng
committed
if (isNotInMIMap(MI))
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.
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,
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),
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) {
if (VNI->kills[j].isPHIKill)
continue;
unsigned KillIdx = VNI->kills[j].killIdx;
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,
Evan Cheng
committed
std::vector<LiveInterval*> &NewLIs) {
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,
Evan Cheng
committed
ImpUse, HasDef, HasUse, MBBVRegsMap, NewLIs);
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);
MO.setIsUndef();
}
Evan Cheng
committed
}
}
}
}
Owen Anderson
committed
std::vector<LiveInterval*> LiveIntervals::
addIntervalsForSpillsFast(const LiveInterval &li,
const MachineLoopInfo *loopInfo,
Evan Cheng
committed
VirtRegMap &vrm) {
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;