Optimize jmp to rts

This commit is contained in:
drmortalwombat 2021-12-12 20:34:33 +01:00
parent fefa2e7d9a
commit 4cf62a67ff
2 changed files with 171 additions and 9 deletions

View File

@ -162,6 +162,12 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
}
else
{
for (int i = 0; i < 4; i++)
{
requiredTemps -= BC_REG_ACCU + i;
requiredTemps -= BC_REG_WORK + i;
}
requiredTemps += BC_REG_LOCALS;
requiredTemps += BC_REG_LOCALS + 1;
if (mLinkerObject)
@ -179,10 +185,28 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
if (mType == ASMIT_RTS)
{
#if 1
if (mFlags & NCIF_LOWER)
{
requiredTemps += BC_REG_ACCU;
if (mFlags & NCIF_UPPER)
{
requiredTemps += BC_REG_ACCU + 1;
if (mFlags & NCIF_LONG)
{
requiredTemps += BC_REG_ACCU + 2;
requiredTemps += BC_REG_ACCU + 3;
}
}
}
#endif
#if 0
for (int i = 0; i < 4; i++)
{
requiredTemps += BC_REG_ACCU + i;
}
#endif
requiredTemps += BC_REG_STACK;
requiredTemps += BC_REG_STACK + 1;
@ -426,6 +450,10 @@ bool NativeCodeInstruction::IsUsedResultInstructions(NumberSet& requiredTemps)
case ASMIT_TYA:
case ASMIT_TAX:
case ASMIT_TXA:
case ASMIT_INX:
case ASMIT_DEX:
case ASMIT_INY:
case ASMIT_DEY:
requiredTemps -= CPU_REG_Z;
break;
}
@ -1458,14 +1486,37 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
case ASMIT_ROL:
case ASMIT_ROR:
case ASMIT_ASL:
case ASMIT_LSR:
if (mMode == ASMIM_IMPLIED)
data.mRegs[CPU_REG_A].Reset();
data.mRegs[CPU_REG_C].Reset();
data.mRegs[CPU_REG_Z].Reset();
break;
case ASMIT_ASL:
case ASMIT_LSR:
if (mMode == ASMIM_IMPLIED)
{
if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE && data.mRegs[CPU_REG_A].mValue == 0 && !(mLive & LIVE_CPU_REG_Z))
{
mType = ASMIT_CLC;
data.mRegs[CPU_REG_C].mMode = NRDM_IMMEDIATE;
data.mRegs[CPU_REG_C].mValue = 0;
changed = true;
}
else
{
data.mRegs[CPU_REG_A].Reset();
data.mRegs[CPU_REG_C].Reset();
data.mRegs[CPU_REG_Z].Reset();
}
}
else
{
data.mRegs[CPU_REG_C].Reset();
data.mRegs[CPU_REG_Z].Reset();
}
break;
case ASMIT_INC:
case ASMIT_DEC:
data.mRegs[CPU_REG_Z].Reset();
@ -2110,7 +2161,7 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet&
if (mType == ASMIT_JSR)
{
#if 1
if (mFlags & NCIF_RUNTIME)
{
for (int i = 0; i < 4; i++)
@ -2137,7 +2188,7 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet&
}
}
}
#endif
for (int i = 0; i < 4; i++)
{
providedTemps += BC_REG_ACCU + i;
@ -2155,12 +2206,30 @@ void NativeCodeInstruction::FilterRegUsage(NumberSet& requiredTemps, NumberSet&
if (mType == ASMIT_RTS)
{
#if 1
if (mFlags & NCIF_LOWER)
{
if (!providedTemps[BC_REG_ACCU + 0]) requiredTemps += BC_REG_ACCU + 0;
if (mFlags & NCIF_UPPER)
{
if (!providedTemps[BC_REG_ACCU + 1]) requiredTemps += BC_REG_ACCU + 1;
if (mFlags & NCIF_LONG)
{
if (!providedTemps[BC_REG_ACCU + 2]) requiredTemps += BC_REG_ACCU + 2;
if (!providedTemps[BC_REG_ACCU + 3]) requiredTemps += BC_REG_ACCU + 3;
}
}
}
#endif
#if 0
for (int i = 0; i < 4; i++)
{
if (!providedTemps[BC_REG_ACCU + i])
requiredTemps += BC_REG_ACCU + i;
}
#endif
if (!providedTemps[BC_REG_STACK])
requiredTemps += BC_REG_STACK;
if (!providedTemps[BC_REG_STACK + 1])
@ -8918,6 +8987,80 @@ void NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
}
}
bool NativeCodeBasicBlock::SimpleLoopReversal(NativeCodeProcedure* proc)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (mTrueJump && !mFalseJump && mTrueJump->mTrueJump == mTrueJump && mIns.Size() > 0 && mTrueJump->mIns.Size() > 1 && mTrueJump->mBranch == ASMIT_BCC)
{
NativeCodeBasicBlock* lb = mTrueJump;
int lbs = lb->mIns.Size();
if (lb->mIns[lbs-1].mType == ASMIT_CPX)
{
if (lb->mIns[lbs-2].mType == ASMIT_INX && mIns.Last().mType == ASMIT_LDX && mIns.Last().mMode == ASMIM_IMMEDIATE && mIns.Last().mAddress == 0)
{
if (lb->mIns[lbs - 1].mMode == ASMIM_ZERO_PAGE)
{
int a = lb->mIns[lbs - 1].mAddress;
int i = 0;
while (i + 2 < lbs && !(lb->mIns[i].RequiresXReg() || lb->mIns[i].ChangesZeroPage(a)))
i++;
if (i + 2 == lbs)
{
mIns[mIns.Size() - 1].mMode = ASMIM_ZERO_PAGE;
mIns[mIns.Size() - 1].mAddress = a;
lb->mIns[lbs - 2].mType = ASMIT_DEX;
lb->mIns[lbs - 1].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
lb->mBranch = ASMIT_BNE;
}
}
}
}
else if (lb->mIns[lbs - 1].mType == ASMIT_CPY)
{
NativeCodeBasicBlock* lb = mTrueJump;
int lbs = lb->mIns.Size();
if (lb->mIns[lbs - 1].mType == ASMIT_CPY)
{
if (lb->mIns[lbs - 2].mType == ASMIT_INY && mIns.Last().mType == ASMIT_LDY && mIns.Last().mMode == ASMIM_IMMEDIATE && mIns.Last().mAddress == 0)
{
if (lb->mIns[lbs - 1].mMode == ASMIM_ZERO_PAGE)
{
int a = lb->mIns[lbs - 1].mAddress;
int i = 0;
while (i + 2 < lbs && !(lb->mIns[i].RequiresYReg() || lb->mIns[i].ChangesZeroPage(a)))
i++;
if (i + 2 == lbs)
{
mIns[mIns.Size() - 1].mMode = ASMIM_ZERO_PAGE;
mIns[mIns.Size() - 1].mAddress = a;
lb->mIns[lbs - 2].mType = ASMIT_DEY;
lb->mIns[lbs - 1].mType = ASMIT_NOP; lb->mIns[lbs - 1].mMode = ASMIM_IMPLIED;
lb->mBranch = ASMIT_BNE;
}
}
}
}
}
}
if (mTrueJump && mTrueJump->SimpleLoopReversal(proc))
changed = true;
if (mFalseJump && mFalseJump->SimpleLoopReversal(proc))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
{
if (!mVisited)
@ -11949,12 +12092,12 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mExitBlock->mLocked = true;
mBlocks.Push(mExitBlock);
mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]);
mEntryBlock->mBranch = ASMIT_JMP;
// Place a temporary RTS
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED));
mExitBlock->mIns.Push(NativeCodeInstruction(ASMIT_RTS, ASMIM_IMPLIED, 0, nullptr, 0));
mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]);
mEntryBlock->mBranch = ASMIT_JMP;
Optimize();
@ -12288,6 +12431,11 @@ void NativeCodeProcedure::Optimize(void)
if (mEntryBlock->OptimizeSimpleLoop(this))
changed = true;
ResetVisited();
if (mEntryBlock->SimpleLoopReversal(this))
changed = true;
ResetVisited();
if (mEntryBlock->MergeBasicBlocks())
changed = true;
@ -12693,6 +12841,8 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (cc.v >> 24) & 0xff));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
mExitBlock->mIns[0].mFlags |= NCIF_LOWER | NCIF_UPPER | NCIF_LONG;
}
else
{
@ -12700,12 +12850,17 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
mExitBlock->mIns[0].mFlags |= NCIF_LOWER | NCIF_UPPER;
if (ins->mSrc[0].mType == IT_INT32)
{
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 16) & 0xff));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 24) & 0xff));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
mExitBlock->mIns[0].mFlags |= NCIF_LONG;
}
}
}
@ -12715,12 +12870,17 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU));
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 1));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
mExitBlock->mIns[0].mFlags |= NCIF_LOWER | NCIF_UPPER;
if (ins->mSrc[0].mType == IT_FLOAT || ins->mSrc[0].mType == IT_INT32)
{
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 2));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 2));
block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 3));
block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 3));
mExitBlock->mIns[0].mFlags |= NCIF_LONG;
}
}

View File

@ -46,6 +46,7 @@ static const uint32 NCIF_UPPER = 0x00000002;
static const uint32 NCIF_RUNTIME = 0x00000004;
static const uint32 NCIF_YZERO = 0x00000008;
static const uint32 NCIF_VOLATILE = 0x00000010;
static const uint32 NCIF_LONG = 0x00000020;
class NativeCodeInstruction
{
@ -132,6 +133,7 @@ public:
void OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock * lblock);
bool OptimizeSimpleLoop(NativeCodeProcedure* proc);
bool SimpleLoopReversal(NativeCodeProcedure* proc);
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, GrowingArray<NativeCodeBasicBlock*>& blocks);
NativeCodeBasicBlock* FindTailBlock(NativeCodeBasicBlock* head);