Newer
Older
Jakob Stoklund Olesen
committed
Eric Christopher
committed
Jakob Stoklund Olesen
committed
Jakob Stoklund Olesen
committed
// Get rid of unused values and set phi-kill flags.
for (LiveRangeEdit::iterator I = Edit.begin(), E = Edit.end(); I != E; ++I)
(*I)->RenumberValues(LIS);
Jakob Stoklund Olesen
committed
Jakob Stoklund Olesen
committed
// Now check if any registers were separated into multiple components.
ConnectedVNInfoEqClasses ConEQ(LIS);
for (unsigned i = 0, e = Edit.size(); i != e; ++i) {
Jakob Stoklund Olesen
committed
// Don't use iterators, they are invalidated by create() below.
LiveInterval *li = Edit.get(i);
Jakob Stoklund Olesen
committed
unsigned NumComp = ConEQ.Classify(li);
if (NumComp <= 1)
continue;
DEBUG(dbgs() << " " << NumComp << " components: " << *li << '\n');
SmallVector<LiveInterval*, 8> dups;
dups.push_back(li);
for (unsigned i = 1; i != NumComp; ++i)
dups.push_back(&Edit.create(MRI, LIS, VRM));
Jakob Stoklund Olesen
committed
ConEQ.Distribute(&dups[0]);
}
Jakob Stoklund Olesen
committed
// Calculate spill weight and allocation hints for new intervals.
VirtRegAuxInfo vrai(VRM.getMachineFunction(), LIS, sa_.Loops);
for (LiveRangeEdit::iterator I = Edit.begin(), E = Edit.end(); I != E; ++I){
Jakob Stoklund Olesen
committed
LiveInterval &li = **I;
vrai.CalculateRegClass(li.reg);
Jakob Stoklund Olesen
committed
vrai.CalculateWeightAndHint(li);
DEBUG(dbgs() << " new interval " << MRI.getRegClass(li.reg)->getName()
Jakob Stoklund Olesen
committed
}
Jakob Stoklund Olesen
committed
}
//===----------------------------------------------------------------------===//
// Loop Splitting
//===----------------------------------------------------------------------===//
Jakob Stoklund Olesen
committed
void SplitEditor::splitAroundLoop(const MachineLoop *Loop) {
Jakob Stoklund Olesen
committed
SplitAnalysis::LoopBlocks Blocks;
sa_.getLoopBlocks(Loop, Blocks);
dbgs() << " splitAround"; sa_.print(Blocks, dbgs()); dbgs() << '\n';
Jakob Stoklund Olesen
committed
// Break critical edges as needed.
SplitAnalysis::BlockPtrSet CriticalExits;
sa_.getCriticalExits(Blocks, CriticalExits);
assert(CriticalExits.empty() && "Cannot break critical exits yet");
// Create new live interval for the loop.
Jakob Stoklund Olesen
committed
Jakob Stoklund Olesen
committed
// Insert copies in the predecessors if live-in to the header.
if (LIS.isLiveInToMBB(Edit.getParent(), Loop->getHeader())) {
Jakob Stoklund Olesen
committed
for (SplitAnalysis::BlockPtrSet::iterator I = Blocks.Preds.begin(),
E = Blocks.Preds.end(); I != E; ++I) {
MachineBasicBlock &MBB = const_cast<MachineBasicBlock&>(**I);
enterIntvAtEnd(MBB);
}
Jakob Stoklund Olesen
committed
}
// Switch all loop blocks.
for (SplitAnalysis::BlockPtrSet::iterator I = Blocks.Loop.begin(),
E = Blocks.Loop.end(); I != E; ++I)
Jakob Stoklund Olesen
committed
// 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);
Jakob Stoklund Olesen
committed
}
// Done.
Jakob Stoklund Olesen
committed
finish();
}
//===----------------------------------------------------------------------===//
// Single Block Splitting
//===----------------------------------------------------------------------===//
/// getMultiUseBlocks - if CurLI has more than one use in a basic block, it
/// may be an advantage to split CurLI for the duration of the block.
bool SplitAnalysis::getMultiUseBlocks(BlockPtrSet &Blocks) {
// If CurLI is local to one block, there is no point to splitting it.
if (UsingBlocks.size() <= 1)
return false;
// Add blocks with multiple uses.
for (BlockCountMap::iterator I = UsingBlocks.begin(), E = UsingBlocks.end();
I != E; ++I)
switch (I->second) {
case 0:
case 1:
continue;
case 2: {
// When there are only two uses and CurLI is both live in and live out,
// we don't really win anything by isolating the block since we would be
// inserting two copies.
// The remaing register would still have two uses in the block. (Unless it
// separates into disconnected components).
if (LIS.isLiveInToMBB(*CurLI, I->first) &&
LIS.isLiveOutOfMBB(*CurLI, I->first))
continue;
} // Fall through.
default:
Blocks.insert(I->first);
}
return !Blocks.empty();
}
/// splitSingleBlocks - Split CurLI into a separate live interval inside each
Jakob Stoklund Olesen
committed
/// basic block in Blocks.
void SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) {
DEBUG(dbgs() << " splitSingleBlocks for " << Blocks.size() << " blocks.\n");
// Determine the first and last instruction using CurLI in each block.
typedef std::pair<SlotIndex,SlotIndex> IndexPair;
typedef DenseMap<const MachineBasicBlock*,IndexPair> IndexPairMap;
IndexPairMap MBBRange;
for (SplitAnalysis::InstrPtrSet::const_iterator I = sa_.UsingInstrs.begin(),
E = sa_.UsingInstrs.end(); I != E; ++I) {
const MachineBasicBlock *MBB = (*I)->getParent();
if (!Blocks.count(MBB))
continue;
SlotIndex Idx = LIS.getInstructionIndex(*I);
DEBUG(dbgs() << " BB#" << MBB->getNumber() << '\t' << Idx << '\t' << **I);
IndexPair &IP = MBBRange[MBB];
if (!IP.first.isValid() || Idx < IP.first)
IP.first = Idx;
if (!IP.second.isValid() || Idx > IP.second)
IP.second = Idx;
}
// Create a new interval for each block.
for (SplitAnalysis::BlockPtrSet::const_iterator I = Blocks.begin(),
E = Blocks.end(); I != E; ++I) {
IndexPair &IP = MBBRange[*I];
DEBUG(dbgs() << " splitting for BB#" << (*I)->getNumber() << ": ["
<< IP.first << ';' << IP.second << ")\n");
assert(IP.first.isValid() && IP.second.isValid());
openIntv();
enterIntvBefore(IP.first);
useIntv(IP.first.getBaseIndex(), IP.second.getBoundaryIndex());
leaveIntvAfter(IP.second);
closeIntv();
}
Jakob Stoklund Olesen
committed
finish();
//===----------------------------------------------------------------------===//
// Sub Block Splitting
//===----------------------------------------------------------------------===//
/// getBlockForInsideSplit - If CurLI is contained inside a single basic block,
/// and it wou pay to subdivide the interval inside that block, return it.
/// Otherwise return NULL. The returned block can be passed to
/// SplitEditor::splitInsideBlock.
const MachineBasicBlock *SplitAnalysis::getBlockForInsideSplit() {
// The interval must be exclusive to one block.
if (UsingBlocks.size() != 1)
return 0;
// Don't to this for less than 4 instructions. We want to be sure that
// splitting actually reduces the instruction count per interval.
if (UsingInstrs.size() < 4)
return UsingBlocks.begin()->first;
/// splitInsideBlock - Split CurLI into multiple intervals inside MBB.
Jakob Stoklund Olesen
committed
void SplitEditor::splitInsideBlock(const MachineBasicBlock *MBB) {
SmallVector<SlotIndex, 32> Uses;
Uses.reserve(sa_.UsingInstrs.size());
for (SplitAnalysis::InstrPtrSet::const_iterator I = sa_.UsingInstrs.begin(),
E = sa_.UsingInstrs.end(); I != E; ++I)
if ((*I)->getParent() == MBB)
Uses.push_back(LIS.getInstructionIndex(*I));
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
DEBUG(dbgs() << " splitInsideBlock BB#" << MBB->getNumber() << " for "
<< Uses.size() << " instructions.\n");
assert(Uses.size() >= 3 && "Need at least 3 instructions");
array_pod_sort(Uses.begin(), Uses.end());
// Simple algorithm: Find the largest gap between uses as determined by slot
// indices. Create new intervals for instructions before the gap and after the
// gap.
unsigned bestPos = 0;
int bestGap = 0;
DEBUG(dbgs() << " dist (" << Uses[0]);
for (unsigned i = 1, e = Uses.size(); i != e; ++i) {
int g = Uses[i-1].distance(Uses[i]);
DEBUG(dbgs() << ") -" << g << "- (" << Uses[i]);
if (g > bestGap)
bestPos = i, bestGap = g;
}
DEBUG(dbgs() << "), best: -" << bestGap << "-\n");
// bestPos points to the first use after the best gap.
assert(bestPos > 0 && "Invalid gap");
// FIXME: Don't create intervals for low densities.
// First interval before the gap. Don't create single-instr intervals.
if (bestPos > 1) {
openIntv();
enterIntvBefore(Uses.front());
useIntv(Uses.front().getBaseIndex(), Uses[bestPos-1].getBoundaryIndex());
leaveIntvAfter(Uses[bestPos-1]);
closeIntv();
}
// Second interval after the gap.
if (bestPos < Uses.size()-1) {
openIntv();
enterIntvBefore(Uses[bestPos]);
useIntv(Uses[bestPos].getBaseIndex(), Uses.back().getBoundaryIndex());
leaveIntvAfter(Uses.back());
closeIntv();
}
Jakob Stoklund Olesen
committed
finish();