Add simple native loop optimisation
This commit is contained in:
parent
f925833884
commit
8e9b0fe54c
|
@ -0,0 +1,16 @@
|
|||
// short index ops
|
||||
#include <stdio.h>
|
||||
|
||||
char a[20];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
for(char i=0; i<20; i++)
|
||||
a[i] = i;
|
||||
char x = 0;
|
||||
for(char i=0; i<20; i++)
|
||||
x += a[i];
|
||||
|
||||
printf("Sum %d\n", x);
|
||||
return 0;
|
||||
}
|
|
@ -238,6 +238,7 @@ int nformf(const sinfo * si, char * str, float f, char type)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
char pdigits = digits - fdigits;
|
||||
|
||||
if (digits > 20)
|
||||
|
|
|
@ -2012,7 +2012,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
|||
|
||||
if (ins->mSTemp[1] < 0)
|
||||
{
|
||||
if (ins->mSTemp[0] == ins->mTTemp)
|
||||
if (ins->mSTemp[0] == ins->mTTemp && InterTypeSize[ins->mTType] == 2)
|
||||
{
|
||||
ByteCodeInstruction bins(bci);
|
||||
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
|
||||
|
@ -2021,7 +2021,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
|||
return;
|
||||
}
|
||||
|
||||
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
||||
ByteCodeInstruction lins(InterTypeSize[ins->mSType[0]] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
|
||||
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]];
|
||||
lins.mRegisterFinal = ins->mSFinal[0];
|
||||
mIns.Push(lins);
|
||||
|
@ -2033,7 +2033,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
|||
}
|
||||
else if (ins->mSTemp[0] < 0)
|
||||
{
|
||||
if (ins->mSTemp[1] == ins->mTTemp)
|
||||
if (ins->mSTemp[1] == ins->mTTemp && InterTypeSize[ins->mTType] == 2)
|
||||
{
|
||||
ByteCodeInstruction bins(bci);
|
||||
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
|
||||
|
@ -2042,7 +2042,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
|||
return;
|
||||
}
|
||||
|
||||
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
||||
ByteCodeInstruction lins(InterTypeSize[ins->mSType[1]] == 1 ? BC_LOAD_REG_8 : BC_LOAD_REG_16);
|
||||
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]];
|
||||
lins.mRegisterFinal = ins->mSFinal[1];
|
||||
mIns.Push(lins);
|
||||
|
@ -2319,7 +2319,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
|||
} break;
|
||||
}
|
||||
|
||||
ByteCodeInstruction sins(BC_STORE_REG_16);
|
||||
ByteCodeInstruction sins(InterTypeSize[ins->mSType[1]] == 1 ? BC_STORE_REG_8 : BC_STORE_REG_16);
|
||||
sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
|
||||
mIns.Push(sins);
|
||||
}
|
||||
|
|
|
@ -648,6 +648,21 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
|
|||
data.mRegs[CPU_REG_Z].mImmediate = true;
|
||||
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
||||
}
|
||||
else if (data.mRegs[CPU_REG_A].mImmediate && data.mRegs[CPU_REG_A].mValue == 0)
|
||||
{
|
||||
if (mType == ASMIT_ORA || mType == ASMIT_EOR)
|
||||
{
|
||||
mType = ASMIT_LDA;
|
||||
data.mRegs[CPU_REG_A].mImmediate = false;
|
||||
data.mRegs[CPU_REG_A].mZeroPage = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mType = ASMIT_LDA;
|
||||
mMode = ASMIM_IMMEDIATE;
|
||||
mAddress = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data.mRegs[CPU_REG_A].Reset();
|
||||
|
@ -4294,6 +4309,144 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data)
|
|||
return changed;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
|
||||
{
|
||||
if (!mVisited)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
int sz = mIns.Size();
|
||||
if (sz > 3 && sz < 16 && mNumEntries == 2 && mTrueJump == this)
|
||||
{
|
||||
if (mIns[sz - 3].mType == ASMIT_INC && mIns[sz - 3].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 2].mMode == ASMIM_ZERO_PAGE && mIns[sz - 3].mAddress == mIns[sz - 2].mAddress &&
|
||||
mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && !(mIns[sz - 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y)) &&
|
||||
mBranch == ASMIT_BCC)
|
||||
{
|
||||
// check for usage of Y register
|
||||
|
||||
bool yother = false, yindex = false;
|
||||
int zreg = mIns[sz - 3].mAddress;
|
||||
int limit = mIns[sz - 1].mAddress;
|
||||
|
||||
for (int i = 0; i < sz - 4; i++)
|
||||
{
|
||||
if (mIns[i].mType == ASMIT_INY || mIns[i].mType == ASMIT_DEY || mIns[i].mType == ASMIT_TAY)
|
||||
yother = true;
|
||||
else if (mIns[i].mType == ASMIT_LDY)
|
||||
{
|
||||
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
||||
yindex = true;
|
||||
else
|
||||
yother = true;
|
||||
}
|
||||
else if (mIns[i].mType == ASMIT_LDX && mIns[i].mAddress == zreg)
|
||||
yother = true;
|
||||
else if (!yindex && (mIns[i].mType == ASMIT_STY || mIns[i].mType == ASMIT_TYA || mIns[i].mMode == ASMIM_ABSOLUTE_Y || mIns[i].mMode == ASMIM_INDIRECT_Y))
|
||||
yother = true;
|
||||
}
|
||||
|
||||
if (!yother)
|
||||
{
|
||||
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
|
||||
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
|
||||
for (int i = 0; i + 3 < sz; i++)
|
||||
{
|
||||
if (mIns[i].mType != ASMIT_LDY)
|
||||
lblock->mIns.Push(mIns[i]);
|
||||
else if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED));
|
||||
}
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_CPY, ASMIM_IMMEDIATE, limit));
|
||||
lblock->mBranch = mBranch;
|
||||
lblock->mTrueJump = lblock;
|
||||
lblock->mFalseJump = eblock;
|
||||
|
||||
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, zreg));
|
||||
eblock->mBranch = ASMIT_JMP;
|
||||
eblock->mTrueJump = mFalseJump;
|
||||
eblock->mFalseJump = nullptr;
|
||||
|
||||
mIns.Clear();
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, zreg));
|
||||
mBranch = ASMIT_JMP;
|
||||
mTrueJump = lblock;
|
||||
mFalseJump = nullptr;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if (mIns[sz - 1].mType == ASMIT_DEC && mIns[sz - 1].mMode == ASMIM_ZERO_PAGE && mBranch == ASMIT_BNE)
|
||||
{
|
||||
// check for usage of Y register
|
||||
|
||||
bool yother = false, yindex = false;
|
||||
int zreg = mIns[sz - 1].mAddress;
|
||||
|
||||
for (int i = 0; i < sz - 1; i++)
|
||||
{
|
||||
if (mIns[i].mType == ASMIT_INY || mIns[i].mType == ASMIT_DEY || mIns[i].mType == ASMIT_TAY)
|
||||
yother = true;
|
||||
else if (mIns[i].mType == ASMIT_LDY)
|
||||
{
|
||||
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
||||
yindex = true;
|
||||
else
|
||||
yother = true;
|
||||
}
|
||||
else if (mIns[i].mType == ASMIT_LDX && mIns[i].mAddress == zreg)
|
||||
yother = true;
|
||||
else if (!yindex && (mIns[i].mType == ASMIT_STY || mIns[i].mType == ASMIT_TYA || mIns[i].mMode == ASMIM_ABSOLUTE_Y || mIns[i].mMode == ASMIM_INDIRECT_Y))
|
||||
yother = true;
|
||||
}
|
||||
|
||||
if (!yother)
|
||||
{
|
||||
NativeCodeBasicBlock* lblock = proc->AllocateBlock();
|
||||
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
|
||||
for (int i = 0; i + 1 < sz; i++)
|
||||
{
|
||||
if (mIns[i].mType != ASMIT_LDY)
|
||||
lblock->mIns.Push(mIns[i]);
|
||||
else if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == zreg)
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_TYA, ASMIM_IMPLIED));
|
||||
}
|
||||
lblock->mIns.Push(NativeCodeInstruction(ASMIT_DEY, ASMIM_IMPLIED));
|
||||
lblock->mBranch = mBranch;
|
||||
lblock->mTrueJump = lblock;
|
||||
lblock->mFalseJump = eblock;
|
||||
|
||||
eblock->mIns.Push(NativeCodeInstruction(ASMIT_STY, ASMIM_ZERO_PAGE, zreg));
|
||||
eblock->mBranch = ASMIT_JMP;
|
||||
eblock->mTrueJump = mFalseJump;
|
||||
eblock->mFalseJump = nullptr;
|
||||
|
||||
mIns.Clear();
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_ZERO_PAGE, zreg));
|
||||
mBranch = ASMIT_JMP;
|
||||
mTrueJump = lblock;
|
||||
mFalseJump = nullptr;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->OptimizeSimpleLoop(proc))
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->OptimizeSimpleLoop(proc))
|
||||
changed = true;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
|
||||
{
|
||||
if (!mVisited)
|
||||
|
@ -4403,6 +4556,14 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
|
|||
mIns[i].mAddress ^= mIns[i + 1].mAddress;
|
||||
mIns[i + 1].mType = ASMIT_NOP;
|
||||
}
|
||||
else if (
|
||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & LIVE_CPU_REG_A) &&
|
||||
mIns[i + 0].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress == mIns[i + 1].mAddress &&
|
||||
(mIns[i + 0].mType == ASMIT_DEC || mIns[i + 0].mType == ASMIT_INC))
|
||||
{
|
||||
mIns[i + 1].mType = ASMIT_NOP;
|
||||
mIns[i + 0].mLive |= LIVE_CPU_REG_Z;
|
||||
}
|
||||
|
||||
if (
|
||||
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 &&
|
||||
|
@ -4482,7 +4643,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
|
|||
mIns[i + 2].mType = ASMIT_NOP;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (
|
||||
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 &&
|
||||
|
@ -4971,7 +5131,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
|
||||
CompileInterBlock(proc, proc->mBlocks[0], entryBlock);
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
bool changed;
|
||||
do
|
||||
{
|
||||
|
@ -4998,6 +5158,10 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
if (entryBlock->PeepHoleOptimizer())
|
||||
changed = true;
|
||||
|
||||
ResetVisited();
|
||||
if (entryBlock->OptimizeSimpleLoop(this))
|
||||
changed = true;
|
||||
|
||||
ResetVisited();
|
||||
if (entryBlock->MergeBasicBlocks())
|
||||
changed = true;
|
||||
|
|
|
@ -86,6 +86,7 @@ public:
|
|||
void Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch);
|
||||
|
||||
bool PeepHoleOptimizer(void);
|
||||
bool OptimizeSimpleLoop(NativeCodeProcedure* proc);
|
||||
|
||||
void PutByte(uint8 code);
|
||||
void PutWord(uint16 code);
|
||||
|
|
Loading…
Reference in New Issue