Optimize outliner compile time performance

This commit is contained in:
drmortalwombat 2025-01-19 18:10:02 +01:00
parent 95732265f6
commit c8abb42c3c
4 changed files with 112 additions and 45 deletions

View File

@ -128,6 +128,7 @@ The compiler is command line driven, and creates an executable .prg file.
* -Oa : optimize inline assembler (part of O2/O3)
* -Oz : enable auto placement of global variables in zero page (part of O3)
* -Op : optimize constant parameters
* -Oo : optimize size using "outliner" (extract repeated code sequences into functions)
* -g : create source level debug info and add source line numbers to asm listing
* -gp : create source level debug info and add source line numbers to asm listing and static profile data
* -tf : target format, may be prg, crt or bin
@ -483,6 +484,8 @@ Set optimizer options that are active for the functions after it
* maxinline : inline any function suitable
* constparams : enable constant parameter folding into called functions
* noconstparams : disable constant parameter folding into called functions
* outline : enable outliner
* nooutline : disable outliner
* 0 : no optimization
* 1 : default optimizations
* 2 : aggressive optimizations

View File

@ -5015,9 +5015,12 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet&
uint32 NativeCodeInstruction::CodeHash(void) const
{
uint32 hash = mType + 0x20 * mMode + 0x100 * mAddress;
uint32 hash = mType + 137 * mMode + 4111 * mAddress;
if (mLinkerObject)
hash += mLinkerObject->mID * 0x1000;
hash += mLinkerObject->mID * 135123;
hash ^= hash >> 13;
hash ^= hash << 11;
hash ^= hash >> 23;
return hash;
}
@ -55514,10 +55517,10 @@ void NativeCodeGenerator::OutlineFunctions(void)
tree->LongestMatch(mapper, 0, 0, lsize, ltree);
if (lsize > 6)
{
SuffixTree* leaf = ltree;
while (leaf->mFirst)
leaf = leaf->mFirst;
NativeCodeBasicBlock* block = mapper.mBlocks[-(1 + leaf->mSeg[leaf->mSize - 1])];
ExpandingArray<SuffixSegment> segs;
ltree->ReplaceCalls(mapper, segs);
NativeCodeBasicBlock* block = segs[0].mBlock;
NativeCodeProcedure* nproc = new NativeCodeProcedure(this);
@ -55541,9 +55544,6 @@ void NativeCodeGenerator::OutlineFunctions(void)
else
nblock->mIns.Push(NativeCodeInstruction(nblock->mIns[nblock->mIns.Size() - 1].mIns, ASMIT_RTS));
ExpandingArray<SuffixSegment> segs;
ltree->ReplaceCalls(mapper, segs);
segs.Sort([](const SuffixSegment& l, const SuffixSegment& r)->bool {
return l.mBlock == r.mBlock ? l.mStart > r.mStart : ptrdiff_t(l.mBlock) < ptrdiff_t(r.mBlock);
});

View File

@ -62,20 +62,32 @@ SuffixTree::SuffixTree(const int* str, int s, SuffixTree* n)
mFirst = nullptr;
}
SuffixTree::~SuffixTree(void)
{
delete[] mFirst;
}
void SuffixTree::AddParents(SuffixTree* parent)
{
mParent = parent;
SuffixTree* n = mFirst;
while (n)
if (mFirst)
{
n->AddParents(this);
n = n->mNext;
for (int i = 0; i < HashSize; i++)
{
SuffixTree* n = mFirst[i];
while (n)
{
n->AddParents(this);
n = n->mNext;
}
}
}
}
void SuffixTree::AddSuffix(const int* str, int s)
{
SuffixTree* c = mFirst;
int hi = str[0] & (HashSize - 1);
SuffixTree* c = mFirst ? mFirst[hi] : nullptr;
while (c && c->mSeg[0] != str[0])
c = c->mNext;
@ -88,15 +100,39 @@ void SuffixTree::AddSuffix(const int* str, int s)
c->AddSuffix(str + k, s - k);
else
{
SuffixTree* t = c->mFirst;
c->mFirst = new SuffixTree(c->mSeg + k, c->mSize - k, nullptr);
c->mFirst->mFirst = t;
c->mFirst = new SuffixTree(str + k, s - k, c->mFirst);
SuffixTree * n = new SuffixTree(c->mSeg + k, c->mSize - k, nullptr);
if (c->mFirst)
{
n->mFirst = new SuffixTree * [HashSize];
for (int i = 0; i < HashSize; i++)
{
n->mFirst[i] = c->mFirst[i];
c->mFirst[i] = nullptr;
}
}
else
{
c->mFirst = new SuffixTree * [HashSize];
for (int i = 0; i < HashSize; i++)
c->mFirst[i] = nullptr;
}
c->mFirst[c->mSeg[k] & (HashSize - 1)] = n;
int hk = str[k] & (HashSize - 1);
c->mFirst[hk] = new SuffixTree(str + k, s - k, c->mFirst[hk]);
c->mSize = k;
}
}
else
mFirst = new SuffixTree(str, s, mFirst);
{
if (!mFirst)
{
mFirst = new SuffixTree * [HashSize];
for (int i = 0; i < HashSize; i++)
mFirst[i] = nullptr;
}
mFirst[hi] = new SuffixTree(str, s, mFirst[hi]);
}
}
void SuffixTree::AddString(const int* str)
@ -120,11 +156,15 @@ void SuffixTree::CollectSuffix(NativeCodeMapper& map, int offset, ExpandingArray
offset += mSize;
if (mFirst)
{
SuffixTree* t = mFirst;
while (t)
for (int i = 0; i < HashSize; i++)
{
t->CollectSuffix(map, offset, segs);
t = t->mNext;
SuffixTree* t = mFirst[i];
while (t)
{
t->CollectSuffix(map, offset, segs);
t = t->mNext;
}
}
}
else
@ -154,22 +194,28 @@ int SuffixTree::LongestMatch(NativeCodeMapper& map, int size, int isize, int& ms
assert(size < 10000);
int cnt = 0;
SuffixTree* t = mFirst;
while (t)
for (int i = 0; i < HashSize; i++)
{
cnt += t->LongestMatch(map, size, isize, msize, mtree);
t = t->mNext;
SuffixTree* t = mFirst[i];
while (t)
{
cnt += t->LongestMatch(map, size, isize, msize, mtree);
t = t->mNext;
}
}
if (size >= 6 && (size - 3) * (cnt - 1) > msize)
{
// Second run to cross check for overlaps
ExpandingArray<SuffixSegment> segs;
SuffixTree* t = mFirst;
while (t)
for (int i = 0; i < HashSize; i++)
{
t->CollectSuffix(map, 0, segs);
t = t->mNext;
SuffixTree* t = mFirst[i];
while (t)
{
t->CollectSuffix(map, 0, segs);
t = t->mNext;
}
}
segs.Sort([](const SuffixSegment& l, const SuffixSegment& r)->bool {
return l.mBlock == r.mBlock ? l.mStart < r.mStart : ptrdiff_t(l.mBlock) < ptrdiff_t(r.mBlock);
@ -214,13 +260,18 @@ void SuffixTree::Print(FILE * file, NativeCodeMapper& map, int depth)
}
fprintf(file, "\n");
SuffixTree* n = mFirst;
while (n)
if (mFirst)
{
n->Print(file, map, depth + 1);
n = n->mNext;
for (int i = 0; i < HashSize; i++)
{
SuffixTree* n = mFirst[i];
while (n)
{
n->Print(file, map, depth + 1);
n = n->mNext;
}
}
}
}
void SuffixTree::ParentPrint(FILE* file, NativeCodeMapper& map)
@ -265,11 +316,17 @@ void SuffixTree::ParentCollect(NativeCodeMapper& map, NativeCodeBasicBlock* bloc
void SuffixTree::ReplaceCalls(NativeCodeMapper& map, ExpandingArray<SuffixSegment>& segs)
{
SuffixTree* n = mFirst;
while (n)
if (mFirst)
{
n->ChildReplaceCalls(map, this, 0, segs);
n = n->mNext;
for (int i = 0; i < HashSize; i++)
{
SuffixTree* n = mFirst[i];
while (n)
{
n->ChildReplaceCalls(map, this, 0, segs);
n = n->mNext;
}
}
}
}
@ -283,11 +340,14 @@ void SuffixTree::ChildReplaceCalls(NativeCodeMapper& map, SuffixTree* tree, int
if (mFirst)
{
SuffixTree* n = mFirst;
while (n)
for (int i = 0; i < HashSize; i++)
{
n->ChildReplaceCalls(map, tree, offset, segs);
n = n->mNext;
SuffixTree* n = mFirst[i];
while (n)
{
n->ChildReplaceCalls(map, tree, offset, segs);
n = n->mNext;
}
}
}
else

View File

@ -41,9 +41,13 @@ public:
const int * mSeg;
int mSize;
SuffixTree* mNext, * mParent, * mFirst;
static const int HashSize = 32;
SuffixTree* mNext, * mParent, ** mFirst;
SuffixTree(const int* str, int s, SuffixTree* n);
~SuffixTree(void);
void AddParents(SuffixTree* parent);
void AddSuffix(const int* str, int s);