#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
-#include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/CommandLine.h"
delete ClonedMIs[i];
}
-namespace llvm {
- inline bool operator<(unsigned V, const IdxMBBPair &IM) {
- return V < IM.first;
- }
-
- inline bool operator<(const IdxMBBPair &IM, unsigned V) {
- return IM.first < V;
- }
-
- struct Idx2MBBCompare {
- bool operator()(const IdxMBBPair &LHS, const IdxMBBPair &RHS) const {
- return LHS.first < RHS.first;
- }
- };
-}
-
/// runOnMachineFunction - Register allocate the whole function
///
bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
mf_ = &fn;
+ mri_ = &mf_->getRegInfo();
tm_ = &fn.getTarget();
- mri_ = tm_->getRegisterInfo();
+ tri_ = tm_->getRegisterInfo();
tii_ = tm_->getInstrInfo();
lv_ = &getAnalysis<LiveVariables>();
- allocatableRegs_ = mri_->getAllocatableSet(fn);
+ allocatableRegs_ = tri_->getAllocatableSet(fn);
// Number MachineInstrs and MachineBasicBlocks.
// Initialize MBB indexes to a sentinal.
DOUT << "********** INTERVALS **********\n";
for (iterator I = begin(), E = end(); I != E; ++I) {
- I->second.print(DOUT, mri_);
+ I->second.print(DOUT, tri_);
DOUT << "\n";
}
void LiveIntervals::print(std::ostream &O, const Module* ) const {
O << "********** INTERVALS **********\n";
for (const_iterator I = begin(), E = end(); I != E; ++I) {
- I->second.print(DOUT, mri_);
+ I->second.print(DOUT, tri_);
DOUT << "\n";
}
unsigned PhysReg = mop.getReg();
if (PhysReg == 0 || PhysReg == li.reg)
continue;
- if (MRegisterInfo::isVirtualRegister(PhysReg)) {
+ if (TargetRegisterInfo::isVirtualRegister(PhysReg)) {
if (!vrm.hasPhys(PhysReg))
continue;
PhysReg = vrm.getPhys(PhysReg);
}
- if (PhysReg && mri_->regsOverlap(PhysReg, reg))
+ if (PhysReg && tri_->regsOverlap(PhysReg, reg))
return true;
}
}
}
void LiveIntervals::printRegName(unsigned reg) const {
- if (MRegisterInfo::isPhysicalRegister(reg))
- cerr << mri_->getName(reg);
+ if (TargetRegisterInfo::isPhysicalRegister(reg))
+ cerr << tri_->getName(reg);
else
cerr << "%reg" << reg;
}
// Get the Idx of the defining instructions.
unsigned defIndex = getDefIndex(MIIdx);
VNInfo *ValNo;
+ MachineInstr *CopyMI = NULL;
unsigned SrcReg, DstReg;
- if (tii_->isMoveInstr(*mi, SrcReg, DstReg))
- ValNo = interval.getNextValue(defIndex, SrcReg, VNInfoAllocator);
- else if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)
- ValNo = interval.getNextValue(defIndex, mi->getOperand(1).getReg(),
- VNInfoAllocator);
- else
- ValNo = interval.getNextValue(defIndex, 0, VNInfoAllocator);
+ if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG ||
+ tii_->isMoveInstr(*mi, SrcReg, DstReg))
+ CopyMI = mi;
+ ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator);
assert(ValNo->id == 0 && "First value in interval is not 0?");
const LiveRange *OldLR = interval.getLiveRangeContaining(RedefIndex-1);
VNInfo *OldValNo = OldLR->valno;
- unsigned OldEnd = OldLR->end;
// Delete the initial value, which should be short and continuous,
// because the 2-addr copy must be in the same MBB as the redef.
// The new value number (#1) is defined by the instruction we claimed
// defined value #0.
- VNInfo *ValNo = interval.getNextValue(0, 0, VNInfoAllocator);
- interval.copyValNumInfo(ValNo, OldValNo);
+ VNInfo *ValNo = interval.getNextValue(OldValNo->def, OldValNo->copy,
+ VNInfoAllocator);
// Value#0 is now defined by the 2-addr instruction.
- OldValNo->def = RedefIndex;
- OldValNo->reg = 0;
+ OldValNo->def = RedefIndex;
+ OldValNo->copy = 0;
// Add the new live interval which replaces the range for the input copy.
LiveRange LR(DefIndex, RedefIndex, ValNo);
DOUT << " replace range with " << LR;
interval.addRange(LR);
interval.addKill(ValNo, RedefIndex);
- interval.removeKills(ValNo, RedefIndex, OldEnd);
// If this redefinition is dead, we need to add a dummy unit live
// range covering the def slot.
interval.addRange(LiveRange(RedefIndex, RedefIndex+1, OldValNo));
DOUT << " RESULT: ";
- interval.print(DOUT, mri_);
+ interval.print(DOUT, tri_);
} else {
// Otherwise, this must be because of phi elimination. If this is the
unsigned Start = getMBBStartIdx(Killer->getParent());
unsigned End = getUseIndex(getInstructionIndex(Killer))+1;
DOUT << " Removing [" << Start << "," << End << "] from: ";
- interval.print(DOUT, mri_); DOUT << "\n";
+ interval.print(DOUT, tri_); DOUT << "\n";
interval.removeRange(Start, End);
- interval.addKill(VNI, Start);
VNI->hasPHIKill = true;
- DOUT << " RESULT: "; interval.print(DOUT, mri_);
+ DOUT << " RESULT: "; interval.print(DOUT, tri_);
// Replace the interval with one of a NEW value number. Note that this
// value number isn't actually defined by an instruction, weird huh? :)
DOUT << " replace range with " << LR;
interval.addRange(LR);
interval.addKill(LR.valno, End);
- DOUT << " RESULT: "; interval.print(DOUT, mri_);
+ DOUT << " RESULT: "; interval.print(DOUT, tri_);
}
// In the case of PHI elimination, each variable definition is only
unsigned defIndex = getDefIndex(MIIdx);
VNInfo *ValNo;
+ MachineInstr *CopyMI = NULL;
unsigned SrcReg, DstReg;
- if (tii_->isMoveInstr(*mi, SrcReg, DstReg))
- ValNo = interval.getNextValue(defIndex, SrcReg, VNInfoAllocator);
- else if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)
- ValNo = interval.getNextValue(defIndex, mi->getOperand(1).getReg(),
- VNInfoAllocator);
- else
- ValNo = interval.getNextValue(defIndex, 0, VNInfoAllocator);
+ if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG ||
+ tii_->isMoveInstr(*mi, SrcReg, DstReg))
+ CopyMI = mi;
+ ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator);
unsigned killIndex = getInstructionIndex(&mbb->back()) + InstrSlots::NUM;
LiveRange LR(defIndex, killIndex, ValNo);
MachineBasicBlock::iterator mi,
unsigned MIIdx,
LiveInterval &interval,
- unsigned SrcReg) {
+ MachineInstr *CopyMI) {
// A physical register cannot be live across basic block, so its
// lifetime must end somewhere in its defining basic block.
DOUT << "\t\tregister: "; DEBUG(printRegName(interval.reg));
// The only case we should have a dead physreg here without a killing or
// instruction where we know it's dead is if it is live-in to the function
// and never used.
- assert(!SrcReg && "physreg was not killed in defining block!");
+ assert(!CopyMI && "physreg was not killed in defining block!");
end = getDefIndex(start) + 1; // It's dead.
exit:
// Already exists? Extend old live interval.
LiveInterval::iterator OldLR = interval.FindLiveRangeContaining(start);
VNInfo *ValNo = (OldLR != interval.end())
- ? OldLR->valno : interval.getNextValue(start, SrcReg, VNInfoAllocator);
+ ? OldLR->valno : interval.getNextValue(start, CopyMI, VNInfoAllocator);
LiveRange LR(start, end, ValNo);
interval.addRange(LR);
interval.addKill(LR.valno, end);
MachineBasicBlock::iterator MI,
unsigned MIIdx,
unsigned reg) {
- if (MRegisterInfo::isVirtualRegister(reg))
+ if (TargetRegisterInfo::isVirtualRegister(reg))
handleVirtualRegisterDef(MBB, MI, MIIdx, getOrCreateInterval(reg));
else if (allocatableRegs_[reg]) {
+ MachineInstr *CopyMI = NULL;
unsigned SrcReg, DstReg;
- if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)
- SrcReg = MI->getOperand(1).getReg();
- else if (!tii_->isMoveInstr(*MI, SrcReg, DstReg))
- SrcReg = 0;
- handlePhysicalRegisterDef(MBB, MI, MIIdx, getOrCreateInterval(reg), SrcReg);
+ if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG ||
+ tii_->isMoveInstr(*MI, SrcReg, DstReg))
+ CopyMI = MI;
+ handlePhysicalRegisterDef(MBB, MI, MIIdx, getOrCreateInterval(reg), CopyMI);
// Def of a register also defines its sub-registers.
- for (const unsigned* AS = mri_->getSubRegisters(reg); *AS; ++AS)
+ for (const unsigned* AS = tri_->getSubRegisters(reg); *AS; ++AS)
// Avoid processing some defs more than once.
if (!MI->findRegisterDefOperand(*AS))
handlePhysicalRegisterDef(MBB, MI, MIIdx, getOrCreateInterval(*AS), 0);
LE = MBB->livein_end(); LI != LE; ++LI) {
handleLiveInRegister(MBB, MIIndex, getOrCreateInterval(*LI));
// Multiple live-ins can alias the same register.
- for (const unsigned* AS = mri_->getSubRegisters(*LI); *AS; ++AS)
+ for (const unsigned* AS = tri_->getSubRegisters(*LI); *AS; ++AS)
if (!hasInterval(*AS))
handleLiveInRegister(MBB, MIIndex, getOrCreateInterval(*AS),
true);
LiveInterval LiveIntervals::createInterval(unsigned reg) {
- float Weight = MRegisterInfo::isPhysicalRegister(reg) ?
+ float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ?
HUGE_VALF : 0.0F;
return LiveInterval(reg, Weight);
}
+/// 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;
+
+ if (VNI->copy->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)
+ return VNI->copy->getOperand(1).getReg();
+ unsigned SrcReg, DstReg;
+ if (tii_->isMoveInstr(*VNI->copy, SrcReg, DstReg))
+ return SrcReg;
+ assert(0 && "Unrecognized copy instruction!");
+ return 0;
+}
//===----------------------------------------------------------------------===//
// Register allocator hooks.
//
+/// 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.isRegister() || !MO.isUse())
+ continue;
+ unsigned Reg = MO.getReg();
+ if (Reg == 0 || Reg == li.reg)
+ continue;
+ // 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();
+ break;
+ }
+ 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,
isLoad = false;
const TargetInstrDesc &TID = MI->getDesc();
- if (TID.isImplicitDef() || tii_->isTriviallyReMaterializable(MI)) {
- isLoad = TID.isSimpleLoad();
+ if (TID.isImplicitDef())
return true;
- }
int FrameIdx = 0;
- if (!tii_->isLoadFromStackSlot(MI, FrameIdx) ||
- !mf_->getFrameInfo()->isFixedObjectIndex(FrameIdx))
- return false;
+ if (tii_->isLoadFromStackSlot(MI, FrameIdx) &&
+ mf_->getFrameInfo()->isImmutableObjectIndex(FrameIdx))
+ // FIXME: Let target specific isReallyTriviallyReMaterializable determines
+ // this but remember this is not safe to fold into a two-address
+ // instruction.
+ // This is a load from fixed stack slot. It can be rematerialized.
+ return true;
- // This is a load from fixed stack slot. It can be rematerialized unless it's
- // re-defined by a two-address instruction.
- isLoad = true;
- for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end();
- i != e; ++i) {
- const VNInfo *VNI = *i;
- if (VNI == ValNo)
- continue;
- unsigned DefIdx = VNI->def;
- if (DefIdx == ~1U)
- continue; // Dead val#.
- MachineInstr *DefMI = (DefIdx == ~0u)
- ? NULL : getInstructionFromIndex(DefIdx);
- if (DefMI && DefMI->isRegReDefinedByTwoAddr(li.reg)) {
- isLoad = false;
- return false;
+ if (tii_->isTriviallyReMaterializable(MI)) {
+ isLoad = TID.isSimpleLoad();
+
+ 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;
+ }
}
+ return true;
}
- return true;
+
+ return false;
}
/// isReMaterializable - Returns true if every definition of MI of every
return false;
MachineInstr *ReMatDefMI = getInstructionFromIndex(DefIdx);
bool DefIsLoad = false;
- if (!ReMatDefMI || !isReMaterializable(li, VNI, ReMatDefMI, DefIsLoad))
+ if (!ReMatDefMI ||
+ !isReMaterializable(li, VNI, ReMatDefMI, DefIsLoad))
return false;
isLoad |= DefIsLoad;
}
return true;
}
+/// 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];
+ MachineOperand &MO = MI->getOperand(OpIdx);
+ // FIXME: fold subreg use.
+ if (MO.getSubReg())
+ return true;
+ if (MO.isDef())
+ MRInfo |= (unsigned)VirtRegMap::isMod;
+ else {
+ // Filter out two-address use operand(s).
+ if (!MO.isImplicit() &&
+ TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) {
+ MRInfo = VirtRegMap::isModRef;
+ continue;
+ }
+ MRInfo |= (unsigned)VirtRegMap::isRef;
+ }
+ FoldOps.push_back(OpIdx);
+ }
+ 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
unsigned InstrIdx,
SmallVector<unsigned, 2> &Ops,
bool isSS, int Slot, unsigned Reg) {
- unsigned MRInfo = 0;
const TargetInstrDesc &TID = MI->getDesc();
// If it is an implicit def instruction, just delete it.
if (TID.isImplicitDef()) {
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;
- for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
- unsigned OpIdx = Ops[i];
- // FIXME: fold subreg use.
- if (MI->getOperand(OpIdx).getSubReg())
- return false;
- if (MI->getOperand(OpIdx).isDef())
- MRInfo |= (unsigned)VirtRegMap::isMod;
- else {
- // Filter out two-address use operand(s).
- if (TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) {
- MRInfo = VirtRegMap::isModRef;
- continue;
- }
- MRInfo |= (unsigned)VirtRegMap::isRef;
- }
- FoldOps.push_back(OpIdx);
- }
+ if (FilterFoldedOps(MI, Ops, MRInfo, FoldOps))
+ return false;
- MachineInstr *fmi = isSS ? tii_->foldMemoryOperand(MI, FoldOps, Slot)
- : tii_->foldMemoryOperand(MI, FoldOps, DefMI);
+ // Can't fold a load from fixed stack slot into a two address instruction.
+ if (isSS && DefMI && (MRInfo & VirtRegMap::isMod))
+ return false;
+
+ MachineInstr *fmi = isSS ? tii_->foldMemoryOperand(*mf_, MI, FoldOps, Slot)
+ : tii_->foldMemoryOperand(*mf_, MI, FoldOps, DefMI);
if (fmi) {
+ // 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.
if (lv_)
lv_->instructionChanged(MI, fmi);
else
- LiveVariables::transferKillDeadInfo(MI, fmi, mri_);
+ fmi->copyKillDeadInfo(MI, tri_);
MachineBasicBlock &MBB = *MI->getParent();
- if (isSS && !mf_->getFrameInfo()->isFixedObjectIndex(Slot))
+ if (isSS && !mf_->getFrameInfo()->isImmutableObjectIndex(Slot))
vrm.virtFolded(Reg, MI, fmi, (VirtRegMap::ModRef)MRInfo);
vrm.transferSpillPts(MI, fmi);
vrm.transferRestorePts(MI, fmi);
/// canFoldMemoryOperand - Returns true if the specified load / store
/// folding is possible.
bool LiveIntervals::canFoldMemoryOperand(MachineInstr *MI,
- SmallVector<unsigned, 2> &Ops) const {
+ SmallVector<unsigned, 2> &Ops,
+ bool ReMatLoad) const {
+ // 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;
- for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
- unsigned OpIdx = Ops[i];
- // FIXME: fold subreg use.
- if (MI->getOperand(OpIdx).getSubReg())
- return false;
- FoldOps.push_back(OpIdx);
- }
+ if (FilterFoldedOps(MI, Ops, MRInfo, FoldOps))
+ return false;
+
+ // Can't fold a remat'ed load into a two address instruction.
+ if (ReMatLoad && (MRInfo & VirtRegMap::isMod))
+ return false;
return tii_->canFoldMemoryOperand(MI, FoldOps);
}
return true;
}
+/// 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.isRegister())
+ continue;
+ unsigned Reg = MO.getReg();
+ if (Reg == 0 || TargetRegisterInfo::isPhysicalRegister(Reg))
+ continue;
+ if (!vrm.isReMaterialized(Reg))
+ continue;
+ MachineInstr *ReMatMI = vrm.getReMaterializedMI(Reg);
+ int OpIdx = ReMatMI->findRegisterUseOperandIdx(li.reg);
+ if (OpIdx != -1)
+ ReMatMI->getOperand(OpIdx).setReg(NewVReg);
+ }
+}
+
/// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper functions
/// for addIntervalsForSpills to rewrite uses / defs for the given live range.
bool LiveIntervals::
-rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit,
- unsigned id, unsigned index, unsigned end, MachineInstr *MI,
+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,
- VirtRegMap &vrm, MachineRegisterInfo &RegInfo,
+ VirtRegMap &vrm,
const TargetRegisterClass* rc,
SmallVector<int, 4> &ReMatIds,
- unsigned &NewVReg, bool &HasDef, bool &HasUse,
const MachineLoopInfo *loopInfo,
+ unsigned &NewVReg, unsigned ImpUse, bool &HasDef, bool &HasUse,
std::map<unsigned,unsigned> &MBBVRegsMap,
std::vector<LiveInterval*> &NewLIs) {
bool CanFold = false;
continue;
unsigned Reg = mop.getReg();
unsigned RegI = Reg;
- if (Reg == 0 || MRegisterInfo::isPhysicalRegister(Reg))
+ if (Reg == 0 || TargetRegisterInfo::isPhysicalRegister(Reg))
continue;
if (Reg != li.reg)
continue;
if (MI == ReMatOrigDefMI && CanDelete) {
DOUT << "\t\t\t\tErasing re-materlizable def: ";
DOUT << MI << '\n';
+ unsigned ImpUse = getReMatImplicitUse(li, MI);
+ if (ImpUse) {
+ // To be deleted MI has a virtual register operand, update the
+ // spill weight of the register interval.
+ unsigned loopDepth = loopInfo->getLoopDepth(MI->getParent());
+ LiveInterval &ImpLi = getInterval(ImpUse);
+ ImpLi.weight -=
+ getSpillWeight(false, true, loopDepth) / ImpLi.getSize();
+ }
RemoveMachineInstrFromMaps(MI);
vrm.RemoveMachineInstrFromMaps(MI);
MI->eraseFromParent();
if (!MOj.isRegister())
continue;
unsigned RegJ = MOj.getReg();
- if (RegJ == 0 || MRegisterInfo::isPhysicalRegister(RegJ))
+ if (RegJ == 0 || TargetRegisterInfo::isPhysicalRegister(RegJ))
continue;
if (RegJ == RegI) {
Ops.push_back(j);
goto RestartInstruction;
}
} else {
- CanFold = canFoldMemoryOperand(MI, Ops);
+ CanFold = canFoldMemoryOperand(MI, Ops, DefIsReMat && isLoad);
}
} else
CanFold = false;
// Create a new virtual register for the spill interval.
bool CreatedNewVReg = false;
if (NewVReg == 0) {
- NewVReg = RegInfo.createVirtualRegister(rc);
+ NewVReg = mri_->createVirtualRegister(rc);
vrm.grow();
CreatedNewVReg = true;
}
mop.setReg(NewVReg);
+ if (mop.isImplicit())
+ rewriteImplicitOps(li, MI, NewVReg, vrm);
// Reuse NewVReg for other reads.
- for (unsigned j = 0, e = Ops.size(); j != e; ++j)
- MI->getOperand(Ops[j]).setReg(NewVReg);
+ 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);
+ }
if (CreatedNewVReg) {
if (DefIsReMat) {
vrm.setVirtIsReMaterialized(NewVReg, ReMatDefMI/*, CanDelete*/);
- if (ReMatIds[id] == VirtRegMap::MAX_STACK_SLOT) {
+ if (ReMatIds[VNI->id] == VirtRegMap::MAX_STACK_SLOT) {
// Each valnum may have its own remat id.
- ReMatIds[id] = vrm.assignVirtReMatId(NewVReg);
+ ReMatIds[VNI->id] = vrm.assignVirtReMatId(NewVReg);
} else {
- vrm.assignVirtReMatId(NewVReg, ReMatIds[id]);
+ vrm.assignVirtReMatId(NewVReg, ReMatIds[VNI->id]);
}
if (!CanDelete || (HasUse && HasDef)) {
// If this is a two-addr instruction then its use operands are
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) {
}
DOUT << "\t\t\t\tAdded new interval: ";
- nI.print(DOUT, mri_);
+ nI.print(DOUT, tri_);
DOUT << '\n';
}
return CanFold;
return VNI;
}
+/// RewriteInfo - Keep track of machine instrs that will be rewritten
+/// during spilling.
+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;
+ }
+};
+
void LiveIntervals::
rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit,
LiveInterval::Ranges::const_iterator &I,
MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI,
unsigned Slot, int LdSlot,
bool isLoad, bool isLoadSS, bool DefIsReMat, bool CanDelete,
- VirtRegMap &vrm, MachineRegisterInfo &RegInfo,
+ VirtRegMap &vrm,
const TargetRegisterClass* rc,
SmallVector<int, 4> &ReMatIds,
const MachineLoopInfo *loopInfo,
std::vector<LiveInterval*> &NewLIs) {
bool AllCanFold = true;
unsigned NewVReg = 0;
- unsigned index = getBaseIndex(I->start);
+ unsigned start = getBaseIndex(I->start);
unsigned end = getBaseIndex(I->end-1) + InstrSlots::NUM;
- for (; index != end; index += InstrSlots::NUM) {
- // skip deleted instructions
- while (index != end && !getInstructionFromIndex(index))
- index += InstrSlots::NUM;
- if (index == end) break;
- MachineInstr *MI = getInstructionFromIndex(index);
+ // First collect all the def / use in this live range that will be rewritten.
+ // Make sure they are sorted according instruction index.
+ std::vector<RewriteInfo> RewriteMIs;
+ for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(li.reg),
+ re = mri_->reg_end(); ri != re; ) {
+ MachineInstr *MI = &(*ri);
+ MachineOperand &O = ri.getOperand();
+ ++ri;
+ unsigned index = getInstructionIndex(MI);
+ if (index < start || index >= end)
+ 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.
+ unsigned NumUses = MIHasUse;
+ 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;
+ }
MachineBasicBlock *MBB = MI->getParent();
+
+ if (ImpUse && MI != ReMatDefMI) {
+ // Re-matting an instruction with virtual register use. Update the
+ // register interval's spill weight.
+ unsigned loopDepth = loopInfo->getLoopDepth(MI->getParent());
+ LiveInterval &ImpLi = getInterval(ImpUse);
+ ImpLi.weight +=
+ getSpillWeight(false, true, loopDepth) * NumUses / ImpLi.getSize();
+ }
+
+ unsigned MBBId = MBB->getNumber();
unsigned ThisVReg = 0;
if (TrySplit) {
- std::map<unsigned,unsigned>::const_iterator NVI =
- MBBVRegsMap.find(MBB->getNumber());
+ std::map<unsigned,unsigned>::const_iterator NVI = MBBVRegsMap.find(MBBId);
if (NVI != MBBVRegsMap.end()) {
ThisVReg = NVI->second;
// One common case:
// = use
// It's better to start a new interval to avoid artifically
// extend the new interval.
- // FIXME: Too slow? Can we fix it after rewriteInstructionsForSpills?
- bool MIHasUse = false;
- bool MIHasDef = false;
- for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
- MachineOperand& mop = MI->getOperand(i);
- if (!mop.isRegister() || mop.getReg() != li.reg)
- continue;
- if (mop.isUse())
- MIHasUse = true;
- else
- MIHasDef = true;
- }
if (MIHasDef && !MIHasUse) {
MBBVRegsMap.erase(MBB->getNumber());
ThisVReg = 0;
bool HasDef = false;
bool HasUse = false;
- bool CanFold = rewriteInstructionForSpills(li, TrySplit, I->valno->id,
+ bool CanFold = rewriteInstructionForSpills(li, I->valno, TrySplit,
index, end, MI, ReMatOrigDefMI, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
- CanDelete, vrm, RegInfo, rc, ReMatIds, NewVReg,
- HasDef, HasUse, loopInfo, MBBVRegsMap, NewLIs);
+ CanDelete, vrm, rc, ReMatIds, loopInfo, NewVReg,
+ ImpUse, HasDef, HasUse, MBBVRegsMap, NewLIs);
if (!HasDef && !HasUse)
continue;
}
// Keep track of the last def and first use in each MBB.
- unsigned MBBId = MBB->getNumber();
if (HasDef) {
if (MI != ReMatOrigDefMI || !CanDelete) {
bool HasKill = false;
"attempt to spill already spilled interval!");
DOUT << "\t\t\t\tadding intervals for spills for interval: ";
- li.print(DOUT, mri_);
+ li.print(DOUT, tri_);
DOUT << '\n';
// Each bit specify whether it a spill is required in the MBB.
std::map<unsigned, std::vector<SRInfo> > RestoreIdxes;
std::map<unsigned,unsigned> MBBVRegsMap;
std::vector<LiveInterval*> NewLIs;
- MachineRegisterInfo &RegInfo = mf_->getRegInfo();
- const TargetRegisterClass* rc = RegInfo.getRegClass(li.reg);
+ const TargetRegisterClass* rc = mri_->getRegClass(li.reg);
unsigned NumValNums = li.getNumValNums();
SmallVector<MachineInstr*, 4> ReMatDefs;
// Note ReMatOrigDefMI has already been deleted.
rewriteInstructionsForSpills(li, false, I, NULL, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
- false, vrm, RegInfo, rc, ReMatIds, loopInfo,
+ false, vrm, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs);
} else {
rewriteInstructionsForSpills(li, false, I, NULL, 0,
Slot, 0, false, false, false,
- false, vrm, RegInfo, rc, ReMatIds, loopInfo,
+ false, vrm, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs);
}
(DefIsReMat && ReMatDefMI->getDesc().isSimpleLoad());
rewriteInstructionsForSpills(li, TrySplit, I, ReMatOrigDefMI, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
- CanDelete, vrm, RegInfo, rc, ReMatIds, loopInfo,
+ CanDelete, vrm, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs);
}
if (isLoadSS || ReMatDefMI->getDesc().isSimpleLoad())
Folded = tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index,
Ops, isLoadSS, LdSlot, VReg);
+ unsigned ImpUse = getReMatImplicitUse(li, ReMatDefMI);
+ if (ImpUse) {
+ // Re-matting an instruction with virtual register use. Add the
+ // register as an implicit use on the use MI and update the register
+ // interval's spill weight.
+ unsigned loopDepth = loopInfo->getLoopDepth(MI->getParent());
+ LiveInterval &ImpLi = getInterval(ImpUse);
+ ImpLi.weight +=
+ getSpillWeight(false, true, loopDepth) / ImpLi.getSize();
+
+ MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true));
+ }
}
}
// If folding is not possible / failed, then tell the spiller to issue a
MachineInstr *LastUse = getInstructionFromIndex(LastUseIdx);
int UseIdx = LastUse->findRegisterUseOperandIdx(LI->reg);
assert(UseIdx != -1);
- if (LastUse->getDesc().getOperandConstraint(UseIdx, TOI::TIED_TO) ==
- -1) {
+ if (LastUse->getOperand(UseIdx).isImplicit() ||
+ LastUse->getDesc().getOperandConstraint(UseIdx,TOI::TIED_TO) == -1){
LastUse->getOperand(UseIdx).setIsKill();
vrm.addKillPoint(LI->reg, LastUseIdx);
}