mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-17 21:29:20 +00: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). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50916 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
f03893acf0
commit
6ae83faadf
@ -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).
|
||||||
|
Loading…
Reference in New Issue
Block a user