From 2ed784ea17d03cf63a42b6b3fe9ea2639129b0cd Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 13 Nov 2021 15:05:53 +0100 Subject: [PATCH] Optimize signed range comparison --- autotest/autotest.bat | 3 + autotest/testinterval.c | 58 +++++++ oscar64/Array.h | 6 + oscar64/InterCode.cpp | 126 ++++++++++++++++ oscar64/InterCode.h | 2 + oscar64/NativeCodeGenerator.cpp | 257 +++++++++++++++++++++++++++++++- oscar64/NativeCodeGenerator.h | 2 + 7 files changed, 452 insertions(+), 2 deletions(-) create mode 100644 autotest/testinterval.c diff --git a/autotest/autotest.bat b/autotest/autotest.bat index f4063a8..b84fbf2 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -54,6 +54,9 @@ if %errorlevel% neq 0 goto :error call :test testint32cmp.c if %errorlevel% neq 0 goto :error +call :test testinterval.c +if %errorlevel% neq 0 goto :error + call :test floatstringtest.c if %errorlevel% neq 0 goto :error diff --git a/autotest/testinterval.c b/autotest/testinterval.c new file mode 100644 index 0000000..ca42f76 --- /dev/null +++ b/autotest/testinterval.c @@ -0,0 +1,58 @@ +#include + +void testint0(void) +{ + int a0n = 0, an0 = 0; + int b0n = 0, bn0 = 0; + + for(int i=-1000; i<1000; i++) + { + if (i >= 0 && i < 500) + a0n += 1; + if (i < 500 && i >= 0) + an0 += 1; + if (i >= 0 && i <= 499) + b0n += 1; + if (i <= 499 && i >= 0) + bn0 += 1; + } + + assert(a0n == 500); + assert(an0 == 500); + assert(b0n == 500); + assert(bn0 == 500); +} + +typedef signed char int8; + +void testbyte0(void) +{ + int8 a0n = 0, an0 = 0; + int8 b0n = 0, bn0 = 0; + + for(int8 i=-100; i<100; i++) + { + if (i >= 0 && i < 50) + a0n += 1; + if (i < 50 && i >= 0) + an0 += 1; + if (i >= 0 && i <= 49) + b0n += 1; + if (i <= 49 && i >= 0) + bn0 += 1; + } + + assert(a0n == 50); + assert(an0 == 50); + assert(b0n == 50); + assert(bn0 == 50); +} + +int main(void) +{ + testint0(); + testbyte0(); + + return 0; +} + diff --git a/oscar64/Array.h b/oscar64/Array.h index c2279ef..08fe5ab 100644 --- a/oscar64/Array.h +++ b/oscar64/Array.h @@ -272,6 +272,12 @@ public: int Size(void) const { return size; } + T Last() const + { + assert(size > 0); + return array[size - 1]; + } + void SetSize(int size, bool clear = false) { Grow(size, clear); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index e9bf8c3..3288a59 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -14,6 +14,11 @@ int InterTypeSize[] = { 2 }; +static bool IsIntegerType(InterType type) +{ + return type >= IT_INT8 && type <= IT_INT32; +} + ValueSet::ValueSet(void) { mSize = 32; @@ -4451,6 +4456,94 @@ bool InterCodeBasicBlock::IsEqual(const InterCodeBasicBlock* block) const return false; } +bool InterCodeBasicBlock::OptimizeIntervalCompare(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + int sz = mInstructions.Size(); + if (sz >= 2 && mTrueJump && mFalseJump && mInstructions[sz - 1]->mCode == IC_BRANCH && mInstructions[sz - 2]->mCode == IC_RELATIONAL_OPERATOR && + mInstructions[sz - 2]->mDst.mTemp == mInstructions[sz - 1]->mSrc[0].mTemp && !mExitRequiredTemps[mInstructions[sz - 1]->mSrc[0].mTemp] && + IsIntegerType(mInstructions[sz - 2]->mSrc[0].mType)) + { + if (mInstructions[sz - 2]->mOperator == IA_CMPGES && mInstructions[sz - 2]->mSrc[0].mTemp == -1) + { + if (mTrueJump->mInstructions.Size() == 2 && mTrueJump->mInstructions[1]->mCode == IC_BRANCH && mTrueJump->mFalseJump == mFalseJump && + mTrueJump->mInstructions[0]->mCode == IC_RELATIONAL_OPERATOR && mTrueJump->mInstructions[0]->mDst.mTemp == mTrueJump->mInstructions[1]->mSrc->mTemp) + { + if (mTrueJump->mInstructions[0]->mSrc[0].mTemp == -1 && mTrueJump->mInstructions[0]->mSrc[1].mTemp == mInstructions[sz - 2]->mSrc[1].mTemp) + { + if (mTrueJump->mInstructions[0]->mOperator == IA_CMPLS && mInstructions[sz - 2]->mSrc[0].mIntConst == 0 && mTrueJump->mInstructions[0]->mSrc[0].mIntConst > 0) + { + mInstructions[sz - 2]->mOperator = IA_CMPLU; + mInstructions[sz - 2]->mSrc[0].mIntConst = mTrueJump->mInstructions[0]->mSrc[0].mIntConst; + mTrueJump->mNumEntries--; + mTrueJump = mTrueJump->mTrueJump; + mTrueJump->mNumEntries++; + changed = true; + } + else if (mTrueJump->mInstructions[0]->mOperator == IA_CMPLES && mInstructions[sz - 2]->mSrc[0].mIntConst == 0 && mTrueJump->mInstructions[0]->mSrc[0].mIntConst > 0) + { + mInstructions[sz - 2]->mOperator = IA_CMPLEU; + mInstructions[sz - 2]->mSrc[0].mIntConst = mTrueJump->mInstructions[0]->mSrc[0].mIntConst; + mTrueJump->mNumEntries--; + mTrueJump = mTrueJump->mTrueJump; + mTrueJump->mNumEntries++; + changed = true; + } + } + } + } + else if (mInstructions[sz - 2]->mOperator == IA_CMPLS && mInstructions[sz - 2]->mSrc[0].mTemp == -1) + { + if (mTrueJump->mInstructions.Size() == 2 && mTrueJump->mInstructions[1]->mCode == IC_BRANCH && mTrueJump->mFalseJump == mFalseJump && + mTrueJump->mInstructions[0]->mCode == IC_RELATIONAL_OPERATOR && mTrueJump->mInstructions[0]->mDst.mTemp == mTrueJump->mInstructions[1]->mSrc->mTemp) + { + if (mTrueJump->mInstructions[0]->mSrc[0].mTemp == -1 && mTrueJump->mInstructions[0]->mSrc[1].mTemp == mInstructions[sz - 2]->mSrc[1].mTemp) + { + if (mTrueJump->mInstructions[0]->mOperator == IA_CMPGES && mInstructions[sz - 2]->mSrc[0].mIntConst > 0 && mTrueJump->mInstructions[0]->mSrc[0].mIntConst == 0) + { + mInstructions[sz - 2]->mOperator = IA_CMPLU; + mTrueJump->mNumEntries--; + mTrueJump = mTrueJump->mTrueJump; + mTrueJump->mNumEntries++; + changed = true; + } + } + } + } + else if (mInstructions[sz - 2]->mOperator == IA_CMPLES && mInstructions[sz - 2]->mSrc[0].mTemp == -1) + { + if (mTrueJump->mInstructions.Size() == 2 && mTrueJump->mInstructions[1]->mCode == IC_BRANCH && mTrueJump->mFalseJump == mFalseJump && + mTrueJump->mInstructions[0]->mCode == IC_RELATIONAL_OPERATOR && mTrueJump->mInstructions[0]->mDst.mTemp == mTrueJump->mInstructions[1]->mSrc->mTemp) + { + if (mTrueJump->mInstructions[0]->mSrc[0].mTemp == -1 && mTrueJump->mInstructions[0]->mSrc[1].mTemp == mInstructions[sz - 2]->mSrc[1].mTemp) + { + if (mTrueJump->mInstructions[0]->mOperator == IA_CMPGES && mInstructions[sz - 2]->mSrc[0].mIntConst > 0 && mTrueJump->mInstructions[0]->mSrc[0].mIntConst == 0) + { + mInstructions[sz - 2]->mOperator = IA_CMPLEU; + mTrueJump->mNumEntries--; + mTrueJump = mTrueJump->mTrueJump; + mTrueJump->mNumEntries++; + changed = true; + } + } + } + } + } + + if (mTrueJump && mTrueJump->OptimizeIntervalCompare()) + changed = true; + if (mFalseJump && mFalseJump->OptimizeIntervalCompare()) + changed = true; + } + + return changed; +} + void InterCodeBasicBlock::FollowJumps(void) { if (!mVisited) @@ -4655,6 +4748,29 @@ static bool IsCommutative(InterOperator op) { return op == IA_ADD || op == IA_MUL || op == IA_AND || op == IA_OR || op == IA_XOR; } +void InterCodeBasicBlock::CompactInstructions(void) +{ + if (!mVisited) + { + mVisited = true; + + int j = 0; + for (int i = 0; i < mInstructions.Size(); i++) + { + if (mInstructions[i]->mCode != IC_NONE) + { + mInstructions[j++] = mInstructions[i]; + } + } + mInstructions.SetSize(j); + + if (mTrueJump) + mTrueJump->CompactInstructions(); + if (mFalseJump) + mFalseJump->CompactInstructions(); + } +} + void InterCodeBasicBlock::PeepholeOptimization(void) { int i; @@ -5528,6 +5644,16 @@ void InterCodeProcedure::Close(void) BuildDominators(); DisassembleDebug("added dominators"); + ResetVisited(); + mEntryBlock->CompactInstructions(); + + BuildDataFlowSets(); + + ResetVisited(); + mEntryBlock->OptimizeIntervalCompare(); + + DisassembleDebug("interval compare"); + BuildDataFlowSets(); ResetVisited(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 4d9a6d3..786bc77 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -514,6 +514,8 @@ public: bool IsEqual(const InterCodeBasicBlock* block) const; + void CompactInstructions(void); + bool OptimizeIntervalCompare(void); }; class InterCodeModule; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index eb21a00..fa59ace 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -8057,6 +8057,37 @@ bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& bre return true; } + else if ( + mIns[j + 0].mType == ASMIT_CLC && + mIns[j + 1].mType == ASMIT_LDA && mIns[j + 1].mMode == ASMIM_ZERO_PAGE && + mIns[j + 2].mType == ASMIT_ADC && mIns[j + 2].mMode == ASMIM_ZERO_PAGE && + mIns[j + 3].mType == ASMIT_STA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == reg && + mIns[j + 4].mType == ASMIT_LDA && mIns[j + 4].mMode == ASMIM_ZERO_PAGE && mIns[j + 4].mAddress == mIns[j + 2].mAddress + 1 && + mIns[j + 5].mType == ASMIT_ADC && mIns[j + 5].mMode == ASMIM_IMMEDIATE && mIns[j + 5].mAddress == 0 && + mIns[j + 6].mType == ASMIT_STA && mIns[j + 6].mMode == ASMIM_ZERO_PAGE && mIns[j + 6].mAddress == reg + 1) + { + breg = mIns[j + 2].mAddress; + ireg = mIns[j + 1].mAddress; + + int k = j + 7; + while (k < at) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1 || mIns[k].mAddress == ireg) && mIns[k].ChangesAddress()) + return false; + if (breg == reg) + { + if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1)) + return false; + if (mIns[k].mMode == ASMIM_INDIRECT_Y && mIns[k].mAddress == breg) + return false; + } + k++; + } + + apos = j; + + return true; + } if (mIns[j + 6].mMode == ASMIM_ZERO_PAGE && (mIns[j + 6].mAddress == reg || mIns[j + 6].mAddress == reg + 1) && mIns[j + 6].ChangesAddress()) return false; @@ -8243,6 +8274,41 @@ bool NativeCodeBasicBlock::MoveLoadStoreUp(int at) return false; } +bool NativeCodeBasicBlock::MoveLoadStoreXUp(int at) +{ + int j = at; + while (j > 0 && !((mIns[j - 1].mType == ASMIT_STA || mIns[j - 1].mType == ASMIT_LDA) && mIns[j - 1].mMode == ASMIM_ZERO_PAGE && mIns[j - 1].mAddress == mIns[at].mAddress)) + { + j--; + if ((mIns[j].mMode == ASMIM_ZERO_PAGE || mIns[j].mMode == ASMIM_INDIRECT_Y) && mIns[j].mAddress == mIns[at + 1].mAddress) + return false; + if (mIns[j].mMode == ASMIM_INDIRECT_Y && mIns[j].mAddress + 1 == mIns[at + 1].mAddress) + return false; + if (mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress && mIns[j].ChangesAddress()) + return false; + if (mIns[j].mMode == ASMIM_ABSOLUTE_Y && mIns[j].mAddress <= mIns[at + 1].mAddress && mIns[j].mType == ASMIT_LDA && !mIns[j].mLinkerObject) + return false; + if (mIns[j].mType == ASMIT_JSR) + return false; + } + + if (j > 0 && j < at) + { + for (int i = at; i > j; i--) + { + mIns[i] = mIns[i - 1]; + } + mIns[j - 1].mLive |= LIVE_CPU_REG_A; + mIns[j] = mIns[at + 1]; + mIns[j].mType = ASMIT_STA; + mIns[at + 1].mType = ASMIT_NOP; + + return true; + } + + return false; +} + bool NativeCodeBasicBlock::MoveLoadAddImmStoreUp(int at) { int j = at - 1; @@ -9105,6 +9171,47 @@ void NativeCodeBasicBlock::BlockSizeReduction(void) j += 2; i += 3; } +#if 1 + else if (i + 3 < mIns.Size() && + mIns[i + 0].mType == ASMIT_ASL && mIns[i + 0].mMode == ASMIM_IMPLIED && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0 && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0xff && + mIns[i + 3].mType == ASMIT_EOR && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0xff && + !(mIns[i + 2].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + { + mIns[j + 0].mType = ASMIT_AND; mIns[j + 0].mMode = ASMIM_IMMEDIATE; mIns[j + 0].mAddress = 0x80; + mIns[j + 1].mType = ASMIT_BPL; mIns[j + 1].mMode = ASMIM_RELATIVE; mIns[j + 1].mAddress = 2; + mIns[j + 2].mType = ASMIT_LDA; mIns[j + 2].mMode = ASMIM_IMMEDIATE; mIns[j + 2].mAddress = 0xff; + j += 3; + i += 4; + } +#endif + else if (i + 3 < mIns.Size() && + mIns[i + 0].mType == ASMIT_CLC && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && + !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X))) + { + mIns[j + 0].mType = ASMIT_LDX; mIns[j + 0].mMode = ASMIM_ZERO_PAGE; mIns[j + 0].mAddress = mIns[i + 1].mAddress; + mIns[j + 1].mType = ASMIT_INX; mIns[j + 1].mMode = ASMIM_IMPLIED; + mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].mMode = ASMIM_ZERO_PAGE; mIns[j + 2].mAddress = mIns[i + 3].mAddress; + j += 3; + i += 4; + } + else if (i + 3 < mIns.Size() && + mIns[i + 0].mType == ASMIT_SEC && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && + mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && + !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z | LIVE_CPU_REG_X))) + { + mIns[j + 0].mType = ASMIT_LDX; mIns[j + 0].mMode = ASMIM_ZERO_PAGE; mIns[j + 0].mAddress = mIns[i + 1].mAddress; + mIns[j + 1].mType = ASMIT_DEX; mIns[j + 1].mMode = ASMIM_IMPLIED; + mIns[j + 2].mType = ASMIT_STX; mIns[j + 2].mMode = ASMIM_ZERO_PAGE; mIns[j + 2].mAddress = mIns[i + 3].mAddress; + j += 3; + i += 4; + } else mIns[j++] = mIns[i++]; } @@ -9245,6 +9352,19 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } #endif +#if 1 + // move load store pairs up to initial store + + for (int i = 2; i + 1 < mIns.Size(); i++) + { + if (mIns[i].mType == ASMIT_LDX && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mType == ASMIT_STX && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && (mIns[i + 1].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z)) == 0) + { + if (MoveLoadStoreXUp(i)) + changed = true; + } + } +#endif + #if 1 // move load - store (),y up to initial store // @@ -9458,6 +9578,32 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) } } + if (sz > 4 && + mIns[sz - 4].mType == ASMIT_ASL && mIns[sz - 4].mMode == ASMIM_IMPLIED && + mIns[sz - 3].mType == ASMIT_LDA && mIns[sz - 3].mMode == ASMIM_IMMEDIATE && mIns[sz - 3].mAddress == 0 && + mIns[sz - 2].mType == ASMIT_ADC && mIns[sz - 2].mMode == ASMIM_IMMEDIATE && mIns[sz - 2].mAddress == 0xff && + mIns[sz - 1].mType == ASMIT_EOR && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && mIns[sz - 1].mAddress == 0xff && !(mIns[sz - 1].mLive & LIVE_CPU_REG_A)) + { + if (mBranch == ASMIT_BEQ) + { + mBranch = ASMIT_BPL; + mIns[sz - 4] = ASMIT_NOP; + mIns[sz - 3] = ASMIT_NOP; + mIns[sz - 2] = ASMIT_NOP; + mIns[sz - 1].mType = ASMIT_ORA; mIns[sz - 1].mAddress = 0; + changed = true; + } + else if (mBranch == ASMIT_BNE) + { + mBranch = ASMIT_BMI; + mIns[sz - 4] = ASMIT_NOP; + mIns[sz - 3] = ASMIT_NOP; + mIns[sz - 2] = ASMIT_NOP; + mIns[sz - 1].mType = ASMIT_ORA; mIns[sz - 1].mAddress = 0; + changed = true; + } + } + for (int i = 0; i < mIns.Size(); i++) { #if 1 @@ -9768,6 +9914,22 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) mIns[i + 1].mType = ASMIT_NOP; progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_TXA && + mIns[i + 1].mType == ASMIT_CMP && (mIns[i + 1].mMode == ASMIM_IMMEDIATE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE)) + { + mIns[i + 1].mType = ASMIT_CPX; + mIns[i + 0].mLive |= CPU_REG_X; + progress = true; + } + else if ( + mIns[i + 0].mType == ASMIT_TYA && + mIns[i + 1].mType == ASMIT_CMP && (mIns[i + 1].mMode == ASMIM_IMMEDIATE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE)) + { + mIns[i + 1].mType = ASMIT_CPY; + mIns[i + 0].mLive |= CPU_REG_Y; + progress = true; + } #if 1 else if ( @@ -10029,6 +10191,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) mIns[i + 0].mType = ASMIT_SEC; progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_LDA && + mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_ADC) + { + mIns[i + 1] = mIns[i + 0]; + mIns[i + 0].mType = ASMIT_CLC; + mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 0].mLive |= LIVE_CPU_REG_C; + mIns[i + 1].mLive |= LIVE_CPU_REG_C; + progress = true; + } else if ( mIns[i + 0].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_TYA && @@ -10044,6 +10218,16 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) mIns[i + 2].mType = ASMIT_TYA; mIns[i + 2].mMode = ASMIM_IMPLIED; progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_STA && + mIns[i + 2].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 2]) && + !mIns[i + 1].ChangesAddress() && !mIns[i + 1].ChangesGlobalMemory() && + !mIns[i + 1].ChangesYReg() && !mIns[i + 1].ChangesXReg()) + { + mIns[i + 0].mType = ASMIT_NOP; + mIns[i + 0].mMode = ASMIM_IMPLIED; + progress = true; + } #if 1 else if ( @@ -10133,6 +10317,28 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) mIns[i + 3].mType = ASMIT_DEC; progress = true; } + else if (mIns[i + 1].mType == ASMIT_LDA && mIns[i + 3].mType == ASMIT_STA && mIns[i + 1].SameEffectiveAddress(mIns[i + 3]) && + mIns[i + 0].mType == ASMIT_CLC && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) && + (mIns[i + 3].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_A)) == 0) + { + mIns[i + 0].mType = ASMIT_NOP; + mIns[i + 1].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 3].mType = ASMIT_INC; + progress = true; + } + else if (mIns[i + 1].mType == ASMIT_LDA && mIns[i + 3].mType == ASMIT_STA && mIns[i + 1].SameEffectiveAddress(mIns[i + 3]) && + mIns[i + 0].mType == ASMIT_SEC && mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 1 && + (mIns[i + 1].mMode == ASMIM_ABSOLUTE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) && + (mIns[i + 3].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_A)) == 0) + { + mIns[i + 0].mType = ASMIT_NOP; + mIns[i + 1].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 3].mType = ASMIT_DEC; + progress = true; + } else if (mIns[i + 0].mType == ASMIT_LDA && mIns[i + 3].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 3]) && mIns[i + 1].mType == ASMIT_CLC && mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && (mIns[i + 2].mAddress & 0xff) == 0xff && (mIns[i + 0].mMode == ASMIM_ABSOLUTE || mIns[i + 0].mMode == ASMIM_ZERO_PAGE) && @@ -10254,10 +10460,25 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) mIns[i + 3].mFlags = mIns[i + 0].mFlags; progress = true; } -#if 0 +#if 1 + else if ( + mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && + mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && mIns[i + 1].mAddress == 0xff && + mIns[i + 2].mType == ASMIT_EOR && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0xff && + mIns[i + 3].mType == ASMIT_LSR && mIns[i + 3].mMode == ASMIM_IMPLIED && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) + { + mIns[i + 0].mType = ASMIT_NOP; + mIns[i + 1].mType = ASMIT_NOP; + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 3].mType = ASMIT_NOP; + progress = true; + } +#endif + +#if 1 if ( mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && - mIns[i + 1].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_INDIRECT_Y && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && !mIns[i + 2].ChangesYReg() && (mIns[i + 2].mMode == ASMIM_IMMEDIATE || mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress != mIns[i + 1].mAddress) && mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_INDIRECT_Y && mIns[i + 1].mAddress == mIns[i + 3].mAddress && !(mIns[i + 3].mLive & LIVE_MEM)) { @@ -10303,6 +10524,38 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass) mIns[i + 2].mAddress = mIns[i + 0].mAddress; progress = true; } +#if 1 + else if ( + mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && + mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && + !mIns[i + 2].ChangesYReg() && (mIns[i + 2].mMode == ASMIM_IMMEDIATE || mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 2].mAddress != mIns[i + 1].mAddress) && + !mIns[i + 3].ChangesYReg() && (mIns[i + 3].mMode == ASMIM_IMMEDIATE || mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress != mIns[i + 1].mAddress) && + mIns[i + 4].mType == ASMIT_STA && mIns[i + 4].mMode == ASMIM_INDIRECT_Y && mIns[i + 1].mAddress == mIns[i + 4].mAddress && !(mIns[i + 4].mLive & LIVE_MEM)) + { + int apos, breg, ireg; + if (FindAddressSumY(i, mIns[i + 1].mAddress, apos, breg, ireg)) + { + if (breg == mIns[i + 1].mAddress) + { + mIns[apos + 3].mType = ASMIT_NOP; + mIns[apos + 3].mMode = ASMIM_IMPLIED; + mIns[apos + 6].mType = ASMIT_NOP; + mIns[apos + 6].mMode = ASMIM_IMPLIED; + } + if (mIns[i + 4].mLive & LIVE_CPU_REG_Y) + { + mIns.Insert(i + 5, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0)); + mIns[i + 5].mLive |= LIVE_CPU_REG_Y; + } + mIns[i + 0].mMode = ASMIM_ZERO_PAGE; + mIns[i + 0].mAddress = ireg; + mIns[i + 1].mAddress = breg; + mIns[i + 4].mAddress = breg; + progress = true; + } + } + +#endif } #if 1 diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 50260ef..12e4b90 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -174,6 +174,8 @@ public: void MarkLoopHead(void); bool MoveLoadStoreUp(int at); + bool MoveLoadStoreXUp(int at); + bool MoveIndirectLoadStoreUp(int at); bool MoveAbsoluteLoadStoreUp(int at); bool MoveLoadAddImmStoreUp(int at);