Optimize small inline function calls
This commit is contained in:
parent
b09e9a2434
commit
2e696d9e1a
|
@ -121,9 +121,9 @@ bool krnio_load(char fnum, char device, char channel)
|
||||||
jsr $FFD5 // load
|
jsr $FFD5 // load
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
bcs W1
|
rol
|
||||||
lda #1
|
eor #1
|
||||||
W1: sta accu
|
sta accu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,9 +144,9 @@ bool krnio_save(char device, const char* start, const char* end)
|
||||||
jsr $FFD8 // save
|
jsr $FFD8 // save
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
bcs W1
|
rol
|
||||||
lda #1
|
eor #1
|
||||||
W1: sta accu
|
sta accu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,10 +158,11 @@ bool krnio_chkout(char fnum)
|
||||||
{
|
{
|
||||||
ldx fnum
|
ldx fnum
|
||||||
jsr $ffc9 // chkout
|
jsr $ffc9 // chkout
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
bcs W1
|
rol
|
||||||
lda #1
|
eor #1
|
||||||
W1: sta accu
|
sta accu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,11 +174,11 @@ bool krnio_chkin(char fnum)
|
||||||
{
|
{
|
||||||
ldx fnum
|
ldx fnum
|
||||||
jsr $ffc6 // chkin
|
jsr $ffc6 // chkin
|
||||||
|
|
||||||
lda #0
|
lda #0
|
||||||
sta accu + 1
|
rol
|
||||||
bcs W1
|
eor #1
|
||||||
lda #1
|
sta accu
|
||||||
W1: sta accu
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,21 +201,17 @@ bool krnio_chrout(char ch)
|
||||||
lda ch
|
lda ch
|
||||||
jsr $ffd2 // chrout
|
jsr $ffd2 // chrout
|
||||||
sta accu
|
sta accu
|
||||||
lda #0
|
|
||||||
sta accu + 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma native(krnio_chrout)
|
#pragma native(krnio_chrout)
|
||||||
|
|
||||||
int krnio_chrin(void)
|
char krnio_chrin(void)
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
jsr $ffcf // chrin
|
jsr $ffcf // chrin
|
||||||
sta accu
|
sta accu
|
||||||
lda #0
|
|
||||||
sta accu + 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ bool krnio_chrout(char ch);
|
||||||
|
|
||||||
// read a single byte from the current input channel
|
// read a single byte from the current input channel
|
||||||
|
|
||||||
int krnio_chrin(void);
|
char krnio_chrin(void);
|
||||||
|
|
||||||
// read a single byte from the given file/channel, returns
|
// read a single byte from the given file/channel, returns
|
||||||
// a negative result on failure. If this was the last byte
|
// a negative result on failure. If this was the last byte
|
||||||
|
|
|
@ -2508,7 +2508,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
if (vl.mType->mFlags & DTF_DEFINED)
|
if (vl.mType->mFlags & DTF_DEFINED)
|
||||||
{
|
{
|
||||||
int64 index = exp->mRight->mDecValue->mInteger;
|
int64 index = exp->mRight->mDecValue->mInteger;
|
||||||
if (index < 0 || index * stride >= vl.mType->mSize * vl.mType->mStripe)
|
if (vl.mType->mSize > 0 && (index < 0 || index * stride >= vl.mType->mSize * vl.mType->mStripe))
|
||||||
mErrors->Error(exp->mLocation, EWARN_INDEX_OUT_OF_BOUNDS, "Constant array index out of bounds");
|
mErrors->Error(exp->mLocation, EWARN_INDEX_OUT_OF_BOUNDS, "Constant array index out of bounds");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ bool LinkerReference::operator!=(const LinkerReference& ref)
|
||||||
|
|
||||||
LinkerObject::LinkerObject(void)
|
LinkerObject::LinkerObject(void)
|
||||||
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr), mStartUsed(0x10000), mEndUsed(0x00000), mMemory(nullptr)
|
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr), mStartUsed(0x10000), mEndUsed(0x00000), mMemory(nullptr)
|
||||||
, mPrefix(nullptr), mSuffix(nullptr)
|
, mPrefix(nullptr), mSuffix(nullptr), mProc(nullptr), mNativeProc(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
LinkerObject::~LinkerObject(void)
|
LinkerObject::~LinkerObject(void)
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
class InterCodeProcedure;
|
class InterCodeProcedure;
|
||||||
class InterVariable;
|
class InterVariable;
|
||||||
|
class NativeCodeProcedure;
|
||||||
|
|
||||||
enum LinkerObjectType
|
enum LinkerObjectType
|
||||||
{
|
{
|
||||||
|
@ -192,6 +193,7 @@ public:
|
||||||
LinkerRegion * mRegion;
|
LinkerRegion * mRegion;
|
||||||
uint8 * mData, * mMemory;
|
uint8 * mData, * mMemory;
|
||||||
InterCodeProcedure * mProc;
|
InterCodeProcedure * mProc;
|
||||||
|
NativeCodeProcedure * mNativeProc;
|
||||||
InterVariable * mVariable;
|
InterVariable * mVariable;
|
||||||
uint32 mFlags;
|
uint32 mFlags;
|
||||||
uint8 mTemporaries[16], mTempSizes[16];
|
uint8 mTemporaries[16], mTempSizes[16];
|
||||||
|
|
|
@ -5053,6 +5053,21 @@ int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBloc
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (target->mIns.Size() == 2 && target->mIns[0].IsSimpleJSR() && target->mIns[1].mType == ASMIT_RTS)
|
||||||
|
{
|
||||||
|
PutByte(0x4c);
|
||||||
|
|
||||||
|
LinkerReference rl;
|
||||||
|
rl.mObject = nullptr;
|
||||||
|
rl.mOffset = mCode.Size();
|
||||||
|
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
|
||||||
|
rl.mRefObject = target->mIns[0].mLinkerObject;
|
||||||
|
rl.mRefOffset = target->mIns[0].mAddress;
|
||||||
|
mRelocations.Push(rl);
|
||||||
|
|
||||||
|
PutWord(0);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
#if JUMP_TO_BRANCH
|
#if JUMP_TO_BRANCH
|
||||||
else if (offset >= -126 && offset <= 129)
|
else if (offset >= -126 && offset <= 129)
|
||||||
{
|
{
|
||||||
|
@ -5113,6 +5128,10 @@ int NativeCodeBasicBlock::JumpByteSize(NativeCodeBasicBlock* target, int offset)
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else if (target->mIns.Size() == 2 && target->mIns[0].IsSimpleJSR() && target->mIns[1].mType == ASMIT_RTS)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
#if JUMP_TO_BRANCH
|
#if JUMP_TO_BRANCH
|
||||||
else if (offset >= -126 && offset <= 129)
|
else if (offset >= -126 && offset <= 129)
|
||||||
{
|
{
|
||||||
|
@ -6636,7 +6655,6 @@ bool NativeCodeBasicBlock::LoadLoadOpStoreIndirectValue(InterCodeProcedure* proc
|
||||||
}
|
}
|
||||||
else if (rins0->mSrc[0].mMemory == IM_INDIRECT && wins->mSrc[1].mMemory == IM_INDIRECT && rins1->mSrc[0].mMemory == IM_FPARAM)
|
else if (rins0->mSrc[0].mMemory == IM_INDIRECT && wins->mSrc[1].mMemory == IM_INDIRECT && rins1->mSrc[0].mMemory == IM_FPARAM)
|
||||||
{
|
{
|
||||||
printf("OOpsie0\n");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -13380,7 +13398,7 @@ void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, NativeCodePro
|
||||||
simple = false;
|
simple = false;
|
||||||
if (dins.mType == ASMIT_JSR)
|
if (dins.mType == ASMIT_JSR)
|
||||||
{
|
{
|
||||||
dins.mFlags |= uflags;
|
dins.mFlags |= uflags | NCIF_JSRFLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dins.mType == ASMIT_BRK || dins.mMode == ASMIM_INDIRECT_X || dins.mMode == ASMIM_INDIRECT ||
|
if (dins.mType == ASMIT_BRK || dins.mMode == ASMIM_INDIRECT_X || dins.mMode == ASMIM_INDIRECT ||
|
||||||
|
@ -18503,6 +18521,42 @@ bool NativeCodeBasicBlock::CrossBlockStoreLoadBypass(NativeCodeProcedure* proc)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::SimpleInlineCalls(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
|
{
|
||||||
|
if (mIns[i].mType == ASMIT_JSR)
|
||||||
|
{
|
||||||
|
if (mIns[i].mLinkerObject && mIns[i].mLinkerObject->mNativeProc)
|
||||||
|
{
|
||||||
|
NativeCodeProcedure* proc = mIns[i].mLinkerObject->mNativeProc;
|
||||||
|
if (proc->mSimpleInline)
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* sins = proc->mEntryBlock->mTrueJump;
|
||||||
|
mIns.Remove(i);
|
||||||
|
for(int j=0; j<sins->mIns.Size(); j++)
|
||||||
|
mIns.Insert(i + j, sins->mIns[j]);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->SimpleInlineCalls())
|
||||||
|
changed = true;
|
||||||
|
if (mFalseJump && mFalseJump->SimpleInlineCalls())
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -22528,6 +22582,8 @@ void NativeCodeBasicBlock::MarkLiveBlockChain(int index, NativeCodeBasicBlock* b
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::CanJoinEntryLoadStoreZP(int saddr, int daddr)
|
bool NativeCodeBasicBlock::CanJoinEntryLoadStoreZP(int saddr, int daddr)
|
||||||
{
|
{
|
||||||
|
mChecked = true;
|
||||||
|
|
||||||
// Avoid moving code into loops
|
// Avoid moving code into loops
|
||||||
if (mLoopHead && (mTrueJump == this || mFalseJump == this))
|
if (mLoopHead && (mTrueJump == this || mFalseJump == this))
|
||||||
return false;
|
return false;
|
||||||
|
@ -22551,11 +22607,26 @@ bool NativeCodeBasicBlock::CanJoinEntryLoadStoreZP(int saddr, int daddr)
|
||||||
at--;
|
at--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mLoopHead && mEntryBlocks.Size() > 0 && daddr >= BC_REG_FPARAMS && daddr < BC_REG_FPARAMS_END)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||||
|
{
|
||||||
|
if (!mEntryBlocks[i]->CanJoinEntryLoadStoreZP(saddr, daddr))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::DoJoinEntryLoadStoreZP(int saddr, int daddr)
|
bool NativeCodeBasicBlock::DoJoinEntryLoadStoreZP(int saddr, int daddr)
|
||||||
{
|
{
|
||||||
|
if (!mChecked)
|
||||||
|
return true;
|
||||||
|
mChecked = false;
|
||||||
|
|
||||||
int at = mIns.Size() - 1;
|
int at = mIns.Size() - 1;
|
||||||
while (at >= 0)
|
while (at >= 0)
|
||||||
{
|
{
|
||||||
|
@ -22566,24 +22637,40 @@ bool NativeCodeBasicBlock::DoJoinEntryLoadStoreZP(int saddr, int daddr)
|
||||||
{
|
{
|
||||||
ins.mLive |= LIVE_CPU_REG_A;
|
ins.mLive |= LIVE_CPU_REG_A;
|
||||||
mIns.Insert(at + 1, NativeCodeInstruction(ins.mIns, ASMIT_STA, ASMIM_ZERO_PAGE, daddr));
|
mIns.Insert(at + 1, NativeCodeInstruction(ins.mIns, ASMIT_STA, ASMIM_ZERO_PAGE, daddr));
|
||||||
|
mExitRequiredRegs += daddr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (ins.mType == ASMIT_STX)
|
else if (ins.mType == ASMIT_STX)
|
||||||
{
|
{
|
||||||
ins.mLive |= LIVE_CPU_REG_X;
|
ins.mLive |= LIVE_CPU_REG_X;
|
||||||
mIns.Insert(at + 1, NativeCodeInstruction(ins.mIns, ASMIT_STX, ASMIM_ZERO_PAGE, daddr));
|
mIns.Insert(at + 1, NativeCodeInstruction(ins.mIns, ASMIT_STX, ASMIM_ZERO_PAGE, daddr));
|
||||||
|
mExitRequiredRegs += daddr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (ins.mType == ASMIT_STY)
|
else if (ins.mType == ASMIT_STY)
|
||||||
{
|
{
|
||||||
ins.mLive |= LIVE_CPU_REG_Y;
|
ins.mLive |= LIVE_CPU_REG_Y;
|
||||||
mIns.Insert(at + 1, NativeCodeInstruction(ins.mIns, ASMIT_STY, ASMIM_ZERO_PAGE, daddr));
|
mIns.Insert(at + 1, NativeCodeInstruction(ins.mIns, ASMIT_STY, ASMIM_ZERO_PAGE, daddr));
|
||||||
|
mExitRequiredRegs += daddr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
at--;
|
at--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mLoopHead)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||||
|
{
|
||||||
|
if (!mEntryBlocks[i]->DoJoinEntryLoadStoreZP(saddr, daddr))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mEntryRequiredRegs += daddr;
|
||||||
|
mExitRequiredRegs += daddr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22597,7 +22684,7 @@ bool NativeCodeBasicBlock::JoinEntryLoadStoreZP(void)
|
||||||
|
|
||||||
CheckLive();
|
CheckLive();
|
||||||
|
|
||||||
if (!mEntryRequiredRegs[CPU_REG_A] || !mEntryRequiredRegs[CPU_REG_X])
|
if (!mLoopHead && mEntryBlocks.Size() < 64 && (!mEntryRequiredRegs[CPU_REG_A] || !mEntryRequiredRegs[CPU_REG_X]))
|
||||||
{
|
{
|
||||||
for (int i = 0; i + 1 < mIns.Size(); i++)
|
for (int i = 0; i + 1 < mIns.Size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -22608,10 +22695,14 @@ bool NativeCodeBasicBlock::JoinEntryLoadStoreZP(void)
|
||||||
if (!ReferencesZeroPage(saddr, 0, i) && !ReferencesZeroPage(daddr, 0, i))
|
if (!ReferencesZeroPage(saddr, 0, i) && !ReferencesZeroPage(daddr, 0, i))
|
||||||
{
|
{
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
uint64 mask = 0;
|
||||||
for (int j = 0; j < mEntryBlocks.Size(); j++)
|
for (int j = 0; j < mEntryBlocks.Size(); j++)
|
||||||
{
|
{
|
||||||
if (mEntryBlocks[j]->CanJoinEntryLoadStoreZP(saddr, daddr))
|
if (mEntryBlocks[j]->CanJoinEntryLoadStoreZP(saddr, daddr))
|
||||||
|
{
|
||||||
|
mask |= 1ull << j;
|
||||||
n++;
|
n++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n == mEntryBlocks.Size())
|
if (n == mEntryBlocks.Size())
|
||||||
|
@ -22630,16 +22721,16 @@ bool NativeCodeBasicBlock::JoinEntryLoadStoreZP(void)
|
||||||
{
|
{
|
||||||
NativeCodeBasicBlock* xblock = mProc->AllocateBlock();
|
NativeCodeBasicBlock* xblock = mProc->AllocateBlock();
|
||||||
|
|
||||||
int j = 0;
|
int j = mEntryBlocks.Size();
|
||||||
while (j < mEntryBlocks.Size())
|
while (j > 0)
|
||||||
{
|
{
|
||||||
|
j--;
|
||||||
NativeCodeBasicBlock* eb = mEntryBlocks[j];
|
NativeCodeBasicBlock* eb = mEntryBlocks[j];
|
||||||
|
|
||||||
if (eb->CanJoinEntryLoadStoreZP(saddr, daddr))
|
if (mask & (1ull << j))
|
||||||
{
|
{
|
||||||
eb->DoJoinEntryLoadStoreZP(saddr, daddr);
|
eb->DoJoinEntryLoadStoreZP(saddr, daddr);
|
||||||
eb->mExitRequiredRegs += daddr;
|
eb->mExitRequiredRegs += daddr;
|
||||||
j++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -25229,6 +25320,57 @@ bool NativeCodeBasicBlock::CrossBlockXYPreservation(void)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::EliminateMicroBlocks(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
if (mIns.Size() > 0 && mIns.Size() <= 2 && mTrueJump && !mFalseJump)
|
||||||
|
{
|
||||||
|
if (mIns[0].mType == ASMIT_STA && !(mIns[0].mLive & LIVE_CPU_REG_A))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = mEntryBlocks[i];
|
||||||
|
int sz = block->mIns.Size();
|
||||||
|
if (sz > 0 && !block->mFalseJump)
|
||||||
|
{
|
||||||
|
if (block->mIns[sz - 1].mType == ASMIT_TYA && HasAsmInstructionMode(ASMIT_STY, mIns[0].mMode))
|
||||||
|
{
|
||||||
|
block->mIns[sz - 1] = NativeCodeInstruction(mIns[0].mIns, ASMIT_STY, mIns[0]);
|
||||||
|
if (mIns.Size() > 1)
|
||||||
|
block->mIns.Push(mIns[1]);
|
||||||
|
block->mTrueJump->RemEntryBlock(block);
|
||||||
|
mTrueJump->AddEntryBlock(block);
|
||||||
|
block->mTrueJump = mTrueJump;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (block->mIns[sz - 1].mType == ASMIT_TXA && HasAsmInstructionMode(ASMIT_STX, mIns[0].mMode))
|
||||||
|
{
|
||||||
|
block->mIns[sz - 1] = NativeCodeInstruction(mIns[0].mIns, ASMIT_STX, mIns[0]);
|
||||||
|
if (mIns.Size() > 1)
|
||||||
|
block->mIns.Push(mIns[1]);
|
||||||
|
block->mTrueJump->RemEntryBlock(block);
|
||||||
|
mTrueJump->AddEntryBlock(block);
|
||||||
|
block->mTrueJump = mTrueJump;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->EliminateMicroBlocks())
|
||||||
|
changed = true;
|
||||||
|
if (mFalseJump && mFalseJump->EliminateMicroBlocks())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::FoldLoopEntry(void)
|
bool NativeCodeBasicBlock::FoldLoopEntry(void)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -34467,6 +34609,23 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sz >= 2 && mIns[0].mType == ASMIT_LDA && mIns[sz - 1].mType == ASMIT_LDA && mIns[0].SameEffectiveAddress(mIns[sz - 1]))
|
||||||
|
{
|
||||||
|
if (!prevBlock)
|
||||||
|
return OptimizeSimpleLoopInvariant(proc, full);
|
||||||
|
|
||||||
|
prevBlock->mIns.Push(mIns[0]);
|
||||||
|
mIns.Remove(0);
|
||||||
|
|
||||||
|
mEntryRequiredRegs += CPU_REG_A;
|
||||||
|
mExitRequiredRegs += CPU_REG_A;
|
||||||
|
prevBlock->mExitRequiredRegs += CPU_REG_A;
|
||||||
|
|
||||||
|
CheckLive();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (sz >= 3 && mIns[0].mType == ASMIT_LDY && mIns[sz - 2].mType == ASMIT_LDA && mIns[0].SameEffectiveAddress(mIns[sz - 2]) &&
|
if (sz >= 3 && mIns[0].mType == ASMIT_LDY && mIns[sz - 2].mType == ASMIT_LDA && mIns[0].SameEffectiveAddress(mIns[sz - 2]) &&
|
||||||
mIns[sz - 1].mType == ASMIT_CMP && HasAsmInstructionMode(ASMIT_CPY, mIns[sz - 1].mMode) && !(mIns[sz - 1].mLive & LIVE_CPU_REG_A))
|
mIns[sz - 1].mType == ASMIT_CMP && HasAsmInstructionMode(ASMIT_CPY, mIns[sz - 1].mMode) && !(mIns[sz - 1].mLive & LIVE_CPU_REG_A))
|
||||||
{
|
{
|
||||||
|
@ -35005,6 +35164,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
|
||||||
|
|
||||||
mEntryRequiredRegs += CPU_REG_X;
|
mEntryRequiredRegs += CPU_REG_X;
|
||||||
mExitRequiredRegs += CPU_REG_X;
|
mExitRequiredRegs += CPU_REG_X;
|
||||||
|
prevBlock->mExitRequiredRegs += CPU_REG_X;
|
||||||
|
|
||||||
CheckLive();
|
CheckLive();
|
||||||
|
|
||||||
|
@ -36902,7 +37062,11 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc, bool f
|
||||||
#if 1
|
#if 1
|
||||||
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
|
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
|
||||||
if (!changed)
|
if (!changed)
|
||||||
|
{
|
||||||
|
CheckLive();
|
||||||
changed = OptimizeSimpleLoopInvariant(proc, nullptr, nullptr, full);
|
changed = OptimizeSimpleLoopInvariant(proc, nullptr, nullptr, full);
|
||||||
|
CheckLive();
|
||||||
|
}
|
||||||
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
|
assert(mBranch != ASMIT_JMP || mFalseJump == nullptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -41694,7 +41858,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_IMMEDIATE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ABSOLUTE_X) &&
|
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_IMMEDIATE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ABSOLUTE_X || mIns[i + 0].mMode == ASMIM_IMMEDIATE_ADDRESS) &&
|
||||||
mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
||||||
{
|
{
|
||||||
mIns[i + 0].mType = ASMIT_LDY; mIns[i + 0].mLive |= mIns[i + 1].mLive;
|
mIns[i + 0].mType = ASMIT_LDY; mIns[i + 0].mLive |= mIns[i + 1].mLive;
|
||||||
|
@ -41703,7 +41867,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_IMMEDIATE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ABSOLUTE_Y) &&
|
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_IMMEDIATE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ABSOLUTE_Y || mIns[i + 0].mMode == ASMIM_IMMEDIATE_ADDRESS) &&
|
||||||
mIns[i + 1].mType == ASMIT_TAX && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
mIns[i + 1].mType == ASMIT_TAX && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
||||||
{
|
{
|
||||||
mIns[i + 0].mType = ASMIT_LDX; mIns[i + 0].mLive |= mIns[i + 1].mLive;
|
mIns[i + 0].mType = ASMIT_LDX; mIns[i + 0].mLive |= mIns[i + 1].mLive;
|
||||||
|
@ -45325,6 +45489,25 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
|
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress != mIns[i + 0].mAddress &&
|
||||||
|
mIns[i + 2].mType == ASMIT_ROL && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress != mIns[i + 0].mAddress &&
|
||||||
|
mIns[i + 3].mType == ASMIT_ROL && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress != mIns[i + 0].mAddress &&
|
||||||
|
mIns[i + 4].mType == ASMIT_ROL && mIns[i + 4].mMode == ASMIM_ZERO_PAGE && mIns[i + 4].mAddress == mIns[i + 0].mAddress &&
|
||||||
|
!(mIns[i + 4].mLive & LIVE_CPU_REG_A))
|
||||||
|
{
|
||||||
|
mIns.Insert(i + 5, mIns[i + 0]);
|
||||||
|
mIns.Remove(i);
|
||||||
|
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 1].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 2].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 3].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 3].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + 4].mLive |= mIns[i + 3].mLive;
|
||||||
|
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
else if (
|
else if (
|
||||||
|
@ -47857,7 +48040,7 @@ NativeCodeBasicBlock::~NativeCodeBasicBlock(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeCodeProcedure::NativeCodeProcedure(NativeCodeGenerator* generator)
|
NativeCodeProcedure::NativeCodeProcedure(NativeCodeGenerator* generator)
|
||||||
: mGenerator(generator)
|
: mGenerator(generator), mSimpleInline(false)
|
||||||
{
|
{
|
||||||
mTempBlocks = 1000;
|
mTempBlocks = 1000;
|
||||||
}
|
}
|
||||||
|
@ -48064,8 +48247,9 @@ void NativeCodeProcedure::LoadTempsFromStack(int tempSave)
|
||||||
void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
mInterProc = proc;
|
mInterProc = proc;
|
||||||
|
mInterProc->mLinkerObject->mNativeProc = this;
|
||||||
|
|
||||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "buildRamTiles");
|
CheckFunc = !strcmp(mInterProc->mIdent->mString, "longor");
|
||||||
|
|
||||||
int nblocks = proc->mBlocks.Size();
|
int nblocks = proc->mBlocks.Size();
|
||||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||||
|
@ -48515,6 +48699,83 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
|
|
||||||
proc->mLinkerObject->mType = LOT_NATIVE_CODE;
|
proc->mLinkerObject->mType = LOT_NATIVE_CODE;
|
||||||
|
|
||||||
|
if (!mInterProc->mNoInline)
|
||||||
|
{
|
||||||
|
if (mEntryBlock->mIns.Size() == 0 && mExitBlock->mIns.Size() == 1 && !mEntryBlock->mTrueJump->mFalseJump && mEntryBlock->mTrueJump->mTrueJump == mExitBlock)
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* block = mEntryBlock->mTrueJump;
|
||||||
|
int sz = block->mIns.Size();
|
||||||
|
if (sz < 20)
|
||||||
|
{
|
||||||
|
int cost = -6;
|
||||||
|
for (int i = 0; i < sz; i++)
|
||||||
|
{
|
||||||
|
const NativeCodeInstruction& ins(block->mIns[i]);
|
||||||
|
switch (ins.mType)
|
||||||
|
{
|
||||||
|
case ASMIT_LDA:
|
||||||
|
case ASMIT_LDX:
|
||||||
|
case ASMIT_LDY:
|
||||||
|
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress >= BC_REG_FPARAMS && ins.mAddress < BC_REG_FPARAMS_END)
|
||||||
|
cost -= 2;
|
||||||
|
else
|
||||||
|
cost += AsmInsSize(ins.mType, ins.mMode);
|
||||||
|
break;
|
||||||
|
case ASMIT_STA:
|
||||||
|
case ASMIT_STX:
|
||||||
|
case ASMIT_STY:
|
||||||
|
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress >= BC_REG_ACCU && ins.mAddress < BC_REG_ACCU + 4)
|
||||||
|
cost -= 2;
|
||||||
|
else
|
||||||
|
cost += AsmInsSize(ins.mType, ins.mMode);
|
||||||
|
break;
|
||||||
|
case ASMIT_JSR:
|
||||||
|
if (ins.mLinkerObject && (ins.mLinkerObject->mFlags & LOBJF_INLINE))
|
||||||
|
cost += 1000;
|
||||||
|
else
|
||||||
|
cost += 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASMIT_TAX:
|
||||||
|
case ASMIT_TXA:
|
||||||
|
case ASMIT_TAY:
|
||||||
|
case ASMIT_TYA:
|
||||||
|
case ASMIT_ASL:
|
||||||
|
case ASMIT_LSR:
|
||||||
|
case ASMIT_ROL:
|
||||||
|
case ASMIT_ROR:
|
||||||
|
case ASMIT_CLC:
|
||||||
|
case ASMIT_SEC:
|
||||||
|
case ASMIT_INX:
|
||||||
|
case ASMIT_INY:
|
||||||
|
case ASMIT_DEX:
|
||||||
|
case ASMIT_DEY:
|
||||||
|
case ASMIT_ADC:
|
||||||
|
case ASMIT_SBC:
|
||||||
|
case ASMIT_AND:
|
||||||
|
case ASMIT_ORA:
|
||||||
|
case ASMIT_EOR:
|
||||||
|
case ASMIT_BIT:
|
||||||
|
case ASMIT_CMP:
|
||||||
|
case ASMIT_CPX:
|
||||||
|
case ASMIT_CPY:
|
||||||
|
cost += AsmInsSize(ins.mType, ins.mMode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
cost += 1000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cost <= 0)
|
||||||
|
{
|
||||||
|
mSimpleInline = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
|
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
|
@ -48524,7 +48785,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
|
|
||||||
void NativeCodeProcedure::Assemble(void)
|
void NativeCodeProcedure::Assemble(void)
|
||||||
{
|
{
|
||||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "mh_size");
|
CheckFunc = !strcmp(mInterProc->mIdent->mString, "longor");
|
||||||
|
|
||||||
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
|
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
|
||||||
{
|
{
|
||||||
|
@ -49569,6 +49830,16 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (step == 15)
|
||||||
|
{
|
||||||
|
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_INLINE)
|
||||||
|
{
|
||||||
|
ResetVisited();
|
||||||
|
if (mEntryBlock->SimpleInlineCalls())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->CheckAsmCode();
|
mEntryBlock->CheckAsmCode();
|
||||||
|
@ -49577,7 +49848,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
#if 1
|
#if 1
|
||||||
if (cnt > 190)
|
if (cnt > 190)
|
||||||
{
|
{
|
||||||
printf("Oops\n");
|
printf("Oops %d\n", step);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -49588,7 +49859,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (!changed && step < 14)
|
if (!changed && step < 15)
|
||||||
{
|
{
|
||||||
ResetIndexFlipped();
|
ResetIndexFlipped();
|
||||||
|
|
||||||
|
@ -49617,6 +49888,18 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
CompressTemporaries(true);
|
CompressTemporaries(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
do {
|
||||||
|
ResetVisited();
|
||||||
|
NativeRegisterDataSet data;
|
||||||
|
mEntryBlock->BuildEntryDataSet(data);
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
} while (mEntryBlock->ExpandADCToBranch(this));
|
||||||
|
|
||||||
|
do {
|
||||||
|
ResetVisited();
|
||||||
|
} while (mEntryBlock->EliminateMicroBlocks());
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
|
|
@ -631,6 +631,8 @@ public:
|
||||||
bool RemoveDoubleZPStore(void);
|
bool RemoveDoubleZPStore(void);
|
||||||
|
|
||||||
bool ExpandADCToBranch(NativeCodeProcedure* proc);
|
bool ExpandADCToBranch(NativeCodeProcedure* proc);
|
||||||
|
bool SimpleInlineCalls(void);
|
||||||
|
|
||||||
bool Split16BitLoopCount(NativeCodeProcedure* proc);
|
bool Split16BitLoopCount(NativeCodeProcedure* proc);
|
||||||
bool SimplifyDiamond(NativeCodeProcedure* proc);
|
bool SimplifyDiamond(NativeCodeProcedure* proc);
|
||||||
bool SimplifyLoopEnd(NativeCodeProcedure* proc);
|
bool SimplifyLoopEnd(NativeCodeProcedure* proc);
|
||||||
|
@ -663,6 +665,7 @@ public:
|
||||||
|
|
||||||
bool CrossBlockXYPreservation(void);
|
bool CrossBlockXYPreservation(void);
|
||||||
bool CrossBlockIncToZeroShortcut(void);
|
bool CrossBlockIncToZeroShortcut(void);
|
||||||
|
bool EliminateMicroBlocks(void);
|
||||||
|
|
||||||
bool AlternateXYUsage(void);
|
bool AlternateXYUsage(void);
|
||||||
bool OptimizeXYPairUsage(void);
|
bool OptimizeXYPairUsage(void);
|
||||||
|
@ -773,7 +776,7 @@ class NativeCodeProcedure
|
||||||
|
|
||||||
int mProgStart, mProgSize, mIndex, mFrameOffset, mStackExpand;
|
int mProgStart, mProgSize, mIndex, mFrameOffset, mStackExpand;
|
||||||
int mFastCallBase;
|
int mFastCallBase;
|
||||||
bool mNoFrame;
|
bool mNoFrame, mSimpleInline;
|
||||||
int mTempBlocks;
|
int mTempBlocks;
|
||||||
|
|
||||||
ExpandingArray<LinkerReference> mRelocations;
|
ExpandingArray<LinkerReference> mRelocations;
|
||||||
|
|
Loading…
Reference in New Issue