From 7d3dc493c0d960cd2032f6b52bd01df310eb2138 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 26 May 2023 20:16:19 +0200 Subject: [PATCH] Fix inter instruction cross block move --- include/string.c | 2 +- oscar64/InterCode.cpp | 45 ++++++++- oscar64/NativeCodeGenerator.cpp | 167 +++++++++++++++++++++++++++++-- oscar64/NativeCodeGenerator.h | 2 + oscar64/oscar64.cpp | 2 +- oscar64/oscar64.rc | 8 +- oscar64setup/oscar64setup.vdproj | 8 +- 7 files changed, 211 insertions(+), 23 deletions(-) diff --git a/include/string.c b/include/string.c index abfe997..2b8a731 100644 --- a/include/string.c +++ b/include/string.c @@ -227,7 +227,7 @@ void * memmove(void * dst, const void * src, int size) if (d < s) { do { - *d++ = *s++; + *d++ = *s++; } while (--sz); } else if (d > s) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 07c5c35..d20d941 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -10004,7 +10004,15 @@ int InterCodeBasicBlock::FindSameInstruction(const InterInstruction* ins) const bool InterCodeBasicBlock::CanMoveInstructionBehindBlock(int ii) const { - return CanMoveInstructionDown(ii, mInstructions.Size()); + if (CanMoveInstructionDown(ii, mInstructions.Size() - 1)) + { + InterInstruction* ins = mInstructions.Last(); + if (ins->mCode == IC_BRANCH && mInstructions[ii]->mDst.mTemp == ins->mSrc[0].mTemp) + return false; + return true; + } + else + return false; } bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii, const InterInstruction* ins) const @@ -12163,6 +12171,39 @@ bool InterCodeBasicBlock::CheckSingleBlockLimitedLoop(InterCodeBasicBlock*& pbl } } } + else if ( + mInstructions[nins - 1]->mCode == IC_BRANCH && + mInstructions[nins - 2]->mCode == IC_BINARY_OPERATOR && mInstructions[nins - 2]->mOperator == IA_ADD) + { + InterInstruction* ains = mInstructions[nins - 2]; + InterInstruction* bins = mInstructions[nins - 1]; + + if (bins->mSrc[0].mTemp == ains->mDst.mTemp && + ains->mSrc[1].mTemp == ains->mDst.mTemp && + ains->mSrc[0].mTemp < 0 && + ains->mSrc[0].mIntConst == -1) + { + int pi = pblock->mInstructions.Size() - 1; + while (pi >= 0 && pblock->mInstructions[pi]->mDst.mTemp != ains->mDst.mTemp) + pi--; + + if (pi >= 0 && pblock->mInstructions[pi]->mCode == IC_CONSTANT) + { + int i = 0; + while (i < nins - 2 && mInstructions[i]->mDst.mTemp != ains->mDst.mTemp) + i++; + if (i == nins - 2) + { + nloop = pblock->mInstructions[pi]->mConst.mIntConst; + + mLocalValueRange[ains->mDst.mTemp].LimitMin(1); + mLocalValueRange[ains->mDst.mTemp].LimitMax(pblock->mInstructions[pi]->mConst.mIntConst); + + return true; + } + } + } + } } return false; @@ -15791,7 +15832,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "strtof"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 805eec3..59b3388 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -16634,26 +16634,30 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) int sz = mIns.Size(); if (mIns[sz - 3].mType == ASMIT_STA && mIns[sz - 3].mMode == ASMIM_ZERO_PAGE && - mIns[sz - 2].mType == ASMIT_LDA && mIns[sz - 2].mMode == ASMIM_ZERO_PAGE && - mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 1].mMode == ASMIM_ZERO_PAGE && mIns[sz - 1].mAddress == mIns[sz - 3].mAddress && !(mIns[sz - 1].mLive & (LIVE_CPU_REG_A | LIVE_MEM))) + mIns[sz - 2].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_CMP, mIns[sz - 2].mMode) && + mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 1].mMode == ASMIM_ZERO_PAGE && mIns[sz - 1].mAddress == mIns[sz - 3].mAddress && !(mIns[sz - 1].mLive & LIVE_CPU_REG_A)) { changed = true; NativeCodeBasicBlock* cblock = proc->AllocateBlock(); - cblock->Close(mBranchIns, mFalseJump, mTrueJump, mBranch); + cblock->Close(mBranchIns, mTrueJump, mFalseJump, mBranch); - mIns[sz - 1].mAddress = mIns[sz - 2].mAddress; mIns[sz - 1].mLive |= LIVE_CPU_REG_Z; - mIns[sz - 2].mType = ASMIT_NOP; mIns[sz - 2].mMode = ASMIM_IMPLIED; + mIns[sz - 3].mLive |= LIVE_CPU_REG_A; + mIns[sz - 2].mType = ASMIT_CMP; mIns[sz - 2].mLive |= LIVE_CPU_REG_Z | LIVE_CPU_REG_C; + mIns[sz - 1].mType = ASMIT_NOP; mIns[sz - 1].mMode = ASMIM_IMPLIED; + mExitRequiredRegs += CPU_REG_Z; if (mBranch == ASMIT_BCC) { - mBranch = ASMIT_BNE; - mTrueJump = cblock; + mTrueJump = mFalseJump; + mFalseJump = cblock; + cblock->mBranch = ASMIT_BNE; } else { - mBranch = ASMIT_BEQ; - mFalseJump = cblock; + mFalseJump = mTrueJump; + mTrueJump = cblock; + cblock->mBranch = ASMIT_BEQ; } } } @@ -27532,6 +27536,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc NativeCodeBasicBlock* lblock = proc->AllocateBlock(); NativeCodeBasicBlock* eblock = proc->AllocateBlock(); + NativeCodeBasicBlock* xblock = mTrueJump == this ? mFalseJump : mTrueJump; + eblock->mBranch = ASMIT_JMP; eblock->mTrueJump = mFalseJump; eblock->mFalseJump = nullptr; @@ -27543,8 +27549,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc lblock->mEntryRequiredRegs = mEntryRequiredRegs; lblock->mExitRequiredRegs = mExitRequiredRegs; - eblock->mEntryRequiredRegs = mExitRequiredRegs; - eblock->mExitRequiredRegs = mExitRequiredRegs; + eblock->mEntryRequiredRegs = xblock->mEntryRequiredRegs; + eblock->mExitRequiredRegs = xblock->mEntryRequiredRegs; mExitRequiredRegs = mEntryRequiredRegs; @@ -27920,6 +27926,27 @@ static bool IsPointerIncAddrs(NativeCodeBasicBlock* block, int reg) return changed; } +bool NativeCodeBasicBlock::Is16BitImmSum(int at, int& val, int& reg) const +{ + if (at + 6 < mIns.Size()) + { + if (mIns[at + 0].mType == ASMIT_CLC && + mIns[at + 1].mType == ASMIT_LDA && mIns[at + 1].mMode == ASMIM_ZERO_PAGE && + mIns[at + 2].mType == ASMIT_ADC && mIns[at + 2].mMode == ASMIM_IMMEDIATE && + mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE && mIns[at + 3].mAddress == mIns[at + 1].mAddress && + mIns[at + 4].mType == ASMIT_LDA && mIns[at + 4].mMode == ASMIM_ZERO_PAGE && mIns[at + 4].mAddress == mIns[at + 1].mAddress + 1 && + mIns[at + 5].mType == ASMIT_ADC && mIns[at + 5].mMode == ASMIM_IMMEDIATE && + mIns[at + 6].mType == ASMIT_STA && mIns[at + 6].mMode == ASMIM_ZERO_PAGE && mIns[at + 6].mAddress == mIns[at + 4].mAddress) + { + reg = mIns[at + 1].mAddress; + val = mIns[at + 2].mAddress + 256 * mIns[at + 5].mAddress; + return true; + } + } + + return false; +} + bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock* prevBlock, NativeCodeBasicBlock* exitBlock, bool full) { @@ -27932,6 +27959,14 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc CheckLive(); + if (!exitBlock) + { + if (mTrueJump == this) + exitBlock = mFalseJump; + else + exitBlock = mTrueJump; + } + int sz = mIns.Size(); if (sz == 2 && (mBranch == ASMIT_BEQ || mBranch == ASMIT_BNE) && mIns[0].mType == ASMIT_LDA && mIns[1].mType == ASMIT_CMP && !(mIns[1].mFlags & NCIF_VOLATILE) && !(mIns[1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) @@ -29004,6 +29039,116 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc } #endif + + if (mIns.Size() > 0 && (mIns.Last().mType == ASMIT_DEX || mIns.Last().mType == ASMIT_DEC || mIns.Last().mType == ASMIT_CPX)) + { + bool yzero = false; + + if (prevBlock) + yzero = prevBlock->RetrieveYValue(prevBlock->mIns.Size() - 1) == 0; + + int nregs = 0; + int iregs[32]; + + for (int i = 0; i + 3 < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_IMMEDIATE && mIns[i].mAddress == 0) + yzero = true; + else if (mIns[i].ChangesYReg()) + { + nregs = 0; + break; + } + + if (mIns[i].mMode == ASMIM_INDIRECT_Y) + { + if (!yzero) + { + nregs = 0; + break; + } + + int reg = mIns[i].mAddress; + + if (ReferencesZeroPage(mIns[i].mAddress, 0, i) || + ReferencesZeroPage(mIns[i].mAddress + 1, 0, i)) + { + nregs = 0; + break; + } + if (exitBlock->mEntryRequiredRegs[reg] || exitBlock->mEntryRequiredRegs[reg + 1] || exitBlock->mEntryRequiredRegs[CPU_REG_Y]) + { + nregs = 0; + break; + } + + int j = i + 1; + while (j < mIns.Size() && ( + mIns[j].mMode == ASMIM_INDIRECT || + !(mIns[j].ReferencesZeroPage(reg) || mIns[j].ReferencesZeroPage(reg + 1)))) + j++; + + if (j == mIns.Size()) + { + nregs = 0; + break; + } + + int sreg, dreg, offset; + if (Is16BitAddSubImmediate(j - 1, sreg, dreg, offset) && sreg == reg && dreg == sreg && offset == 1) + { + if (ReferencesZeroPage(reg, j + 6) || ReferencesZeroPage(reg + 1, j + 6)) + { + nregs = 0; + break; + } + iregs[nregs++] = sreg; + } + else + { + nregs = 0; + break; + } + } + } + + if (nregs) + { + if (!prevBlock) + return OptimizeSimpleLoopInvariant(proc, full); + + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].mMode == ASMIM_ZERO_PAGE) + { + int j = 0; + while (j < nregs && iregs[j] != mIns[i].mAddress && iregs[j] + 1 != mIns[i].mAddress) + j++; + if (j < nregs) + { + mIns[i].mType = ASMIT_NOP; + mIns[i].mMode = ASMIM_IMPLIED; + } + } + else if (mIns[i].mType == ASMIT_LDY) + { + mIns[i].mType = ASMIT_NOP; + mIns[i].mMode = ASMIM_IMPLIED; + } + + mIns[i].mLive |= LIVE_CPU_REG_Y; + } + int j = mIns.Size(); + while (j > 0 && (mIns[j - 1].mLive & LIVE_CPU_REG_Z)) + j--; + mIns.Insert(j, NativeCodeInstruction(mIns[0].mIns, ASMIT_INY)); + prevBlock->mIns.Push(NativeCodeInstruction(mIns[0].mIns, ASMIT_LDY, ASMIM_IMMEDIATE, 0)); + + changed = true; + } + } + + CheckLive(); return changed; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 7b7f01e..820de71 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -478,6 +478,8 @@ public: bool BypassRegisterConditionBlock(void); bool FoldLoopEntry(void); + bool Is16BitImmSum(int at, int & val, int& reg) const; + bool Check16BitSum(int at, NativeRegisterSum16Info& info); bool Propagate16BitSum(const ExpandingArray& cinfo); diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index e9018fb..03663ef 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.19.201"); + strcpy(strProductVersion, "1.19.202"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index 4c05dde..7e9de7d 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,19,201,0 - PRODUCTVERSION 1,19,201,0 + FILEVERSION 1,19,202,0 + PRODUCTVERSION 1,19,202,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.19.201.0" + VALUE "FileVersion", "1.19.202.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.19.201.0" + VALUE "ProductVersion", "1.19.202.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index e247e65..c02c7db 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -5233,15 +5233,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{AED61249-4A7B-4472-9783-1F5014AC87EF}" - "PackageCode" = "8:{99957648-E168-4853-BA75-AA7B61A0AE71}" + "ProductCode" = "8:{121C9EAF-FA66-4A4C-9CBB-B9CAC3B869C7}" + "PackageCode" = "8:{249C96D2-72FE-4889-8F29-99C7507EC96D}" "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.19.201" + "ProductVersion" = "8:1.19.202" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:" @@ -5755,7 +5755,7 @@ { "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_FB2E467BC172457785F4279BB0BFE8B6" { - "SourcePath" = "8:..\\Debug\\oscar64.exe" + "SourcePath" = "8:..\\Release\\oscar64.exe" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"