diff options
author | Evan Cheng <evan.cheng@apple.com> | 2007-12-05 03:22:34 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2007-12-05 03:22:34 +0000 |
commit | 018f9b020bb12b731b0a7081578e5f82fb35092d (patch) | |
tree | 5cf58e923ef6ad5f63c7cf3c83aa6f68266b5315 /lib/CodeGen/LiveIntervalAnalysis.cpp | |
parent | d64b5c82b97ad1b74eb9fd2f23257a7899b0c307 (diff) |
- Mark last use of a split interval as kill instead of letting spiller track it.
This allows an important optimization to be re-enabled.
- If all uses / defs of a split interval can be folded, give the interval a
low spill weight so it would not be picked in case spilling is needed (avoid
pushing other intervals in the same BB to be spilled).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44601 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/LiveIntervalAnalysis.cpp')
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 99 |
1 files changed, 73 insertions, 26 deletions
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 7a97624e76..5c95eb16d8 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -691,6 +691,22 @@ bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI, return false; } +/// canFoldMemoryOperand - Returns true if the specified load / store +/// folding is possible. +bool LiveIntervals::canFoldMemoryOperand(MachineInstr *MI, + SmallVector<unsigned, 2> &Ops) const { + 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); + } + + return mri_->canFoldMemoryOperand(MI, FoldOps); +} + bool LiveIntervals::intervalIsInOneMBB(const LiveInterval &li) const { SmallPtrSet<MachineBasicBlock*, 4> MBBs; for (LiveInterval::Ranges::const_iterator @@ -710,7 +726,7 @@ bool LiveIntervals::intervalIsInOneMBB(const LiveInterval &li) const { /// rewriteInstructionForSpills, rewriteInstructionsForSpills - Helper functions /// for addIntervalsForSpills to rewrite uses / defs for the given live range. -void LiveIntervals:: +bool LiveIntervals:: rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit, unsigned id, unsigned index, unsigned end, MachineInstr *MI, MachineInstr *ReMatOrigDefMI, MachineInstr *ReMatDefMI, @@ -723,6 +739,7 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit, const LoopInfo *loopInfo, std::map<unsigned,unsigned> &MBBVRegsMap, std::vector<LiveInterval*> &NewLIs) { + bool CanFold = false; RestartInstruction: for (unsigned i = 0; i != MI->getNumOperands(); ++i) { MachineOperand& mop = MI->getOperand(i); @@ -760,11 +777,6 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit, } } - // Do not fold load / store here if we are splitting. We'll find an - // optimal point to insert a load / store later. - if (TryFold) - TryFold = !TrySplit && NewVReg == 0; - // Scan all of the operands of this instruction rewriting operands // to use NewVReg instead of li.reg as appropriate. We do this for // two reasons: @@ -795,15 +807,23 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit, } } - if (TryFold && - tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, - Ops, FoldSS, FoldSlot, Reg)) { - // Folding the load/store can completely change the instruction in - // unpredictable ways, rescan it from the beginning. - HasUse = false; - HasDef = false; - goto RestartInstruction; - } + if (TryFold) { + // Do not fold load / store here if we are splitting. We'll find an + // optimal point to insert a load / store later. + if (!TrySplit) { + if (tryFoldMemoryOperand(MI, vrm, ReMatDefMI, index, + Ops, FoldSS, FoldSlot, Reg)) { + // Folding the load/store can completely change the instruction in + // unpredictable ways, rescan it from the beginning. + HasUse = false; + HasDef = false; + CanFold = false; + goto RestartInstruction; + } + } else { + CanFold = canFoldMemoryOperand(MI, Ops); + } + } else CanFold = false; // Create a new virtual register for the spill interval. bool CreatedNewVReg = false; @@ -879,8 +899,8 @@ rewriteInstructionForSpills(const LiveInterval &li, bool TrySplit, nI.print(DOUT, mri_); DOUT << '\n'; } + return CanFold; } - bool LiveIntervals::anyKillInMBBAfterIdx(const LiveInterval &li, const VNInfo *VNI, MachineBasicBlock *MBB, unsigned Idx) const { @@ -920,6 +940,7 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, std::map<unsigned, std::vector<SRInfo> > &RestoreIdxes, std::map<unsigned,unsigned> &MBBVRegsMap, std::vector<LiveInterval*> &NewLIs) { + bool AllCanFold = true; unsigned NewVReg = 0; unsigned index = getBaseIndex(I->start); unsigned end = getBaseIndex(I->end-1) + InstrSlots::NUM; @@ -931,12 +952,12 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, MachineInstr *MI = getInstructionFromIndex(index); MachineBasicBlock *MBB = MI->getParent(); - NewVReg = 0; + unsigned ThisVReg = 0; if (TrySplit) { std::map<unsigned,unsigned>::const_iterator NVI = MBBVRegsMap.find(MBB->getNumber()); if (NVI != MBBVRegsMap.end()) { - NewVReg = NVI->second; + ThisVReg = NVI->second; // One common case: // x = use // ... @@ -959,21 +980,35 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, } if (MIHasDef && !MIHasUse) { MBBVRegsMap.erase(MBB->getNumber()); - NewVReg = 0; + ThisVReg = 0; } } } - bool IsNew = NewVReg == 0; + + bool IsNew = ThisVReg == 0; + if (IsNew) { + // This ends the previous live interval. If all of its def / use + // can be folded, give it a low spill weight. + if (NewVReg && TrySplit && AllCanFold) { + LiveInterval &nI = getOrCreateInterval(NewVReg); + nI.weight /= 10.0F; + } + AllCanFold = true; + } + NewVReg = ThisVReg; + bool HasDef = false; bool HasUse = false; - rewriteInstructionForSpills(li, TrySplit, I->valno->id, index, end, - MI, ReMatOrigDefMI, ReMatDefMI, Slot, LdSlot, - isLoad, isLoadSS, DefIsReMat, CanDelete, vrm, - RegMap, rc, ReMatIds, NewVReg, HasDef, HasUse, - loopInfo, MBBVRegsMap, NewLIs); + bool CanFold = rewriteInstructionForSpills(li, TrySplit, I->valno->id, + index, end, MI, ReMatOrigDefMI, ReMatDefMI, + Slot, LdSlot, isLoad, isLoadSS, DefIsReMat, + CanDelete, vrm, RegMap, rc, ReMatIds, NewVReg, + HasDef, HasUse, loopInfo, MBBVRegsMap, NewLIs); if (!HasDef && !HasUse) continue; + AllCanFold &= CanFold; + // Update weight of spill interval. LiveInterval &nI = getOrCreateInterval(NewVReg); if (!TrySplit) { @@ -1058,6 +1093,12 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, unsigned loopDepth = loopInfo->getLoopDepth(MBB->getBasicBlock()); nI.weight += getSpillWeight(HasDef, HasUse, loopDepth); } + + if (NewVReg && TrySplit && AllCanFold) { + // If all of its def / use can be folded, give it a low spill weight. + LiveInterval &nI = getOrCreateInterval(NewVReg); + nI.weight /= 10.0F; + } } bool LiveIntervals::alsoFoldARestore(int Id, int index, unsigned vr, @@ -1331,8 +1372,14 @@ addIntervalsForSpills(const LiveInterval &li, // load / rematerialization for us. if (Folded) nI.removeRange(getLoadIndex(index), getUseIndex(index)+1); - else + else { vrm.addRestorePoint(VReg, MI); + LiveRange *LR = &nI.ranges[nI.ranges.size()-1]; + MachineInstr *LastUse = getInstructionFromIndex(getBaseIndex(LR->end)); + int UseIdx = LastUse->findRegisterUseOperandIdx(VReg); + assert(UseIdx != -1); + LastUse->getOperand(UseIdx).setIsKill(); + } } Id = RestoreMBBs.find_next(Id); } |