Transfer simply defined values directly without recomputing liveness and SSA.

Values that map to a single new value in a new interval after splitting don't
need new PHIDefs, and if the parent value was never rematerialized the live
range will be the same.

llvm-svn: 126894
This commit is contained in:
Jakob Stoklund Olesen 2011-03-02 23:05:19 +00:00
parent 3648263a3e
commit 503b143a62
3 changed files with 74 additions and 28 deletions

View File

@ -41,11 +41,11 @@ class LiveRangeEdit {
/// remattable_ - Values defined by remattable instructions as identified by /// remattable_ - Values defined by remattable instructions as identified by
/// tii.isTriviallyReMaterializable(). /// tii.isTriviallyReMaterializable().
SmallPtrSet<VNInfo*,4> remattable_; SmallPtrSet<const VNInfo*,4> remattable_;
/// rematted_ - Values that were actually rematted, and so need to have their /// rematted_ - Values that were actually rematted, and so need to have their
/// live range trimmed or entirely removed. /// live range trimmed or entirely removed.
SmallPtrSet<VNInfo*,4> rematted_; SmallPtrSet<const VNInfo*,4> rematted_;
/// scanRemattable - Identify the parent_ values that may rematerialize. /// scanRemattable - Identify the parent_ values that may rematerialize.
void scanRemattable(LiveIntervals &lis, void scanRemattable(LiveIntervals &lis,
@ -120,12 +120,12 @@ public:
/// markRematerialized - explicitly mark a value as rematerialized after doing /// markRematerialized - explicitly mark a value as rematerialized after doing
/// it manually. /// it manually.
void markRematerialized(VNInfo *ParentVNI) { void markRematerialized(const VNInfo *ParentVNI) {
rematted_.insert(ParentVNI); rematted_.insert(ParentVNI);
} }
/// didRematerialize - Return true if ParentVNI was rematerialized anywhere. /// didRematerialize - Return true if ParentVNI was rematerialized anywhere.
bool didRematerialize(VNInfo *ParentVNI) const { bool didRematerialize(const VNInfo *ParentVNI) const {
return rematted_.count(ParentVNI); return rematted_.count(ParentVNI);
} }
}; };

View File

@ -16,6 +16,7 @@
#include "SplitKit.h" #include "SplitKit.h"
#include "LiveRangeEdit.h" #include "LiveRangeEdit.h"
#include "VirtRegMap.h" #include "VirtRegMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/CalcSpillWeights.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineDominators.h"
@ -33,6 +34,9 @@ static cl::opt<bool>
AllowSplit("spiller-splits-edges", AllowSplit("spiller-splits-edges",
cl::desc("Allow critical edge splitting during spilling")); cl::desc("Allow critical edge splitting during spilling"));
STATISTIC(NumFinished, "Number of splits finished");
STATISTIC(NumSimple, "Number of splits that were simple");
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Split Analysis // Split Analysis
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -497,9 +501,6 @@ VNInfo *SplitEditor::defFromParent(unsigned RegIdx,
Def = LIS.InsertMachineInstrInMaps(CopyMI).getDefIndex(); Def = LIS.InsertMachineInstrInMaps(CopyMI).getDefIndex();
} }
// Temporarily mark all values as complex mapped.
markComplexMapped(RegIdx, ParentVNI);
// Define the value in Reg. // Define the value in Reg.
VNInfo *VNI = defValue(RegIdx, ParentVNI, Def); VNInfo *VNI = defValue(RegIdx, ParentVNI, Def);
VNI->setCopy(CopyMI); VNI->setCopy(CopyMI);
@ -625,15 +626,14 @@ SlotIndex SplitEditor::leaveIntvAtTop(MachineBasicBlock &MBB) {
void SplitEditor::overlapIntv(SlotIndex Start, SlotIndex End) { void SplitEditor::overlapIntv(SlotIndex Start, SlotIndex End) {
assert(OpenIdx && "openIntv not called before overlapIntv"); assert(OpenIdx && "openIntv not called before overlapIntv");
assert(Edit.getParent().getVNInfoAt(Start) == const VNInfo *ParentVNI = Edit.getParent().getVNInfoAt(Start);
Edit.getParent().getVNInfoAt(End.getPrevSlot()) && assert(ParentVNI == Edit.getParent().getVNInfoAt(End.getPrevSlot()) &&
"Parent changes value in extended range"); "Parent changes value in extended range");
assert(Edit.get(0)->getVNInfoAt(Start) && "Start must come from leaveIntv*");
assert(LIS.getMBBFromIndex(Start) == LIS.getMBBFromIndex(End) && assert(LIS.getMBBFromIndex(Start) == LIS.getMBBFromIndex(End) &&
"Range cannot span basic blocks"); "Range cannot span basic blocks");
// Treat this as useIntv() for now.
// The complement interval will be extended as needed by extendRange(). // The complement interval will be extended as needed by extendRange().
markComplexMapped(0, ParentVNI);
DEBUG(dbgs() << " overlapIntv [" << Start << ';' << End << "):"); DEBUG(dbgs() << " overlapIntv [" << Start << ';' << End << "):");
RegAssign.insert(Start, End, OpenIdx); RegAssign.insert(Start, End, OpenIdx);
DEBUG(dump()); DEBUG(dump());
@ -646,6 +646,47 @@ void SplitEditor::closeIntv() {
OpenIdx = 0; OpenIdx = 0;
} }
/// transferSimpleValues - Transfer all simply defined values to the new live
/// ranges.
/// Values that were rematerialized or that have multiple defs are left alone.
bool SplitEditor::transferSimpleValues() {
bool Skipped = false;
RegAssignMap::const_iterator AssignI = RegAssign.begin();
for (LiveInterval::const_iterator ParentI = Edit.getParent().begin(),
ParentE = Edit.getParent().end(); ParentI != ParentE; ++ParentI) {
DEBUG(dbgs() << " blit " << *ParentI << ':');
VNInfo *ParentVNI = ParentI->valno;
// RegAssign has holes where RegIdx 0 should be used.
SlotIndex Start = ParentI->start;
AssignI.advanceTo(Start);
do {
unsigned RegIdx;
SlotIndex End = ParentI->end;
if (!AssignI.valid()) {
RegIdx = 0;
} else if (AssignI.start() <= Start) {
RegIdx = AssignI.value();
if (AssignI.stop() < End) {
End = AssignI.stop();
++AssignI;
}
} else {
RegIdx = 0;
End = std::min(End, AssignI.start());
}
DEBUG(dbgs() << " [" << Start << ';' << End << ")=" << RegIdx);
if (VNInfo *VNI = Values.lookup(std::make_pair(RegIdx, ParentVNI->id))) {
DEBUG(dbgs() << ':' << VNI->id);
Edit.get(RegIdx)->addRange(LiveRange(Start, End, VNI));
} else
Skipped = true;
Start = End;
} while (Start != ParentI->end);
DEBUG(dbgs() << '\n');
}
return Skipped;
}
void SplitEditor::extendPHIKillRanges() { void SplitEditor::extendPHIKillRanges() {
// Extend live ranges to be live-out for successor PHI values. // Extend live ranges to be live-out for successor PHI values.
for (LiveInterval::const_vni_iterator I = Edit.getParent().vni_begin(), for (LiveInterval::const_vni_iterator I = Edit.getParent().vni_begin(),
@ -670,7 +711,7 @@ void SplitEditor::extendPHIKillRanges() {
} }
/// rewriteAssigned - Rewrite all uses of Edit.getReg(). /// rewriteAssigned - Rewrite all uses of Edit.getReg().
void SplitEditor::rewriteAssigned() { void SplitEditor::rewriteAssigned(bool ExtendRanges) {
for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Edit.getReg()), for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Edit.getReg()),
RE = MRI.reg_end(); RI != RE;) { RE = MRI.reg_end(); RI != RE;) {
MachineOperand &MO = RI.getOperand(); MachineOperand &MO = RI.getOperand();
@ -700,7 +741,8 @@ void SplitEditor::rewriteAssigned() {
<< Idx << ':' << RegIdx << '\t' << *MI); << Idx << ':' << RegIdx << '\t' << *MI);
// Extend liveness to Idx. // Extend liveness to Idx.
extendRange(RegIdx, Idx); if (ExtendRanges)
extendRange(RegIdx, Idx);
} }
} }
@ -728,6 +770,7 @@ void SplitEditor::rewriteComponents(const SmallVectorImpl<LiveInterval*> &Intvs,
void SplitEditor::finish() { void SplitEditor::finish() {
assert(OpenIdx == 0 && "Previous LI not closed before rewrite"); assert(OpenIdx == 0 && "Previous LI not closed before rewrite");
++NumFinished;
// At this point, the live intervals in Edit contain VNInfos corresponding to // At this point, the live intervals in Edit contain VNInfos corresponding to
// the inserted copies. // the inserted copies.
@ -739,10 +782,12 @@ void SplitEditor::finish() {
if (ParentVNI->isUnused()) if (ParentVNI->isUnused())
continue; continue;
unsigned RegIdx = RegAssign.lookup(ParentVNI->def); unsigned RegIdx = RegAssign.lookup(ParentVNI->def);
// Mark all values as complex to force liveness computation.
// This should really only be necessary for remat victims, but we are lazy.
markComplexMapped(RegIdx, ParentVNI);
defValue(RegIdx, ParentVNI, ParentVNI->def); defValue(RegIdx, ParentVNI, ParentVNI->def);
// Mark rematted values as complex everywhere to force liveness computation.
// The new live ranges may be truncated.
if (Edit.didRematerialize(ParentVNI))
for (unsigned i = 0, e = Edit.size(); i != e; ++i)
markComplexMapped(i, ParentVNI);
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -751,18 +796,15 @@ void SplitEditor::finish() {
assert((*I)->hasAtLeastOneValue() && "Split interval has no value"); assert((*I)->hasAtLeastOneValue() && "Split interval has no value");
#endif #endif
// FIXME: Don't recompute the liveness of all values, infer it from the // Transfer the simply mapped values, check if any are complex.
// overlaps between the parent live interval and RegAssign. bool Complex = transferSimpleValues();
// The extendRange algorithm is only necessary when: if (Complex)
// - The parent value maps to multiple defs, and new phis are needed, or extendPHIKillRanges();
// - The value has been rematerialized before some uses, and we want to else
// minimize the live range so it only reaches the remaining uses. ++NumSimple;
// All other values have simple liveness that can be computed from RegAssign
// and the parent live interval.
// Rewrite instructions. // Rewrite virtual registers, possibly extending ranges.
extendPHIKillRanges(); rewriteAssigned(Complex);
rewriteAssigned();
// FIXME: Delete defs that were rematted everywhere. // FIXME: Delete defs that were rematted everywhere.

View File

@ -246,12 +246,16 @@ class SplitEditor {
SlotIndex Idx, SlotIndex Idx,
const MachineBasicBlock *IdxMBB); const MachineBasicBlock *IdxMBB);
/// transferSimpleValues - Transfer simply defined values to the new ranges.
/// Return true if any complex ranges were skipped.
bool transferSimpleValues();
/// extendPHIKillRanges - Extend the ranges of all values killed by original /// extendPHIKillRanges - Extend the ranges of all values killed by original
/// parent PHIDefs. /// parent PHIDefs.
void extendPHIKillRanges(); void extendPHIKillRanges();
/// rewriteAssigned - Rewrite all uses of Edit.getReg() to assigned registers. /// rewriteAssigned - Rewrite all uses of Edit.getReg() to assigned registers.
void rewriteAssigned(); void rewriteAssigned(bool ExtendRanges);
/// rewriteComponents - Rewrite all uses of Intv[0] according to the eq /// rewriteComponents - Rewrite all uses of Intv[0] according to the eq
/// classes in ConEQ. /// classes in ConEQ.