Propagate x and y across block boundaries

This commit is contained in:
drmortalwombat 2022-06-02 22:19:10 +02:00
parent 1b8e1f4048
commit 0ba2ddf195
5 changed files with 212 additions and 23 deletions

View File

@ -6161,6 +6161,43 @@ void NativeCodeBasicBlock::ShiftRegisterLeft(InterCodeProcedure* proc, int reg,
}
}
void NativeCodeBasicBlock::ShiftRegisterLeftFromByte(InterCodeProcedure* proc, int reg, int shift, int max)
{
if (shift == 0)
{
}
else if (shift == 1)
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
if (max >= 128)
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, reg));
while (shift > 0 && max < 256)
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
shift--;
max *= 2;
}
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
if (max > 255)
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
while (shift > 0)
{
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
shift--;
}
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
}
void NativeCodeBasicBlock::ShiftRegisterLeftByte(InterCodeProcedure* proc, int reg, int shift)
{
if (shift == 0)
@ -6244,6 +6281,8 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, dreg + 1));
}
else if (ins->mSrc[index].IsUByte())
ShiftRegisterLeftFromByte(proc, dreg, lshift, ins->mSrc[index].mRange.mMaxValue);
else
ShiftRegisterLeft(proc, dreg, lshift);
return dreg;
@ -10958,18 +10997,28 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == yreg &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == yoffset + 2 &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
!(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_C)))
!(mIns[i + 3].mLive & (LIVE_CPU_REG_Y | LIVE_CPU_REG_C)))
{
for (int j = ypred; j < i + 3; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_INY;
mIns[i + 1].mType = ASMIT_INY; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
mIns[i + 3].mType = ASMIT_STY;
mIns[i + 2].mType = ASMIT_STY; mIns[i + 2].CopyMode(mIns[i + 3]);
ypred = i + 1;
yoffset++;
if (mIns[i + 3].mLive & LIVE_CPU_REG_A)
{
mIns[i + 3].mType = ASMIT_TYA;
mIns[i + 3].mMode = ASMIM_IMPLIED;
}
else
{
mIns[i + 3].mType = ASMIT_NOP;
mIns[i + 3].mMode = ASMIM_IMPLIED;
}
changed = true;
}
else if (i + 1 < mIns.Size() &&
@ -12559,6 +12608,33 @@ bool NativeCodeBasicBlock::SameTail(const NativeCodeInstruction& ins) const
return false;
}
bool NativeCodeBasicBlock::HasTailSTA(int& addr, int& index) const
{
int i = mIns.Size();
while (i > 0)
{
i--;
if (mIns[i].ChangesAccu())
return false;
if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE)
{
index = i;
addr = mIns[i].mAddress;
i++;
while (i < mIns.Size())
{
if (mIns[i].ReferencesZeroPage(addr))
return false;
i++;
}
return true;
}
}
return false;
}
void NativeCodeBasicBlock::AddEntryBlock(NativeCodeBasicBlock* block)
{
int i = 0;
@ -12682,6 +12758,32 @@ bool NativeCodeBasicBlock::PropagateSinglePath(void)
CheckLive();
#if 1
if (mTrueJump && mFalseJump && mTrueJump->mEntryProvidedRegs.Size() && mFalseJump->mEntryRequiredRegs.Size())
{
if (mTrueJump->mEntryRequiredRegs[CPU_REG_X] && !mFalseJump->mEntryRequiredRegs[CPU_REG_X] && mTrueJump->mNumEntries == 1 && !mTrueJump->mEntryRequiredRegs[CPU_REG_Z]||
mFalseJump->mEntryRequiredRegs[CPU_REG_X] && !mTrueJump->mEntryRequiredRegs[CPU_REG_X] && mFalseJump->mNumEntries == 1 && !mFalseJump->mEntryRequiredRegs[CPU_REG_Z])
{
int i = mIns.Size();
while (i > 0 && !mIns[i - 1].ReferencesXReg())
i--;
if (i > 0 && mIns[i - 1].mType == ASMIT_LDX && !(mIns[i - 1].mLive & LIVE_CPU_REG_Z))
{
if (mIns[i - 1].mMode == ASMIM_IMMEDIATE || (mIns[i - 1].mMode == ASMIM_ZERO_PAGE && !ChangedOnPath(this, i, mIns.Size(), mIns[i - 1].mAddress)))
{
if (mTrueJump->mEntryRequiredRegs[CPU_REG_X])
mTrueJump->mIns.Insert(0, mIns[i - 1]);
else
mFalseJump->mIns.Insert(0, mIns[i - 1]);
mIns.Remove(i - 1);
changed = true;
}
}
}
}
#endif
if (mTrueJump && mFalseJump && mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1)
{
int i = 0;
@ -12810,7 +12912,31 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
changed = true;
}
else
{
int addr, index, taddr, tindex;
if (eb->HasTailSTA(addr, index))
{
i = 1;
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->HasTailSTA(taddr, tindex) && taddr == addr)
i++;
if (i == mEntryBlocks.Size())
{
mIns.Insert(0, eb->mIns[index]);
mIns[0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_Y;
for (int i = 0; i < mEntryBlocks.Size(); i++)
{
NativeCodeBasicBlock* b = mEntryBlocks[i];
b->HasTailSTA(taddr, tindex);
for (int j = tindex + 1; j < b->mIns.Size(); j++)
b->mIns[j].mLive |= LIVE_CPU_REG_A;
b->mIns.Remove(tindex);
}
changed = true;
}
}
break;
}
}
}
@ -21027,7 +21153,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 1].mType == ASMIT_ROR && mIns[i + 1].mMode == ASMIM_IMPLIED &&
mIns[i + 2].mType == ASMIT_AND && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0x80 && !(mIns[i + 2].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
{
@ -21105,7 +21231,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
{
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mLive |= LIVE_CPU_REG_A;
mIns[i + 2].mType = ASMIT_STA;
mIns[i + 2].mType = ASMIT_STA;
progress = true;
}
else if (
@ -21115,7 +21241,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
{
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mLive |= LIVE_CPU_REG_A;
mIns[i + 2].mType = ASMIT_STA;
mIns[i + 2].mType = ASMIT_STA;
progress = true;
}
else if (
@ -21203,7 +21329,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
{
mIns[i + 0].mType = ASMIT_LDY; mIns[i + 0].mLive |= LIVE_CPU_REG_Y;
mIns[i + 1].mType = ASMIT_INY; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_Y;
mIns[i + 2].mType = ASMIT_STY;
mIns[i + 2].mType = ASMIT_STY;
progress = true;
}
else if (
@ -21227,7 +21353,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & LIVE_CPU_REG_A) &&
mIns[i + 2].mType == ASMIT_CPX && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == mIns[i + 2].mAddress && !(mIns[i + 2].mLive & LIVE_MEM))
{
@ -21241,7 +21367,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
}
else if (
mIns[i + 0].mType == ASMIT_LDA && !mIns[i + 0].RequiresXReg() &&
mIns[i + 1].mType == ASMIT_LDX &&
mIns[i + 1].mType == ASMIT_LDX &&
mIns[i + 2].mType == ASMIT_STX && !(mIns[i + 2].mLive & LIVE_CPU_REG_X) && !mIns[i + 0].MayBeChangedOnAddress(mIns[i + 2]))
{
NativeCodeInstruction ins = mIns[i + 0];
@ -21383,7 +21509,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
}
else if (
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) &&
mIns[i + 1].mType == ASMIT_TAX &&
mIns[i + 1].mType == ASMIT_TAX &&
mIns[i + 2].mType == ASMIT_STA && (mIns[i + 2].mMode == ASMIM_ZERO_PAGE || mIns[i + 2].mMode == ASMIM_ABSOLUTE) &&
!(mIns[i + 2].mLive & LIVE_CPU_REG_A))
{
@ -21394,7 +21520,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
}
else if (
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) &&
mIns[i + 1].mType == ASMIT_TAY &&
mIns[i + 1].mType == ASMIT_TAY &&
mIns[i + 2].mType == ASMIT_STA && (mIns[i + 2].mMode == ASMIM_ZERO_PAGE || mIns[i + 2].mMode == ASMIM_ABSOLUTE) &&
!(mIns[i + 2].mLive & LIVE_CPU_REG_A))
{
@ -21403,6 +21529,46 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 2].mType = ASMIT_STY;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDX && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) &&
(mIns[i + 1].mType == ASMIT_INX || mIns[i + 1].mType == ASMIT_DEX) &&
mIns[i + 2].mType == ASMIT_STX && mIns[i + 2].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 2].mLive & LIVE_CPU_REG_X))
{
mIns[i + 2].mType = mIns[i + 1].mType == ASMIT_INX ? ASMIT_INC : ASMIT_DEC;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDY && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) &&
(mIns[i + 1].mType == ASMIT_INY || mIns[i + 1].mType == ASMIT_DEY) &&
mIns[i + 2].mType == ASMIT_STY && mIns[i + 2].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 2].mLive & LIVE_CPU_REG_Y))
{
mIns[i + 2].mType = mIns[i + 1].mType == ASMIT_INY ? ASMIT_INC : ASMIT_DEC;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDX &&
mIns[i + 1].mType == ASMIT_TXA &&
mIns[i + 2].mType == ASMIT_CPX && !(mIns[i + 2].mLive & LIVE_CPU_REG_X))
{
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_CMP;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDY &&
mIns[i + 1].mType == ASMIT_TYA &&
mIns[i + 2].mType == ASMIT_CPY && !(mIns[i + 2].mLive & LIVE_CPU_REG_Y))
{
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_CMP;
progress = true;
}
if (
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress <= 1 &&
@ -22119,7 +22285,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE &&
mIns[i + 3].mType == ASMIT_EOR && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0xff && !(mIns[i + 3].mLive & LIVE_CPU_REG_C))
{
int val = mIns[i + 2].mAddress;
int val = mIns[i + 2].mAddress;
mIns[i + 0].mType = ASMIT_SEC;
mIns[i + 2].CopyMode(mIns[i + 1]);
@ -22130,6 +22296,23 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LSR && mIns[i + 0].mMode == ASMIM_IMPLIED &&
mIns[i + 1].mType == ASMIT_EOR && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0x40 &&
mIns[i + 2].mType == ASMIT_SEC &&
mIns[i + 3].mType == ASMIT_SBC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0x40 && !(mIns[i + 3].mLive & LIVE_CPU_REG_C))
{
mIns[i + 0].mType = ASMIT_CMP;
mIns[i + 0].mMode = ASMIM_IMMEDIATE;
mIns[i + 0].mAddress = 0x80;
mIns[i + 0].mLive |= LIVE_CPU_REG_C;
mIns[i + 1].mType = ASMIT_ROR;
mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
progress = true;
}
#if 1
else if (
mIns[i + 0].mType == ASMIT_LDX && mIns[i + 0].mMode == ASMIM_ABSOLUTE_Y &&
@ -22482,10 +22665,14 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
{
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 + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE)
{
int n = 3;
if (mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))
n--;
proc->ResetPatched();
if (CheckSingleUseGlobalLoad(this, mIns[i + 1].mAddress, i + 2, mIns[i], 3))
if (CheckSingleUseGlobalLoad(this, mIns[i + 1].mAddress, i + 2, mIns[i], n))
{
proc->ResetPatched();
if (PatchSingleUseGlobalLoad(this, mIns[i + 1].mAddress, i + 2, mIns[i]))
@ -24251,7 +24438,7 @@ void NativeCodeProcedure::Optimize(void)
}
#endif
#if 1
if (step > 2)
if (step > 2 && !changed)
{
ResetVisited();
if (mEntryBlock->JoinTailCodeSequences(this, step > 3))

View File

@ -222,6 +222,7 @@ public:
void ShiftRegisterLeft(InterCodeProcedure* proc, int reg, int shift);
void ShiftRegisterLeftByte(InterCodeProcedure* proc, int reg, int shift);
void ShiftRegisterLeftFromByte(InterCodeProcedure* proc, int reg, int shift, int max);
int ShortMultiply(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins, int index, int mul);
bool CheckPredAccuStore(int reg);
@ -314,6 +315,7 @@ public:
NativeCodeBasicBlock* AddDominatorBlock(NativeCodeProcedure* proc, NativeCodeBasicBlock* pblock);
bool JoinTailCodeSequences(NativeCodeProcedure* proc, bool loops);
bool SameTail(const NativeCodeInstruction& ins) const;
bool HasTailSTA(int& addr, int& index) const;
bool PropagateSinglePath(void);
NativeRegisterDataSet mEntryRegisterDataSet;

View File

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

View File

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

View File

@ -4127,15 +4127,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{A0EA5973-AD76-484C-B67E-4289D67E95D6}"
"PackageCode" = "8:{06EA7EB2-B913-4F30-8E87-E092699B4F9A}"
"ProductCode" = "8:{46C39DF3-C3FA-4E28-9728-9F27246FC4D8}"
"PackageCode" = "8:{02BA08A4-074F-42A1-B22E-C06F2E0184FA}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.7.132"
"ProductVersion" = "8:1.7.133"
"Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"