Improve zero page variable usage

This commit is contained in:
drmortalwombat 2024-04-08 22:04:50 +02:00
parent 7b20e6cca0
commit fefa462730
7 changed files with 212 additions and 51 deletions

View File

@ -239,7 +239,7 @@ int iec_write_bytes(const char * data, int num)
int iec_read_bytes(char * data, int num) int iec_read_bytes(char * data, int num)
{ {
char i = 0; int i = 0;
while (i < num) while (i < num)
{ {
char ch = iec_read(); char ch = iec_read();

View File

@ -21199,6 +21199,7 @@ void InterCodeProcedure::Close(void)
if (var && !var->mTemp && !var->mLinkerObject) if (var && !var->mTemp && !var->mLinkerObject)
{ {
var->mLinkerObject = mModule->mLinker->AddObject(mLocation, var->mIdent, mLinkerObject->mStackSection, LOT_BSS); var->mLinkerObject = mModule->mLinker->AddObject(mLocation, var->mIdent, mLinkerObject->mStackSection, LOT_BSS);
var->mLinkerObject->mVariable = var;
var->mLinkerObject->mFlags |= LOBJF_LOCAL_VAR; var->mLinkerObject->mFlags |= LOBJF_LOCAL_VAR;
var->mLinkerObject->AddSpace(var->mSize); var->mLinkerObject->AddSpace(var->mSize);
var->mIndex = mModule->mGlobalVars.Size(); var->mIndex = mModule->mGlobalVars.Size();

View File

@ -665,6 +665,7 @@ void InterCodeGenerator::InitGlobalVariable(InterCodeModule * mod, Declaration*
var->mOffset = 0; var->mOffset = 0;
var->mSize = dec->mSize; var->mSize = dec->mSize;
var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment); var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment);
var->mLinkerObject->mVariable = var;
var->mIdent = dec->mQualIdent; var->mIdent = dec->mQualIdent;
Declaration* decb = dec->mBase; Declaration* decb = dec->mBase;
@ -2082,6 +2083,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
var->mOffset = 0; var->mOffset = 0;
var->mSize = dec->mSize; var->mSize = dec->mSize;
var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment); var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment);
var->mLinkerObject->mVariable = var;
if (dec->mBase->mFlags & DTF_CONST) if (dec->mBase->mFlags & DTF_CONST)
var->mLinkerObject->mFlags |= LOBJF_CONST; var->mLinkerObject->mFlags |= LOBJF_CONST;
@ -2120,6 +2122,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (dec->mFlags & DTF_VAR_ALIASING) if (dec->mFlags & DTF_VAR_ALIASING)
var->mAliased = true; var->mAliased = true;
var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment); var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment);
var->mLinkerObject->mVariable = var;
dec->mLinkerObject = var->mLinkerObject; dec->mLinkerObject = var->mLinkerObject;
var->mIdent = dec->mQualIdent; var->mIdent = dec->mQualIdent;
dec->mVarIndex = proc->mModule->mGlobalVars.Size(); dec->mVarIndex = proc->mModule->mGlobalVars.Size();
@ -5297,6 +5300,7 @@ void InterCodeGenerator::BuildInitializer(InterCodeModule * mod, uint8* dp, int
if (dec->mFlags & DTF_VAR_ALIASING) if (dec->mFlags & DTF_VAR_ALIASING)
var->mAliased = true; var->mAliased = true;
var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment); var->mLinkerObject = mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_DATA, dec->mAlignment);
var->mLinkerObject->mVariable = var;
dec->mLinkerObject = var->mLinkerObject; dec->mLinkerObject = var->mLinkerObject;
var->mLinkerObject->AddData(dec->mData, dec->mSize); var->mLinkerObject->AddData(dec->mData, dec->mSize);
mod->mGlobalVars.Push(var); mod->mGlobalVars.Push(var);

View File

@ -359,6 +359,7 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, L
obj->mSection = section; obj->mSection = section;
obj->mRegion = nullptr; obj->mRegion = nullptr;
obj->mProc = nullptr; obj->mProc = nullptr;
obj->mVariable = nullptr;
obj->mFlags = 0; obj->mFlags = 0;
obj->mAlignment = alignment; obj->mAlignment = alignment;
section->mObjects.Push(obj); section->mObjects.Push(obj);

View File

@ -9,6 +9,7 @@
#include "CompilerTypes.h" #include "CompilerTypes.h"
class InterCodeProcedure; class InterCodeProcedure;
class InterVariable;
enum LinkerObjectType enum LinkerObjectType
{ {
@ -191,6 +192,7 @@ public:
LinkerRegion * mRegion; LinkerRegion * mRegion;
uint8 * mData, * mMemory; uint8 * mData, * mMemory;
InterCodeProcedure * mProc; InterCodeProcedure * mProc;
InterVariable * mVariable;
uint32 mFlags; uint32 mFlags;
uint8 mTemporaries[16], mTempSizes[16]; uint8 mTemporaries[16], mTempSizes[16];
int mNumTemporaries; int mNumTemporaries;

View File

@ -92,6 +92,79 @@ void NativeRegisterDataSet::ResetMask(void)
mRegs[i].ResetMask(); mRegs[i].ResetMask();
} }
void NativeRegisterDataSet::ResetCall(const NativeCodeInstruction& ins, int fastCallBase)
{
mRegs[CPU_REG_C].Reset();
mRegs[CPU_REG_Z].Reset();
mRegs[CPU_REG_A].Reset();
mRegs[CPU_REG_X].Reset();
mRegs[CPU_REG_Y].Reset();
for (int i = 0; i < NUM_REGS; i++)
{
if (mRegs[i].mMode == NRDM_ABSOLUTE ||
mRegs[i].mMode == NRDM_ABSOLUTE_X ||
mRegs[i].mMode == NRDM_ABSOLUTE_Y)
{
if (mRegs[i].mLinkerObject && mRegs[i].mLinkerObject->mVariable)
{
InterVariable* var = mRegs[i].mLinkerObject->mVariable;
if (ins.mLinkerObject && ins.mLinkerObject->mProc)
{
if (!(var->mLinkerObject->mFlags & LOBJF_LOCAL_VAR))
{
if (var->mIndex && var->mIndex < ins.mLinkerObject->mProc->mModule->mGlobalVars.Size() && var == ins.mLinkerObject->mProc->mModule->mGlobalVars[var->mIndex])
{
if (ins.mLinkerObject->mProc->ModifiesGlobal(var->mIndex))
mRegs[i].Reset();
}
else
mRegs[i].Reset();
}
}
else if (var->mAliased)
mRegs[i].Reset();
}
else
mRegs[i].Reset();
}
else if (mRegs[i].mMode == NRDM_INDIRECT_Y)
{
mRegs[i].Reset();
}
}
ResetWorkRegs();
if (!(ins.mFlags & NCIF_RUNTIME) || (ins.mFlags & NCIF_FEXEC))
{
if (ins.mLinkerObject && ins.mLinkerObject->mProc)
{
for (int i = BC_REG_TMP; i < BC_REG_TMP + ins.mLinkerObject->mProc->mCallerSavedTemps; i++)
ResetZeroPage(i);
}
else
{
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++)
ResetZeroPage(i);
}
if (ins.mLinkerObject && (ins.mLinkerObject->mFlags & LOBJF_ZEROPAGESET))
{
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS + fastCallBase; i++)
if (ins.mLinkerObject->mZeroPageSet[i])
ResetZeroPage(i);
}
else
{
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS + fastCallBase; i++)
ResetZeroPage(i);
}
}
}
void NativeRegisterDataSet::ResetWorkRegs(void) void NativeRegisterDataSet::ResetWorkRegs(void)
@ -3042,41 +3115,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
if (mType == ASMIT_JSR) if (mType == ASMIT_JSR)
{ {
data.mRegs[CPU_REG_C].Reset(); data.ResetCall(*this, fastCallBase);
data.mRegs[CPU_REG_Z].Reset();
data.mRegs[CPU_REG_A].Reset();
data.mRegs[CPU_REG_X].Reset();
data.mRegs[CPU_REG_Y].Reset();
data.ResetIndirect(0);
data.ResetWorkRegs();
if (!(mFlags & NCIF_RUNTIME) || (mFlags & NCIF_FEXEC))
{
if (mLinkerObject && mLinkerObject->mProc)
{
for (int i = BC_REG_TMP; i < BC_REG_TMP + mLinkerObject->mProc->mCallerSavedTemps; i++)
data.ResetZeroPage(i);
}
else
{
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++)
data.ResetZeroPage(i);
}
if (mLinkerObject && (mLinkerObject->mFlags & LOBJF_ZEROPAGESET))
{
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS + fastCallBase; i++)
if (mLinkerObject->mZeroPageSet[i])
data.ResetZeroPage(i);
}
else
{
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS + fastCallBase; i++)
data.ResetZeroPage(i);
}
}
return false; return false;
} }
@ -19636,7 +19675,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
} }
} }
if (mIns.Size() >= 3 && mFalseJump && (mBranch == ASMIT_BCC || mBranch == ASMIT_BCS)) if (mExitRequiredRegs.Size() > 0 && mIns.Size() >= 3 && mFalseJump && (mBranch == ASMIT_BCC || mBranch == ASMIT_BCS))
{ {
int sz = mIns.Size(); int sz = mIns.Size();
@ -21328,9 +21367,15 @@ bool NativeCodeBasicBlock::PropagateSinglePath(void)
{ {
mExitRequiredRegs += CPU_REG_A; mExitRequiredRegs += CPU_REG_A;
if (mTrueJump->mEntryRequiredRegs[CPU_REG_Y]) if (mTrueJump->mEntryRequiredRegs[CPU_REG_Y])
{
mTrueJump->mEntryRequiredRegs += CPU_REG_A;
mTrueJump->PrependInstruction(mIns[i - 1]); mTrueJump->PrependInstruction(mIns[i - 1]);
}
else else
{
mFalseJump->mEntryRequiredRegs += CPU_REG_A;
mFalseJump->PrependInstruction(mIns[i - 1]); mFalseJump->PrependInstruction(mIns[i - 1]);
}
mIns.Remove(i - 1); mIns.Remove(i - 1);
changed = true; changed = true;
} }
@ -26710,6 +26755,11 @@ void NativeCodeBasicBlock::PropagateZPAbsolute(const NativeRegisterDataSet& data
if (mLoopHead) if (mLoopHead)
{ {
if (mNumEntries == 2 && (mTrueJump == this || mFalseJump == this))
{
ResetModifiedDataSet(mDataSet);
}
else
mDataSet.Reset(); mDataSet.Reset();
} }
else if (mNumEntries > 0) else if (mNumEntries > 0)
@ -26782,7 +26832,10 @@ void NativeCodeBasicBlock::PropagateZPAbsolute(const NativeRegisterDataSet& data
else if (mIns[i].mType == ASMIT_STY && mIns[i].mMode == ASMIM_ZERO_PAGE) else if (mIns[i].mType == ASMIT_STY && mIns[i].mMode == ASMIM_ZERO_PAGE)
mDataSet.mRegs[mIns[i].mAddress] = mDataSet.mRegs[CPU_REG_Y]; mDataSet.mRegs[mIns[i].mAddress] = mDataSet.mRegs[CPU_REG_Y];
else if (mIns[i].mType == ASMIT_JSR) else if (mIns[i].mType == ASMIT_JSR)
mDataSet.Reset(); {
mDataSet.ResetCall(mIns[i], mProc->mFastCallBase);
// mDataSet.Reset();
}
else else
{ {
if (mIns[i].mMode == ASMIM_ZERO_PAGE) if (mIns[i].mMode == ASMIM_ZERO_PAGE)
@ -33200,24 +33253,49 @@ bool NativeCodeBasicBlock::OptimizeSingleEntryLoop(NativeCodeProcedure* proc)
if (mLoopHead && mEntryBlocks.Size() > 1) if (mLoopHead && mEntryBlocks.Size() > 1)
{ {
NativeCodeBasicBlock* pblock = nullptr; NativeCodeBasicBlock* pblock = nullptr;
ExpandingArray<NativeCodeBasicBlock*> lblocks; ExpandingArray<NativeCodeBasicBlock*> lblocks, pblocks;
int i = 0; bool addprefix = false;
while (i < mEntryBlocks.Size()) for(int i=0; i<mEntryBlocks.Size(); i++)
{ {
NativeCodeBasicBlock* b = mEntryBlocks[i]; NativeCodeBasicBlock* b = mEntryBlocks[i];
if (b == this || b->IsDominatedBy(this)) if (b == this || b->IsDominatedBy(this))
lblocks.Push(b); lblocks.Push(b);
else if (pblock || b->mFalseJump)
{
pblock = nullptr;
break;
}
else else
pblock = b; {
i++; if (b->mFalseJump)
addprefix = true;
pblocks.Push(b);
} }
}
if (pblocks.Size() > 1 || addprefix)
{
pblock = mProc->AllocateBlock();
pblock->mEntryRequiredRegs = mEntryRequiredRegs;
pblock->mExitRequiredRegs = mExitRequiredRegs;
pblock->Close(pblocks[0]->mBranchIns, this, nullptr, ASMIT_JMP);
AddEntryBlock(pblock);
for (int i = 0; i < pblocks.Size(); i++)
{
NativeCodeBasicBlock* b = pblocks[i];
if (this == b->mTrueJump)
{
b->mTrueJump = pblock;
RemEntryBlock(b);
pblock->AddEntryBlock(b);
}
if (this == b->mFalseJump)
{
b->mFalseJump = pblock;
RemEntryBlock(b);
pblock->AddEntryBlock(b);
}
}
}
else if (pblocks.Size() == 1)
pblock = pblocks[0];
if (pblock && lblocks.Size() + 1 == mEntryBlocks.Size()) if (pblock && lblocks.Size() + 1 == mEntryBlocks.Size())
{ {
@ -36260,6 +36338,80 @@ bool NativeCodeBasicBlock::OptimizeSingleEntryLoopInvariant(NativeCodeProcedure*
} }
} }
} }
int tz = tail->mIns.Size();
if (mIns.Size() > 0 && mIns[0].mType == ASMIT_LDY && mIns[0].mMode == ASMIM_ZERO_PAGE &&
tz > 0 && (tail->mIns[tz - 1].mType == ASMIT_INC || tail->mIns[tz - 1].mType == ASMIT_DEC) && tail->mIns[tz - 1].SameEffectiveAddress(mIns[0]))
{
if (!ChangesYReg(1) && !ReferencesZeroPage(mIns[0].mAddress, 1) &&
!tail->ChangesYReg() && !tail->ReferencesZeroPage(mIns[0].mAddress, 0, tz - 1))
{
int i = 0;
while (i < lblocks.Size() && (lblocks[i] == tail || (!lblocks[i]->ChangesYReg() && !lblocks[i]->ReferencesZeroPage(mIns[0].mAddress))))
i++;
if (i == lblocks.Size())
{
if (this == tail->mTrueJump)
{
tail->mFalseJump->mEntryRequiredRegs += CPU_REG_Y;
tail->mFalseJump->mIns.Insert(0, NativeCodeInstruction(mIns[0].mIns, ASMIT_STY, mIns[0]));
}
else
{
tail->mTrueJump->mEntryRequiredRegs += CPU_REG_Y;
tail->mTrueJump->mIns.Insert(0, NativeCodeInstruction(mIns[0].mIns, ASMIT_STY, mIns[0]));
}
if (tail->mIns[tz - 1].mType == ASMIT_INC)
tail->mIns[tz - 1].mType = ASMIT_INY;
else
tail->mIns[tz - 1].mType = ASMIT_DEY;
tail->mIns[tz - 1].mMode = ASMIM_IMPLIED;
prev->mIns.Push(mIns[0]);
mIns.Remove(0);
mEntryRequiredRegs += CPU_REG_Y;
mExitRequiredRegs += CPU_REG_Y;
prev->mExitRequiredRegs += CPU_REG_Y;
for (int i = 0; i < lblocks.Size(); i++)
{
lblocks[i]->mEntryRequiredRegs += CPU_REG_Y;
lblocks[i]->mExitRequiredRegs += CPU_REG_Y;
}
changed = true;
}
}
}
}
if (mEntryBlocks.Size() == 2)
{
if (!tail->mExitRequiredRegs[CPU_REG_X] && !mEntryRequiredRegs[CPU_REG_X])
{
int ei = tail->mIns.Size() - 1;
while (ei >= 0 && !tail->mIns[ei].ReferencesXReg())
ei--;
if (ei >= 0 && tail->mIns[ei].mType == ASMIT_STX && tail->mIns[ei].mMode == ASMIM_ZERO_PAGE)
{
int si = 0;
while (si < mIns.Size() && !mIns[si].ChangesXReg())
si++;
if (si >= 0 && mIns[si].mType == ASMIT_LDX && mIns[si].SameEffectiveAddress(tail->mIns[ei]))
{
prev->mIns.Push(mIns[si]);
mIns.Remove(si);
tail->mIns.Remove(ei);
for (int i = 0; i < si; i++)
mIns[i].mLive |= LIVE_CPU_REG_X;
for (int i = ei; i < tail->mIns.Size(); i++)
tail->mIns[i].mLive |= LIVE_CPU_REG_X;
mEntryRequiredRegs += CPU_REG_X;
tail->mExitRequiredRegs += CPU_REG_X;
changed = true;
}
}
}
} }
return changed; return changed;
@ -46234,7 +46386,7 @@ void NativeCodeBasicBlock::CheckLive(void)
#if _DEBUG #if _DEBUG
uint32 live = 0; uint32 live = 0;
if (mFalseJump && mFalseJump->mEntryRequiredRegs.Size() > 0 && mFalseJump->mEntryRequiredRegs[CPU_REG_X]) if (mFalseJump && mFalseJump->mEntryRequiredRegs.Size() > 0 && mFalseJump->mEntryRequiredRegs[CPU_REG_X] && mExitRequiredRegs.Size() > 0)
{ {
if (mFalseJump->mIns.Size() > 0 && mFalseJump->mIns[0].RequiresXReg()) if (mFalseJump->mIns.Size() > 0 && mFalseJump->mIns[0].RequiresXReg())
assert(mExitRequiredRegs[CPU_REG_X]); assert(mExitRequiredRegs[CPU_REG_X]);
@ -46977,7 +47129,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
{ {
mInterProc = proc; mInterProc = proc;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "test"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "memmove");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];

View File

@ -43,6 +43,7 @@ struct NativeRegisterDataSet
void Reset(void); void Reset(void);
void ResetMask(void); void ResetMask(void);
void ResetCall(const NativeCodeInstruction & ins, int fastCallBase);
void ResetZeroPage(int addr); void ResetZeroPage(int addr);
void ResetZeroPageRange(int addr, int num); void ResetZeroPageRange(int addr, int num);