Reverse cross block accu to index propagation

This commit is contained in:
drmortalwombat 2025-02-28 16:20:07 +01:00
parent ee0e4d5428
commit 5c70c20c6e
2 changed files with 178 additions and 8 deletions

View File

@ -14827,27 +14827,39 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::ForwardAccuBranch(bool eq, bool ne,
} }
void NativeCodeBasicBlock::RemoveJumpToBranch(void) bool NativeCodeBasicBlock::RemoveJumpToBranch(void)
{ {
bool changed = false;
if (!mVisited) if (!mVisited)
{ {
mVisited = true; mVisited = true;
if (mTrueJump) mTrueJump->RemoveJumpToBranch(); if (mTrueJump && mTrueJump->RemoveJumpToBranch()) changed = true;
if (mFalseJump) mFalseJump->RemoveJumpToBranch(); if (mFalseJump && mFalseJump->RemoveJumpToBranch()) changed = true;
if (mTrueJump && !mFalseJump && mTrueJump != this && mTrueJump->mIns.Size() == 0) if (mTrueJump && !mFalseJump && mTrueJump != this && mTrueJump->mIns.Size() == 0)
{ {
mTrueJump->mEntryBlocks.RemoveAll(this);
mTrueJump->mNumEntries--; mTrueJump->mNumEntries--;
mBranch = mTrueJump->mBranch; mBranch = mTrueJump->mBranch;
mFalseJump = mTrueJump->mFalseJump; mFalseJump = mTrueJump->mFalseJump;
mTrueJump = mTrueJump->mTrueJump; mTrueJump = mTrueJump->mTrueJump;
if (mTrueJump) if (mTrueJump)
{
mTrueJump->mNumEntries++; mTrueJump->mNumEntries++;
mTrueJump->mEntryBlocks.Push(this);
}
if (mFalseJump) if (mFalseJump)
{
mFalseJump->mNumEntries++; mFalseJump->mNumEntries++;
mFalseJump->mEntryBlocks.Push(this);
}
changed = true;
} }
} }
return changed;
} }
bool NativeCodeBasicBlock::MergeBasicBlocks(void) bool NativeCodeBasicBlock::MergeBasicBlocks(void)
@ -22727,6 +22739,145 @@ bool NativeCodeBasicBlock::LocalRegisterXYMap(void)
return changed; return changed;
} }
bool NativeCodeBasicBlock::CanReplaceExitAccuWithX(NativeCodeBasicBlock* target)
{
if (mTrueJump && target != mTrueJump && (mTrueJump->mEntryRequiredRegs[CPU_REG_X] || mTrueJump->mEntryRequiredRegs[CPU_REG_A]))
return false;
if (mFalseJump && target != mFalseJump && (mFalseJump->mEntryRequiredRegs[CPU_REG_X] || mFalseJump->mEntryRequiredRegs[CPU_REG_A]))
return false;
int i = mIns.Size() - 1;
while (i >= 0)
{
NativeCodeInstruction& ins(mIns[i]);
if (ins.mType == ASMIT_LDA)
{
if (HasAsmInstructionMode(ASMIT_LDX, ins.mMode))
return true;
}
if (ins.ReferencesXReg() || ins.ReferencesAccu())
return false;
i--;
}
return false;
}
bool NativeCodeBasicBlock::CanReplaceExitAccuWithY(NativeCodeBasicBlock* target)
{
if (mTrueJump && target != mTrueJump && (mTrueJump->mEntryRequiredRegs[CPU_REG_Y] || mTrueJump->mEntryRequiredRegs[CPU_REG_A]))
return false;
if (mFalseJump && target != mFalseJump && (mFalseJump->mEntryRequiredRegs[CPU_REG_Y] || mFalseJump->mEntryRequiredRegs[CPU_REG_A]))
return false;
int i = mIns.Size() - 1;
while (i >= 0)
{
NativeCodeInstruction& ins(mIns[i]);
if (ins.mType == ASMIT_LDA)
{
if (HasAsmInstructionMode(ASMIT_LDY, ins.mMode))
return true;
}
if (ins.ReferencesYReg() || ins.ReferencesAccu())
return false;
i--;
}
return false;
}
void NativeCodeBasicBlock::ReplaceExitAccuWithX(NativeCodeBasicBlock* target)
{
int i = mIns.Size() - 1;
while (i >= 0)
{
NativeCodeInstruction& ins(mIns[i]);
ins.mLive |= LIVE_CPU_REG_X;
if (ins.mType == ASMIT_LDA)
{
ins.mType = ASMIT_LDX;
mExitRequiredRegs += CPU_REG_X;
return;
}
i--;
}
}
void NativeCodeBasicBlock::ReplaceExitAccuWithY(NativeCodeBasicBlock* target)
{
int i = mIns.Size() - 1;
while (i >= 0)
{
NativeCodeInstruction& ins(mIns[i]);
ins.mLive |= LIVE_CPU_REG_Y;
if (ins.mType == ASMIT_LDA)
{
ins.mType = ASMIT_LDY;
mExitRequiredRegs += CPU_REG_Y;
return;
}
i--;
}
}
bool NativeCodeBasicBlock::ReverseLoadAccuToRegXY(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (mIns.Size() > 2)
{
if (mIns[0].mType == ASMIT_STA && mIns[0].mMode == ASMIM_ZERO_PAGE && (mIns[1].mType == ASMIT_TAX || mIns[1].mType == ASMIT_TAY) && !(mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
if (mIns[1].mType == ASMIT_TAY)
{
int i = 0;
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->CanReplaceExitAccuWithY(this))
i++;
if (i == mEntryBlocks.Size())
{
for (int j = 0; j < mEntryBlocks.Size(); j++)
mEntryBlocks[j]->ReplaceExitAccuWithY(this);
mEntryRequiredRegs += CPU_REG_Y;
mIns[0].mType = ASMIT_STY; mIns[0].mLive |= LIVE_CPU_REG_Y;
mIns[1].mType = ASMIT_NOP; mIns[1].mMode = ASMIM_IMPLIED;
changed = true;
}
}
else
{
int i = 0;
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->CanReplaceExitAccuWithX(this))
i++;
if (i == mEntryBlocks.Size())
{
for (int j = 0; j < mEntryBlocks.Size(); j++)
mEntryBlocks[j]->ReplaceExitAccuWithX(this);
mEntryRequiredRegs += CPU_REG_X;
mIns[0].mType = ASMIT_STX; mIns[0].mLive |= LIVE_CPU_REG_X;
mIns[1].mType = ASMIT_NOP; mIns[1].mMode = ASMIM_IMPLIED;
changed = true;
}
}
}
}
if (mTrueJump && mTrueJump->ReverseLoadAccuToRegXY())
changed = true;
if (mFalseJump && mFalseJump->ReverseLoadAccuToRegXY())
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::LoopRegisterXYMap(void) bool NativeCodeBasicBlock::LoopRegisterXYMap(void)
{ {
bool changed = false; bool changed = false;
@ -47809,12 +47960,16 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerIterate4(int i, int pass)
else if ( else if (
mIns[i + 0].mType == ASMIT_TXA && mIns[i + 0].mType == ASMIT_TXA &&
mIns[i + 1].mType == ASMIT_SEC && mIns[i + 1].mType == ASMIT_SEC &&
mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 2 && mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress <= 3 &&
mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & LIVE_CPU_REG_C)) mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & LIVE_CPU_REG_C))
{ {
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; if (mIns[i + 2].mAddress == 3)
mIns[i + 0].mType = ASMIT_DEX;
else
mIns[i + 0].mType = ASMIT_NOP;
mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mLive |= LIVE_CPU_REG_X | LIVE_CPU_REG_Z;
mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X | LIVE_CPU_REG_Z; mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X | LIVE_CPU_REG_Z;
if (mIns[i + 2].mAddress == 2) if (mIns[i + 2].mAddress >= 2)
mIns[i + 2].mType = ASMIT_DEX; mIns[i + 2].mType = ASMIT_DEX;
else else
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP;
@ -53098,7 +53253,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mInterProc->mLinkerObject->mNativeProc = this; mInterProc->mLinkerObject->mNativeProc = this;
CheckFunc = !strcmp(mIdent->mString, "shot_damage"); CheckFunc = !strcmp(mIdent->mString, "shots_hide");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];
@ -54926,6 +55081,14 @@ void NativeCodeProcedure::Optimize(void)
ResetVisited(); ResetVisited();
if (mEntryBlock->OptimizeLoopRegisterWrapAround()) if (mEntryBlock->OptimizeLoopRegisterWrapAround())
changed = true; changed = true;
ResetVisited();
if (mEntryBlock->RemoveJumpToBranch())
changed = true;
ResetVisited();
if (mEntryBlock->ReverseLoadAccuToRegXY())
changed = true;
} }
#if _DEBUG #if _DEBUG

View File

@ -445,7 +445,7 @@ public:
void CountEntries(NativeCodeBasicBlock* fromJump); void CountEntries(NativeCodeBasicBlock* fromJump);
NativeCodeBasicBlock * ForwardAccuBranch(bool eq, bool ne, bool pl, bool mi, int limit); NativeCodeBasicBlock * ForwardAccuBranch(bool eq, bool ne, bool pl, bool mi, int limit);
bool MergeBasicBlocks(void); bool MergeBasicBlocks(void);
void RemoveJumpToBranch(void); bool RemoveJumpToBranch(void);
void MarkLoopHead(void); void MarkLoopHead(void);
@ -576,6 +576,13 @@ public:
bool ReverseReplaceTAX(int at); bool ReverseReplaceTAX(int at);
bool CanReplaceExitAccuWithX(NativeCodeBasicBlock * target);
bool CanReplaceExitAccuWithY(NativeCodeBasicBlock* target);
void ReplaceExitAccuWithX(NativeCodeBasicBlock* target);
void ReplaceExitAccuWithY(NativeCodeBasicBlock* target);
bool ReverseLoadAccuToRegXY(void);
void ResetModifiedDataSet(NativeRegisterDataSet& data); void ResetModifiedDataSet(NativeRegisterDataSet& data);
bool ValueForwarding(NativeCodeProcedure* proc, const NativeRegisterDataSet& data, bool global, bool final); bool ValueForwarding(NativeCodeProcedure* proc, const NativeRegisterDataSet& data, bool global, bool final);