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).



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50916 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dale Johannesen 2008-05-09 21:24:35 +00:00
parent f03893acf0
commit 6ae83faadf

View File

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