Checkpoint SplitKit progress.

We are now at a point where we can split around simple single-entry, single-exit
loops, although still with some bugs.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110257 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2010-08-04 22:08:39 +00:00
parent 40e0bad331
commit 7536f72a97
3 changed files with 224 additions and 87 deletions

View File

@ -110,7 +110,8 @@ bool InlineSpiller::split() {
splitAnalysis_.analyze(li_);
if (const MachineLoop *loop = splitAnalysis_.getBestSplitLoop()) {
SplitEditor(splitAnalysis_, lis_, vrm_).splitAroundLoop(loop);
SplitEditor(splitAnalysis_, lis_, vrm_, *newIntervals_)
.splitAroundLoop(loop);
return true;
}
return false;
@ -372,7 +373,9 @@ void InlineSpiller::spill(LiveInterval *li,
if (li_->empty())
return;
stackSlot_ = vrm_.assignVirt2StackSlot(li->reg);
stackSlot_ = vrm_.getStackSlot(li->reg);
if (stackSlot_ == VirtRegMap::NO_STACK_SLOT)
stackSlot_ = vrm_.assignVirt2StackSlot(li->reg);
// Iterate over instructions using register.
for (MachineRegisterInfo::reg_iterator RI = mri_.reg_begin(li->reg);

View File

@ -222,6 +222,13 @@ const MachineLoop *SplitAnalysis::getBestSplitLoop() {
for (LoopPtrSet::const_iterator I = usingLoops_.begin(),
E = usingLoops_.end(); I != E; ++I) {
getLoopBlocks(*I, Blocks);
// FIXME: We need an SSA updater to properly handle multiple exit blocks.
if (Blocks.Exits.size() > 1) {
DEBUG(dbgs() << "MultipleExits: " << **I);
continue;
}
LoopPtrSet *LPS = 0;
switch(analyzeLoopPeripheralUse(Blocks)) {
case OutsideLoop:
@ -277,11 +284,14 @@ const MachineLoop *SplitAnalysis::getBestSplitLoop() {
//===----------------------------------------------------------------------===//
/// Create a new SplitEditor for editing the LiveInterval analyzed by SA.
SplitEditor::SplitEditor(SplitAnalysis &sa, LiveIntervals &lis, VirtRegMap &vrm)
SplitEditor::SplitEditor(SplitAnalysis &sa, LiveIntervals &lis, VirtRegMap &vrm,
std::vector<LiveInterval*> &intervals)
: sa_(sa), lis_(lis), vrm_(vrm),
mri_(vrm.getMachineFunction().getRegInfo()),
tii_(*vrm.getMachineFunction().getTarget().getInstrInfo()),
dupli_(0), openli_(0)
dupli_(0), openli_(0),
intervals_(intervals),
firstInterval(intervals_.size())
{
const LiveInterval *curli = sa_.getCurLI();
assert(curli && "SplitEditor created from empty SplitAnalysis");
@ -313,44 +323,56 @@ VNInfo *SplitEditor::mapValue(VNInfo *dupliVNI) {
return VNI;
}
/// Create a new virtual register and live interval to be used by following
/// use* and copy* calls.
void SplitEditor::openLI() {
assert(!openli_ && "Previous LI not closed before openLI");
openli_ = createInterval();
/// Insert a COPY instruction curli -> li. Allocate a new value from li
/// defined by the COPY. Note that rewrite() will deal with the curli
/// register, so this function can be used to copy from any interval - openli,
/// curli, or dupli.
VNInfo *SplitEditor::insertCopy(LiveInterval &LI,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) {
unsigned curli = sa_.getCurLI()->reg;
MachineInstr *MI = BuildMI(MBB, I, DebugLoc(), tii_.get(TargetOpcode::COPY),
LI.reg).addReg(curli);
SlotIndex DefIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex();
return LI.getNextValue(DefIdx, MI, true, lis_.getVNInfoAllocator());
}
/// copyToPHI - Insert a copy to openli at the end of A, and catch it with a
/// PHI def at the beginning of the successor B. This call is ignored if dupli
/// is not live out of A.
void SplitEditor::copyToPHI(MachineBasicBlock &A, MachineBasicBlock &B) {
assert(openli_ && "openLI not called before copyToPHI");
/// Create a new virtual register and live interval.
void SplitEditor::openIntv() {
assert(!openli_ && "Previous LI not closed before openIntv");
openli_ = createInterval();
intervals_.push_back(openli_);
liveThrough_ = false;
}
/// enterIntvAtEnd - Enter openli at the end of MBB.
/// PhiMBB is a successor inside openli where a PHI value is created.
/// Currently, all entries must share the same PhiMBB.
void SplitEditor::enterIntvAtEnd(MachineBasicBlock &A, MachineBasicBlock &B) {
assert(openli_ && "openIntv not called before enterIntvAtEnd");
SlotIndex EndA = lis_.getMBBEndIdx(&A);
VNInfo *DupVNIA = dupli_->getVNInfoAt(EndA.getPrevIndex());
if (!DupVNIA) {
DEBUG(dbgs() << " ignoring copyToPHI, dupli not live out of BB#"
DEBUG(dbgs() << " ignoring enterIntvAtEnd, dupli not live out of BB#"
<< A.getNumber() << ".\n");
return;
}
// Insert the COPY instruction at the end of A.
MachineInstr *MI = BuildMI(A, A.getFirstTerminator(), DebugLoc(),
tii_.get(TargetOpcode::COPY), dupli_->reg)
.addReg(openli_->reg);
SlotIndex DefIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex();
// Add a phi kill value and live range out of A.
VNInfo *VNIA = openli_->getNextValue(DefIdx, MI, true,
lis_.getVNInfoAllocator());
openli_->addRange(LiveRange(DefIdx, EndA, VNIA));
VNInfo *VNIA = insertCopy(*openli_, A, A.getFirstTerminator());
openli_->addRange(LiveRange(VNIA->def, EndA, VNIA));
// FIXME: If this is the only entry edge, we don't need the extra PHI value.
// FIXME: If there are multiple entry blocks (so not a loop), we need proper
// SSA update.
// Now look at the start of B.
SlotIndex StartB = lis_.getMBBStartIdx(&B);
SlotIndex EndB = lis_.getMBBEndIdx(&B);
LiveRange *DupB = dupli_->getLiveRangeContaining(StartB);
if (!DupB) {
DEBUG(dbgs() << " copyToPHI:, dupli not live in to BB#"
DEBUG(dbgs() << " enterIntvAtEnd: dupli not live in to BB#"
<< B.getNumber() << ".\n");
return;
}
@ -375,16 +397,16 @@ void SplitEditor::copyToPHI(MachineBasicBlock &A, MachineBasicBlock &B) {
}
DEBUG(dbgs() << " copyToPHI at " << DefIdx << ": " << *openli_ << '\n');
DEBUG(dbgs() << " enterIntvAtEnd: " << *openli_ << '\n');
}
/// useLI - indicate that all instructions in MBB should use openli.
void SplitEditor::useLI(const MachineBasicBlock &MBB) {
useLI(lis_.getMBBStartIdx(&MBB), lis_.getMBBEndIdx(&MBB));
/// useIntv - indicate that all instructions in MBB should use openli.
void SplitEditor::useIntv(const MachineBasicBlock &MBB) {
useIntv(lis_.getMBBStartIdx(&MBB), lis_.getMBBEndIdx(&MBB));
}
void SplitEditor::useLI(SlotIndex Start, SlotIndex End) {
assert(openli_ && "openLI not called before useLI");
void SplitEditor::useIntv(SlotIndex Start, SlotIndex End) {
assert(openli_ && "openIntv not called before useIntv");
// Map the dupli values from the interval into openli_
LiveInterval::const_iterator B = dupli_->begin(), E = dupli_->end();
@ -392,8 +414,7 @@ void SplitEditor::useLI(SlotIndex Start, SlotIndex End) {
if (I != B) {
--I;
// I begins before Start, but overlaps. openli may already have a value from
// copyToLI.
// I begins before Start, but overlaps. openli may already have a value.
if (I->end > Start && !openli_->liveAt(Start))
openli_->addRange(LiveRange(Start, std::min(End, I->end),
mapValue(I->valno)));
@ -408,24 +429,95 @@ void SplitEditor::useLI(SlotIndex Start, SlotIndex End) {
<< '\n');
}
/// copyFromLI - Insert a copy back to dupli from openli at position I.
SlotIndex SplitEditor::copyFromLI(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) {
assert(openli_ && "openLI not called before copyFromLI");
/// leaveIntvAtTop - Leave the interval at the top of MBB.
/// Currently, only one value can leave the interval.
void SplitEditor::leaveIntvAtTop(MachineBasicBlock &MBB) {
assert(openli_ && "openIntv not called before leaveIntvAtTop");
SlotIndex Start = lis_.getMBBStartIdx(&MBB);
LiveRange *DupLR = dupli_->getLiveRangeContaining(Start);
// Is dupli even live-in to MBB?
if (!DupLR) {
DEBUG(dbgs() << " leaveIntvAtTop at " << Start << ": not live\n");
return;
}
// Is dupli defined by PHI at the beginning of MBB?
bool isPHIDef = DupLR->valno->isPHIDef() &&
DupLR->valno->def.getBaseIndex() == Start;
// If MBB is using a value of dupli that was defined outside the openli range,
// we don't want to copy it back here.
if (!isPHIDef && !openli_->liveAt(DupLR->valno->def)) {
DEBUG(dbgs() << " leaveIntvAtTop at " << Start
<< ": using external value\n");
liveThrough_ = true;
return;
}
// Insert the COPY instruction.
MachineInstr *MI =
BuildMI(MBB, I, DebugLoc(), tii_.get(TargetOpcode::COPY), openli_->reg)
.addReg(dupli_->reg);
SlotIndex Idx = lis_.InsertMachineInstrInMaps(MI);
MachineInstr *MI = BuildMI(MBB, MBB.begin(), DebugLoc(),
tii_.get(TargetOpcode::COPY), openli_->reg)
.addReg(dupli_->reg);
SlotIndex Idx = lis_.InsertMachineInstrInMaps(MI).getDefIndex();
DEBUG(dbgs() << " copyFromLI at " << Idx << ": " << *openli_ << '\n');
return Idx;
// Adjust dupli and openli values.
if (isPHIDef) {
// dupli was already a PHI on entry to MBB. Simply insert an openli PHI,
// and shift the dupli def down to the COPY.
VNInfo *VNI = openli_->getNextValue(SlotIndex(Start, true), 0, false,
lis_.getVNInfoAllocator());
VNI->setIsPHIDef(true);
openli_->addRange(LiveRange(VNI->def, Idx, VNI));
dupli_->removeRange(Start, Idx);
DupLR->valno->def = Idx;
DupLR->valno->setIsPHIDef(false);
} else {
// The dupli value was defined somewhere inside the openli range.
DEBUG(dbgs() << " leaveIntvAtTop source value defined at "
<< DupLR->valno->def << "\n");
// FIXME: We may not need a PHI here if all predecessors have the same
// value.
VNInfo *VNI = openli_->getNextValue(SlotIndex(Start, true), 0, false,
lis_.getVNInfoAllocator());
VNI->setIsPHIDef(true);
openli_->addRange(LiveRange(VNI->def, Idx, VNI));
// FIXME: What if DupLR->valno is used by multiple exits? SSA Update.
// closeIntv is going to remove the superfluous live ranges.
DupLR->valno->def = Idx;
DupLR->valno->setIsPHIDef(false);
}
DEBUG(dbgs() << " leaveIntvAtTop at " << Idx << ": " << *openli_ << '\n');
}
/// closeLI - Indicate that we are done editing the currently open
/// closeIntv - Indicate that we are done editing the currently open
/// LiveInterval, and ranges can be trimmed.
void SplitEditor::closeLI() {
assert(openli_ && "openLI not called before closeLI");
void SplitEditor::closeIntv() {
assert(openli_ && "openIntv not called before closeIntv");
DEBUG(dbgs() << " closeIntv cleaning up\n");
DEBUG(dbgs() << " dup " << *dupli_ << '\n');
DEBUG(dbgs() << " open " << *openli_ << '\n');
if (liveThrough_) {
DEBUG(dbgs() << " value live through region, leaving dupli as is.\n");
} else {
// live out with copies inserted, or killed by region. Either way we need to
// remove the overlapping region from dupli.
for (LiveInterval::iterator I = openli_->begin(), E = openli_->end();
I != E; ++I) {
dupli_->removeRange(I->start, I->end);
}
// FIXME: A block branching to the entry block may also branch elsewhere
// curli is live. We need both openli and curli to be live in that case.
DEBUG(dbgs() << " dup2 " << *dupli_ << '\n');
}
openli_ = 0;
}
@ -433,6 +525,39 @@ void SplitEditor::closeLI() {
/// instructions using curli to use the new intervals.
void SplitEditor::rewrite() {
assert(!openli_ && "Previous LI not closed before rewrite");
const LiveInterval *curli = sa_.getCurLI();
for (MachineRegisterInfo::reg_iterator RI = mri_.reg_begin(curli->reg),
RE = mri_.reg_end(); RI != RE;) {
MachineOperand &MO = RI.getOperand();
MachineInstr *MI = MO.getParent();
++RI;
if (MI->isDebugValue()) {
DEBUG(dbgs() << "Zapping " << *MI);
// FIXME: We can do much better with debug values.
MO.setReg(0);
continue;
}
SlotIndex Idx = lis_.getInstructionIndex(MI);
Idx = MO.isUse() ? Idx.getUseIndex() : Idx.getDefIndex();
LiveInterval *LI = dupli_;
for (unsigned i = firstInterval, e = intervals_.size(); i != e; ++i) {
LiveInterval *testli = intervals_[i];
if (testli->liveAt(Idx)) {
LI = testli;
break;
}
}
if (LI)
MO.setReg(LI->reg);
DEBUG(dbgs() << "rewrite " << Idx << '\t' << *MI);
}
// dupli_ goes in last, after rewriting.
if (dupli_)
intervals_.push_back(dupli_);
// FIXME: *Calculate spill weights, allocation hints, and register classes for
// firstInterval..
}
@ -450,37 +575,29 @@ void SplitEditor::splitAroundLoop(const MachineLoop *Loop) {
assert(CriticalExits.empty() && "Cannot break critical exits yet");
// Create new live interval for the loop.
openLI();
openIntv();
// Insert copies in the predecessors.
for (SplitAnalysis::BlockPtrSet::iterator I = Blocks.Preds.begin(),
E = Blocks.Preds.end(); I != E; ++I) {
MachineBasicBlock &MBB = const_cast<MachineBasicBlock&>(**I);
copyToPHI(MBB, *Loop->getHeader());
enterIntvAtEnd(MBB, *Loop->getHeader());
}
// Switch all loop blocks.
for (SplitAnalysis::BlockPtrSet::iterator I = Blocks.Loop.begin(),
E = Blocks.Loop.end(); I != E; ++I)
useLI(**I);
useIntv(**I);
// Insert back copies in the exit blocks.
for (SplitAnalysis::BlockPtrSet::iterator I = Blocks.Exits.begin(),
E = Blocks.Exits.end(); I != E; ++I) {
MachineBasicBlock &MBB = const_cast<MachineBasicBlock&>(**I);
SlotIndex Start = lis_.getMBBStartIdx(&MBB);
VNInfo *VNI = sa_.getCurLI()->getVNInfoAt(Start);
// Only insert a back copy if curli is live and is either a phi or a value
// defined inside the loop.
if (!VNI) continue;
if (openli_->liveAt(VNI->def) ||
(VNI->isPHIDef() && VNI->def.getBaseIndex() == Start))
copyFromLI(MBB, MBB.begin());
leaveIntvAtTop(MBB);
}
// Done.
closeLI();
closeIntv();
rewrite();
abort();
}

View File

@ -121,14 +121,14 @@ public:
/// SplitEditor - Edit machine code and LiveIntervals for live range
/// splitting.
///
/// 1. Create a SplitEditor from a SplitAnalysis. This will create a new
/// LiveInterval, dupli, that is identical to SA.curli.
/// 2. Start a new live interval with openLI.
/// 3. Insert copies to the new interval with copyTo* and mark the ranges where
/// it should be used with use*.
/// 4. Insert back-copies with copyFromLI.
/// 5. Finish the current LI with closeLI and repeat from 2.
/// 6. Rewrite instructions with rewrite().
/// - Create a SplitEditor from a SplitAnalysis. This will create a new
/// LiveInterval, dupli, that is identical to SA.curli.
/// - Start a new live interval with openIntv.
/// - Mark the places where the new interval is entered using enterIntv*
/// - Mark the ranges where the new interval is used with useIntv*
/// - Mark the places where the interval is exited with exitIntv*.
/// - Finish the current interval with closeIntv and repeat from 2.
/// - Rewrite instructions with rewrite().
///
class SplitEditor {
SplitAnalysis &sa_;
@ -138,7 +138,7 @@ class SplitEditor {
const TargetInstrInfo &tii_;
/// dupli_ - Created as a copy of sa_.curli_, ranges are carved out as new
/// intervals get added through openLI / closeLI.
/// intervals get added through openIntv / closeIntv.
LiveInterval *dupli_;
/// Currently open LiveInterval.
@ -148,43 +148,60 @@ class SplitEditor {
/// register class and spill slot as curli.
LiveInterval *createInterval();
/// valueMap_ - Map values in dupli to values in openli. These are direct 1-1
/// valueMap_ - Map values in dupli to values in openIntv. These are direct 1-1
/// mappings, and do not include values created by inserted copies.
DenseMap<VNInfo*,VNInfo*> valueMap_;
/// mapValue - Return the openli value that corresponds to the given dupli
/// mapValue - Return the openIntv value that corresponds to the given dupli
/// value.
VNInfo *mapValue(VNInfo *dupliVNI);
VNInfo *mapValue(VNInfo *dupliVNI);
/// A dupli value is live through openIntv.
bool liveThrough_;
/// All the new intervals created for this split are added to intervals_.
std::vector<LiveInterval*> &intervals_;
/// The index into intervals_ of the first interval we added. There may be
/// others from before we got it.
unsigned firstInterval;
/// Insert a COPY instruction curli -> li. Allocate a new value from li
/// defined by the COPY
VNInfo *insertCopy(LiveInterval &LI,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I);
public:
/// Create a new SplitEditor for editing the LiveInterval analyzed by SA.
SplitEditor(SplitAnalysis&, LiveIntervals&, VirtRegMap&);
/// Newly created intervals will be appended to newIntervals.
SplitEditor(SplitAnalysis &SA, LiveIntervals&, VirtRegMap&,
std::vector<LiveInterval*> &newIntervals);
/// getAnalysis - Get the corresponding analysis.
SplitAnalysis &getAnalysis() { return sa_; }
/// Create a new virtual register and live interval to be used by following
/// use* and copy* calls.
void openLI();
/// Create a new virtual register and live interval.
void openIntv();
/// copyToPHI - Insert a copy to openli at the end of A, and catch it with a
/// PHI def at the beginning of the successor B. This call is ignored if dupli
/// is not live out of A.
void copyToPHI(MachineBasicBlock &A, MachineBasicBlock &B);
/// enterIntvAtEnd - Enter openli at the end of MBB.
/// PhiMBB is a successor inside openli where a PHI value is created.
/// Currently, all entries must share the same PhiMBB.
void enterIntvAtEnd(MachineBasicBlock &MBB, MachineBasicBlock &PhiMBB);
/// useLI - indicate that all instructions in MBB should use openli.
void useLI(const MachineBasicBlock &MBB);
/// useIntv - indicate that all instructions in MBB should use openli.
void useIntv(const MachineBasicBlock &MBB);
/// useLI - indicate that all instructions in range should use openli.
void useLI(SlotIndex Start, SlotIndex End);
/// useIntv - indicate that all instructions in range should use openli.
void useIntv(SlotIndex Start, SlotIndex End);
/// copyFromLI - Insert a copy back to dupli from openli at position I.
/// This also marks the remainder of MBB as not used by openli.
SlotIndex copyFromLI(MachineBasicBlock &MBB, MachineBasicBlock::iterator I);
/// leaveIntvAtTop - Leave the interval at the top of MBB.
/// Currently, only one value can leave the interval.
void leaveIntvAtTop(MachineBasicBlock &MBB);
/// closeLI - Indicate that we are done editing the currently open
/// closeIntv - Indicate that we are done editing the currently open
/// LiveInterval, and ranges can be trimmed.
void closeLI();
void closeIntv();
/// rewrite - after all the new live ranges have been created, rewrite
/// instructions using curli to use the new intervals.