Optimize cross block XY register usage

This commit is contained in:
drmortalwombat 2023-02-02 20:10:35 +01:00
parent d15fd8a451
commit 932a65be8c
6 changed files with 718 additions and 20 deletions

View File

@ -8523,7 +8523,7 @@ void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArra
else if (li0->mCode == IC_CONSTANT && li1->mCode == IC_LEA) else if (li0->mCode == IC_CONSTANT && li1->mCode == IC_LEA)
{ {
InterInstruction* ai0 = ltvalue[li1->mSrc[0].mTemp], * ai1 = ltvalue[li1->mSrc[1].mTemp]; InterInstruction* ai0 = ltvalue[li1->mSrc[0].mTemp], * ai1 = ltvalue[li1->mSrc[1].mTemp];
if (ai0 && ai1 && ai0->mCode == IC_CONSTANT && ai0->mConst.mIntConst >= 0) if (ai0 && ai1 && ai0->mCode == IC_CONSTANT)// && ai0->mConst.mIntConst >= 0)
{ {
InterInstruction* cai = new InterInstruction(ins->mLocation, IC_CONSTANT); InterInstruction* cai = new InterInstruction(ins->mLocation, IC_CONSTANT);
cai->mDst.mTemp = spareTemps++; cai->mDst.mTemp = spareTemps++;

View File

@ -126,6 +126,17 @@ void NativeRegisterDataSet::ResetZeroPage(int addr)
} }
} }
int NativeRegisterDataSet::FindAbsolute(LinkerObject* linkerObject, int addr)
{
for (int i = 0; i < 256; i++)
{
if (mRegs[i].mMode == NRDM_ABSOLUTE && mRegs[i].mLinkerObject == linkerObject && mRegs[i].mValue == addr)
return i;
}
return -1;
}
void NativeRegisterDataSet::ResetAbsolute(LinkerObject* linkerObject, int addr) void NativeRegisterDataSet::ResetAbsolute(LinkerObject* linkerObject, int addr)
{ {
for (int i = 0; i < NUM_REGS; i++) for (int i = 0; i < NUM_REGS; i++)
@ -1198,6 +1209,28 @@ bool NativeCodeInstruction::UsesZeroPage(int address) const
return false; return false;
} }
else if (mType == ASMIT_RTS)
{
if (mFlags & NCIF_LOWER)
{
if (address == BC_REG_ACCU + 0)
return true;
if (mFlags & NCIF_UPPER)
{
if (address == BC_REG_ACCU + 1)
return true;
if (mFlags & NCIF_LONG)
{
if (address == BC_REG_ACCU + 2 || address == BC_REG_ACCU + 3)
return true;
}
}
}
return false;
}
else else
return false; return false;
} }
@ -3203,6 +3236,21 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
changed = true; changed = true;
} }
#endif #endif
#if 1
if (mMode == ASMIM_ABSOLUTE && final && !(mFlags & NCIF_VOLATILE) && !ChangesAddress() && HasAsmInstructionMode(mType, ASMIM_ZERO_PAGE))
{
int i = data.FindAbsolute(mLinkerObject, mAddress);
if (i >= 0)
{
mMode = ASMIM_ZERO_PAGE;
mAddress = i;
mLinkerObject = nullptr;
changed = true;
}
}
#endif
if (mMode == ASMIM_ZERO_PAGE) if (mMode == ASMIM_ZERO_PAGE)
{ {
switch (mType) switch (mType)
@ -3434,7 +3482,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
mAddress = data.mRegs[mAddress].mValue; mAddress = data.mRegs[mAddress].mValue;
changed = true; changed = true;
} }
else if (data.mRegs[mAddress].mMode == NRDM_ABSOLUTE) else if (data.mRegs[mAddress].mMode == NRDM_ABSOLUTE && !final)
{ {
mMode = ASMIM_ABSOLUTE; mMode = ASMIM_ABSOLUTE;
mLinkerObject = data.mRegs[mAddress].mLinkerObject; mLinkerObject = data.mRegs[mAddress].mLinkerObject;
@ -13930,6 +13978,8 @@ bool NativeCodeBasicBlock::SimplifyDiamond(NativeCodeProcedure* proc)
{ {
if (!mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump && mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1 && mTrueJump->mTrueJump->mNumEntries == 2) if (!mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump && mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1 && mTrueJump->mTrueJump->mNumEntries == 2)
{ {
NativeCodeBasicBlock* mblock = mTrueJump->mTrueJump;
if (mTrueJump->mIns.Size() == 1 && mFalseJump->mIns.Size() == 1 && if (mTrueJump->mIns.Size() == 1 && mFalseJump->mIns.Size() == 1 &&
mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE) mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE)
{ {
@ -13976,6 +14026,15 @@ bool NativeCodeBasicBlock::SimplifyDiamond(NativeCodeProcedure* proc)
} }
} }
} }
if (mblock->mIns.Size() > 0 && mblock->mIns[0].mType == ASMIT_STX && !(mblock->mIns[0].mLive & LIVE_CPU_REG_X) &&
!mTrueJump->ChangesXReg() && !mFalseJump->ChangesXReg())
{
mIns.Push(mblock->mIns[0]);
mblock->mIns.Remove(0);
mIns[mIns.Size() - 1].mLive |= LIVE_CPU_REG_X;
changed = true;
}
} }
#if 1 #if 1
if (mTrueJump->mEntryRequiredRegs[CPU_REG_Y] && !mFalseJump->mEntryRequiredRegs[CPU_REG_Y] && !mTrueJump->mEntryRequiredRegs[CPU_REG_Z] && mTrueJump->mNumEntries == 1) if (mTrueJump->mEntryRequiredRegs[CPU_REG_Y] && !mFalseJump->mEntryRequiredRegs[CPU_REG_Y] && !mTrueJump->mEntryRequiredRegs[CPU_REG_Z] && mTrueJump->mNumEntries == 1)
@ -14777,6 +14836,34 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
mBranch = ASMIT_BCC; mBranch = ASMIT_BCC;
break; break;
} }
else if (mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0xff &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 2]) &&
HasAsmInstructionMode(ASMIT_DEC, mIns[i + 2].mMode) &&
!(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
{
changed = true;
NativeCodeBasicBlock* iblock = proc->AllocateBlock();
NativeCodeBasicBlock* fblock = proc->AllocateBlock();
fblock->mTrueJump = mTrueJump;
fblock->mFalseJump = mFalseJump;
fblock->mBranch = mBranch;
for (int j = i + 3; j < mIns.Size(); j++)
fblock->mIns.Push(mIns[j]);
iblock->mIns.Push(mIns[i + 2]);
mIns.SetSize(i);
iblock->mIns[0].mType = ASMIT_DEC;
iblock->mTrueJump = fblock;
iblock->mBranch = ASMIT_JMP;
mTrueJump = fblock;
mFalseJump = iblock;
mBranch = ASMIT_BCS;
break;
}
else if (mIns[i + 0].mType == ASMIT_TXA && else if (mIns[i + 0].mType == ASMIT_TXA &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 &&
mIns[i + 2].mType == ASMIT_TAX && mIns[i + 2].mType == ASMIT_TAX &&
@ -18417,6 +18504,578 @@ bool NativeCodeBasicBlock::PatchForwardSumYPointer(const NativeCodeBasicBlock* b
} }
bool NativeCodeBasicBlock::CrossBlockXYFlood(NativeCodeProcedure* proc)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
for (int i = 0; i < mIns.Size(); i++)
{
if ((mIns[i].mType == ASMIT_STA || mIns[i].mType == ASMIT_STX || mIns[i].mType == ASMIT_STY) && mIns[i].mMode == ASMIM_ZERO_PAGE && !(mIns[i].mLive & LIVE_CPU_REG_Z))
{
proc->ResetPatched();
if (mIns[i].mType != ASMIT_STY && !(mIns[i].mLive & LIVE_CPU_REG_X) &&CheckCrossBlockXFlood(this, mIns[i].mAddress, i + 1))
{
if (mIns[i].mType == ASMIT_STX)
mIns[i].mType = ASMIT_NOP;
else
mIns[i].mType = ASMIT_TAX;
mIns[i].mMode = ASMIM_IMPLIED;
mIns[i].mLive |= LIVE_CPU_REG_X;
proc->ResetPatched();
if (PatchCrossBlockXFlood(this, mIns[i].mAddress, i + 1))
{
changed = true;
}
}
else
{
proc->ResetPatched();
if (mIns[i].mType != ASMIT_STX && !(mIns[i].mLive & LIVE_CPU_REG_Y) && CheckCrossBlockYFlood(this, mIns[i].mAddress, i + 1))
{
if (mIns[i].mType == ASMIT_STY)
mIns[i].mType = ASMIT_NOP;
else
mIns[i].mType = ASMIT_TAY;
mIns[i].mMode = ASMIM_IMPLIED;
mIns[i].mLive |= LIVE_CPU_REG_Y;
proc->ResetPatched();
if (PatchCrossBlockYFlood(this, mIns[i].mAddress, i + 1))
{
changed = true;
}
}
}
}
}
if (mTrueJump && mTrueJump->CrossBlockXYFlood(proc))
changed = true;
if (mFalseJump && mFalseJump->CrossBlockXYFlood(proc))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::CheckCrossBlockXFlood(const NativeCodeBasicBlock* block, int reg, int at)
{
if (at == 0 && this == block)
return false;
if (!mPatched)
{
mPatched = true;
if (at == 0)
{
if (!mEntryRequiredRegs[reg])
return true;
if (mNumEntries > 1)
{
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->CheckCrossBlockXFloodExit(block, reg))
return false;
}
}
while (at < mIns.Size())
{
NativeCodeInstruction& ins(mIns[at]);
if (ins.mMode == ASMIM_INDIRECT_Y && (ins.mAddress == reg || ins.mAddress == reg + 1))
return false;
else if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.mType == ASMIT_LDA)
{
if (!(ins.mLive & LIVE_MEM))
return true;
}
else if (ins.mType == ASMIT_INC || ins.mType == ASMIT_DEC)
{
}
else if (ins.mType == ASMIT_LDX)
{
return !(ins.mLive & (LIVE_MEM | LIVE_CPU_REG_Z));
}
else if (ins.mType == ASMIT_INC || ins.mType == ASMIT_DEC)
{
}
else
return false;
}
else if (ins.ChangesXReg() || ins.RequiresXReg() || ins.ChangesZeroPage(reg) || ins.ReferencesZeroPage(reg))
return false;
at++;
}
mPatchExit = true;
if (mTrueJump && !mTrueJump->CheckCrossBlockXFlood(block, reg, 0))
return false;
if (mFalseJump && !mFalseJump->CheckCrossBlockXFlood(block, reg, 0))
return false;
}
return true;
}
bool NativeCodeBasicBlock::CheckCrossBlockXFloodExit(const NativeCodeBasicBlock* block, int reg)
{
if (!mPatchExit)
{
mPatchExit = true;
if (mTrueJump && !mTrueJump->CheckCrossBlockXFlood(block, reg, 0))
return false;
if (mFalseJump && !mFalseJump->CheckCrossBlockXFlood(block, reg, 0))
return false;
int at = mIns.Size() - 1;
while (at >= 0)
{
NativeCodeInstruction& ins(mIns[at]);
if (ins.mMode == ASMIM_INDIRECT_Y && (ins.mAddress == reg || ins.mAddress == reg + 1))
return false;
else if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.mType == ASMIT_LDA)
{
}
else if (ins.mType == ASMIT_INC || ins.mType == ASMIT_DEC)
{
}
else if (ins.mType == ASMIT_STA || ins.mType == ASMIT_STX)
{
return !(ins.mLive & LIVE_CPU_REG_Z);
}
else
return false;
}
else if (ins.ChangesXReg() || ins.RequiresXReg() || ins.ChangesZeroPage(reg) || ins.ReferencesZeroPage(reg))
return false;
at--;
}
mPatched = true;
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->CheckCrossBlockXFloodExit(block, reg))
return false;
}
return true;
}
bool NativeCodeBasicBlock::PatchCrossBlockXFloodExit(const NativeCodeBasicBlock* block, int reg)
{
bool changed = false;
if (!mPatchExit)
{
mPatchExit = true;
mExitRequiredRegs += CPU_REG_X;
if (mTrueJump && mTrueJump->PatchCrossBlockXFlood(block, reg, 0))
changed = true;
if (mFalseJump && mFalseJump->PatchCrossBlockXFlood(block, reg, 0))
changed = true;
int at = mIns.Size() - 1;
while (at >= 0)
{
NativeCodeInstruction& ins(mIns[at]);
ins.mLive |= LIVE_CPU_REG_X;
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.mType == ASMIT_LDA)
{
ins.mType = ASMIT_TXA;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_INC)
{
ins.mType = ASMIT_INX;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_DEC)
{
ins.mType = ASMIT_DEX;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_STA)
{
ins.mType = ASMIT_TAX;
ins.mMode = ASMIM_IMPLIED;
return true;
}
else if (ins.mType == ASMIT_STX)
{
ins.mType = ASMIT_NOP;
ins.mMode = ASMIM_IMPLIED;
return true;
}
}
at--;
}
mPatched = true;
mEntryRequiredRegs += CPU_REG_X;
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (mEntryBlocks[i]->PatchCrossBlockXFloodExit(block, reg))
changed = true;
return changed;
}
return false;
}
bool NativeCodeBasicBlock::PatchCrossBlockXFlood(const NativeCodeBasicBlock* block, int reg, int at)
{
bool changed = false;
if (!mPatched)
{
mPatched = true;
if (at == 0)
{
if (!mEntryRequiredRegs[reg])
return false;
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (mEntryBlocks[i]->PatchCrossBlockXFloodExit(block, reg))
changed = true;
mEntryRequiredRegs += CPU_REG_X;
}
while (at < mIns.Size())
{
NativeCodeInstruction& ins(mIns[at]);
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.mType == ASMIT_LDA)
{
ins.mType = ASMIT_TXA;
ins.mMode = ASMIM_IMPLIED;
if (!(ins.mLive & LIVE_MEM))
return true;
changed = true;
}
else if (ins.mType == ASMIT_INC)
{
ins.mType = ASMIT_INX;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_DEC)
{
ins.mType = ASMIT_DEX;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_LDX)
{
ins.mType = ASMIT_NOP;
return true;
}
}
ins.mLive |= LIVE_CPU_REG_X;
at++;
}
mPatchExit = true;
mExitRequiredRegs |= CPU_REG_X;
if (mTrueJump && mTrueJump->PatchCrossBlockXFlood(block, reg, 0))
changed = true;
if (mFalseJump && mFalseJump->PatchCrossBlockXFlood(block, reg, 0))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::CheckCrossBlockYFlood(const NativeCodeBasicBlock* block, int reg, int at)
{
if (at == 0 && this == block)
return false;
if (!mPatched)
{
mPatched = true;
if (at == 0)
{
if (!mEntryRequiredRegs[reg])
return true;
if (mNumEntries > 1)
{
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->CheckCrossBlockYFloodExit(block, reg))
return false;
}
}
while (at < mIns.Size())
{
NativeCodeInstruction& ins(mIns[at]);
if (ins.mMode == ASMIM_INDIRECT_Y && (ins.mAddress == reg || ins.mAddress == reg + 1))
return false;
else if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.mType == ASMIT_LDA)
{
if (!(ins.mLive & LIVE_MEM))
return true;
}
else if (ins.mType == ASMIT_INC || ins.mType == ASMIT_DEC)
{
}
else if (ins.mType == ASMIT_LDY)
{
return !(ins.mLive & (LIVE_MEM | LIVE_CPU_REG_Z));
}
else if (ins.mType == ASMIT_INC || ins.mType == ASMIT_DEC)
{
}
else
return false;
}
else if (ins.ChangesYReg() || ins.RequiresYReg() || ins.ChangesZeroPage(reg) || ins.ReferencesZeroPage(reg))
return false;
at++;
}
mPatchExit = true;
if (mTrueJump && !mTrueJump->CheckCrossBlockYFlood(block, reg, 0))
return false;
if (mFalseJump && !mFalseJump->CheckCrossBlockYFlood(block, reg, 0))
return false;
}
return true;
}
bool NativeCodeBasicBlock::CheckCrossBlockYFloodExit(const NativeCodeBasicBlock* block, int reg)
{
if (!mPatchExit)
{
mPatchExit = true;
if (mTrueJump && !mTrueJump->CheckCrossBlockYFlood(block, reg, 0))
return false;
if (mFalseJump && !mFalseJump->CheckCrossBlockYFlood(block, reg, 0))
return false;
int at = mIns.Size() - 1;
while (at >= 0)
{
NativeCodeInstruction& ins(mIns[at]);
if (ins.mMode == ASMIM_INDIRECT_Y && (ins.mAddress == reg || ins.mAddress == reg + 1))
return false;
else if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.mType == ASMIT_LDA)
{
}
else if (ins.mType == ASMIT_INC || ins.mType == ASMIT_DEC)
{
}
else if (ins.mType == ASMIT_STA || ins.mType == ASMIT_STY)
{
return !(ins.mLive & LIVE_CPU_REG_Z);
}
else
return false;
}
else if (ins.ChangesYReg() || ins.RequiresYReg() || ins.ChangesZeroPage(reg) || ins.ReferencesZeroPage(reg))
return false;
at--;
}
mPatched = true;
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->CheckCrossBlockYFloodExit(block, reg))
return false;
}
return true;
}
bool NativeCodeBasicBlock::PatchCrossBlockYFloodExit(const NativeCodeBasicBlock* block, int reg)
{
bool changed = false;
if (!mPatchExit)
{
mPatchExit = true;
mExitRequiredRegs += CPU_REG_Y;
if (mTrueJump && mTrueJump->PatchCrossBlockYFlood(block, reg, 0))
changed = true;
if (mFalseJump && mFalseJump->PatchCrossBlockYFlood(block, reg, 0))
changed = true;
int at = mIns.Size() - 1;
while (at >= 0)
{
NativeCodeInstruction& ins(mIns[at]);
ins.mLive |= LIVE_CPU_REG_Y;
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.mType == ASMIT_LDA)
{
ins.mType = ASMIT_TYA;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_INC)
{
ins.mType = ASMIT_INY;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_DEC)
{
ins.mType = ASMIT_DEY;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_STA)
{
ins.mType = ASMIT_TAY;
ins.mMode = ASMIM_IMPLIED;
return true;
}
else if (ins.mType == ASMIT_STY)
{
ins.mType = ASMIT_NOP;
ins.mMode = ASMIM_IMPLIED;
return true;
}
}
at--;
}
mPatched = true;
mEntryRequiredRegs += CPU_REG_Y;
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (mEntryBlocks[i]->PatchCrossBlockYFloodExit(block, reg))
changed = true;
return changed;
}
return false;
}
bool NativeCodeBasicBlock::PatchCrossBlockYFlood(const NativeCodeBasicBlock* block, int reg, int at)
{
bool changed = false;
if (!mPatched)
{
mPatched = true;
if (at == 0)
{
if (!mEntryRequiredRegs[reg])
return false;
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (mEntryBlocks[i]->PatchCrossBlockYFloodExit(block, reg))
changed = true;
mEntryRequiredRegs += CPU_REG_Y;
}
while (at < mIns.Size())
{
NativeCodeInstruction& ins(mIns[at]);
if (ins.mMode == ASMIM_ZERO_PAGE && ins.mAddress == reg)
{
if (ins.mType == ASMIT_LDA)
{
ins.mType = ASMIT_TYA;
ins.mMode = ASMIM_IMPLIED;
if (!(ins.mLive & LIVE_MEM))
return true;
changed = true;
}
else if (ins.mType == ASMIT_INC)
{
ins.mType = ASMIT_INY;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_DEC)
{
ins.mType = ASMIT_DEY;
ins.mMode = ASMIM_IMPLIED;
changed = true;
}
else if (ins.mType == ASMIT_LDY)
{
ins.mType = ASMIT_NOP;
return true;
}
}
ins.mLive |= LIVE_CPU_REG_Y;
at++;
}
mPatchExit = true;
mExitRequiredRegs |= CPU_REG_Y;
if (mTrueJump && mTrueJump->PatchCrossBlockYFlood(block, reg, 0))
changed = true;
if (mFalseJump && mFalseJump->PatchCrossBlockYFlood(block, reg, 0))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::IsDominatedBy(const NativeCodeBasicBlock* block) const bool NativeCodeBasicBlock::IsDominatedBy(const NativeCodeBasicBlock* block) const
{ {
@ -22580,7 +23239,7 @@ bool NativeCodeBasicBlock::BitFieldForwarding(const NativeRegisterDataSet& data)
return changed; return changed;
} }
bool NativeCodeBasicBlock::GlobalValueForwarding(void) bool NativeCodeBasicBlock::GlobalValueForwarding(bool final)
{ {
bool changed = false; bool changed = false;
@ -22610,16 +23269,16 @@ bool NativeCodeBasicBlock::GlobalValueForwarding(void)
{ {
AsmInsType carryop; AsmInsType carryop;
if (mIns[i].ValueForwarding(mDataSet, carryop, true, false)) if (mIns[i].ValueForwarding(mDataSet, carryop, true, final))
changed = true; changed = true;
if (carryop != ASMIT_NOP) if (carryop != ASMIT_NOP)
mIns.Insert(i + 1, NativeCodeInstruction(carryop)); mIns.Insert(i + 1, NativeCodeInstruction(carryop));
} }
if (this->mTrueJump && this->mTrueJump->GlobalValueForwarding()) if (this->mTrueJump && this->mTrueJump->GlobalValueForwarding(final))
changed = true; changed = true;
if (this->mFalseJump && this->mFalseJump->GlobalValueForwarding()) if (this->mFalseJump && this->mFalseJump->GlobalValueForwarding(final))
changed = true; changed = true;
} }
@ -30720,6 +31379,21 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 2].mLive |= LIVE_CPU_REG_A; mIns[i + 2].mLive |= LIVE_CPU_REG_A;
progress = true; progress = true;
} }
else if (
mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].mType == ASMIT_SEC &&
mIns[i + 2].mType == ASMIT_LDA && !mIns[i + 2].SameEffectiveAddress(mIns[i + 0]) &&
mIns[i + 3].mType == ASMIT_SBC && mIns[i + 3].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 3].mLive & LIVE_MEM))
{
mIns[i + 0].mType = ASMIT_EOR;
mIns[i + 0].mMode = ASMIM_IMMEDIATE;
mIns[i + 0].mAddress = 0xff;
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mLive |= LIVE_CPU_REG_A;
mIns[i + 2].mType = ASMIT_ADC;
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
progress = true;
}
else if ( else if (
mIns[i + 0].mType == ASMIT_CLC && mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress < 4 && mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress < 4 &&
@ -31487,7 +32161,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
if (mFalseJump) if (mFalseJump)
mFalseJump->CheckLive(); mFalseJump->CheckLive();
#if 1 #if 1
if (i + 1 < mIns.Size()) if (pass < 7 && i + 1 < mIns.Size())
{ {
if ( if (
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ABSOLUTE_X || mIns[i + 0].mMode == ASMIM_ABSOLUTE_Y || mIns[i + 0].mMode == ASMIM_INDIRECT_Y) && mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ABSOLUTE_X || mIns[i + 0].mMode == ASMIM_ABSOLUTE_Y || mIns[i + 0].mMode == ASMIM_INDIRECT_Y) &&
@ -33797,7 +34471,7 @@ void NativeCodeProcedure::RebuildEntry(void)
void NativeCodeProcedure::Optimize(void) void NativeCodeProcedure::Optimize(void)
{ {
CheckFunc = !strcmp(mInterProc->mIdent->mString, "missile_animate"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "heapcheck");
#if 1 #if 1
int step = 0; int step = 0;
@ -33903,7 +34577,7 @@ void NativeCodeProcedure::Optimize(void)
if (step > 1) if (step > 1)
{ {
ResetVisited(); ResetVisited();
if (mEntryBlock->GlobalValueForwarding()) if (mEntryBlock->GlobalValueForwarding(step == 7))
changed = true; changed = true;
} }
#endif #endif
@ -34289,6 +34963,15 @@ void NativeCodeProcedure::Optimize(void)
changed = true; changed = true;
} }
#if 1
if (step == 7)
{
ResetVisited();
if (mEntryBlock->CrossBlockXYFlood(this))
changed = true;
}
#endif
#if 1 #if 1
if (step >= 6) if (step >= 6)
{ {
@ -34369,7 +35052,7 @@ void NativeCodeProcedure::Optimize(void)
mEntryBlock->CheckVisited(); mEntryBlock->CheckVisited();
ResetVisited(); ResetVisited();
if (mEntryBlock->GlobalValueForwarding()) if (mEntryBlock->GlobalValueForwarding(true))
changed = true; changed = true;
#endif #endif
} }
@ -34468,6 +35151,7 @@ void NativeCodeProcedure::ResetPatched(void)
mBlocks[i]->mPatchStart = false; mBlocks[i]->mPatchStart = false;
mBlocks[i]->mPatchLoop = false; mBlocks[i]->mPatchLoop = false;
mBlocks[i]->mPatchLoopChanged = false; mBlocks[i]->mPatchLoopChanged = false;
mBlocks[i]->mPatchExit = false;
} }
} }

View File

@ -46,6 +46,7 @@ struct NativeRegisterDataSet
void ResetZeroPage(int addr); void ResetZeroPage(int addr);
void ResetAbsolute(LinkerObject * linkerObject, int addr); void ResetAbsolute(LinkerObject * linkerObject, int addr);
int FindAbsolute(LinkerObject* linkerObject, int addr);
void ResetIndirect(int reg); void ResetIndirect(int reg);
void ResetX(void); void ResetX(void);
void ResetY(void); void ResetY(void);
@ -177,7 +178,7 @@ public:
GrowingArray<NativeCodeBasicBlock*> mEntryBlocks; GrowingArray<NativeCodeBasicBlock*> mEntryBlocks;
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset, mTemp; int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset, mTemp;
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched, mPatchFail, mPatchChecked, mPatchStart, mPatchLoop, mPatchLoopChanged; bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched, mPatchFail, mPatchChecked, mPatchStart, mPatchLoop, mPatchLoopChanged, mPatchExit;
bool mEntryRegA, mEntryRegX, mEntryRegY, mExitRegA, mExitRegX; bool mEntryRegA, mEntryRegX, mEntryRegY, mExitRegA, mExitRegX;
NativeCodeBasicBlock * mDominator, * mSameBlock; NativeCodeBasicBlock * mDominator, * mSameBlock;
@ -386,7 +387,7 @@ public:
bool ReverseReplaceTAX(int at); bool ReverseReplaceTAX(int at);
bool ValueForwarding(const NativeRegisterDataSet& data, bool global, bool final); bool ValueForwarding(const NativeRegisterDataSet& data, bool global, bool final);
bool GlobalValueForwarding(void); bool GlobalValueForwarding(bool final);
bool BitFieldForwarding(const NativeRegisterDataSet& data); bool BitFieldForwarding(const NativeRegisterDataSet& data);
bool ReverseBitfieldForwarding(void); bool ReverseBitfieldForwarding(void);
@ -501,11 +502,24 @@ public:
bool CheckForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, const NativeCodeInstruction & iins, int at, int yval); bool CheckForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, const NativeCodeInstruction & iins, int at, int yval);
bool PatchForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, const NativeCodeInstruction & iins, int at, int yval); bool PatchForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, const NativeCodeInstruction & iins, int at, int yval);
bool CrossBlockXYFlood(NativeCodeProcedure * proc);
bool CheckCrossBlockXFlood(const NativeCodeBasicBlock* block, int reg, int at);
bool CheckCrossBlockXFloodExit(const NativeCodeBasicBlock* block, int reg);
bool PatchCrossBlockXFlood(const NativeCodeBasicBlock* block, int reg, int at);
bool PatchCrossBlockXFloodExit(const NativeCodeBasicBlock* block, int reg);
bool CheckCrossBlockYFlood(const NativeCodeBasicBlock* block, int reg, int at);
bool CheckCrossBlockYFloodExit(const NativeCodeBasicBlock* block, int reg);
bool PatchCrossBlockYFlood(const NativeCodeBasicBlock* block, int reg, int at);
bool PatchCrossBlockYFloodExit(const NativeCodeBasicBlock* block, int reg);
bool IsDominatedBy(const NativeCodeBasicBlock* block) const; bool IsDominatedBy(const NativeCodeBasicBlock* block) const;
void CheckLive(void); void CheckLive(void);
void CheckBlocks(bool sequence = false); void CheckBlocks(bool sequence = false);
void CheckVisited(void); void CheckVisited(void);
}; };
class NativeCodeProcedure class NativeCodeProcedure

View File

@ -74,7 +74,7 @@ int main2(int argc, const char** argv)
#else #else
strcpy(strProductName, "oscar64"); strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.15.182"); strcpy(strProductVersion, "1.15.183");
#ifdef __APPLE__ #ifdef __APPLE__
uint32_t length = sizeof(basePath); uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,15,182,0 FILEVERSION 1,15,183,0
PRODUCTVERSION 1,15,182,0 PRODUCTVERSION 1,15,183,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "oscar64" VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler" VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.15.182.0" VALUE "FileVersion", "1.15.183.0"
VALUE "InternalName", "oscar64.exe" VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe" VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64" VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.15.182.0" VALUE "ProductVersion", "1.15.183.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -4554,15 +4554,15 @@
{ {
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64" "ProductName" = "8:oscar64"
"ProductCode" = "8:{D9D7E97A-B793-4546-B204-9518010E2DB9}" "ProductCode" = "8:{0316346F-2B7D-478A-BD0C-8AAF6E0371EA}"
"PackageCode" = "8:{40E0B5C5-53B2-4285-802B-FBA08B4E661D}" "PackageCode" = "8:{BAD074A9-2FC1-4FF7-B987-B330F1B645A2}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0" "AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE" "RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE" "InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.15.182" "ProductVersion" = "8:1.15.183"
"Manufacturer" = "8:oscar64" "Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:" "ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:" "ARPHELPLINK" = "8:"