1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

Rewrite tail merging algorithm to handle the

case where there are multiple blocks with a large
number of common tail instructions more efficiently
(compile time optimization).

llvm-svn: 50916
This commit is contained in:
Dale Johannesen 2008-05-09 21:24:35 +00:00
parent 9b85a8dc92
commit 09a45f2ca3

View File

@ -72,7 +72,10 @@ namespace {
MachineBasicBlock *SplitMBBAt(MachineBasicBlock &CurMBB,
MachineBasicBlock::iterator BBI1);
std::vector<std::pair<unsigned,MachineBasicBlock*> > MergePotentials;
typedef std::pair<unsigned,MachineBasicBlock*> MergePotentialsElt;
std::vector<MergePotentialsElt> MergePotentials;
typedef std::vector<MergePotentialsElt>::iterator MPIterator;
const TargetRegisterInfo *RegInfo;
RegScavenger *RS;
// Branch optzn.
@ -506,129 +509,153 @@ static bool MergeCompare(const std::pair<unsigned,MachineBasicBlock*> &p,
bool BranchFolder::TryMergeBlocks(MachineBasicBlock *SuccBB,
MachineBasicBlock* PredBB) {
// We cannot jump to the entry block, which affects various choices below.
MachineBasicBlock *Entry = MergePotentials.begin()->second->
getParent()->begin();
// It doesn't make sense to save a single instruction since tail merging
// will add a jump.
// FIXME: Ask the target to provide the threshold?
unsigned minCommonTailLength = (SuccBB ? 1 : 2) + 1;
MadeChange = false;
DOUT << "\nTryMergeBlocks " << MergePotentials.size();
// Sort by hash value so that blocks with identical end sequences sort
// together.
std::stable_sort(MergePotentials.begin(), MergePotentials.end(), MergeCompare);
// Walk through equivalence sets looking for actual exact matches.
while (MergePotentials.size() > 1) {
unsigned CurHash = (MergePotentials.end()-1)->first;
unsigned PrevHash = (MergePotentials.end()-2)->first;
MachineBasicBlock *CurMBB = (MergePotentials.end()-1)->second;
unsigned CurHash = prior(MergePotentials.end())->first;
// If there is nothing that matches the hash of the current basic block,
// give up.
if (CurHash != PrevHash) {
if (SuccBB && CurMBB != PredBB)
FixTail(CurMBB, SuccBB, TII);
MergePotentials.pop_back();
continue;
}
// Look through all the other blocks that have the same hash as this
// one, and build a vector of all those that have the (same) largest number
// of instructions in common.
// Order of elements in SameTails is the reverse of the order in which
// those blocks appear in MergePotentials (where they are not necessarily
// consecutive).
typedef std::pair<MPIterator, MachineBasicBlock::iterator> SameTailElt;
std::vector<SameTailElt> SameTails;
// Look through all the pairs of blocks that have the same hash as this
// one, and find the pair that has the largest number of instructions in
// common.
// Since instructions may get combined later (e.g. single stores into
// store multiple) this measure is not particularly accurate.
MachineBasicBlock::iterator BBI1, BBI2;
unsigned FoundI = ~0U, FoundJ = ~0U;
unsigned maxCommonTailLength = 0U;
for (int i = MergePotentials.size()-1;
i != -1 && MergePotentials[i].first == CurHash; --i) {
for (int j = i-1;
j != -1 && MergePotentials[j].first == CurHash; --j) {
MachineBasicBlock::iterator TrialBBI1, TrialBBI2;
SameTails.clear();
MachineBasicBlock::iterator TrialBBI1, TrialBBI2;
MPIterator HighestMPIter = prior(MergePotentials.end());
for (MPIterator CurMPIter = prior(MergePotentials.end()),
B = MergePotentials.begin();
CurMPIter!=B && CurMPIter->first==CurHash;
--CurMPIter) {
for (MPIterator I = prior(CurMPIter); I->first==CurHash ; --I) {
unsigned CommonTailLen = ComputeCommonTailLength(
MergePotentials[i].second,
MergePotentials[j].second,
TrialBBI1, TrialBBI2);
if (CommonTailLen >= minCommonTailLength &&
CommonTailLen > maxCommonTailLength) {
FoundI = i;
FoundJ = j;
maxCommonTailLength = CommonTailLen;
BBI1 = TrialBBI1;
BBI2 = TrialBBI2;
CurMPIter->second,
I->second,
TrialBBI1, TrialBBI2);
if (CommonTailLen >= minCommonTailLength) {
if (CommonTailLen > maxCommonTailLength) {
SameTails.clear();
maxCommonTailLength = CommonTailLen;
HighestMPIter = CurMPIter;
SameTails.push_back(std::make_pair(CurMPIter, TrialBBI1));
}
if (HighestMPIter == CurMPIter &&
CommonTailLen == maxCommonTailLength)
SameTails.push_back(std::make_pair(I, TrialBBI2));
}
if (I==B)
break;
}
}
// If we didn't find any pair that has at least minCommonTailLength
// instructions in common, bail out. All entries with this
// hash code can go away now.
if (FoundI == ~0U) {
for (int i = MergePotentials.size()-1;
i != -1 && MergePotentials[i].first == CurHash; --i) {
// instructions in common, remove all blocks with this hash code and retry.
if (SameTails.empty()) {
for (MPIterator CurMPIter = prior(MergePotentials.end()),
B = MergePotentials.begin();
CurMPIter->first==CurHash;
--CurMPIter) {
// Put the unconditional branch back, if we need one.
CurMBB = MergePotentials[i].second;
MachineBasicBlock *CurMBB = CurMPIter->second;
if (SuccBB && CurMBB != PredBB)
FixTail(CurMBB, SuccBB, TII);
MergePotentials.pop_back();
MergePotentials.erase(CurMPIter);
if (CurMPIter==B)
break;
}
continue;
}
// Otherwise, move the block(s) to the right position(s). So that
// BBI1/2 will be valid, the last must be I and the next-to-last J.
if (FoundI != MergePotentials.size()-1)
std::swap(MergePotentials[FoundI], *(MergePotentials.end()-1));
if (FoundJ != MergePotentials.size()-2)
std::swap(MergePotentials[FoundJ], *(MergePotentials.end()-2));
// If one of the blocks is the entire common tail (and not the entry
// block, which we can't jump to), treat all blocks with this same
// tail at once.
unsigned int i;
for (i=0; i<SameTails.size(); i++) {
MachineBasicBlock *MBB = SameTails[i].first->second;
if (MBB->begin() == SameTails[i].second && MBB != Entry)
break;
}
if (i!=SameTails.size()) {
MachineBasicBlock *MBB = SameTails[i].first->second;
// MBB is common tail. Adjust all other BB's to jump to this one.
// Traversal must be forwards so erases work.
DOUT << "\nUsing common tail " << MBB->getNumber() << " for ";
for (unsigned int j=0; j<SameTails.size(); ++j) {
if (i==j)
continue;
DOUT << SameTails[j].first->second->getNumber() << ",";
// Hack the end off BB j, making it jump to BB i instead.
ReplaceTailWithBranchTo(SameTails[j].second, MBB);
// This modifies BB j, so remove it from the worklist.
MergePotentials.erase(SameTails[j].first);
}
DOUT << "\n";
// We leave i in the worklist in case there are other blocks that
// match it with a smaller number of instructions.
MadeChange = true;
continue;
}
CurMBB = (MergePotentials.end()-1)->second;
MachineBasicBlock *MBB2 = (MergePotentials.end()-2)->second;
// Otherwise, merge the 2 blocks in SameTails that are latest in
// MergePotentials; these are at indices 0 and 1 in SameTails.
MachineBasicBlock::iterator BBI1 = (SameTails[0]).second;
MachineBasicBlock::iterator BBI2 = (SameTails[1]).second;
MachineBasicBlock *MBB1 = (SameTails[0]).first->second;
MachineBasicBlock *MBB2 = (SameTails[1]).first->second;
// If neither block is the entire common tail, split the tail of one block
// to make it redundant with the other tail. Also, we cannot jump to the
DOUT << "\nMerging " << MBB1->getNumber() << "," <<
MBB2->getNumber() << ", size " << maxCommonTailLength;
// Neither block is the entire common tail; split the tail of one block
// to make it redundant with the other tail. We cannot jump to the
// entry block, so if one block is the entry block, split the other one.
MachineBasicBlock *Entry = CurMBB->getParent()->begin();
if (CurMBB->begin() == BBI1 && CurMBB != Entry)
; // CurMBB is common tail
else if (MBB2->begin() == BBI2 && MBB2 != Entry)
; // MBB2 is common tail
else {
if (0) { // Enable this to disable partial tail merges.
MergePotentials.pop_back();
continue;
}
MachineBasicBlock::iterator TrialBBI1, TrialBBI2;
unsigned CommonTailLen = ComputeCommonTailLength(CurMBB, MBB2,
TrialBBI1, TrialBBI2);
if (CommonTailLen < minCommonTailLength)
continue;
// The second half of the split block will remain in SameTails, and will
// consist entirely of common code. Thus in the case where there are multiple
// blocks that would all need to be split, the next iteration of the
// outer loop will handle all the rest of them.
// Decide whether we want to split CurMBB or MBB2.
if (ShouldSplitFirstBlock(CurMBB, BBI1, MBB2, BBI2, PredBB)) {
CurMBB = SplitMBBAt(*CurMBB, BBI1);
BBI1 = CurMBB->begin();
MergePotentials.back().second = CurMBB;
} else {
MBB2 = SplitMBBAt(*MBB2, BBI2);
BBI2 = MBB2->begin();
(MergePotentials.end()-2)->second = MBB2;
}
// Decide whether we want to split MBB1 or MBB2.
if (ShouldSplitFirstBlock(MBB1, BBI1, MBB2, BBI2, PredBB)) {
MBB1 = SplitMBBAt(*MBB1, BBI1);
BBI1 = MBB1->begin();
SameTails[0].first->second = MBB1;
} else {
MBB2 = SplitMBBAt(*MBB2, BBI2);
BBI2 = MBB2->begin();
SameTails[1].first->second = MBB2;
}
if (MBB2->begin() == BBI2 && MBB2 != Entry) {
// Hack the end off CurMBB, making it jump to MBBI@ instead.
// Hack the end off MBB1, making it jump to MBB2 instead.
ReplaceTailWithBranchTo(BBI1, MBB2);
// This modifies CurMBB, so remove it from the worklist.
MergePotentials.pop_back();
// This modifies MBB1, so remove it from the worklist.
MergePotentials.erase(SameTails[0].first);
} else {
assert(CurMBB->begin() == BBI1 && CurMBB != Entry &&
assert(MBB1->begin() == BBI1 && MBB1 != Entry &&
"Didn't split block correctly?");
// Hack the end off MBB2, making it jump to CurMBB instead.
ReplaceTailWithBranchTo(BBI2, CurMBB);
// Hack the end off MBB2, making it jump to MBB1 instead.
ReplaceTailWithBranchTo(BBI2, MBB1);
// This modifies MBB2, so remove it from the worklist.
MergePotentials.erase(MergePotentials.end()-2);
MergePotentials.erase(SameTails[1].first);
}
MadeChange = true;
}
@ -648,7 +675,8 @@ bool BranchFolder::TailMergeBlocks(MachineFunction &MF) {
MergePotentials.push_back(std::make_pair(HashEndOfMBB(I, 2U), I));
}
// See if we can do any tail merging on those.
if (MergePotentials.size() < TailMergeThreshold)
if (MergePotentials.size() < TailMergeThreshold &&
MergePotentials.size() >= 2)
MadeChange |= TryMergeBlocks(NULL, NULL);
// Look at blocks (IBB) with multiple predecessors (PBB).