X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=inline;f=lib%2FCodeGen%2FLiveIntervalAnalysis.cpp;h=d710d48034b6c38f5f2c542a16b34a754c793200;hb=433f6f62ca858c20d5d3f561e63818c2fda06ebe;hp=a64bf60f3b243c9427e70f8fc4faf24ad04ee403;hpb=c8d044e4f779fdcfc5e7d592927740fd8f672a70;p=oota-llvm.git diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index a64bf60f3b2..d710d48034b 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -79,26 +79,11 @@ void LiveIntervals::releaseMemory() { 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(); tri_ = tm_->getRegisterInfo(); tii_ = tm_->getInstrInfo(); @@ -339,7 +324,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, // 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: "; @@ -414,7 +399,7 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB, // 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; @@ -425,11 +410,11 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB, // [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: @@ -474,8 +459,9 @@ void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB, handlePhysicalRegisterDef(MBB, MI, MIIdx, getOrCreateInterval(reg), CopyMI); // Def of a register also defines its sub-registers. for (const unsigned* AS = tri_->getSubRegisters(reg); *AS; ++AS) - // Avoid processing some defs more than once. - if (!MI->findRegisterDefOperand(*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); } } @@ -492,11 +478,11 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB, 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: @@ -614,6 +600,38 @@ unsigned LiveIntervals::getVNInfoSourceReg(const VNInfo *VNI) const { // 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, @@ -624,35 +642,38 @@ 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()->isImmutableObjectIndex(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 @@ -670,13 +691,47 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li, bool &isLoad) { 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 &Ops, + unsigned &MRInfo, + SmallVector &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 @@ -686,7 +741,6 @@ bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI, unsigned InstrIdx, SmallVector &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()) { @@ -697,28 +751,23 @@ bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI, return true; } + // Filter the list of operand indexes that are to be folded. Abort if + // any operand will prevent folding. + unsigned MRInfo = 0; SmallVector 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; + + // 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_) @@ -743,15 +792,18 @@ bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI, /// canFoldMemoryOperand - Returns true if the specified load / store /// folding is possible. bool LiveIntervals::canFoldMemoryOperand(MachineInstr *MI, - SmallVector &Ops) const { + SmallVector &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 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); } @@ -773,19 +825,43 @@ 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, MachineRegisterInfo &RegInfo, + VirtRegMap &vrm, const TargetRegisterClass* rc, SmallVector &ReMatIds, - unsigned &NewVReg, bool &HasDef, bool &HasUse, const MachineLoopInfo *loopInfo, + unsigned &NewVReg, unsigned ImpUse, bool &HasDef, bool &HasUse, std::map &MBBVRegsMap, std::vector &NewLIs) { bool CanFold = false; @@ -810,6 +886,15 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit, 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(); @@ -870,7 +955,7 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit, goto RestartInstruction; } } else { - CanFold = canFoldMemoryOperand(MI, Ops); + CanFold = canFoldMemoryOperand(MI, Ops, DefIsReMat && isLoad); } } else CanFold = false; @@ -878,24 +963,30 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit, // 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 @@ -914,6 +1005,11 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit, 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) { @@ -974,13 +1070,30 @@ static const VNInfo *findDefinedVNInfo(const LiveInterval &li, unsigned DefIdx) 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 &ReMatIds, const MachineLoopInfo *loopInfo, @@ -992,20 +1105,59 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, std::vector &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 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::const_iterator NVI = - MBBVRegsMap.find(MBB->getNumber()); + std::map::const_iterator NVI = MBBVRegsMap.find(MBBId); if (NVI != MBBVRegsMap.end()) { ThisVReg = NVI->second; // One common case: @@ -1016,18 +1168,6 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, // = 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; @@ -1049,11 +1189,11 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, 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; @@ -1068,7 +1208,6 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, } // 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; @@ -1198,8 +1337,7 @@ addIntervalsForSpills(const LiveInterval &li, std::map > RestoreIdxes; std::map MBBVRegsMap; std::vector NewLIs; - MachineRegisterInfo &RegInfo = mf_->getRegInfo(); - const TargetRegisterClass* rc = RegInfo.getRegClass(li.reg); + const TargetRegisterClass* rc = mri_->getRegClass(li.reg); unsigned NumValNums = li.getNumValNums(); SmallVector ReMatDefs; @@ -1244,13 +1382,13 @@ addIntervalsForSpills(const LiveInterval &li, // 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); } @@ -1318,7 +1456,7 @@ addIntervalsForSpills(const LiveInterval &li, (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); } @@ -1433,6 +1571,18 @@ addIntervalsForSpills(const LiveInterval &li, 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 @@ -1456,10 +1606,10 @@ addIntervalsForSpills(const LiveInterval &li, LiveRange *LR = &LI->ranges[LI->ranges.size()-1]; unsigned LastUseIdx = getBaseIndex(LR->end); MachineInstr *LastUse = getInstructionFromIndex(LastUseIdx); - int UseIdx = LastUse->findRegisterUseOperandIdx(LI->reg); + int UseIdx = LastUse->findRegisterUseOperandIdx(LI->reg, false); 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); }