Move conditions out of loops

This commit is contained in:
drmortalwombat 2023-11-28 17:40:44 +01:00
parent 8fd560a643
commit cf28c1a618
5 changed files with 649 additions and 6 deletions

View File

@ -628,6 +628,178 @@ unsigned long lmul16f16(unsigned long x, unsigned long y)
return ll; return ll;
} }
#if 1
long lmul16f16s(long x, long y)
{
__asm
{
lda #0
// fractional
sta __tmp + 0
sta __tmp + 1
// result
sta __accu + 0
sta __accu + 1
sta __accu + 2
sta __accu + 3
lda x + 0
ora x + 1
ora y + 0
ora y + 1
bne w0b
l2:
lsr x + 2
bcc ws1
clc
lda y + 2
adc __accu + 2
sta __accu + 2
lda y + 3
adc __accu + 3
sta __accu + 3
ws1:
lsr x + 3
bcc ws2
clc
lda y + 2
adc __accu + 3
sta __accu + 3
ws2:
asl y + 2
rol y + 3
lda x + 2
ora x + 3
bne l2
rts
w0b:
lda y + 3
and #$80
beq w0
lda #$ff
w0:
// overflow
sta __tmp + 2
sta __tmp + 3
lda x + 3
bpl w0a
sec
lda #0
sbc y + 0
sta __accu + 2
lda #0
sbc y + 1
sta __accu + 3
w0a:
ldx #8
l1:
lsr x + 0
bcc w1
clc
lda y + 0
adc __tmp + 0
sta __tmp + 0
lda y + 1
adc __tmp + 1
sta __tmp + 1
lda y + 2
adc __accu + 0
sta __accu + 0
lda y + 3
adc __accu + 1
sta __accu + 1
lda __tmp + 2
adc __accu + 2
sta __accu + 2
lda __tmp + 3
adc __accu + 3
sta __accu + 3
w1:
lsr x + 1
bcc w2
clc
lda y + 0
adc __tmp + 1
sta __tmp + 1
lda y + 1
adc __accu + 0
sta __accu + 0
lda y + 2
adc __accu + 1
sta __accu + 1
lda y + 3
adc __accu + 2
sta __accu + 2
lda __tmp + 2
adc __accu + 3
sta __accu + 3
w2:
lsr x + 2
bcc w3
clc
lda y + 0
adc __accu + 0
sta __accu + 0
lda y + 1
adc __accu + 1
sta __accu + 1
lda y + 2
adc __accu + 2
sta __accu + 2
lda y + 3
adc __accu + 3
sta __accu + 3
w3:
lsr x + 3
bcc w4
clc
lda y + 0
adc __accu + 1
sta __accu + 1
lda y + 1
adc __accu + 2
sta __accu + 2
lda y + 2
adc __accu + 3
sta __accu + 3
w4:
asl y + 0
rol y + 1
rol y + 2
rol y + 3
rol __tmp + 2
rol __tmp + 3
dex
beq w5
jmp l1
w5:
}
}
#else
__native long lmul16f16s(long x, long y) __native long lmul16f16s(long x, long y)
{ {
unsigned lox = x; unsigned lox = x;
@ -656,6 +828,7 @@ __native long lmul16f16s(long x, long y)
return r; return r;
} }
#endif
__native unsigned long ldiv16f16(unsigned long x, unsigned long y) __native unsigned long ldiv16f16(unsigned long x, unsigned long y)
{ {

View File

@ -4847,6 +4847,14 @@ InterCodeBasicBlock::~InterCodeBasicBlock(void)
{ {
} }
InterCodeBasicBlock* InterCodeBasicBlock::Clone(void)
{
InterCodeBasicBlock* nblock = new InterCodeBasicBlock(mProc);
for (int i = 0; i < mInstructions.Size(); i++)
nblock->mInstructions.Push(mInstructions[i]->Clone());
return nblock;
}
void InterCodeBasicBlock::Append(InterInstruction * code) void InterCodeBasicBlock::Append(InterInstruction * code)
{ {
@ -14007,6 +14015,143 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt
} }
} }
static bool IsTempModifiedInBlocks(const ExpandingArray<InterCodeBasicBlock*>& body, int temp)
{
for (int j = 0; j < body.Size(); j++)
if (body[j]->IsTempModified(temp))
return true;
return false;
}
static bool IsInsSrcModifiedInBlocks(const ExpandingArray<InterCodeBasicBlock*>& body, const InterInstruction * ins)
{
for (int i = 0; i < ins->mNumOperands; i++)
{
if (ins->mSrc[i].mTemp >= 0 && IsTempModifiedInBlocks(body, ins->mSrc[i].mTemp))
return true;
}
return false;
}
bool InterCodeBasicBlock::MoveConditionOutOfLoop(void)
{
if (!mVisited)
{
mVisited = true;
if (mLoopHead)
{
ExpandingArray<InterCodeBasicBlock*> body, path;
body.Push(this);
bool innerLoop = true;
for (int i = 0; i < mEntryBlocks.Size(); i++)
{
if (mEntryBlocks[i] != mLoopPrefix)
{
if (!mEntryBlocks[i]->CollectLoopBody(this, body))
innerLoop = false;
}
}
if (innerLoop)
{
// Find all conditions based on invariants
for (int i = 0; i < body.Size(); i++)
{
InterCodeBasicBlock* block = body[i];
int nins = block->mInstructions.Size();
if (block->mFalseJump && block->mInstructions[nins-1]->mCode == IC_BRANCH && body.Contains(block->mFalseJump) && body.Contains(block->mTrueJump))
{
int ncins = 0;
if (!IsInsSrcModifiedInBlocks(body, block->mInstructions[nins - 1]))
ncins = 1;
else if (nins > 1 && block->mInstructions[nins - 2]->mCode == IC_RELATIONAL_OPERATOR &&
block->mInstructions[nins - 1]->mSrc[0].mTemp == block->mInstructions[nins - 2]->mDst.mTemp && block->mInstructions[nins - 1]->mSrc[0].mFinal &&
!IsInsSrcModifiedInBlocks(body, block->mInstructions[nins - 2]))
ncins = 2;
if (ncins > 0)
{
// The condition is not modified on the path
// Now check the number of instructions in the conditional section
int ninside = 0, noutside = 0;
for (int i = 0; i < body.Size(); i++)
{
bool tdom = block->mTrueJump->IsDirectDominatorBlock(body[i]);
bool fdom = block->mFalseJump->IsDirectDominatorBlock(body[i]);
if (tdom != fdom)
ninside += body[i]->mInstructions.Size();
else
noutside += body[i]->mInstructions.Size();
}
// Less than four instructions outside of condition, or twice as many
// inside as outside is the trigger
if (noutside - ncins < 4 || ninside > 2 * (noutside - ncins))
{
// Now clone the loop into a true and a false branch
GrowingArray<InterCodeBasicBlock*> copies(nullptr);
for (int i = 0; i < body.Size(); i++)
{
InterCodeBasicBlock* nblock = body[i]->Clone();
copies[body[i]->mIndex] = nblock;
}
for (int i = 0; i < body.Size(); i++)
{
InterCodeBasicBlock* rblock = body[i];
InterCodeBasicBlock* nblock = copies[rblock->mIndex];
if (rblock->mTrueJump)
{
InterCodeBasicBlock* tblock = copies[rblock->mTrueJump->mIndex];
if (tblock)
nblock->mTrueJump = tblock;
else
nblock->mTrueJump = rblock->mTrueJump;
}
if (rblock->mFalseJump)
{
InterCodeBasicBlock* tblock = copies[rblock->mFalseJump->mIndex];
if (tblock)
nblock->mFalseJump = tblock;
else
nblock->mFalseJump = rblock->mFalseJump;
}
}
mLoopPrefix->mInstructions.Pop();
for (int i = 0; i < ncins; i++)
mLoopPrefix->mInstructions.Push(block->mInstructions[nins - ncins + i]->Clone());
block->mInstructions[nins - 1]->mSrc[0].mTemp = -1;
block->mInstructions[nins - 1]->mSrc[0].mIntConst = 1;
mLoopPrefix->mFalseJump = copies[mLoopPrefix->mTrueJump->mIndex];
InterCodeBasicBlock* nblock = copies[block->mIndex];
nblock->mInstructions[nins - 1]->mSrc[0].mTemp = -1;
nblock->mInstructions[nins - 1]->mSrc[0].mIntConst = 0;
return true;
}
}
}
}
}
}
if (mTrueJump && mTrueJump->MoveConditionOutOfLoop())
return true;
if (mFalseJump && mFalseJump->MoveConditionOutOfLoop())
return true;
}
return false;
}
void InterCodeBasicBlock::PushMoveOutOfLoop(void) void InterCodeBasicBlock::PushMoveOutOfLoop(void)
{ {
@ -17977,6 +18122,38 @@ void InterCodeProcedure::CheckUsedDefinedTemps(void)
#endif #endif
} }
void InterCodeProcedure::MoveConditionsOutOfLoop(void)
{
BuildTraces(false);
BuildLoopPrefix();
ResetEntryBlocks();
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
Disassemble("PreMoveConditionOutOfLoop");
ResetVisited();
while (mEntryBlock->MoveConditionOutOfLoop())
{
Disassemble("MoveConditionOutOfLoop");
BuildDataFlowSets();
TempForwarding();
RemoveUnusedInstructions();
BuildTraces(false);
BuildLoopPrefix();
ResetEntryBlocks();
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
Disassemble("PostMoveConditionOutOfLoop");
ResetVisited();
}
}
void InterCodeProcedure::PropagateMemoryAliasingInfo(void) void InterCodeProcedure::PropagateMemoryAliasingInfo(void)
{ {
GrowingInstructionPtrArray tvalue(nullptr); GrowingInstructionPtrArray tvalue(nullptr);
@ -18607,7 +18784,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "parse_expression"); CheckFunc = !strcmp(mIdent->mString, "main");
CheckCase = false; CheckCase = false;
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];
@ -19258,6 +19435,11 @@ void InterCodeProcedure::Close(void)
RemoveUnusedLocalStoreInstructions(); RemoveUnusedLocalStoreInstructions();
if (mCompilerOptions & COPT_OPTIMIZE_BASIC)
{
MoveConditionsOutOfLoop();
}
#if 1 #if 1
ResetVisited(); ResetVisited();

View File

@ -398,6 +398,8 @@ public:
InterCodeBasicBlock(InterCodeProcedure * proc); InterCodeBasicBlock(InterCodeProcedure * proc);
~InterCodeBasicBlock(void); ~InterCodeBasicBlock(void);
InterCodeBasicBlock* Clone(void);
void Append(InterInstruction * code); void Append(InterInstruction * code);
const InterInstruction* FindByDst(int dst) const; const InterInstruction* FindByDst(int dst) const;
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump); void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
@ -576,6 +578,7 @@ public:
void CollectLoopPath(const ExpandingArray<InterCodeBasicBlock*>& body, ExpandingArray<InterCodeBasicBlock*>& path); void CollectLoopPath(const ExpandingArray<InterCodeBasicBlock*>& body, ExpandingArray<InterCodeBasicBlock*>& path);
void InnerLoopOptimization(const NumberSet& aliasedParams); void InnerLoopOptimization(const NumberSet& aliasedParams);
void PushMoveOutOfLoop(void); void PushMoveOutOfLoop(void);
bool MoveConditionOutOfLoop(void);
void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue); void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue);
void RemoveUnusedMallocs(void); void RemoveUnusedMallocs(void);
@ -716,6 +719,7 @@ protected:
void CheckUsedDefinedTemps(void); void CheckUsedDefinedTemps(void);
void WarnUsedUndefinedVariables(void); void WarnUsedUndefinedVariables(void);
void PropagateMemoryAliasingInfo(void); void PropagateMemoryAliasingInfo(void);
void MoveConditionsOutOfLoop(void);
void PeepholeOptimization(void); void PeepholeOptimization(void);

View File

@ -164,6 +164,25 @@ void NativeRegisterDataSet::ResetAbsolute(LinkerObject* linkerObject, int addr)
} }
} }
void NativeRegisterDataSet::ResetAbsoluteXY(LinkerObject* linkerObject, int addr)
{
for (int i = 0; i < NUM_REGS; i++)
{
if (mRegs[i].mMode == NRDM_ABSOLUTE)
{
if (mRegs[i].mLinkerObject == linkerObject && mRegs[i].mValue < addr + 256 && mRegs[i].mValue >= addr)
mRegs[i].Reset();
}
else if (mRegs[i].mMode == NRDM_ABSOLUTE_X || mRegs[i].mMode == NRDM_ABSOLUTE_Y)
{
if (mRegs[i].mLinkerObject == linkerObject && mRegs[i].mValue < addr + 256 && mRegs[i].mValue + 256 > addr)
mRegs[i].Reset();
}
else if (mRegs[i].mMode == NRDM_INDIRECT_Y)
mRegs[i].Reset();
}
}
void NativeRegisterDataSet::ResetX(void) void NativeRegisterDataSet::ResetX(void)
{ {
for (int i = 0; i < NUM_REGS; i++) for (int i = 0; i < NUM_REGS; i++)
@ -4047,7 +4066,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
} }
if (ChangesAddress()) if (ChangesAddress())
data.ResetIndirect(mAddress); data.ResetAbsoluteXY(mLinkerObject, mAddress);
} }
else if (mMode == ASMIM_ABSOLUTE_Y) else if (mMode == ASMIM_ABSOLUTE_Y)
{ {
@ -4111,7 +4130,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
} }
if (ChangesAddress()) if (ChangesAddress())
data.ResetIndirect(mAddress); data.ResetAbsoluteXY(mLinkerObject, mAddress);
} }
else if (mMode == ASMIM_ABSOLUTE) else if (mMode == ASMIM_ABSOLUTE)
{ {
@ -15404,6 +15423,57 @@ bool NativeCodeBasicBlock::PropagateCommonSubExpression(void)
return changed; return changed;
} }
bool NativeCodeBasicBlock::LocalSwapXY(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
int pre = -1;
if (mEntryRequiredRegs[CPU_REG_X] || mEntryRequiredRegs[CPU_REG_Y])
pre = -2;
for (int i = 0; i < mIns.Size(); i++)
{
uint32 live = mIns[i].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Y);
if (live)
{
if (pre == -1)
pre = i;
}
else if (!live)
{
if (pre >= 0)
{
int k = pre;
while (k <= i && mIns[k].CanSwapXYReg())
k++;
if (k > i)
{
for (int k = pre; k <= i; k++)
{
if (mIns[k].SwapXYReg())
changed = true;
}
}
}
pre = -1;
}
}
if (mTrueJump && mTrueJump->LocalSwapXY())
changed = true;
if (mFalseJump && mFalseJump->LocalSwapXY())
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::GlobalSwapXY(void) bool NativeCodeBasicBlock::GlobalSwapXY(void)
{ {
bool changed = false; bool changed = false;
@ -15498,6 +15568,66 @@ bool NativeCodeBasicBlock::GlobalSwapXY(void)
return changed; return changed;
} }
bool NativeCodeBasicBlock::UntangleXYUsage(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
int xins = -1, yins = -1;
for (int i = 0; i + 1 < mIns.Size(); i++)
{
NativeCodeInstruction& ins(mIns[i]);
NativeCodeInstruction& nins(mIns[i + 1]);
if (ins.mType == ASMIT_LDX)
{
if (yins >= 0 && mIns[yins].SameEffectiveAddress(ins) && nins.mMode == ASMIM_ABSOLUTE_X && HasAsmInstructionMode(nins.mType, ASMIM_ABSOLUTE_Y))
{
mIns.Insert(i, NativeCodeInstruction(nins.mIns, nins.mType, ASMIM_ABSOLUTE_Y, nins.mAddress, nins.mLinkerObject, nins.mFlags));
mIns[i + 1].mLive |= mIns[i].mLive;
mIns.Remove(i + 2);
for (int j = yins; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
changed = true;
}
else
xins = i;
}
else if (ins.mType == ASMIT_LDY)
{
if (xins >= 0 && mIns[xins].SameEffectiveAddress(ins) && nins.mMode == ASMIM_ABSOLUTE_Y && HasAsmInstructionMode(nins.mType, ASMIM_ABSOLUTE_X))
{
mIns.Insert(i, NativeCodeInstruction(nins.mIns, nins.mType, ASMIM_ABSOLUTE_X, nins.mAddress, nins.mLinkerObject, nins.mFlags));
mIns[i + 1].mLive |= mIns[i].mLive;
mIns.Remove(i + 2);
for (int j = xins; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_X;
changed = true;
}
else
yins = i;
}
else
{
if (xins >= 0 && (mIns[xins].MayBeChangedOnAddress(ins) || ins.ChangesXReg()))
xins = -1;
if (yins >= 0 && (mIns[yins].MayBeChangedOnAddress(ins) || ins.ChangesYReg()))
yins = -1;
}
}
if (mTrueJump && mTrueJump->UntangleXYUsage())
changed = true;
if (mFalseJump && mFalseJump->UntangleXYUsage())
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::OptimizeXYPairUsage(void) bool NativeCodeBasicBlock::OptimizeXYPairUsage(void)
{ {
bool changed = false; bool changed = false;
@ -16514,6 +16644,7 @@ bool NativeCodeBasicBlock::EliminateDeadLoops(void)
mTrueJump = eblock; mTrueJump = eblock;
mBranch = ASMIT_JMP; mBranch = ASMIT_JMP;
mEntryBlocks.RemoveAll(this); mEntryBlocks.RemoveAll(this);
mFalseJump = nullptr;
mNumEntries--; mNumEntries--;
changed = true; changed = true;
} }
@ -16526,6 +16657,7 @@ bool NativeCodeBasicBlock::EliminateDeadLoops(void)
mTrueJump = eblock; mTrueJump = eblock;
mBranch = ASMIT_JMP; mBranch = ASMIT_JMP;
mEntryBlocks.RemoveAll(this); mEntryBlocks.RemoveAll(this);
mFalseJump = nullptr;
mNumEntries--; mNumEntries--;
changed = true; changed = true;
} }
@ -26649,6 +26781,68 @@ bool NativeCodeBasicBlock::MoveIndirectLoadStoreDown(int at)
return false; return false;
} }
bool NativeCodeBasicBlock::MoveLDXUp(int at)
{
NativeCodeInstruction& lins(mIns[at]);
int i = at;
while (i > 0)
{
i--;
NativeCodeInstruction& ins(mIns[i]);
if (ins.mType == ASMIT_STA && ins.SameEffectiveAddress(lins))
{
if (ins.mLive & LIVE_CPU_REG_Z)
return false;
mIns.Insert(i + 1, NativeCodeInstruction(lins.mIns, ASMIT_TAX));
mIns.Remove(at + 1);
while (i < at)
{
mIns[i].mLive |= LIVE_CPU_REG_X;
i++;
}
return true;
}
if (ins.ReferencesXReg() || lins.MayBeChangedOnAddress(ins))
return false;
}
return false;
}
bool NativeCodeBasicBlock::MoveLDYUp(int at)
{
NativeCodeInstruction& lins(mIns[at]);
int i = at;
while (i > 0)
{
i--;
NativeCodeInstruction& ins(mIns[i]);
if (ins.mType == ASMIT_STA && ins.SameEffectiveAddress(lins))
{
if (ins.mLive & LIVE_CPU_REG_Z)
return false;
mIns.Insert(i + 1, NativeCodeInstruction(lins.mIns, ASMIT_TAY));
mIns.Remove(at + 1);
while (i < at)
{
mIns[i].mLive |= LIVE_CPU_REG_Y;
i++;
}
return true;
}
if (ins.ReferencesYReg() || lins.MayBeChangedOnAddress(ins))
return false;
}
return false;
}
bool NativeCodeBasicBlock::MoveIndirectLoadStoreDownY(int at) bool NativeCodeBasicBlock::MoveIndirectLoadStoreDownY(int at)
{ {
int j = at + 3; int j = at + 3;
@ -35270,6 +35464,17 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen
j += 2; j += 2;
i += 4; i += 4;
} }
else if (i + 4 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_SEC &&
mIns[i + 1].mType == ASMIT_LDA &&
mIns[i + 2].mType == ASMIT_SBC &&
mIns[i + 3].mType == ASMIT_SEC &&
mIns[i + 4].mType == ASMIT_SBC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0x01)
{
mIns[j + 0] = NativeCodeInstruction(mIns[i + 0].mIns, ASMIT_CLC);
j += 3;
i += 5;
}
#endif #endif
else if (i + 1 < mIns.Size() && else if (i + 1 < mIns.Size() &&
mIns[i + 0].ChangesZFlag() && mIns[i + 1].mType == ASMIT_LDA && mIns[i + 0].SameEffectiveAddress(mIns[i + 1]) && !(mIns[i + 1].mLive & LIVE_CPU_REG_A)) mIns[i + 0].ChangesZFlag() && mIns[i + 1].mType == ASMIT_LDA && mIns[i + 0].SameEffectiveAddress(mIns[i + 1]) && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
@ -35929,6 +36134,27 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
#endif #endif
// Move LDX/LDY up to STA of same address
#if 1
if (pass >= 9)
{
for (int i = 2; i < mIns.Size(); i++)
{
if (mIns[i].mType == ASMIT_LDX && (mIns[i].mMode == ASMIM_ZERO_PAGE || mIns[i].mMode == ASMIM_ABSOLUTE) && !(mIns[i].mLive & LIVE_CPU_REG_Z))
{
if (MoveLDXUp(i))
changed = true;
}
else if (mIns[i].mType == ASMIT_LDY && (mIns[i].mMode == ASMIM_ZERO_PAGE || mIns[i].mMode == ASMIM_ABSOLUTE) && !(mIns[i].mLive & LIVE_CPU_REG_Z))
{
if (MoveLDYUp(i))
changed = true;
}
}
CheckLive();
}
#endif
#if 1 #if 1
// move ORA #imm up a shift chain to an LDA #imm // move ORA #imm up a shift chain to an LDA #imm
@ -37813,6 +38039,43 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mMode = ASMIM_IMPLIED;
progress = true; progress = true;
} }
else if (mIns[i + 0].ChangesAccuAndFlag() && mIns[i + 1].mType == ASMIT_TAX && !(mIns[i + 1].mLive & LIVE_CPU_REG_X))
{
mIns[i + 0].mLive |= (mIns[i + 1].mLive & LIVE_CPU_REG_Z);
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (mIns[i + 0].ChangesAccuAndFlag() && mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_Y))
{
mIns[i + 0].mLive |= (mIns[i + 1].mLive & LIVE_CPU_REG_Z);
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (mIns[i + 0].mType == ASMIT_LDX && mIns[i + 1].mType == ASMIT_CPX && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X)))
{
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mType = ASMIT_CMP;
progress = true;
}
else if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 1].mType == ASMIT_CPY && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y)))
{
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mType = ASMIT_CMP;
progress = true;
}
else if (mIns[i + 0].mType == ASMIT_LDX && mIns[i + 1].mType == ASMIT_STX && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X)))
{
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mType = ASMIT_STA;
progress = true;
}
else if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 1].mType == ASMIT_STY && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y)))
{
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mType = ASMIT_STA;
progress = true;
}
#endif #endif
else if ( else if (
mIns[i + 0].mType == ASMIT_INC && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mType == ASMIT_INC && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
@ -43264,7 +43527,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
{ {
mInterProc = proc; mInterProc = proc;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "board_draw_item"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "interpret_expression");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];
@ -44448,9 +44711,11 @@ void NativeCodeProcedure::Optimize(void)
ResetVisited(); ResetVisited();
if (mEntryBlock->OptimizeXYPairUsage()) if (mEntryBlock->OptimizeXYPairUsage())
changed = true; changed = true;
ResetVisited();
if (mEntryBlock->UntangleXYUsage())
changed = true;
} }
#endif #endif
#if _DEBUG #if _DEBUG
ResetVisited(); ResetVisited();
mEntryBlock->CheckBlocks(); mEntryBlock->CheckBlocks();
@ -44653,6 +44918,18 @@ void NativeCodeProcedure::Optimize(void)
} }
} }
} }
if (step == 11)
{
if (changed)
swappedXY = false;
else if (!swappedXY)
{
ResetVisited();
changed = mEntryBlock->LocalSwapXY();
swappedXY = true;
}
}
#endif #endif
#if _DEBUG #if _DEBUG
ResetVisited(); ResetVisited();
@ -44673,7 +44950,7 @@ void NativeCodeProcedure::Optimize(void)
} }
#if 1 #if 1
if (!changed && step < 11) if (!changed && step < 12)
{ {
cnt = 0; cnt = 0;
step++; step++;

View File

@ -47,6 +47,7 @@ struct NativeRegisterDataSet
void ResetZeroPage(int addr); void ResetZeroPage(int addr);
void ResetZeroPageRange(int addr, int num); void ResetZeroPageRange(int addr, int num);
void ResetAbsolute(LinkerObject * linkerObject, int addr); void ResetAbsolute(LinkerObject * linkerObject, int addr);
void ResetAbsoluteXY(LinkerObject* linkerObject, int addr);
int FindAbsolute(LinkerObject* linkerObject, int addr); int FindAbsolute(LinkerObject* linkerObject, int addr);
void ResetIndirect(int reg); void ResetIndirect(int reg);
void ResetX(void); void ResetX(void);
@ -407,6 +408,10 @@ public:
bool MoveIndirectLoadStoreDown(int at); bool MoveIndirectLoadStoreDown(int at);
bool MoveIndirectLoadStoreDownY(int at); bool MoveIndirectLoadStoreDownY(int at);
bool MoveLDXUp(int at);
bool MoveLDYUp(int at);
bool MoveIndirectLoadStoreUp(int at); bool MoveIndirectLoadStoreUp(int at);
bool MoveAbsoluteLoadStoreUp(int at); bool MoveAbsoluteLoadStoreUp(int at);
bool MoveLoadStoreOutOfXYRangeUp(int at); bool MoveLoadStoreOutOfXYRangeUp(int at);
@ -624,6 +629,8 @@ public:
bool OptimizeXYPairUsage(void); bool OptimizeXYPairUsage(void);
bool CanGlobalSwapXY(void); bool CanGlobalSwapXY(void);
bool GlobalSwapXY(void); bool GlobalSwapXY(void);
bool LocalSwapXY(void);
bool UntangleXYUsage(void);
bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex); bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex);
bool PropagateCommonSubExpression(void); bool PropagateCommonSubExpression(void);