Simple loop invariant optimization for native code

This commit is contained in:
drmortalwombat 2022-01-04 14:07:56 +01:00
parent 78615c0725
commit 639a33f9eb
3 changed files with 123 additions and 56 deletions

View File

@ -117,13 +117,15 @@ void vspr_init(char * screen)
void vspr_set(char sp, int xpos, int ypos, char image, char color) void vspr_set(char sp, int xpos, int ypos, char image, char color)
{ {
vspriteYLow[sp] = (char)ypos; char yp = (char)ypos;
if ((ypos & 0xff00 ) || (xpos & 0xfe00))
yp = 0xff;
vspriteYLow[sp] = yp;
vspriteXLow[sp] = (char)xpos; vspriteXLow[sp] = (char)xpos;
vspriteXHigh[sp] = (char)(xpos >> 8); vspriteXHigh[sp] = (char)(xpos >> 8);
vspriteImage[sp] = image; vspriteImage[sp] = image;
vspriteColor[sp] = color; vspriteColor[sp] = color;
if ((ypos & 0xff00 ) || (xpos & 0xfe00))
vspriteYLow[sp] = 0xff;
} }
#pragma native(vspr_set) #pragma native(vspr_set)

View File

@ -7695,7 +7695,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) if (ins->mSrc[1].mLinkerObject->mSize < 256 || ins->mSrc[0].IsUByte())
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
else else
#endif #endif
@ -7708,6 +7708,9 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
if (ins->mSrc[0].IsUByte())
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
else
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
} }
@ -7717,6 +7720,9 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_UPPER)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_UPPER));
if (ins->mSrc[0].IsUByte())
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
else
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
} }
@ -7726,6 +7732,9 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp])); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
if (ins->mSrc[0].IsUByte())
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
else
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
} }
@ -7754,6 +7763,8 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const
if (ins->mSrc[0].mIntConst) if (ins->mSrc[0].mIntConst)
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, (ins->mSrc[0].mIntConst >> 8) & 0xff));
} }
else if (ins->mSrc[0].IsUByte())
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
else else
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
@ -9485,7 +9496,6 @@ bool NativeCodeBasicBlock::FindDirectAddressSumY(int at, int reg, int& apos, int
return false; return false;
} }
bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg) bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg)
{ {
int j = at - 7; int j = at - 7;
@ -10111,95 +10121,142 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
return changed; return changed;
} }
void NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock* lblock) bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc)
{ {
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
eblock->mBranch = ASMIT_JMP;
eblock->mTrueJump = mFalseJump;
eblock->mFalseJump = nullptr;
lblock->mBranch = mBranch;
lblock->mTrueJump = lblock;
lblock->mFalseJump = eblock;
for (int i = 0; i < mIns.Size(); i++)
lblock->mIns.Push(mIns[i]);
mIns.SetSize(0);
mBranch = ASMIT_JMP;
mTrueJump = lblock;
mFalseJump = nullptr;
return lblock->OptimizeSimpleLoopInvariant(proc, this, eblock);
}
bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock* prevBlock, NativeCodeBasicBlock* exitBlock)
{
bool changed = false;
int ai = 0; int ai = 0;
while (ai < lblock->mIns.Size() && !lblock->mIns[ai].ChangesAccu()) while (ai < mIns.Size() && !mIns[ai].ChangesAccu())
ai++; ai++;
if (ai < lblock->mIns.Size()) if (ai < mIns.Size())
{ {
if (lblock->mIns[ai].mType == ASMIT_LDA && lblock->mIns[ai].mMode == ASMIM_IMMEDIATE) if (mIns[ai].mType == ASMIT_LDA && mIns[ai].mMode == ASMIM_IMMEDIATE)
{ {
int i = ai + 1; int i = ai + 1;
while (i < lblock->mIns.Size() && !lblock->mIns[i].ChangesAccu()) while (i < mIns.Size() && !mIns[i].ChangesAccu())
i++; i++;
if (i == lblock->mIns.Size()) if (i == mIns.Size())
{ {
mIns.Push(lblock->mIns[ai]); if (!prevBlock)
lblock->mIns.Remove(ai); return OptimizeSimpleLoopInvariant(proc);
prevBlock->mIns.Push(mIns[ai]);
mIns.Remove(ai);
changed = true;
} }
} }
else if (lblock->mIns[ai].mType == ASMIT_LDA && lblock->mIns[ai].mMode == ASMIM_ZERO_PAGE) else if (mIns[ai].mType == ASMIT_LDA && mIns[ai].mMode == ASMIM_ZERO_PAGE)
{ {
int i = ai + 1; int i = ai + 1;
while (i < lblock->mIns.Size() && !lblock->mIns[i].ChangesAccu() && !lblock->mIns[i].ChangesZeroPage(lblock->mIns[ai].mAddress)) while (i < mIns.Size() && !mIns[i].ChangesAccu() && !mIns[i].ChangesZeroPage(mIns[ai].mAddress))
i++; i++;
if (i == lblock->mIns.Size()) if (i == mIns.Size())
{ {
mIns.Push(lblock->mIns[ai]); if (!prevBlock)
lblock->mIns.Remove(ai); return OptimizeSimpleLoopInvariant(proc);
prevBlock->mIns.Push(mIns[ai]);
mIns.Remove(ai);
changed = true;
} }
} }
} }
ai = 0; ai = 0;
while (ai < lblock->mIns.Size() && !lblock->mIns[ai].ChangesYReg()) while (ai < mIns.Size() && !mIns[ai].ChangesYReg())
ai++; ai++;
if (ai < lblock->mIns.Size()) if (ai < mIns.Size())
{ {
if (lblock->mIns[ai].mType == ASMIT_LDY && lblock->mIns[ai].mMode == ASMIM_IMMEDIATE) if (mIns[ai].mType == ASMIT_LDY && mIns[ai].mMode == ASMIM_IMMEDIATE)
{ {
int i = ai + 1; int i = ai + 1;
while (i < lblock->mIns.Size() && !lblock->mIns[i].ChangesYReg()) while (i < mIns.Size() && !mIns[i].ChangesYReg())
i++; i++;
if (i == lblock->mIns.Size()) if (i == mIns.Size())
{ {
mIns.Push(lblock->mIns[ai]); if (!prevBlock)
lblock->mIns.Remove(ai); return OptimizeSimpleLoopInvariant(proc);
prevBlock->mIns.Push(mIns[ai]);
mIns.Remove(ai);
changed = true;
} }
} }
else if (lblock->mIns[ai].mType == ASMIT_LDY && lblock->mIns[ai].mMode == ASMIM_ZERO_PAGE) else if (mIns[ai].mType == ASMIT_LDY && mIns[ai].mMode == ASMIM_ZERO_PAGE)
{ {
int i = 0; int i = 0;
while (i < lblock->mIns.Size() && (i == ai || !lblock->mIns[i].ChangesYReg())) while (i < mIns.Size() && (i == ai || !mIns[i].ChangesYReg()))
i++; i++;
if (i == lblock->mIns.Size()) if (i == mIns.Size())
{ {
int addr = lblock->mIns[ai].mAddress; int addr = mIns[ai].mAddress;
i = 0; i = 0;
while (i < lblock->mIns.Size() && while (i < mIns.Size() &&
(lblock->mIns[i].mMode != ASMIM_ZERO_PAGE || lblock->mIns[i].mAddress != addr || (mIns[i].mMode != ASMIM_ZERO_PAGE || mIns[i].mAddress != addr ||
lblock->mIns[i].mType == ASMIT_LDA || lblock->mIns[i].mType == ASMIT_STA || lblock->mIns[i].mType == ASMIT_INC || lblock->mIns[i].mType == ASMIT_DEC || lblock->mIns[i].mType == ASMIT_LDY)) mIns[i].mType == ASMIT_LDA || mIns[i].mType == ASMIT_STA || mIns[i].mType == ASMIT_INC || mIns[i].mType == ASMIT_DEC || mIns[i].mType == ASMIT_LDY))
i++; i++;
if (i == lblock->mIns.Size()) if (i == mIns.Size())
{ {
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, addr)); if (!prevBlock)
lblock->mFalseJump->mIns.Push(NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, addr)); return OptimizeSimpleLoopInvariant(proc);
for (int i = 0; i < lblock->mIns.Size(); i++)
changed = true;
prevBlock->mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, addr));
exitBlock->mIns.Push(NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, addr));
for (int i = 0; i < mIns.Size(); i++)
{ {
if (lblock->mIns[i].mMode == ASMIM_ZERO_PAGE && lblock->mIns[i].mAddress == addr) if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == addr)
{ {
if (lblock->mIns[i].mType == ASMIT_LDA) if (mIns[i].mType == ASMIT_LDA)
{ {
lblock->mIns[i].mType = ASMIT_TYA; lblock->mIns[i].mMode = ASMIM_IMPLIED; mIns[i].mType = ASMIT_TYA; mIns[i].mMode = ASMIM_IMPLIED;
} }
else if (lblock->mIns[i].mType == ASMIT_STA) else if (mIns[i].mType == ASMIT_STA)
{ {
lblock->mIns[i].mType = ASMIT_TAY; lblock->mIns[i].mMode = ASMIM_IMPLIED; mIns[i].mType = ASMIT_TAY; mIns[i].mMode = ASMIM_IMPLIED;
} }
else if (lblock->mIns[i].mType == ASMIT_LDY) else if (mIns[i].mType == ASMIT_LDY)
{ {
lblock->mIns[i].mType = ASMIT_NOP; lblock->mIns[i].mMode = ASMIM_IMPLIED; mIns[i].mType = ASMIT_NOP; mIns[i].mMode = ASMIM_IMPLIED;
} }
else if (lblock->mIns[i].mType == ASMIT_INC) else if (mIns[i].mType == ASMIT_INC)
{ {
lblock->mIns[i].mType = ASMIT_INY; lblock->mIns[i].mMode = ASMIM_IMPLIED; mIns[i].mType = ASMIT_INY; mIns[i].mMode = ASMIM_IMPLIED;
} }
else if (lblock->mIns[i].mType == ASMIT_DEC) else if (mIns[i].mType == ASMIT_DEC)
{ {
lblock->mIns[i].mType = ASMIT_DEY; lblock->mIns[i].mMode = ASMIM_IMPLIED; mIns[i].mType = ASMIT_DEY; mIns[i].mMode = ASMIM_IMPLIED;
} }
} }
} }
@ -10207,6 +10264,8 @@ void NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
} }
} }
} }
return changed;
} }
bool NativeCodeBasicBlock::SimpleLoopReversal(NativeCodeProcedure* proc) bool NativeCodeBasicBlock::SimpleLoopReversal(NativeCodeProcedure* proc)
@ -10433,7 +10492,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock; mTrueJump = lblock;
mFalseJump = nullptr; mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock); lblock->OptimizeSimpleLoopInvariant(proc, this, eblock);
changed = true; changed = true;
@ -10467,7 +10526,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock; mTrueJump = lblock;
mFalseJump = nullptr; mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock); lblock->OptimizeSimpleLoopInvariant(proc, this, eblock);
changed = true; changed = true;
@ -10569,7 +10628,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock; mTrueJump = lblock;
mFalseJump = nullptr; mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock); lblock->OptimizeSimpleLoopInvariant(proc, this, eblock);
changed = true; changed = true;
@ -10651,7 +10710,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock; mTrueJump = lblock;
mFalseJump = nullptr; mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock); lblock->OptimizeSimpleLoopInvariant(proc, this, eblock);
changed = true; changed = true;
@ -10685,13 +10744,17 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock; mTrueJump = lblock;
mFalseJump = nullptr; mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock); lblock->OptimizeSimpleLoopInvariant(proc, this, eblock);
changed = true; changed = true;
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
} }
} }

View File

@ -142,7 +142,9 @@ public:
bool PeepHoleOptimizer(int pass); bool PeepHoleOptimizer(int pass);
void BlockSizeReduction(void); void BlockSizeReduction(void);
void OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock * lblock); bool OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc);
bool OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock * prevBlock, NativeCodeBasicBlock* exitBlock);
bool OptimizeSimpleLoop(NativeCodeProcedure* proc); bool OptimizeSimpleLoop(NativeCodeProcedure* proc);
bool SimpleLoopReversal(NativeCodeProcedure* proc); bool SimpleLoopReversal(NativeCodeProcedure* proc);
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, GrowingArray<NativeCodeBasicBlock*>& blocks); bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, GrowingArray<NativeCodeBasicBlock*>& blocks);