From 018f9b020bb12b731b0a7081578e5f82fb35092d Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 5 Dec 2007 03:22:34 +0000 Subject: [PATCH] - 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 --- include/llvm/CodeGen/LiveIntervalAnalysis.h | 2 + lib/CodeGen/LiveIntervalAnalysis.cpp | 99 +++++++++++++++------ lib/CodeGen/VirtRegMap.cpp | 2 - 3 files changed, 75 insertions(+), 28 deletions(-) diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index a40d0abcb1c..19865e59c1e 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -278,6 +278,8 @@ namespace llvm { SmallVector &Ops, bool isSS, int Slot, unsigned Reg); + /// canFoldMemoryOperand - Returns true if the specified load / store + /// folding is possible. bool canFoldMemoryOperand(MachineInstr *MI, SmallVector &Ops) const; diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 7a97624e76e..5c95eb16d83 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 &Ops) const { + 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); + } + + return mri_->canFoldMemoryOperand(MI, FoldOps); +} + bool LiveIntervals::intervalIsInOneMBB(const LiveInterval &li) const { SmallPtrSet 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 &MBBVRegsMap, std::vector &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 > &RestoreIdxes, std::map &MBBVRegsMap, std::vector &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::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); } diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index 6c04439bcb9..050f17fe7a1 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -1295,8 +1295,6 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { // the value and there isn't an earlier def that has already clobbered the // physreg. if (PhysReg && - Spills.canClobberPhysReg(SS) && - !ReusedOperands.isClobbered(PhysReg) && DeadStore->findRegisterUseOperandIdx(PhysReg, true) != -1 && MRI->unfoldMemoryOperand(MF, &MI, PhysReg, false, true, NewMIs)) { MBB.insert(MII, NewMIs[0]);