Optimize linker placement, avoiding array crossing page boundaries

This commit is contained in:
drmortalwombat 2022-04-03 11:40:23 +02:00
parent 58c99a5dca
commit aafb4adfa2
6 changed files with 152 additions and 157 deletions

View File

@ -48,6 +48,7 @@ void Compiler::AddDefine(const Ident* ident, const char* value)
bool Compiler::ParseSource(void)
{
mPreprocessor->mCompilerOptions = mCompilerOptions;
mLinker->mCompilerOptions = mCompilerOptions;
CompilationUnit* cunit;
while (mErrors->mErrorCount == 0 && (cunit = mCompilationUnits->PendingUnit()))

View File

@ -8712,6 +8712,17 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
int j = i;
while (j > 0 && CanBypassLoadUp(ins, mInstructions[j - 1]))
{
if (ins->mSrc[0].mFinal)
{
for (int k = 0; k < mInstructions[j - 1]->mNumOperands; k++)
{
if (mInstructions[j - 1]->mSrc[k].mTemp == ins->mSrc[0].mTemp)
{
mInstructions[j - 1]->mSrc[k].mFinal = true;
ins->mSrc[0].mFinal = false;
}
}
}
mInstructions[j] = mInstructions[j - 1];
j--;
}
@ -8728,12 +8739,24 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
while (i >= 0)
{
// move non indirect loads down
if (mInstructions[i]->mCode == IC_LOAD && (mInstructions[i]->mSrc[0].mMemory != IM_INDIRECT || mInstructions[i]->mDst.mType != IT_INT8))
if (mInstructions[i]->mCode == IC_LOAD && (mInstructions[i]->mSrc[0].mMemory != IM_INDIRECT || mInstructions[i]->mDst.mType != IT_INT8 || !mInstructions[i]->mSrc[0].mFinal))
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypassLoad(ins, mInstructions[j + 1]))
{
if (!ins->mSrc[0].mFinal)
{
for (int k = 0; k < mInstructions[j + 1]->mNumOperands; k++)
{
if (mInstructions[j + 1]->mSrc[k].mTemp == ins->mSrc[0].mTemp && mInstructions[j + 1]->mSrc[k].mFinal)
{
mInstructions[j + 1]->mSrc[k].mFinal = false;
ins->mSrc[0].mFinal = true;
}
}
}
mInstructions[j] = mInstructions[j + 1];
j++;
}
@ -8776,7 +8799,17 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
{
if (i + 2 < mInstructions.Size())
{
if (mInstructions[i + 0]->mDst.mTemp >= 0 &&
if (mInstructions[i + 0]->mCode == IC_LOAD &&
mInstructions[i + 1]->mCode == IC_LOAD &&
mInstructions[i + 1]->mSrc[0].mTemp == mInstructions[i + 0]->mSrc[0].mTemp &&
mInstructions[i + 0]->mSrc[0].mIntConst > mInstructions[i + 1]->mSrc[0].mIntConst)
{
InterInstruction* ins(mInstructions[i + 0]);
mInstructions[i + 0] = mInstructions[i + 1];
mInstructions[i + 1] = ins;
changed = true;
}
else if (mInstructions[i + 0]->mDst.mTemp >= 0 &&
mInstructions[i + 1]->mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1]->mSrc[0].mTemp == mInstructions[i]->mDst.mTemp &&
(mInstructions[i + 2]->mCode == IC_RELATIONAL_OPERATOR || mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR) && mInstructions[i + 2]->mSrc[0].mTemp == mInstructions[i]->mDst.mTemp && mInstructions[i + 2]->mSrc[0].mFinal)
{

View File

@ -1,7 +1,7 @@
#include "Linker.h"
#include <string.h>
#include <stdio.h>
#include "CompilerTypes.h"
LinkerRegion::LinkerRegion(void)
: mSections(nullptr), mFreeChunks(FreeChunk{ 0, 0 } )
@ -43,7 +43,7 @@ uint8* LinkerObject::AddSpace(int size)
}
Linker::Linker(Errors* errors)
: mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr), mRegions(nullptr)
: mErrors(errors), mSections(nullptr), mReferences(nullptr), mObjects(nullptr), mRegions(nullptr), mCompilerOptions(COPT_DEFAULT)
{
for (int i = 0; i < 64; i++)
{
@ -177,7 +177,7 @@ void Linker::ReferenceObject(LinkerObject* obj)
}
}
bool LinkerRegion::Allocate(LinkerObject* lobj)
bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj)
{
int i = 0;
while (i < mFreeChunks.Size())
@ -185,7 +185,9 @@ bool LinkerRegion::Allocate(LinkerObject* lobj)
int start = (mFreeChunks[i].mStart + lobj->mAlignment - 1) & ~(lobj->mAlignment - 1);
int end = start + lobj->mSize;
if (end <= mFreeChunks[i].mEnd)
if (!(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && (lobj->mFlags & LOBJF_NO_CROSS) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00))
;
else if (end <= mFreeChunks[i].mEnd)
{
lobj->mFlags |= LOBJF_PLACED;
lobj->mAddress = start;
@ -217,6 +219,12 @@ bool LinkerRegion::Allocate(LinkerObject* lobj)
int start = (mStart + mUsed + lobj->mAlignment - 1) & ~(lobj->mAlignment - 1);
int end = start + lobj->mSize;
if (!(linker->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && (lobj->mFlags & LOBJF_NO_CROSS) && lobj->mSize <= 256 && (start & 0xff00) != ((end - 1) & 0xff00))
{
start = (start + 0x00ff) & 0xff00;
end = start + lobj->mSize;
}
if (end <= mEnd)
{
lobj->mFlags |= LOBJF_PLACED;
@ -294,7 +302,7 @@ void Linker::Link(void)
for (int k = 0; k < lsec->mObjects.Size(); k++)
{
LinkerObject* lobj = lsec->mObjects[k];
if ((lobj->mFlags & LOBJF_REFERENCED) && !(lobj->mFlags & LOBJF_PLACED) && lrgn->Allocate(lobj) )
if ((lobj->mFlags & LOBJF_REFERENCED) && !(lobj->mFlags & LOBJF_PLACED) && lrgn->Allocate(this, lobj) )
{
if (lsec->mType == LST_DATA)
lrgn->mNonzero = lrgn->mUsed;

View File

@ -91,7 +91,7 @@ public:
GrowingArray<FreeChunk> mFreeChunks;
bool Allocate(LinkerObject* obj);
bool Allocate(Linker * linker, LinkerObject* obj);
void PlaceStackSection(LinkerSection* stackSection, LinkerSection* section);
};
@ -129,6 +129,7 @@ static const uint32 LOBJF_INLINE = 0x00000008;
static const uint32 LOBJF_CONST = 0x00000010;
static const uint32 LOBJF_RELEVANT = 0x00000020;
static const uint32 LOBJF_STATIC_STACK = 0x00000040;
static const uint32 LOBJF_NO_CROSS = 0x00000080;
class LinkerObject
{
@ -187,6 +188,8 @@ public:
bool WriteCrtFile(const char* filename);
bool WriteBinFile(const char* filename);
uint64 mCompilerOptions;
GrowingArray<LinkerReference*> mReferences;
GrowingArray<LinkerRegion*> mRegions;
GrowingArray<LinkerSection*> mSections;

View File

@ -3029,6 +3029,9 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
rl.mRefObject = mLinkerObject;
rl.mRefOffset = mAddress;
if (mLinkerObject)
mLinkerObject->mFlags |= LOBJF_NO_CROSS;
block->mRelocations.Push(rl);
block->PutByte(0);
}
@ -3058,6 +3061,9 @@ void NativeCodeInstruction::Assemble(NativeCodeBasicBlock* block)
rl.mOffset++;
}
if (mode != ASMIM_ABSOLUTE)
mLinkerObject->mFlags |= LOBJF_NO_CROSS;
block->mRelocations.Push(rl);
block->PutWord(0);
}
@ -9656,6 +9662,15 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
changed = true;
}
else if (yoffset == 1)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_DEY; mIns[i + 0].mMode = ASMIM_IMPLIED;
yoffset = 0;
changed = true;
}
else if (yoffset == 2 && i + 2 < mIns.Size() && mIns[i + 1].mType == ASMIT_INY && mIns[i + 2].mType == ASMIT_INY)
{
for (int j = ypred; j < i; j++)
@ -9666,6 +9681,35 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
changed = true;
}
else if (yoffset == 2 && i + 1 < mIns.Size() && mIns[i + 1].mType == ASMIT_INY)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEY;
changed = true;
}
else if (yoffset == 3 && i + 2 < mIns.Size() && mIns[i + 1].mType == ASMIT_INY && mIns[i + 2].mType == ASMIT_INY)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_DEY; mIns[i + 2].mMode = ASMIM_IMPLIED;
changed = true;
}
else if (yoffset == 3 && i + 1 < mIns.Size() && mIns[i + 1].mType == ASMIT_INY)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_DEY; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED;
yoffset = 2;
changed = true;
}
else
yoffset = 0;
ypred = i;
@ -9744,7 +9788,7 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
}
else if (mIns[i].mType == ASMIT_DEY)
{
yoffset = (yoffset + 1) & 255;
yoffset = (yoffset - 1) & 255;
}
else if (mIns[i].ChangesYReg())
{
@ -9890,7 +9934,7 @@ bool NativeCodeBasicBlock::ForwardZpXIndex(bool full)
}
else if (mIns[i].mType == ASMIT_DEX)
{
xoffset = (xoffset + 1) & 255;
xoffset = (xoffset - 1) & 255;
}
else if (mIns[i].ChangesXReg())
{
@ -10569,7 +10613,7 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::SplitMatchingTails(NativeCodeProced
return nullptr;
}
bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc)
bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool loops)
{
bool changed = false;
@ -10612,14 +10656,14 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc)
NativeCodeBasicBlock* nblock = SplitMatchingTails(proc);
if (nblock)
{
if (nblock->JoinTailCodeSequences(proc))
if (nblock->JoinTailCodeSequences(proc, loops))
changed = true;
}
}
}
#endif
#if 1
if (mIns.Size() >= 1 && mEntryBlocks.Size() == 2)
if (loops && mIns.Size() >= 1 && mEntryBlocks.Size() == 2)
{
NativeCodeBasicBlock* pblock = mEntryBlocks[0], * lblock = mEntryBlocks[1];
int ps = pblock->mIns.Size(), ls = lblock->mIns.Size();
@ -10815,9 +10859,9 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc)
}
}
#endif
if (mTrueJump && mTrueJump->JoinTailCodeSequences(proc))
if (mTrueJump && mTrueJump->JoinTailCodeSequences(proc, loops))
changed = true;
if (mFalseJump && mFalseJump->JoinTailCodeSequences(proc))
if (mFalseJump && mFalseJump->JoinTailCodeSequences(proc, loops))
changed = true;
}
@ -10901,6 +10945,8 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(const NativeCodeBasicBlock*
if (!mEntryRequiredRegs[reg])
return true;
assert(mNumEntries == mEntryBlocks.Size());
if (mNumEntries > 1)
{
if (mLoopHead)
@ -11139,6 +11185,20 @@ bool NativeCodeBasicBlock::IsDominatedBy(const NativeCodeBasicBlock* block) cons
{
if (this == block)
return true;
#if 0
if (mEntryBlocks.Size())
{
if (mLoopHead)
return false;
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->IsDominatedBy(block))
return false;
return true;
}
return false;
#else
else
{
NativeCodeBasicBlock* dom = mDominator;
@ -11151,6 +11211,7 @@ bool NativeCodeBasicBlock::IsDominatedBy(const NativeCodeBasicBlock* block) cons
return false;
}
#endif
}
bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(const NativeCodeBasicBlock * block, int reg, int at, int yval)
@ -11704,6 +11765,25 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to)
}
mIns.Remove(start);
return true;
}
else if (mIns[start].mType == ASMIT_LDA && mIns[start].mMode == ASMIM_ABSOLUTE_X && mIns[start + 1].ChangesAccu() && !mIns[start + 1].ChangesAddress() && !mIns[start + 1].RequiresYReg())
{
for (int i = from + 1; i < to; i++)
{
if (mIns[start].MayBeChangedOnAddress(mIns[i]) || mIns[start + 1].MayBeChangedOnAddress(mIns[i]))
return false;
}
mIns.Remove(to);
for (int i = start; i < from; i++)
{
mIns.Insert(to, mIns[start]);
mIns.Remove(start);
}
mIns.Remove(start);
return true;
}
}
@ -14492,6 +14572,7 @@ bool NativeCodeBasicBlock::OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCo
{
block->mIns[i].mType = ASMIT_NOP; block->mIns[i].mMode = ASMIM_IMPLIED;
}
block->mIns[i].mLive |= LIVE_CPU_REG_Y;
}
}
}
@ -14559,6 +14640,7 @@ bool NativeCodeBasicBlock::OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCo
{
block->mIns[i].mType = ASMIT_NOP; block->mIns[i].mMode = ASMIM_IMPLIED;
}
block->mIns[i].mLive |= LIVE_CPU_REG_X;
}
}
}
@ -18917,146 +18999,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
}
#endif
#if 0
if (i + 7 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 &&
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 &&
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
mIns[i + 6].mType == ASMIT_LDY && mIns[i + 6].mMode == ASMIM_IMMEDIATE && mIns[i + 6].mAddress == 0 &&
mIns[i + 7].mMode == ASMIM_INDIRECT_Y && mIns[i + 7].mAddress == mIns[i + 2].mAddress && !(mIns[i + 7].mLive & LIVE_MEM))
{
for (int j = 0; j < 6; j++)
{
mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED;
}
if (mIns[i + 7].mLive & LIVE_CPU_REG_Y)
{
mIns.Insert(i + 8, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
mIns[i + 8].mLive |= LIVE_CPU_REG_Y;
}
mIns[i + 6].mType = ASMIT_TAY;
mIns[i + 6].mMode = ASMIM_IMPLIED;
mIns[i + 7].mAddress = mIns[i + 1].mAddress;
progress = true;
}
}
#endif
#if 0
if (i + 8 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 &&
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 &&
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
!mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 6].RequiresYReg() &&
mIns[i + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE && mIns[i + 7].mAddress == 0 &&
mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 2].mAddress && !(mIns[i + 8].mLive & LIVE_MEM))
{
for (int j = 0; j < 6; j++)
{
mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED;
}
if (mIns[i + 8].mLive & LIVE_CPU_REG_Y)
{
mIns.Insert(i + 9, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
mIns[i + 9].mLive |= LIVE_CPU_REG_Y;
}
mIns[i + 0].mType = ASMIT_TAY;
mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED;
mIns[i + 8].mAddress = mIns[i + 1].mAddress;
progress = true;
}
}
#endif
#if 0
if (i + 11 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 &&
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 &&
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
!mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 6].RequiresYReg() &&
mIns[i + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE && mIns[i + 7].mAddress == 0 &&
mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 2].mAddress &&
!mIns[i + 9].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 9].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 9].RequiresYReg() &&
mIns[i + 10].mType == ASMIT_LDY && mIns[i + 10].mMode == ASMIM_IMMEDIATE && mIns[i + 10].mAddress == 1 &&
mIns[i + 11].mMode == ASMIM_INDIRECT_Y && mIns[i + 11].mAddress == mIns[i + 2].mAddress &&
!(mIns[i + 11].mLive & LIVE_MEM))
{
for (int j = 0; j < 6; j++)
{
mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED;
}
if (mIns[i + 11].mLive & LIVE_CPU_REG_Y)
{
mIns.Insert(i + 12, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 1));
mIns[i + 12].mLive |= LIVE_CPU_REG_Y;
}
mIns[i + 0].mType = ASMIT_TAY;
mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED;
mIns[i + 8].mAddress = mIns[i + 1].mAddress;
mIns[i + 10].mType = ASMIT_INY; mIns[i + 10].mMode = ASMIM_IMPLIED;
mIns[i + 11].mAddress = mIns[i + 1].mAddress;
progress = true;
}
}
#endif
#if 0
if (i + 9 < mIns.Size())
{
if (
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 &&
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 &&
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
mIns[i + 6].mType == ASMIT_LDY && mIns[i + 6].mMode == ASMIM_IMMEDIATE && mIns[i + 6].mAddress == 0 &&
mIns[i + 7].mType == ASMIT_LDA && mIns[i + 7].mMode == ASMIM_INDIRECT_Y && mIns[i + 7].mAddress == mIns[i + 2].mAddress &&
!mIns[i + 8].ChangesYReg() && (mIns[i + 8].mMode == ASMIM_IMMEDIATE || mIns[i + 8].mMode == ASMIM_ZERO_PAGE && mIns[i + 8].mAddress != mIns[i + 2].mAddress && mIns[i + 8].mAddress != mIns[i + 1].mAddress) &&
mIns[i + 9].mType == ASMIT_STA && mIns[i + 9].mMode == ASMIM_INDIRECT_Y && mIns[i + 9].mAddress == mIns[i + 2].mAddress && !(mIns[i + 9].mLive & LIVE_MEM)
)
{
for(int j=0; j<6; j++)
{
mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED;
}
if (mIns[i + 9].mLive & LIVE_CPU_REG_Y)
{
mIns.Insert(i + 10, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
mIns[i + 10].mLive |= LIVE_CPU_REG_Y;
}
mIns[i + 6].mType = ASMIT_TAY;
mIns[i + 6].mMode = ASMIM_IMPLIED;
mIns[i + 7].mAddress = mIns[i + 1].mAddress;
mIns[i + 9].mAddress = mIns[i + 1].mAddress;
progress = true;
}
}
#endif
#endif
#if 1
@ -20179,8 +20121,16 @@ void NativeCodeProcedure::Optimize(void)
mBlocks[i]->mFromJump = nullptr;
mBlocks[i]->mDominator = nullptr;
}
ResetEntryBlocks();
mEntryBlock->CountEntries(nullptr);
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
mEntryBlock->BuildDominatorTree(nullptr);
#if 1
do
{
@ -20246,7 +20196,7 @@ void NativeCodeProcedure::Optimize(void)
if (step > 2)
{
ResetVisited();
if (mEntryBlock->JoinTailCodeSequences(this))
if (mEntryBlock->JoinTailCodeSequences(this, step > 3))
changed = true;
}
#endif

View File

@ -283,7 +283,7 @@ public:
NativeCodeBasicBlock * SplitMatchingTails(NativeCodeProcedure* proc);
bool JoinTailCodeSequences(NativeCodeProcedure* proc);
bool JoinTailCodeSequences(NativeCodeProcedure* proc, bool loops);
bool SameTail(const NativeCodeInstruction& ins) const;
NativeRegisterDataSet mEntryRegisterDataSet;