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;
|
char pdigits = digits - fdigits;
|
||||||
|
|
||||||
if (digits > 20)
|
if (digits > 20)
|
||||||
|
|
|
@ -2012,7 +2012,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
||||||
|
|
||||||
if (ins->mSTemp[1] < 0)
|
if (ins->mSTemp[1] < 0)
|
||||||
{
|
{
|
||||||
if (ins->mSTemp[0] == ins->mTTemp)
|
if (ins->mSTemp[0] == ins->mTTemp && InterTypeSize[ins->mTType] == 2)
|
||||||
{
|
{
|
||||||
ByteCodeInstruction bins(bci);
|
ByteCodeInstruction bins(bci);
|
||||||
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
|
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
|
||||||
|
@ -2021,7 +2021,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
||||||
return;
|
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.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSTemp[0]];
|
||||||
lins.mRegisterFinal = ins->mSFinal[0];
|
lins.mRegisterFinal = ins->mSFinal[0];
|
||||||
mIns.Push(lins);
|
mIns.Push(lins);
|
||||||
|
@ -2033,7 +2033,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
||||||
}
|
}
|
||||||
else if (ins->mSTemp[0] < 0)
|
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);
|
ByteCodeInstruction bins(bci);
|
||||||
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
|
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
|
||||||
|
@ -2042,7 +2042,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
||||||
return;
|
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.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSTemp[1]];
|
||||||
lins.mRegisterFinal = ins->mSFinal[1];
|
lins.mRegisterFinal = ins->mSFinal[1];
|
||||||
mIns.Push(lins);
|
mIns.Push(lins);
|
||||||
|
@ -2319,7 +2319,7 @@ void ByteCodeBasicBlock::BinaryOperator(InterCodeProcedure* proc, const InterIns
|
||||||
} break;
|
} 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];
|
sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mTTemp];
|
||||||
mIns.Push(sins);
|
mIns.Push(sins);
|
||||||
}
|
}
|
||||||
|
|
|
@ -648,6 +648,21 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data)
|
||||||
data.mRegs[CPU_REG_Z].mImmediate = true;
|
data.mRegs[CPU_REG_Z].mImmediate = true;
|
||||||
data.mRegs[CPU_REG_Z].mValue = mAddress;
|
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
|
else
|
||||||
{
|
{
|
||||||
data.mRegs[CPU_REG_A].Reset();
|
data.mRegs[CPU_REG_A].Reset();
|
||||||
|
@ -4294,6 +4309,144 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data)
|
||||||
return changed;
|
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)
|
bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
{
|
{
|
||||||
if (!mVisited)
|
if (!mVisited)
|
||||||
|
@ -4403,6 +4556,14 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i].mAddress ^= mIns[i + 1].mAddress;
|
mIns[i].mAddress ^= mIns[i + 1].mAddress;
|
||||||
mIns[i + 1].mType = ASMIT_NOP;
|
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 (
|
if (
|
||||||
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 &&
|
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;
|
mIns[i + 2].mType = ASMIT_NOP;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (
|
if (
|
||||||
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 &&
|
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);
|
CompileInterBlock(proc, proc->mBlocks[0], entryBlock);
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
bool changed;
|
bool changed;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -4998,6 +5158,10 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
if (entryBlock->PeepHoleOptimizer())
|
if (entryBlock->PeepHoleOptimizer())
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
if (entryBlock->OptimizeSimpleLoop(this))
|
||||||
|
changed = true;
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (entryBlock->MergeBasicBlocks())
|
if (entryBlock->MergeBasicBlocks())
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
|
@ -86,6 +86,7 @@ public:
|
||||||
void Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch);
|
void Close(NativeCodeBasicBlock* trueJump, NativeCodeBasicBlock* falseJump, AsmInsType branch);
|
||||||
|
|
||||||
bool PeepHoleOptimizer(void);
|
bool PeepHoleOptimizer(void);
|
||||||
|
bool OptimizeSimpleLoop(NativeCodeProcedure* proc);
|
||||||
|
|
||||||
void PutByte(uint8 code);
|
void PutByte(uint8 code);
|
||||||
void PutWord(uint16 code);
|
void PutWord(uint16 code);
|
||||||
|
|
Loading…
Reference in New Issue