//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "VirtRegMap.h"
#include "llvm/Value.h"
-#include "llvm/Analysis/LoopInfo.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/SSARegMap.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"
cl::init(false), cl::Hidden);
cl::opt<bool> SplitAtBB("split-intervals-at-bb",
- cl::init(false), cl::Hidden);
+ cl::init(true), cl::Hidden);
cl::opt<int> SplitLimit("split-limit",
cl::init(-1), cl::Hidden);
}
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addPreserved<LiveVariables>();
AU.addRequired<LiveVariables>();
+ AU.addPreservedID(MachineLoopInfoID);
+ AU.addPreservedID(MachineDominatorsID);
AU.addPreservedID(PHIEliminationID);
AU.addRequiredID(PHIEliminationID);
AU.addRequiredID(TwoAddressInstructionPassID);
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.
}
// Set the MBB2IdxMap entry for this MBB.
- MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex - 1);
+ MBB2IdxMap[MBB->getNumber()] = (StartIdx == MIIndex)
+ ? std::make_pair(StartIdx, StartIdx) // Empty MBB
+ : std::make_pair(StartIdx, MIIndex - 1);
Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB));
}
std::sort(Idx2MBBMap.begin(), Idx2MBBMap.end(), Idx2MBBCompare());
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;
}
DOUT << "\t\tregister: "; DEBUG(printRegName(interval.reg));
LiveVariables::VarInfo& vi = lv_->getVarInfo(interval.reg);
+ if (mi->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
+ DOUT << "is a implicit_def\n";
+ return;
+ }
+
// Virtual registers may be defined multiple times (due to phi
// elimination and 2-addr elimination). Much of what we do only has to be
// done once for the vreg. We use an empty interval to detect the first
// 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 ||
+ mi->getOpcode() == TargetInstrInfo::INSERT_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?");
// are actually two values in the live interval. Because of this we
// need to take the LiveRegion that defines this register and split it
// into two values.
- unsigned DefIndex = getDefIndex(getInstructionIndex(vi.DefInst));
+ assert(interval.containsOneValue());
+ unsigned DefIndex = getDefIndex(interval.getValNumInfo(0)->def);
unsigned RedefIndex = getDefIndex(MIIdx);
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.
- if (lv_->RegisterDefIsDead(mi, interval.reg))
+ if (mi->registerDefIsDead(interval.reg, tri_))
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 ||
+ mi->getOpcode() == TargetInstrInfo::INSERT_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));
// If it is not used after definition, it is considered dead at
// the instruction defining it. Hence its interval is:
// [defSlot(def), defSlot(def)+1)
- if (lv_->RegisterDefIsDead(mi, interval.reg)) {
+ if (mi->registerDefIsDead(interval.reg, tri_)) {
DOUT << " dead";
end = getDefIndex(start) + 1;
goto exit;
// [defSlot(def), useSlot(kill)+1)
while (++mi != MBB->end()) {
baseIndex += InstrSlots::NUM;
- if (lv_->KillsRegister(mi, interval.reg)) {
+ if (mi->killsRegister(interval.reg, tri_)) {
DOUT << " killed";
end = getUseIndex(baseIndex) + 1;
goto exit;
- } else if (lv_->ModifiesRegister(mi, interval.reg)) {
+ } else if (mi->modifiesRegister(interval.reg, tri_)) {
// Another instruction redefines the register before it is ever read.
// Then the register is essentially dead at the instruction that defines
// it. Hence its interval is:
// 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 ||
+ MI->getOpcode() == TargetInstrInfo::INSERT_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)
- // Avoid processing some defs more than once.
- if (!MI->findRegisterDefOperand(*AS))
+ for (const unsigned* AS = tri_->getSubRegisters(reg); *AS; ++AS)
+ // If MI also modifies the sub-register explicitly, avoid processing it
+ // more than once. Do not pass in TRI here so it checks for exact match.
+ if (!MI->modifiesRegister(*AS))
handlePhysicalRegisterDef(MBB, MI, MIIdx, getOrCreateInterval(*AS), 0);
}
}
unsigned start = baseIndex;
unsigned end = start;
while (mi != MBB->end()) {
- if (lv_->KillsRegister(mi, interval.reg)) {
+ if (mi->killsRegister(interval.reg, tri_)) {
DOUT << " killed";
end = getUseIndex(baseIndex) + 1;
goto exit;
- } else if (lv_->ModifiesRegister(mi, interval.reg)) {
+ } else if (mi->modifiesRegister(interval.reg, tri_)) {
// Another instruction redefines the register before it is ever read.
// Then the register is essentially dead at the instruction that defines
// it. Hence its interval is:
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();
+ if (VNI->copy->getOpcode() == TargetInstrInfo::INSERT_SUBREG)
+ return VNI->copy->getOperand(2).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,
- const VNInfo *ValNo, MachineInstr *MI) {
+ const VNInfo *ValNo, MachineInstr *MI,
+ bool &isLoad) {
if (DisableReMat)
return false;
- if (tii_->isTriviallyReMaterializable(MI))
+ isLoad = false;
+ if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
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.
+ if (tii_->isTriviallyReMaterializable(MI)) {
+ const TargetInstrDesc &TID = MI->getDesc();
+ 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 false;
+}
+
+/// isReMaterializable - Returns true if every definition of MI of every
+/// val# of the specified interval is re-materializable.
+bool LiveIntervals::isReMaterializable(const LiveInterval &li, bool &isLoad) {
+ isLoad = false;
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))
+ // Is the def for the val# rematerializable?
+ if (DefIdx == ~0u)
+ return false;
+ MachineInstr *ReMatDefMI = getInstructionFromIndex(DefIdx);
+ bool DefIsLoad = false;
+ if (!ReMatDefMI ||
+ !isReMaterializable(li, VNI, ReMatDefMI, DefIsLoad))
return false;
+ isLoad |= DefIsLoad;
}
return true;
}
-/// 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) {
- unsigned MRInfo = 0;
- const TargetInstrDescriptor *TID = MI->getInstrDescriptor();
- SmallVector<unsigned, 2> FoldOps;
+/// 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 (MI->getOperand(OpIdx).getSubReg())
- return false;
- if (MI->getOperand(OpIdx).isDef())
+ if (MO.getSubReg())
+ return true;
+ if (MO.isDef())
MRInfo |= (unsigned)VirtRegMap::isMod;
else {
// Filter out two-address use operand(s).
- if (TID->getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) {
+ if (!MO.isImplicit() &&
+ TID.getOperandConstraint(OpIdx, TOI::TIED_TO) != -1) {
MRInfo = VirtRegMap::isModRef;
continue;
}
}
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
+/// 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;
- MachineInstr *fmi = isSS ? mri_->foldMemoryOperand(MI, FoldOps, Slot)
- : mri_->foldMemoryOperand(MI, FoldOps, DefMI);
+ // 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))
+ 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);
+ vrm.transferEmergencySpills(MI, fmi);
mi2iMap_.erase(MI);
i2miMap_[InstrIdx /InstrSlots::NUM] = fmi;
mi2iMap_[fmi] = InstrIdx;
/// 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 ReMat) 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;
+
+ // It's only legal to remat for a use, not a def.
+ if (ReMat && (MRInfo & VirtRegMap::isMod))
+ return false;
- return mri_->canFoldMemoryOperand(MI, FoldOps);
+ return tii_->canFoldMemoryOperand(MI, FoldOps);
}
bool LiveIntervals::intervalIsInOneMBB(const LiveInterval &li) const {
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);
+ MachineOperand *UseMO = ReMatMI->findRegisterUseOperand(li.reg);
+ if (UseMO)
+ UseMO->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, SSARegMap *RegMap,
+ VirtRegMap &vrm,
const TargetRegisterClass* rc,
SmallVector<int, 4> &ReMatIds,
- unsigned &NewVReg, bool &HasDef, bool &HasUse,
- const LoopInfo *loopInfo,
+ 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 (!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);
HasUse = false;
HasDef = false;
CanFold = false;
+ if (isRemoved(MI))
+ break;
goto RestartInstruction;
}
} else {
- CanFold = canFoldMemoryOperand(MI, Ops);
+ CanFold = canFoldMemoryOperand(MI, Ops, DefIsReMat);
}
- } else CanFold = false;
+ } else
+ CanFold = false;
// Create a new virtual register for the spill interval.
bool CreatedNewVReg = false;
if (NewVReg == 0) {
- NewVReg = RegMap->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, SSARegMap *RegMap,
+ VirtRegMap &vrm,
const TargetRegisterClass* rc,
SmallVector<int, 4> &ReMatIds,
- const LoopInfo *loopInfo,
+ const MachineLoopInfo *loopInfo,
BitVector &SpillMBBs,
std::map<unsigned, std::vector<SRInfo> > &SpillIdxes,
BitVector &RestoreMBBs,
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 to 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;
+ assert(!O.isImplicit() && "Spilling register that's used as implicit use?");
+ 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 to HUGE_VALF to prevent it from
+ // being spilled.
+ LiveInterval &ImpLi = getInterval(ImpUse);
+ ImpLi.weight = HUGE_VALF;
+ }
+
+ 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, RegMap, 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;
}
// Update spill weight.
- unsigned loopDepth = loopInfo->getLoopDepth(MBB->getBasicBlock());
+ unsigned loopDepth = loopInfo->getLoopDepth(MBB);
nI.weight += getSpillWeight(HasDef, HasUse, loopDepth);
}
Restores[i].index = -1;
}
+/// 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; ) {
+ MachineOperand &O = ri.getOperand();
+ MachineInstr *MI = &*ri;
+ ++ri;
+ 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)
+ MO.setReg(NewVReg);
+ }
+ }
+ }
+}
+
std::vector<LiveInterval*> LiveIntervals::
addIntervalsForSpills(const LiveInterval &li,
- const LoopInfo *loopInfo, VirtRegMap &vrm) {
+ const MachineLoopInfo *loopInfo, VirtRegMap &vrm) {
// Since this is called after the analysis is done we don't know if
// LiveVariables is available
lv_ = getAnalysisToUpdate<LiveVariables>();
"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;
- SSARegMap *RegMap = mf_->getSSARegMap();
- const TargetRegisterClass* rc = RegMap->getRegClass(li.reg);
+ const TargetRegisterClass* rc = mri_->getRegClass(li.reg);
unsigned NumValNums = li.getNumValNums();
SmallVector<MachineInstr*, 4> ReMatDefs;
// 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);
+ }
+ vrm.removeKillPoint(li.reg);
bool DefIsReMat = vrm.isReMaterialized(li.reg);
Slot = vrm.getStackSlot(li.reg);
assert(Slot != VirtRegMap::MAX_STACK_SLOT);
int LdSlot = 0;
bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot);
bool isLoad = isLoadSS ||
- (DefIsReMat && (ReMatDefMI->getInstrDescriptor()->Flags & M_LOAD_FLAG));
+ (DefIsReMat && (ReMatDefMI->getDesc().isSimpleLoad()));
bool IsFirstRange = true;
for (LiveInterval::Ranges::const_iterator
I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) {
// Note ReMatOrigDefMI has already been deleted.
rewriteInstructionsForSpills(li, false, I, NULL, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
- false, vrm, RegMap, 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, RegMap, rc, ReMatIds, loopInfo,
+ false, vrm, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs);
}
IsFirstRange = false;
}
+
+ handleSpilledImpDefs(li, vrm, rc, NewLIs);
return NewLIs;
}
// Is the def for the val# rematerializable?
MachineInstr *ReMatDefMI = (DefIdx == ~0u)
? 0 : getInstructionFromIndex(DefIdx);
- if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI)) {
+ bool dummy;
+ if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI, dummy)) {
// Remember how to remat the def of this val#.
ReMatOrigDefs[VN] = ReMatDefMI;
// Original def may be modified so we have to make a copy here. vrm must
// delete these!
ReMatDefs[VN] = ReMatDefMI = ReMatDefMI->clone();
- vrm.setVirtIsReMaterialized(li.reg, ReMatDefMI);
bool CanDelete = true;
if (VNI->hasPHIKill) {
int LdSlot = 0;
bool isLoadSS = DefIsReMat && tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot);
bool isLoad = isLoadSS ||
- (DefIsReMat && (ReMatDefMI->getInstrDescriptor()->Flags & M_LOAD_FLAG));
+ (DefIsReMat && ReMatDefMI->getDesc().isSimpleLoad());
rewriteInstructionsForSpills(li, TrySplit, I, ReMatOrigDefMI, ReMatDefMI,
Slot, LdSlot, isLoad, isLoadSS, DefIsReMat,
- CanDelete, vrm, RegMap, rc, ReMatIds, loopInfo,
+ CanDelete, vrm, rc, ReMatIds, loopInfo,
SpillMBBs, SpillIdxes, RestoreMBBs, RestoreIdxes,
MBBVRegsMap, NewLIs);
}
// Insert spills / restores if we are splitting.
- if (!TrySplit)
+ if (!TrySplit) {
+ handleSpilledImpDefs(li, vrm, rc, NewLIs);
return NewLIs;
+ }
SmallPtrSet<LiveInterval*, 4> AddedKill;
SmallVector<unsigned, 2> Ops;
if (CanFold && !Ops.empty()) {
if (tryFoldMemoryOperand(MI, vrm, NULL, index, Ops, true, Slot,VReg)){
Folded = true;
- if (FoundUse > 0)
+ if (FoundUse > 0) {
// Also folded uses, do not issue a load.
eraseRestoreInfo(Id, index, VReg, RestoreMBBs, RestoreIdxes);
+ nI.removeRange(getLoadIndex(index), getUseIndex(index)+1);
+ }
nI.removeRange(getDefIndex(index), getStoreIndex(index));
}
}
- // Else tell the spiller to issue a spill.
+ // Otherwise tell the spiller to issue a spill.
if (!Folded) {
LiveRange *LR = &nI.ranges[nI.ranges.size()-1];
bool isKill = LR->end == getStoreIndex(index);
int LdSlot = 0;
bool isLoadSS = tii_->isLoadFromStackSlot(ReMatDefMI, LdSlot);
// If the rematerializable def is a load, also try to fold it.
- if (isLoadSS ||
- (ReMatDefMI->getInstrDescriptor()->Flags & M_LOAD_FLAG))
+ 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 to HUGE_VALF to prevent it from being
+ // spilled.
+ LiveInterval &ImpLi = getInterval(ImpUse);
+ ImpLi.weight = HUGE_VALF;
+ MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true));
+ }
}
}
// If folding is not possible / failed, then tell the spiller to issue a
LI->weight /= LI->getSize();
if (!AddedKill.count(LI)) {
LiveRange *LR = &LI->ranges[LI->ranges.size()-1];
- MachineInstr *LastUse = getInstructionFromIndex(getBaseIndex(LR->end));
- int UseIdx = LastUse->findRegisterUseOperandIdx(LI->reg);
+ unsigned LastUseIdx = getBaseIndex(LR->end);
+ MachineInstr *LastUse = getInstructionFromIndex(LastUseIdx);
+ int UseIdx = LastUse->findRegisterUseOperandIdx(LI->reg, false);
assert(UseIdx != -1);
- if (LastUse->getInstrDescriptor()->
- 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);
+ }
}
RetNewLIs.push_back(LI);
}
}
+ handleSpilledImpDefs(li, vrm, rc, RetNewLIs);
return RetNewLIs;
}
+
+/// hasAllocatableSuperReg - Return true if the specified physical register has
+/// any super register that's allocatable.
+bool LiveIntervals::hasAllocatableSuperReg(unsigned Reg) const {
+ for (const unsigned* AS = tri_->getSuperRegisters(Reg); *AS; ++AS)
+ if (allocatableRegs_[*AS] && hasInterval(*AS))
+ return true;
+ return false;
+}
+
+/// getRepresentativeReg - Find the largest super register of the specified
+/// physical register.
+unsigned LiveIntervals::getRepresentativeReg(unsigned Reg) const {
+ // Find the largest super-register that is allocatable.
+ unsigned BestReg = Reg;
+ for (const unsigned* AS = tri_->getSuperRegisters(Reg); *AS; ++AS) {
+ unsigned SuperReg = *AS;
+ if (!hasAllocatableSuperReg(SuperReg) && hasInterval(SuperReg)) {
+ BestReg = SuperReg;
+ break;
+ }
+ }
+ return BestReg;
+}
+
+/// getNumConflictsWithPhysReg - Return the number of uses and defs of the
+/// specified interval that conflicts with the specified physical register.
+unsigned LiveIntervals::getNumConflictsWithPhysReg(const LiveInterval &li,
+ unsigned PhysReg) const {
+ unsigned NumConflicts = 0;
+ const LiveInterval &pli = getInterval(getRepresentativeReg(PhysReg));
+ for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg),
+ E = mri_->reg_end(); I != E; ++I) {
+ MachineOperand &O = I.getOperand();
+ MachineInstr *MI = O.getParent();
+ unsigned Index = getInstructionIndex(MI);
+ if (pli.liveAt(Index))
+ ++NumConflicts;
+ }
+ return NumConflicts;
+}
+
+/// spillPhysRegAroundRegDefsUses - Spill the specified physical register
+/// around all defs and uses of the specified interval.
+void LiveIntervals::spillPhysRegAroundRegDefsUses(const LiveInterval &li,
+ unsigned PhysReg, VirtRegMap &vrm) {
+ unsigned SpillReg = getRepresentativeReg(PhysReg);
+
+ for (const unsigned *AS = tri_->getAliasSet(PhysReg); *AS; ++AS)
+ // If there are registers which alias PhysReg, but which are not a
+ // sub-register of the chosen representative super register. Assert
+ // since we can't handle it yet.
+ assert(*AS == SpillReg || !allocatableRegs_[*AS] ||
+ tri_->isSuperRegister(*AS, SpillReg));
+
+ LiveInterval &pli = getInterval(SpillReg);
+ SmallPtrSet<MachineInstr*, 8> SeenMIs;
+ for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(li.reg),
+ E = mri_->reg_end(); I != E; ++I) {
+ MachineOperand &O = I.getOperand();
+ MachineInstr *MI = O.getParent();
+ if (SeenMIs.count(MI))
+ continue;
+ SeenMIs.insert(MI);
+ unsigned Index = getInstructionIndex(MI);
+ if (pli.liveAt(Index)) {
+ vrm.addEmergencySpill(SpillReg, MI);
+ pli.removeRange(getLoadIndex(Index), getStoreIndex(Index)+1);
+ for (const unsigned* AS = tri_->getSubRegisters(SpillReg); *AS; ++AS) {
+ if (!hasInterval(*AS))
+ continue;
+ LiveInterval &spli = getInterval(*AS);
+ if (spli.liveAt(Index))
+ spli.removeRange(getLoadIndex(Index), getStoreIndex(Index)+1);
+ }
+ }
+ }
+}