Join common branch code sequences

This commit is contained in:
drmortalwombat 2023-11-26 15:46:59 +01:00
parent eec4ed45d1
commit 57537cd43a
4 changed files with 470 additions and 41 deletions

View File

@ -680,17 +680,21 @@ __native unsigned long ldiv16f16(unsigned long x, unsigned long y)
__native long ldiv16f16s(long x, long y) __native long ldiv16f16s(long x, long y)
{ {
bool sign = false;
if (x < 0) if (x < 0)
{ {
if (y < 0) x = -x;
return ldiv16f16(-x, -y); sign = true;
else
return -ldiv16f16(-x, y);
} }
else if (y < 0) if (y < 0)
{ {
return -ldiv16f16(x, -y); y = -y;
sign = !sign;
} }
x = ldiv16f16(x, y);
if (sign)
return -x;
else else
return ldiv16f16(x, y); return x;
} }

View File

@ -9137,6 +9137,10 @@ bool InterCodeBasicBlock::RemoveUnusedIndirectStoreInstructions(void)
stores.Push(ins); stores.Push(ins);
} }
} }
else if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE)
{
stores.SetSize(0);
}
else else
{ {
int j = 0; int j = 0;
@ -11406,30 +11410,33 @@ bool InterCodeBasicBlock::MergeCommonPathInstructions(void)
if (mTrueJump->CanMoveInstructionBeforeBlock(ti) && mFalseJump->CanMoveInstructionBeforeBlock(fi)) if (mTrueJump->CanMoveInstructionBeforeBlock(ti) && mFalseJump->CanMoveInstructionBeforeBlock(fi))
{ {
int tindex = mInstructions.Size() - 1; int tindex = mInstructions.Size() - 1;
if (mInstructions.Size() >= 2 && mInstructions[tindex - 1]->mDst.mTemp == mInstructions[tindex]->mSrc[0].mTemp && if (mInstructions[tindex]->mCode != IC_BRANCH || tins->mDst.mTemp != mInstructions[tindex]->mSrc[0].mTemp)
CanSwapInstructions(mInstructions[tindex - 1], tins))
// CanBypassUp(tins, mInstructions[tindex - 1]))
tindex--;
mInstructions.Insert(tindex, tins);
tindex++;
if (tins->mDst.mTemp != -1)
{ {
if (fins->mDst.mTemp != tins->mDst.mTemp) if (mInstructions.Size() >= 2 && mInstructions[tindex - 1]->mDst.mTemp == mInstructions[tindex]->mSrc[0].mTemp &&
CanSwapInstructions(mInstructions[tindex - 1], tins))
// CanBypassUp(tins, mInstructions[tindex - 1]))
tindex--;
mInstructions.Insert(tindex, tins);
tindex++;
if (tins->mDst.mTemp != -1)
{ {
InterInstruction* nins = new InterInstruction(tins->mLocation, IC_LOAD_TEMPORARY); if (fins->mDst.mTemp != tins->mDst.mTemp)
nins->mDst.mTemp = fins->mDst.mTemp; {
nins->mDst.mType = fins->mDst.mType; InterInstruction* nins = new InterInstruction(tins->mLocation, IC_LOAD_TEMPORARY);
nins->mSrc[0].mTemp = tins->mDst.mTemp; nins->mDst.mTemp = fins->mDst.mTemp;
nins->mSrc[0].mType = tins->mDst.mType; nins->mDst.mType = fins->mDst.mType;
assert(nins->mSrc[0].mTemp >= 0); nins->mSrc[0].mTemp = tins->mDst.mTemp;
mFalseJump->mInstructions.Insert(0, nins); nins->mSrc[0].mType = tins->mDst.mType;
fi++; assert(nins->mSrc[0].mTemp >= 0);
mFalseJump->mInstructions.Insert(0, nins);
fi++;
}
} }
mTrueJump->mInstructions.Remove(ti);
mFalseJump->mInstructions.Remove(fi);
changed = true;
} }
mTrueJump->mInstructions.Remove(ti);
mFalseJump->mInstructions.Remove(fi);
changed = true;
} }
} }
} }
@ -18163,6 +18170,8 @@ void InterCodeProcedure::RemoveUnusedStoreInstructions(InterMemory paramMemory)
ResetVisited(); ResetVisited();
mEntryBlock->RemoveUnusedIndirectStoreInstructions(); mEntryBlock->RemoveUnusedIndirectStoreInstructions();
DisassembleDebug("RemoveUnusedIndirectStoreInstructions");
} }
} }
@ -18538,7 +18547,9 @@ void InterCodeProcedure::PropagateConstOperationsUp(void)
ResetVisited(); ResetVisited();
if (mEntryBlock->SplitSingleBranchUseConst()) if (mEntryBlock->SplitSingleBranchUseConst())
changed = true; changed = true;
DisassembleDebug("SplitSingleBranchUseConst");
ResetVisited(); ResetVisited();
if (mEntryBlock->CommonTailCodeMerge()) if (mEntryBlock->CommonTailCodeMerge())
{ {
@ -18546,6 +18557,8 @@ void InterCodeProcedure::PropagateConstOperationsUp(void)
BuildDataFlowSets(); BuildDataFlowSets();
} }
DisassembleDebug("CommonTailCodeMerge");
ResetVisited(); ResetVisited();
mEntryBlock->BuildConstTempSets(); mEntryBlock->BuildConstTempSets();
@ -18594,7 +18607,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "interpret_expression"); CheckFunc = !strcmp(mIdent->mString, "parse_expression");
CheckCase = false; CheckCase = false;
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];

View File

@ -20,6 +20,8 @@ static const uint32 LIVE_CPU_REG_X = 0x00000002;
static const uint32 LIVE_CPU_REG_Y = 0x00000004; static const uint32 LIVE_CPU_REG_Y = 0x00000004;
static const uint32 LIVE_CPU_REG_C = 0x00000008; static const uint32 LIVE_CPU_REG_C = 0x00000008;
static const uint32 LIVE_CPU_REG_Z = 0x00000010; static const uint32 LIVE_CPU_REG_Z = 0x00000010;
static const uint32 LIVE_CPU_REG = 0x0000001f;
static const uint32 LIVE_MEM = 0x00000020; static const uint32 LIVE_MEM = 0x00000020;
static const uint32 LIVE_ALL = 0x000000ff; static const uint32 LIVE_ALL = 0x000000ff;
@ -1542,8 +1544,15 @@ bool NativeCodeInstruction::MayBeMovedBefore(const NativeCodeInstruction& ins)
return false; return false;
if (RequiresCarry() && ins.ChangesCarry() || ins.RequiresCarry() && ChangesCarry()) if (RequiresCarry() && ins.ChangesCarry() || ins.RequiresCarry() && ChangesCarry())
return false; return false;
if ((mLive & LIVE_CPU_REG_A) && ins.ChangesAccu())
if ((ins.mLive & LIVE_CPU_REG_Z) && ChangesZFlag()) return false;
if ((mLive & LIVE_CPU_REG_X) && ins.ChangesXReg())
return false;
if ((mLive & LIVE_CPU_REG_Y) && ins.ChangesYReg())
return false;
if ((mLive & LIVE_CPU_REG_C) && ins.ChangesCarry())
return false;
if ((mLive & LIVE_CPU_REG_Z) && ins.ChangesZFlag())
return false; return false;
return true; return true;
@ -19674,6 +19683,35 @@ bool NativeCodeBasicBlock::CanForward16BitAddSubImmediate(int sreg, int dreg, in
return false; return false;
} }
bool NativeCodeBasicBlock::CanForwardLoadStore(const NativeCodeInstruction& lins, const NativeCodeInstruction& sins, int& index) const
{
int i = mIns.Size() - 1;
while (i > 0)
{
if (lins.MayBeChangedOnAddress(mIns[i]))
return false;
if (mIns[i].MayBeSameAddress(sins))
{
index = i - 1;
if (mIns[i].mType == ASMIT_STA && mIns[i - 1].mType == ASMIT_LDA && !(mIns[i].mLive & LIVE_CPU_REG_A) ||
mIns[i].mType == ASMIT_STX && mIns[i - 1].mType == ASMIT_LDX && !(mIns[i].mLive & LIVE_CPU_REG_X) ||
mIns[i].mType == ASMIT_STY && mIns[i - 1].mType == ASMIT_LDY && !(mIns[i].mLive & LIVE_CPU_REG_Y))
{
if (!(mIns[i].mLive & LIVE_CPU_REG_Z) && mIns[i].SameEffectiveAddress(sins) && mIns[i - 1].SameEffectiveAddress(lins))
return true;
}
return false;
}
if (mIns[i].mType == ASMIT_JSR)
return false;
if (sins.MayBeChangedOnAddress(mIns[i]))
return false;
i--;
}
return false;
}
bool NativeCodeBasicBlock::CanForwardZPMove(int saddr, int daddr, int & index) const bool NativeCodeBasicBlock::CanForwardZPMove(int saddr, int daddr, int & index) const
{ {
int i = mIns.Size() - 1; int i = mIns.Size() - 1;
@ -20627,6 +20665,51 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
} }
} }
} }
#if 1
if (!changed && !mEntryRequiredRegs[CPU_REG_Z] && (!mEntryRequiredRegs[CPU_REG_A] || !mEntryRequiredRegs[CPU_REG_X] || !mEntryRequiredRegs[CPU_REG_Y]))
{
for (int i = eb->mIns.Size() - 1; i > 0; i--)
{
if ((eb->mIns[i - 1].mType == ASMIT_LDA && eb->mIns[i - 0].mType == ASMIT_STA ||
eb->mIns[i - 1].mType == ASMIT_LDX && eb->mIns[i - 0].mType == ASMIT_STX ||
eb->mIns[i - 1].mType == ASMIT_LDY && eb->mIns[i - 0].mType == ASMIT_STY) &&
(eb->mIns[i - 1].mMode == ASMIM_ZERO_PAGE || eb->mIns[i - 1].mMode == ASMIM_ABSOLUTE) &&
(eb->mIns[i - 0].mMode == ASMIM_ZERO_PAGE || eb->mIns[i - 0].mMode == ASMIM_ABSOLUTE))
{
int j = 0;
while (j < mEntryBlocks.Size() && mEntryBlocks[j]->CanForwardLoadStore(eb->mIns[i - 1], eb->mIns[i - 0], mEntryBlocks[j]->mTemp))
j++;
if (j == mEntryBlocks.Size())
{
const InterInstruction* iins(eb->mIns[i].mIns);
if (!mEntryRequiredRegs[CPU_REG_A])
{
mIns.Insert(0, NativeCodeInstruction(iins, ASMIT_LDA, eb->mIns[i - 1]));
mIns.Insert(1, NativeCodeInstruction(iins, ASMIT_STA, eb->mIns[i]));
changed = true;
}
else if (!mEntryRequiredRegs[CPU_REG_X])
{
mIns.Insert(0, NativeCodeInstruction(iins, ASMIT_LDX, eb->mIns[i - 1]));
mIns.Insert(1, NativeCodeInstruction(iins, ASMIT_STX, eb->mIns[i]));
changed = true;
}
else if (!mEntryRequiredRegs[CPU_REG_Y])
{
mIns.Insert(0, NativeCodeInstruction(iins, ASMIT_LDY, eb->mIns[i - 1]));
mIns.Insert(1, NativeCodeInstruction(iins, ASMIT_STY, eb->mIns[i]));
changed = true;
}
for (int j = 0; j < mEntryBlocks.Size(); j++)
mEntryBlocks[j]->mIns.Remove(mEntryBlocks[j]->mTemp, 2);
}
}
}
}
#endif
} }
if (mEntryBlocks.Size() >= 1) if (mEntryBlocks.Size() >= 1)
@ -21918,6 +22001,246 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
return changed; return changed;
} }
bool NativeCodeBasicBlock::MayBeMovedBeforeBlock(int at)
{
int i = at;
while (i > 0)
{
i--;
if (!mIns[at].MayBeMovedBefore(mIns[i]))
return false;
}
return true;
}
bool NativeCodeBasicBlock::SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end)
{
uint32 changes = 0;
uint32 requires = 0;
for (int i = start; i < end; i++)
{
const NativeCodeInstruction& ins(block->mIns[i]);
if (ins.RequiresAccu() && !(changes & LIVE_CPU_REG_A)) requires |= LIVE_CPU_REG_A;
if (ins.RequiresXReg() && !(changes & LIVE_CPU_REG_X)) requires |= LIVE_CPU_REG_X;
if (ins.RequiresYReg() && !(changes & LIVE_CPU_REG_Y)) requires |= LIVE_CPU_REG_Y;
if (ins.RequiresCarry() && !(changes & LIVE_CPU_REG_C)) requires |= LIVE_CPU_REG_C;
if (ins.ChangesAccu()) changes |= LIVE_CPU_REG_A;
if (ins.ChangesXReg()) changes |= LIVE_CPU_REG_X;
if (ins.ChangesYReg()) changes |= LIVE_CPU_REG_Y;
if (ins.ChangesCarry()) changes |= LIVE_CPU_REG_C;
if (ins.ChangesZFlag()) changes |= LIVE_CPU_REG_Z;
}
uint32 live = 0;
if (mBranch == ASMIT_BCC || mBranch == ASMIT_BCS)
live |= LIVE_CPU_REG_C;
if (mBranch == ASMIT_BEQ || mBranch == ASMIT_BNE || mBranch == ASMIT_BMI || mBranch == ASMIT_BPL)
live |= LIVE_CPU_REG_Z;
if (mExitRequiredRegs[CPU_REG_A])
live |= LIVE_CPU_REG_A;
if (mExitRequiredRegs[CPU_REG_X])
live |= LIVE_CPU_REG_X;
if (mExitRequiredRegs[CPU_REG_Y])
live |= LIVE_CPU_REG_Y;
if (mExitRequiredRegs[CPU_REG_C])
live |= LIVE_CPU_REG_C;
int at = mIns.Size();
while (at > 0)
{
if (live & changes)
{
at--;
const NativeCodeInstruction& ins(mIns[at]);
if (ins.ChangesAccu())
{
if (requires & LIVE_CPU_REG_A)
return false;
live &= ~LIVE_CPU_REG_A;
}
if (ins.ChangesXReg())
{
if (requires & LIVE_CPU_REG_X)
return false;
live &= ~LIVE_CPU_REG_X;
}
if (ins.ChangesYReg())
{
if (requires & LIVE_CPU_REG_Y)
return false;
live &= ~LIVE_CPU_REG_Y;
}
if (ins.ChangesCarry())
{
if (requires & LIVE_CPU_REG_C)
return false;
live &= ~LIVE_CPU_REG_C;
}
if (ins.ChangesZFlag()) live &= ~LIVE_CPU_REG_Z;
if (ins.RequiresAccu())
live |= LIVE_CPU_REG_A;
if (ins.RequiresXReg())
live |= LIVE_CPU_REG_X;
if (ins.RequiresYReg())
live |= LIVE_CPU_REG_Y;
if (ins.RequiresCarry())
live |= LIVE_CPU_REG_C;
}
else
{
for (int i = start; i < end; i++)
{
for (int j = at; j < mIns.Size(); j++)
{
if (block->mIns[i].MayBeChangedOnAddress(mIns[j]) || mIns[j].MayBeChangedOnAddress(block->mIns[i]))
return false;
}
}
for (int i = start; i < end; i++)
{
mIns.Insert(at, block->mIns[i]);
mIns[at].mLive |= live;
at++;
}
return true;
}
}
return false;
}
bool NativeCodeBasicBlock::MayBeMovedBeforeBlock(int start, int end)
{
uint32 changes = 0;
uint32 requires = 0;
if (start == 0)
return true;
for (int i = start; i < end; i++)
{
const NativeCodeInstruction& ins(mIns[i]);
if (ins.RequiresAccu() && !(changes & LIVE_CPU_REG_A)) requires |= LIVE_CPU_REG_A;
if (ins.RequiresXReg() && !(changes & LIVE_CPU_REG_X)) requires |= LIVE_CPU_REG_X;
if (ins.RequiresYReg() && !(changes & LIVE_CPU_REG_Y)) requires |= LIVE_CPU_REG_Y;
if (ins.RequiresCarry() && !(changes & LIVE_CPU_REG_C)) requires |= LIVE_CPU_REG_C;
if (ins.ChangesAccu()) changes |= LIVE_CPU_REG_A;
if (ins.ChangesXReg()) changes |= LIVE_CPU_REG_X;
if (ins.ChangesYReg()) changes |= LIVE_CPU_REG_Y;
if (ins.ChangesCarry()) changes |= LIVE_CPU_REG_C;
if (ins.ChangesZFlag()) changes |= LIVE_CPU_REG_Z;
}
for (int i = 0; i < start; i++)
{
const NativeCodeInstruction& ins(mIns[i]);
if (ins.ChangesAccu() && (requires & LIVE_CPU_REG_A))
return false;
if (ins.ChangesXReg() && (requires & LIVE_CPU_REG_X))
return false;
if (ins.ChangesYReg() && (requires & LIVE_CPU_REG_Y))
return false;
if (ins.ChangesCarry() && (requires & LIVE_CPU_REG_C))
return false;
for (int j = start; j < end; j++)
{
if (mIns[i].MayBeChangedOnAddress(mIns[j]) || mIns[j].MayBeChangedOnAddress(mIns[i]))
return false;
}
}
return true;
}
bool NativeCodeBasicBlock::JoinCommonBranchCodeSequences(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (mTrueJump && mFalseJump && mTrueJump->mIns.Size() > 0 && mFalseJump->mIns.Size() > 0 &&
mTrueJump != this && mFalseJump != this &&
mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1)
{
int i = 0;
while (i < mTrueJump->mIns.Size())
{
int j = 0;
while (j < mFalseJump->mIns.Size() && !mFalseJump->mIns[j].IsSame(mTrueJump->mIns[i]))
j++;
if (j < mFalseJump->mIns.Size())
{
int n = 0;
while (i + n < mTrueJump->mIns.Size() && j + n < mFalseJump->mIns.Size() && ((mTrueJump->mIns[i + n].mLive & LIVE_CPU_REG) || (mFalseJump->mIns[j + n].mLive & LIVE_CPU_REG)))
n++;
if (i + n < mTrueJump->mIns.Size() && j + n < mFalseJump->mIns.Size())
{
if (mTrueJump->MayBeMovedBeforeBlock(i, i + n + 1) && mFalseJump->MayBeMovedBeforeBlock(j, j + n + 1))
{
if (SafeInjectSequenceFromBack(mTrueJump, i, i + n + 1))
{
for (int k = 0; k < i; k++)
mTrueJump->mIns[k].mLive |= mTrueJump->mIns[i].mLive;
for (int k = 0; k < j; k++)
mFalseJump->mIns[k].mLive |= mFalseJump->mIns[j].mLive;
if (mTrueJump->mIns[i].mLive & LIVE_CPU_REG_A)
{
mTrueJump->mEntryRequiredRegs += CPU_REG_A;
mFalseJump->mEntryRequiredRegs += CPU_REG_A;
}
if (mTrueJump->mIns[i].mLive & LIVE_CPU_REG_X)
{
mTrueJump->mEntryRequiredRegs += CPU_REG_X;
mFalseJump->mEntryRequiredRegs += CPU_REG_X;
}
if (mTrueJump->mIns[i].mLive & LIVE_CPU_REG_Y)
{
mTrueJump->mEntryRequiredRegs += CPU_REG_Y;
mFalseJump->mEntryRequiredRegs += CPU_REG_Y;
}
if (mTrueJump->mIns[i].mLive & LIVE_CPU_REG_C)
{
mTrueJump->mEntryRequiredRegs += CPU_REG_C;
mFalseJump->mEntryRequiredRegs += CPU_REG_C;
}
mTrueJump->mIns.Remove(i, n + 1);
mFalseJump->mIns.Remove(j, n + 1);
changed = true;
}
else
i++;
}
else
i++;
}
else
i++;
}
else
i++;
}
}
CheckLive();
if (mTrueJump && mTrueJump->JoinCommonBranchCodeSequences())
changed = true;
if (mFalseJump && mFalseJump->JoinCommonBranchCodeSequences())
changed = true;
}
return changed;
}
void NativeCodeBasicBlock::DoCrossBlockAShortcut(int addr) void NativeCodeBasicBlock::DoCrossBlockAShortcut(int addr)
{ {
mExitRequiredRegs += CPU_REG_A; mExitRequiredRegs += CPU_REG_A;
@ -23457,15 +23780,18 @@ bool NativeCodeBasicBlock::PatchCrossBlock16BitFloodExit(const NativeCodeBasicBl
{ {
NativeCodeInstruction& ins(mIns[at]); NativeCodeInstruction& ins(mIns[at]);
if (ins.mAddress == dreg) if (ins.mMode == ASMIM_ZERO_PAGE || ins.mMode == ASMIM_ZERO_PAGE_X || ins.mMode == ASMIM_ZERO_PAGE_Y || ins.mMode == ASMIM_INDIRECT_X || ins.mMode == ASMIM_INDIRECT_Y)
{ {
ins.mAddress = sreg; if (ins.mAddress == dreg)
changed = true; {
} ins.mAddress = sreg;
else if (ins.mAddress == dreg + 1) changed = true;
{ }
ins.mAddress = sreg + 1; else if (ins.mAddress == dreg + 1)
changed = true; {
ins.mAddress = sreg + 1;
changed = true;
}
} }
at--; at--;
@ -26862,6 +27188,54 @@ bool NativeCodeBasicBlock::MoveZeroPageCrossBlockUp(int at, const NativeCodeInst
} }
bool NativeCodeBasicBlock::ShortcutCrossBlockCondition(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
int sz = mIns.Size();
if (sz > 0 && mIns[sz - 1].mType == ASMIT_LDA && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && !mFalseJump)
{
if (mTrueJump->mIns.Size() == 2 && mTrueJump->mIns[0].mType == ASMIT_STA &&
mTrueJump->mIns[1].mType == ASMIT_ORA && mTrueJump->mIns[1].mMode == ASMIM_IMMEDIATE && mTrueJump->mIns[1].mAddress == 0 &&
(mTrueJump->mBranch == ASMIT_BEQ || mTrueJump->mBranch == ASMIT_BNE))
{
mIns.Push(mTrueJump->mIns[0]);
mTrueJump->mNumEntries--;
mTrueJump->mEntryBlocks.Remove(mTrueJump->mEntryBlocks.IndexOf(this));
if (mTrueJump->mBranch == ASMIT_BEQ)
{
if (mIns[sz - 1].mAddress == 0)
mTrueJump = mTrueJump->mTrueJump;
else
mTrueJump = mTrueJump->mFalseJump;
}
else
{
if (mIns[sz - 1].mAddress != 0)
mTrueJump = mTrueJump->mTrueJump;
else
mTrueJump = mTrueJump->mFalseJump;
}
mTrueJump->mNumEntries++;
mTrueJump->mEntryBlocks.Push(this);
changed = true;
}
}
if (mTrueJump && mTrueJump->ShortcutCrossBlockCondition())
changed = true;
if (mFalseJump && mFalseJump->ShortcutCrossBlockCondition())
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::ShortcutCrossBlockMoves(NativeCodeProcedure* proc) bool NativeCodeBasicBlock::ShortcutCrossBlockMoves(NativeCodeProcedure* proc)
{ {
bool changed = false; bool changed = false;
@ -40445,6 +40819,20 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 1].mType == ASMIT_STA &&
mIns[i + 2].mType == ASMIT_CLC &&
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 255 &&
mIns[i + 4].mType == ASMIT_STA && mIns[i + 4].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 4].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)) &&
HasAsmInstructionMode(ASMIT_DEC, mIns[i + 0].mMode))
{
mIns[i + 4].mType = ASMIT_DEC;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
progress = true; progress = true;
} }
#endif #endif
@ -42803,7 +43191,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
{ {
mInterProc = proc; mInterProc = proc;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "interpret_expression"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "dungeon_init");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];
@ -43711,6 +44099,14 @@ void NativeCodeProcedure::Optimize(void)
changed = true; changed = true;
} }
#endif #endif
if (step > 6 && !changed)
{
ResetVisited();
if (mEntryBlock->ShortcutCrossBlockCondition())
changed = true;
}
#if _DEBUG #if _DEBUG
ResetVisited(); ResetVisited();
mEntryBlock->CheckBlocks(true); mEntryBlock->CheckBlocks(true);
@ -43731,6 +44127,16 @@ void NativeCodeProcedure::Optimize(void)
changed = true; changed = true;
} }
if (step > 2 && !changed)
{
ResetVisited();
if (mEntryBlock->JoinCommonBranchCodeSequences())
{
changed = true;
BuildDataFlowSets();
}
}
if (step > 4) if (step > 4)
{ {
ResetVisited(); ResetVisited();

View File

@ -459,6 +459,7 @@ public:
bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins); bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins);
bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc); bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc);
bool ShortcutCrossBlockCondition(void);
bool CanReplaceYRegWithXReg(int start, int end); bool CanReplaceYRegWithXReg(int start, int end);
bool CanReplaceXRegWithYReg(int start, int end); bool CanReplaceXRegWithYReg(int start, int end);
@ -518,6 +519,11 @@ public:
bool HasTailSTY(int& addr, int& index) const; bool HasTailSTY(int& addr, int& index) const;
bool HasTailSTAX16(int& addr, int& index0) const; bool HasTailSTAX16(int& addr, int& index0) const;
bool MayBeMovedBeforeBlock(int at);
bool MayBeMovedBeforeBlock(int start, int end);
bool SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end);
bool JoinCommonBranchCodeSequences(void);
bool CanJoinEntryLoadStoreZP(int saddr, int daddr); bool CanJoinEntryLoadStoreZP(int saddr, int daddr);
bool DoJoinEntryLoadStoreZP(int saddr, int daddr); bool DoJoinEntryLoadStoreZP(int saddr, int daddr);
bool JoinEntryLoadStoreZP(void); bool JoinEntryLoadStoreZP(void);
@ -621,8 +627,8 @@ public:
bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex); bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex);
bool PropagateCommonSubExpression(void); bool PropagateCommonSubExpression(void);
bool ForwardAbsoluteLoadStores(void);
bool CanForwardZPMove(int saddr, int daddr, int & index) const; bool CanForwardZPMove(int saddr, int daddr, int & index) const;
bool CanForwardLoadStore(const NativeCodeInstruction & lins, const NativeCodeInstruction & sins, int& index) const;
bool Is16BitAddSubImmediate(int at, int& sreg, int &dreg, int& offset) const; bool Is16BitAddSubImmediate(int at, int& sreg, int &dreg, int& offset) const;
bool CanForward16BitAddSubImmediate(int sreg, int dreg, int offset, int & index) const; bool CanForward16BitAddSubImmediate(int sreg, int dreg, int offset, int & index) const;