Pointer and float loop optimizations

This commit is contained in:
drmortalwombat 2022-03-12 12:52:43 +01:00
parent 3cb4bd0fba
commit 736298238e
4 changed files with 271 additions and 14 deletions

View File

@ -2800,7 +2800,7 @@ void InterInstruction::Disassemble(FILE* file)
{ {
if (this->mCode != IC_NONE) if (this->mCode != IC_NONE)
{ {
static char memchars[] = "NPLGFPITAZ"; static char memchars[] = "NPLGFPITAZZ";
fprintf(file, "\t"); fprintf(file, "\t");
switch (this->mCode) switch (this->mCode)
@ -3784,6 +3784,92 @@ void InterCodeBasicBlock::MarkAliasedLocalTemps(const GrowingIntArray& localTabl
} }
} }
bool InterCodeBasicBlock::PropagateNonLocalUsedConstTemps(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
int i = 0;
while (i < mInstructions.Size())
{
InterInstruction* ins(mInstructions[i]);
if (ins->mCode == IC_CONSTANT && ins->mSingleAssignment)
{
int ttemp = ins->mDst.mTemp;
InterCodeBasicBlock* target = this;
while (target && !target->mLocalUsedTemps[ttemp])
{
InterCodeBasicBlock* ttarget = nullptr;
if (!target->mFalseJump)
ttarget = target->mTrueJump;
else if (!target->mFalseJump->mFalseJump && target->mFalseJump->mTrueJump == target->mTrueJump && !target->mFalseJump->mLocalUsedTemps[ttemp])
ttarget = target->mTrueJump;
else if (!target->mTrueJump->mFalseJump && target->mTrueJump->mTrueJump == target->mFalseJump && !target->mTrueJump->mLocalUsedTemps[ttemp])
ttarget = target->mFalseJump;
while (ttarget && ttarget->mLoopHead)
{
if (ttarget->mFalseJump == ttarget && !ttarget->mLocalUsedTemps[ttemp])
ttarget = ttarget->mTrueJump;
else if (ttarget->mTrueJump == ttarget && !ttarget->mLocalUsedTemps[ttemp])
ttarget = ttarget->mFalseJump;
else
ttarget = nullptr;
}
target = ttarget;
}
if (target && this != target)
{
target->mInstructions.Insert(0, ins);
mInstructions.Remove(i);
changed = true;
}
else
i++;
}
else
i++;
}
if (mTrueJump && mTrueJump->PropagateNonLocalUsedConstTemps())
changed = true;
if (mFalseJump && mFalseJump->PropagateNonLocalUsedConstTemps())
changed = true;
}
return changed;
}
void InterCodeBasicBlock::CollectLocalUsedTemps(int numTemps)
{
if (!mVisited)
{
mVisited = true;
mLocalUsedTemps.Reset(numTemps);
for (int i = 0; i < mInstructions.Size(); i++)
{
InterInstruction* ins(mInstructions[i]);
for (int j = 0; j < ins->mNumOperands; j++)
{
if (ins->mSrc[j].mTemp >= 0)
mLocalUsedTemps += ins->mSrc[j].mTemp;
}
}
if (mTrueJump) mTrueJump->CollectLocalUsedTemps(numTemps);
if (mFalseJump) mFalseJump->CollectLocalUsedTemps(numTemps);
}
}
void InterCodeBasicBlock::CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps) void InterCodeBasicBlock::CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps)
{ {
int i; int i;
@ -8018,6 +8104,39 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
i--; i--;
} }
#endif #endif
#if 1
// move indirect load/store pairs up
i = 0;
while (i + 1 < mInstructions.Size())
{
if (mInstructions[i + 0]->mCode == IC_LOAD && mInstructions[i + 1]->mCode == IC_STORE && mInstructions[i + 1]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mFinal)
{
if (mInstructions[i + 0]->mSrc[0].mMemory == IM_INDIRECT)
{
InterInstruction* lins(mInstructions[i + 0]);
InterInstruction* sins(mInstructions[i + 1]);
int j = i;
while (j > 0 &&
CanBypassLoadUp(lins, mInstructions[j - 1]) &&
CanBypassStore(sins, mInstructions[j - 1]))
{
mInstructions[j + 1] = mInstructions[j - 1];
j--;
}
if (i != j)
{
mInstructions[j + 0] = lins;
mInstructions[j + 1] = sins;
}
}
}
i++;
}
#endif
#if 1 #if 1
i = 0; i = 0;
while (i < mInstructions.Size()) while (i < mInstructions.Size())
@ -9009,6 +9128,7 @@ void InterCodeProcedure::Close(void)
ResetVisited(); ResetVisited();
mEntryBlock->CompactInstructions(); mEntryBlock->CompactInstructions();
BuildDataFlowSets(); BuildDataFlowSets();
ResetVisited(); ResetVisited();
@ -9078,12 +9198,19 @@ void InterCodeProcedure::Close(void)
#endif #endif
BuildDataFlowSets(); BuildDataFlowSets();
TempForwarding(); TempForwarding();
RemoveUnusedInstructions(); RemoveUnusedInstructions();
DisassembleDebug("Moved single path instructions"); DisassembleDebug("Moved single path instructions");
PropagateNonLocalUsedTemps();
BuildDataFlowSets();
TempForwarding();
RemoveUnusedInstructions();
DisassembleDebug("propagate non local used temps");
#if 1 #if 1
do do
{ {
@ -9438,13 +9565,20 @@ void InterCodeProcedure::BuildLoopPrefix(void)
mEntryBlock->CollectEntries(); mEntryBlock->CollectEntries();
} }
bool InterCodeProcedure::PropagateNonLocalUsedTemps(void)
{
ResetVisited();
mEntryBlock->CollectLocalUsedTemps(mTemporaries.Size());
ResetVisited();
return mEntryBlock->PropagateNonLocalUsedConstTemps();
}
bool InterCodeProcedure::GlobalConstantPropagation(void) bool InterCodeProcedure::GlobalConstantPropagation(void)
{ {
NumberSet assignedTemps(mTemporaries.Size()); NumberSet assignedTemps(mTemporaries.Size());
GrowingInstructionPtrArray ctemps(nullptr); GrowingInstructionPtrArray ctemps(nullptr);
ResetVisited(); ResetVisited();
mEntryBlock->CollectConstTemps(ctemps, assignedTemps); mEntryBlock->CollectConstTemps(ctemps, assignedTemps);

View File

@ -326,6 +326,7 @@ public:
bool mVisited, mInPath, mLoopHead, mChecked, mConditionBlockTrue, mUnreachable, mLoopPath; bool mVisited, mInPath, mLoopHead, mChecked, mConditionBlockTrue, mUnreachable, mLoopPath;
NumberSet mLocalUsedTemps;
NumberSet mLocalRequiredTemps, mLocalProvidedTemps; NumberSet mLocalRequiredTemps, mLocalProvidedTemps;
NumberSet mEntryRequiredTemps, mEntryProvidedTemps; NumberSet mEntryRequiredTemps, mEntryProvidedTemps;
NumberSet mExitRequiredTemps, mExitProvidedTemps; NumberSet mExitRequiredTemps, mExitProvidedTemps;
@ -368,6 +369,8 @@ public:
void CollectLocalAddressTemps(GrowingIntArray& localTable, GrowingIntArray& paramTable); void CollectLocalAddressTemps(GrowingIntArray& localTable, GrowingIntArray& paramTable);
void MarkAliasedLocalTemps(const GrowingIntArray& localTable, NumberSet& aliasedLocals, const GrowingIntArray& paramTable, NumberSet& aliasedParams); void MarkAliasedLocalTemps(const GrowingIntArray& localTable, NumberSet& aliasedLocals, const GrowingIntArray& paramTable, NumberSet& aliasedParams);
void CollectLocalUsedTemps(int numTemps);
bool PropagateNonLocalUsedConstTemps(void);
void CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps); void CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps);
bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps); bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps);
@ -518,6 +521,7 @@ protected:
void TempForwarding(void); void TempForwarding(void);
void RemoveUnusedInstructions(void); void RemoveUnusedInstructions(void);
bool GlobalConstantPropagation(void); bool GlobalConstantPropagation(void);
bool PropagateNonLocalUsedTemps(void);
void BuildLoopPrefix(void); void BuildLoopPrefix(void);
void SingleAssignmentForwarding(void); void SingleAssignmentForwarding(void);

View File

@ -724,6 +724,11 @@ bool NativeCodeInstruction::ReferencesXReg(void) const
return ChangesXReg() || RequiresXReg(); return ChangesXReg() || RequiresXReg();
} }
bool NativeCodeInstruction::ReferencesZeroPage(int address) const
{
return UsesZeroPage(address);
}
bool NativeCodeInstruction::ChangesZeroPage(int address) const bool NativeCodeInstruction::ChangesZeroPage(int address) const
{ {
if (mMode == ASMIM_ZERO_PAGE && mAddress == address) if (mMode == ASMIM_ZERO_PAGE && mAddress == address)
@ -8393,7 +8398,7 @@ void NativeCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const In
} }
} }
void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0) void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0, bool addrvalid)
{ {
bool isub = false; bool isub = false;
int ireg = ins->mSrc[0].mTemp; int ireg = ins->mSrc[0].mTemp;
@ -8440,7 +8445,7 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const
// if the global variable is smaller than 256 bytes, we can safely ignore the upper byte? // if the global variable is smaller than 256 bytes, we can safely ignore the upper byte?
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_UPPER)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[1].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_UPPER));
#if 1 #if 1
if (ins->mSrc[1].mLinkerObject->mSize < 256 || ins->mSrc[0].IsUByte()) if (ins->mSrc[1].mLinkerObject->mSize < 256 || ins->mSrc[0].IsUByte() || (addrvalid && ins->mSrc[1].mLinkerObject->mSize <= 256))
mIns.Push(NativeCodeInstruction(iop, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(iop, ASMIM_IMMEDIATE, 0));
else else
#endif #endif
@ -12173,6 +12178,37 @@ bool NativeCodeBasicBlock::MoveLoadStoreXUp(int at)
return false; return false;
} }
bool NativeCodeBasicBlock::MoveLoadAddImmStoreAbsXUp(int at)
{
int j = at - 1, top = at;
while (j > 0)
{
if (mIns[j].ChangesXReg())
break;
if (mIns[j].MayBeSameAddress(mIns[at + 3]))
break;
if (mIns[j].MayBeSameAddress(mIns[at + 0]) && mIns[j].ChangesAddress())
break;
if (!(mIns[j - 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
top = j;
j--;
}
if (top < at)
{
mIns.Insert(top, mIns[at + 3]); mIns.Remove(at + 4);
mIns.Insert(top, mIns[at + 3]); mIns.Remove(at + 4);
mIns.Insert(top, mIns[at + 3]); mIns.Remove(at + 4);
mIns.Insert(top, mIns[at + 3]); mIns.Remove(at + 4);
return true;
}
else
return false;
}
bool NativeCodeBasicBlock::MoveLoadAddImmStoreUp(int at) bool NativeCodeBasicBlock::MoveLoadAddImmStoreUp(int at)
{ {
int j = at - 1; int j = at - 1;
@ -12807,6 +12843,38 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
} }
} }
if (sz >= 2 &&
mIns[0].mType == ASMIT_LDA && mIns[0].mMode == ASMIM_ZERO_PAGE && !(mIns[0].mLive & LIVE_MEM) &&
mIns[1].mType == ASMIT_STA && mIns[1].mMode == ASMIM_ZERO_PAGE && !(mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
int i = mIns.Size() - 1;
while (i > 1 && !mIns[i].ReferencesZeroPage(mIns[1].mAddress) && !mIns[i].ReferencesZeroPage(mIns[0].mAddress))
i--;
if (i > 1)
{
i--;
if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[1].mAddress &&
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == mIns[0].mAddress && !(mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
if (!prevBlock)
return OptimizeSimpleLoopInvariant(proc);
prevBlock->mIns.Push(mIns[0]);
prevBlock->mIns.Push(mIns[1]);
exitBlock->mIns.Insert(0, mIns[i + 0]);
exitBlock->mIns.Insert(1, mIns[i + 1]);
mIns.Remove(i); mIns.Remove(i);
mIns.Remove(0); mIns.Remove(0);
return true;
}
}
}
int ai = 0; int ai = 0;
while (ai < mIns.Size() && !mIns[ai].ChangesAccu()) while (ai < mIns.Size() && !mIns[ai].ChangesAccu())
@ -13513,11 +13581,12 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV); assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV);
} }
} }
#if 1
if (!changed)
changed = OptimizeSimpleLoopInvariant(proc, nullptr, nullptr);
#endif
} }
#if 1
if (!changed)
changed = OptimizeSimpleLoopInvariant(proc, nullptr, nullptr);
#endif
} }
if (mTrueJump && mTrueJump->OptimizeSimpleLoop(proc)) if (mTrueJump && mTrueJump->OptimizeSimpleLoop(proc))
@ -14658,6 +14727,24 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
#endif #endif
#if 1
// move load - add # - store with absolute,x up as far possible
//
for (int i = 2; i + 3 < mIns.Size(); i++)
{
if (
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ABSOLUTE_X &&
mIns[i + 1].mType == ASMIT_CLC &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ABSOLUTE_X && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_C)))
{
if (MoveLoadAddImmStoreAbsXUp(i))
changed = true;
}
}
#endif
#if 1 #if 1
// move load - add ZP - store up to initial store // move load - add ZP - store up to initial store
// //
@ -17377,7 +17464,23 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED; mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
progress = true; progress = true;
} }
#if 0
else if (
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ABSOLUTE_Y &&
mIns[i + 2].mType == ASMIT_LDY && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress != mIns[i + 0].mAddress &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ABSOLUTE_Y &&
mIns[i + 4].mType == ASMIT_LDY && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && mIns[i + 4].mAddress == mIns[i + 0].mAddress && !(mIns[i + 2].mLive & LIVE_CPU_REG_X))
{
mIns[i + 1].mLive |= LIVE_CPU_REG_Y;
mIns[i + 2].mType = ASMIT_LDX; mIns[i + 2].mLive |= LIVE_CPU_REG_X;
mIns[i + 3].mMode = ASMIM_ABSOLUTE_X; mIns[i + 3].mLive |= LIVE_CPU_REG_Y;
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
progress = true;
}
#endif
} }
#if 1 #if 1
if (pass > 2 && i + 4 < mIns.Size()) if (pass > 2 && i + 4 < mIns.Size())
{ {
@ -19190,7 +19293,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
iblock->mInstructions[i + 1]->mCode == IC_LEA && iblock->mInstructions[i + 1]->mCode == IC_LEA &&
iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[1].mFinal) iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[1].mFinal)
{ {
block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 1], ins, nullptr); block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 1], ins, nullptr, false);
i++; i++;
} }
else else
@ -19219,7 +19322,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
case IC_UNARY_OPERATOR: case IC_UNARY_OPERATOR:
if (i + 1 < iblock->mInstructions.Size() && ins->mOperator == IA_NEG && iblock->mInstructions[i + 1]->mCode == IC_LEA && iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[0].mFinal) if (i + 1 < iblock->mInstructions.Size() && ins->mOperator == IA_NEG && iblock->mInstructions[i + 1]->mCode == IC_LEA && iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp && iblock->mInstructions[i + 1]->mSrc[0].mFinal)
{ {
block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 1], nullptr, ins); block->LoadEffectiveAddress(iproc, iblock->mInstructions[i + 1], nullptr, ins, false);
i++; i++;
} }
else else
@ -19229,7 +19332,17 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
block->NumericConversion(iproc, this, ins); block->NumericConversion(iproc, this, ins);
break; break;
case IC_LEA: case IC_LEA:
block->LoadEffectiveAddress(iproc, ins, nullptr, nullptr); {
bool avalid = false;
if (i + 1 < iblock->mInstructions.Size())
{
if (iblock->mInstructions[i + 1]->mCode == IC_LOAD && iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp)
avalid = true;
else if (iblock->mInstructions[i + 1]->mCode == IC_STORE && iblock->mInstructions[i + 1]->mSrc[1].mTemp == ins->mDst.mTemp)
avalid = true;
}
block->LoadEffectiveAddress(iproc, ins, nullptr, nullptr, avalid);
}
break; break;
case IC_CONSTANT: case IC_CONSTANT:
block->LoadConstant(iproc, ins); block->LoadConstant(iproc, ins);

View File

@ -103,6 +103,8 @@ public:
bool ChangesZeroPage(int address) const; bool ChangesZeroPage(int address) const;
bool UsesZeroPage(int address) const; bool UsesZeroPage(int address) const;
bool ReferencesZeroPage(int address) const;
bool ChangesGlobalMemory(void) const; bool ChangesGlobalMemory(void) const;
bool SameEffectiveAddress(const NativeCodeInstruction& ins) const; bool SameEffectiveAddress(const NativeCodeInstruction& ins) const;
bool MayBeChangedOnAddress(const NativeCodeInstruction& ins) const; bool MayBeChangedOnAddress(const NativeCodeInstruction& ins) const;
@ -189,7 +191,7 @@ public:
NativeCodeBasicBlock* BinaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0); NativeCodeBasicBlock* BinaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0);
void UnaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); void UnaryOperator(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
void RelationalOperator(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure * nproc, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump); void RelationalOperator(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure * nproc, NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock * falseJump);
void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0); void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins, const InterInstruction* sins1, const InterInstruction* sins0, bool addrvalid);
void NumericConversion(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins); void NumericConversion(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
NativeCodeBasicBlock * CopyValue(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc); NativeCodeBasicBlock * CopyValue(InterCodeProcedure* proc, const InterInstruction * ins, NativeCodeProcedure* nproc);
NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc); NativeCodeBasicBlock * StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc);
@ -225,10 +227,14 @@ public:
bool MoveIndirectLoadStoreUp(int at); bool MoveIndirectLoadStoreUp(int at);
bool MoveAbsoluteLoadStoreUp(int at); bool MoveAbsoluteLoadStoreUp(int at);
bool MoveLoadStoreOutOfXYRangeUp(int at); bool MoveLoadStoreOutOfXYRangeUp(int at);
bool MoveLoadAddImmStoreAbsXUp(int at);
bool MoveLoadAddImmStoreUp(int at); bool MoveLoadAddImmStoreUp(int at);
bool MoveCLCLoadAddZPStoreUp(int at); bool MoveCLCLoadAddZPStoreUp(int at);
bool MoveLoadAddZPStoreUp(int at); bool MoveLoadAddZPStoreUp(int at);
bool MoveLoadShiftRotateUp(int at); bool MoveLoadShiftRotateUp(int at);
bool MoveCLCLoadAddZPStoreDown(int at); bool MoveCLCLoadAddZPStoreDown(int at);
bool FindDirectAddressSumY(int at, int reg, int& apos, int& breg); bool FindDirectAddressSumY(int at, int reg, int& apos, int& breg);
bool PatchDirectAddressSumY(int at, int reg, int apos, int breg); bool PatchDirectAddressSumY(int at, int reg, int apos, int breg);