From 0309fcb2860e3191c888a7e5582bfa13299cabc9 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 20 Nov 2023 08:29:23 +0100 Subject: [PATCH] Fixed copy with offset --- include/conio.h | 1 - oscar64/GlobalOptimizer.cpp | 12 ++- oscar64/InterCode.cpp | 129 ++++++++++++++++++++++++++++++-- oscar64/InterCode.h | 2 + oscar64/NativeCodeGenerator.cpp | 115 +++++++++++++++++++++------- 5 files changed, 223 insertions(+), 36 deletions(-) diff --git a/include/conio.h b/include/conio.h index 32968e8..62a51ad 100644 --- a/include/conio.h +++ b/include/conio.h @@ -41,7 +41,6 @@ void dispmode80col(void); #define PETSCII_F7 0x88 #define PETSCII_F8 0x8c - int kbhit(void); int getche(void); diff --git a/oscar64/GlobalOptimizer.cpp b/oscar64/GlobalOptimizer.cpp index 87f027f..1b55005 100644 --- a/oscar64/GlobalOptimizer.cpp +++ b/oscar64/GlobalOptimizer.cpp @@ -604,8 +604,16 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin return exp->mDecValue; case EX_INITIALIZATION: case EX_ASSIGNMENT: - ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags); - rdec = Analyze(exp->mRight, procDec, ANAFL_RHS); + if (exp->mToken == TK_ASSIGN) + ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags); + else + ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS | flags); + + if (exp->mLeft->mDecType->IsReference()) + rdec = Analyze(exp->mRight, procDec, ANAFL_LHS | ANAFL_RHS); + else + rdec = Analyze(exp->mRight, procDec, ANAFL_RHS); + RegisterProc(rdec); return ldec; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index aa011c6..51509e9 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -9446,6 +9446,76 @@ static bool IsValidSignedIntRange(InterType t, int64 value) } } +bool InterCodeBasicBlock::ForwardShortLoadStoreOffsets(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i < mInstructions.Size(); i++) + { + InterInstruction* lins = mInstructions[i]; + if (lins->mCode == IC_LEA && lins->mSrc[1].mTemp >= 0 && lins->mSrc[0].mTemp < 0 && lins->mSrc[0].IsUByte()) + { + for (int j = i + 1; j < mInstructions.Size(); j++) + { + InterInstruction* lins2 = mInstructions[j]; + if (lins2->mCode == IC_LEA && lins2->mSrc[1].mTemp == lins->mDst.mTemp && lins2->mSrc[0].mTemp >= 0) + { + int k = j + 1; + while (k < mInstructions.Size() && !mInstructions[k]->ReferencesTemp(lins2->mDst.mTemp) && !mInstructions[k]->ReferencesTemp(lins->mSrc[1].mTemp)) + k++; + if (k < mInstructions.Size()) + { + InterInstruction* mins = mInstructions[k]; + if (mins->mCode == IC_LOAD && mins->mSrc[0].mTemp == lins2->mDst.mTemp && mins->mSrc[0].mFinal) + { + lins2->mSrc[1].mTemp = lins->mSrc[1].mTemp; + lins->mSrc[1].mFinal = false; + mins->mSrc[0].mIntConst += lins->mSrc[0].mIntConst; + changed = true; + } + else if (mins->mCode == IC_STORE && mins->mSrc[1].mTemp == lins2->mDst.mTemp && mins->mSrc[1].mFinal) + { + lins2->mSrc[1].mTemp = lins->mSrc[1].mTemp; + lins->mSrc[1].mFinal = false; + mins->mSrc[1].mIntConst += lins->mSrc[0].mIntConst; + changed = true; + } + else if (mins->mCode == IC_COPY && mins->mSrc[0].mTemp == lins2->mDst.mTemp && mins->mSrc[0].mFinal) + { + lins2->mSrc[1].mTemp = lins->mSrc[1].mTemp; + lins->mSrc[1].mFinal = false; + mins->mSrc[0].mIntConst += lins->mSrc[0].mIntConst; + changed = true; + } + else if (mins->mCode == IC_COPY && mins->mSrc[1].mTemp == lins2->mDst.mTemp && mins->mSrc[1].mFinal) + { + lins2->mSrc[1].mTemp = lins->mSrc[1].mTemp; + lins->mSrc[1].mFinal = false; + mins->mSrc[1].mIntConst += lins->mSrc[0].mIntConst; + changed = true; + } + } + } + + if (lins2->mDst.mTemp == lins->mDst.mTemp) + break; + } + } + } + + if (mTrueJump && mTrueJump->ForwardShortLoadStoreOffsets()) + changed = true; + if (mFalseJump && mFalseJump->ForwardShortLoadStoreOffsets()) + changed = true; + } + + return changed; +} + bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps) { bool changed = false; @@ -16375,7 +16445,6 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 0]->mCode = IC_NONE; mInstructions[i + 0]->mNumOperands = 0; changed = true; } - } @@ -18525,7 +18594,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "interpret_builtin"); + CheckFunc = !strcmp(mIdent->mString, "test"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -19273,6 +19342,12 @@ void InterCodeProcedure::Close(void) CombineIndirectAddressing(); + BuildDataFlowSets(); + ResetVisited(); + mEntryBlock->ForwardShortLoadStoreOffsets(); + + DisassembleDebug("ForwardShortLoadStoreOffsets"); + #if 1 for (int i = 0; i < 8; i++) { @@ -19613,21 +19688,47 @@ void InterCodeProcedure::MapVariables(void) } } +static bool IsReadModifyWrite(const InterCodeBasicBlock* block, int at) +{ + if (block->mInstructions[at]->mCode == IC_LOAD && + block->mInstructions[at + 2]->mCode == IC_STORE && + block->mInstructions[at + 1]->mDst.mTemp == block->mInstructions[at + 2]->mSrc[0].mTemp && + block->mInstructions[at]->mSrc[0].IsEqual(block->mInstructions[at + 2]->mSrc[1])) + { + if (block->mInstructions[at + 1]->mCode == IC_BINARY_OPERATOR) + { + return + block->mInstructions[at + 1]->mSrc[0].mTemp == block->mInstructions[at]->mDst.mTemp || + block->mInstructions[at + 1]->mSrc[1].mTemp == block->mInstructions[at]->mDst.mTemp; + } + else if (block->mInstructions[at + 1]->mCode == IC_UNARY_OPERATOR) + { + return + block->mInstructions[at + 1]->mSrc[0].mTemp == block->mInstructions[at]->mDst.mTemp; + } + } + + return false; +} + bool InterCodeBasicBlock::SameExitCode(const InterCodeBasicBlock* block) const { - if (mInstructions.Size() > 1 && block->mInstructions.Size() > 1) + int sz0 = mInstructions.Size(); + int sz1 = block->mInstructions.Size(); + + if (sz0 > 1 && sz1 > 1) { - InterInstruction* ins0 = mInstructions[mInstructions.Size() - 2]; - InterInstruction* ins1 = block->mInstructions[block->mInstructions.Size() - 2]; + InterInstruction* ins0 = mInstructions[sz0 - 2]; + InterInstruction* ins1 = block->mInstructions[sz1 - 2]; if (ins0->IsEqual(ins1)) { if (ins0->mCode == IC_STORE && ins0->mSrc[1].mTemp >= 0) { - int j0 = mInstructions.Size() - 3; + int j0 = sz0 - 3; while (j0 >= 0 && mInstructions[j0]->mDst.mTemp != ins0->mSrc[1].mTemp) j0--; - int j1 = block->mInstructions.Size() - 3; + int j1 = sz1 - 3; while (j1 >= 0 && block->mInstructions[j1]->mDst.mTemp != ins0->mSrc[1].mTemp) j1--; @@ -19641,6 +19742,20 @@ bool InterCodeBasicBlock::SameExitCode(const InterCodeBasicBlock* block) const return false; } } + + if (InterTypeSize[ins0->mSrc[0].mType] == 4) + { + bool rm0 = sz0 >= 4 && IsReadModifyWrite(this, sz0 - 4); + bool rm1 = sz1 >= 4 && IsReadModifyWrite(block, sz1 - 4); + + if (rm0 && rm1) + { + if (!(mInstructions[sz0 - 3]->IsEqual(block->mInstructions[sz1 - 3]))) + return false; + } + else if (rm0 || rm1) + return false; + } } else if (ins0->mCode == IC_LOAD && ins0->mSrc[0].mTemp >= 0) { diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 27f7c8b..0d56e25 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -484,6 +484,8 @@ public: bool SimplifyPointerOffsets(void); bool EliminateAliasValues(const GrowingInstructionPtrArray& tvalue, const GrowingInstructionPtrArray& avalue); + bool ForwardShortLoadStoreOffsets(void); + void CalculateSingleUsedTemps(FastNumberSet& fused, FastNumberSet& fsingle); bool CalculateSingleAssignmentTemps(FastNumberSet& tassigned, GrowingInstructionPtrArray& tvalue, NumberSet& modifiedParams, InterMemory paramMemory); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 42b9c98..f74c204 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -5934,7 +5934,7 @@ void NativeCodeBasicBlock::StoreByteIndexedValue(InterCodeProcedure* proc, const void NativeCodeBasicBlock::LoadAbsoluteByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* rins) { mIns.Push(NativeCodeInstruction(iins, ASMIT_LDX, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[iins->mSrc[0].mTemp])); - int address = iins->mSrc[1].mIntConst + rins->mSrc[0].mIntConst; + int address = int(iins->mSrc[1].mIntConst + rins->mSrc[0].mIntConst); uint32 flags = NCIF_LOWER | NCIF_UPPER; if (rins->mVolatile) @@ -5950,7 +5950,7 @@ void NativeCodeBasicBlock::LoadAbsoluteByteIndexedValue(InterCodeProcedure* proc void NativeCodeBasicBlock::StoreAbsoluteByteIndexedValue(InterCodeProcedure* proc, const InterInstruction* iins, const InterInstruction* wins) { mIns.Push(NativeCodeInstruction(iins, ASMIT_LDX, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[iins->mSrc[0].mTemp])); - int address = iins->mSrc[1].mIntConst + wins->mSrc[1].mIntConst; + int address = int(iins->mSrc[1].mIntConst + wins->mSrc[1].mIntConst); uint32 flags = NCIF_LOWER | NCIF_UPPER; if (wins->mVolatile) @@ -7037,7 +7037,7 @@ void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterI for (int i = 0; i < size; i++) { - CheckFrameIndex(ins, areg, index, i * stride); + CheckFrameIndex(ins, areg, index, 1); if (reg == areg) accu = true; @@ -7287,7 +7287,7 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, #endif int sreg, dreg; - + int si = 0, di = 0; if (ins->mSrc[0].mTemp < 0) { @@ -7330,14 +7330,22 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, else if (ins->mSrc[0].mIntConst != 0) { int index = int(ins->mSrc[0].mIntConst); - mIns.Push(NativeCodeInstruction(ins, ASMIT_CLC, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); - mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, index & 0xff)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); - sreg = BC_REG_ACCU; + if (size <= msize && (size - 1) * sstride + 1 + index <= 256) + { + si = index; + sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; + } + else + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_CLC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp])); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, index & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); + sreg = BC_REG_ACCU; + } } else if (size * sstride > 256 && !ins->mSrc[0].mFinal) { @@ -7406,14 +7414,22 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, else if (ins->mSrc[1].mIntConst != 0) { int index = int(ins->mSrc[1].mIntConst); - mIns.Push(NativeCodeInstruction(ins, ASMIT_CLC, ASMIM_IMPLIED)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); - mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, index & 0xff)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ADDR)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ADDR + 1)); - dreg = BC_REG_ADDR; + if (size <= msize && (size - 1) * dstride + 1 + index <= 256) + { + di = index; + dreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; + } + else + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_CLC, ASMIM_IMPLIED)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp])); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, index & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ADDR)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_ADDR + 1)); + dreg = BC_REG_ADDR; + } } else if (size * dstride > 256 && !ins->mSrc[1].mFinal) { @@ -7430,8 +7446,6 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc, if (size <= msize) { - int si = 0; - int di = 0; for (int i = 0; i < size; i++) { mIns.Push(NativeCodeInstruction(ins, ASMIT_LDY, ASMIM_IMMEDIATE, si)); @@ -16670,6 +16684,30 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) break; } + else if (i + 4 == mIns.Size() && + mIns[i + 0].mType == ASMIT_LDA && + mIns[i + 1].mType == ASMIT_CLC && + 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 + 0].SameEffectiveAddress(mIns[i + 3]) && + !(mIns[i + 3].mLive & LIVE_CPU_REG_A) && + mExitRequiredRegs.Size() && !mExitRequiredRegs[CPU_REG_C] && + (mBranch == ASMIT_BCC || mBranch == ASMIT_BCS)) + { + mIns[i + 3].mType = ASMIT_INC; + mIns[i + 3].mLive |= LIVE_CPU_REG_Z; + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; + + if (mBranch == ASMIT_BCC) + mBranch = ASMIT_BNE; + else + mBranch = ASMIT_BEQ; + + changed = true; + break; + + } #endif #if 1 if (i + 6 < mIns.Size()) @@ -17873,6 +17911,31 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) } + if (mIns.Size() >= 3 && mFalseJump && mBranch == ASMIT_BCC && mExitRequiredRegs.Size()) + { + int sz = mIns.Size(); + if (mIns[sz - 3].mType == ASMIT_LDA && + mIns[sz - 2].mType == ASMIT_ADC && mIns[sz - 2].mMode == ASMIM_IMMEDIATE && mIns[sz - 2].mAddress == 0 && + mIns[sz - 1].mType == ASMIT_STA && mIns[sz - 1].SameEffectiveAddress(mIns[sz - 3]) && + HasAsmInstructionMode(ASMIT_INC, mIns[sz - 1].mMode) && + !(mIns[sz - 1].mLive & LIVE_CPU_REG_A) && !mExitRequiredRegs[CPU_REG_C]) + { + NativeCodeBasicBlock* tblock = this->SplitAt(sz - 3); + + tblock->mBranch = ASMIT_BNE; + tblock->mIns[0].mType = ASMIT_INC; + tblock->mIns.SetSize(1); + + mBranch = ASMIT_BCC; + mFalseJump = tblock; + mTrueJump = tblock->mTrueJump; + mTrueJump->mNumEntries++; + mTrueJump->mEntryBlocks.Push(this); + changed = true; + } + + } + if (mIns.Size() >= 8 && mFalseJump && (mBranch == ASMIT_BNE || mBranch == ASMIT_BEQ)) { int sz = mIns.Size(); @@ -27210,7 +27273,7 @@ bool NativeCodeBasicBlock::ReplaceFinalZeroPageUse(NativeCodeProcedure* nproc) mIns[i + 2].mAddress >= BC_REG_TMP) { nproc->ResetPatched(); - if (IsFinalZeroPageUse(this, i + 6, mIns[i + 2].mAddress, mIns[i + 0].mAddress, true, false)) + if (IsFinalZeroPageUse(this, i + 6, mIns[i + 2].mAddress, mIns[i + 0].mAddress, true, true)) { nproc->ResetPatched(); if (ForwardReplaceZeroPage(i + 6, mIns[i + 2].mAddress, mIns[i + 0].mAddress, true)) @@ -27236,7 +27299,7 @@ bool NativeCodeBasicBlock::ReplaceFinalZeroPageUse(NativeCodeProcedure* nproc) mIns[i + 1].mAddress >= BC_REG_TMP) { nproc->ResetPatched(); - if (IsFinalZeroPageUse(this, i + 5, mIns[i + 1].mAddress, mIns[i + 0].mAddress, true, false)) + if (IsFinalZeroPageUse(this, i + 5, mIns[i + 1].mAddress, mIns[i + 0].mAddress, true, true)) { nproc->ResetPatched(); if (ForwardReplaceZeroPage(i + 5, mIns[i + 1].mAddress, mIns[i + 0].mAddress, true)) @@ -42726,7 +42789,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "interpret_builtin"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "interpret_expression"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -43519,13 +43582,13 @@ void NativeCodeProcedure::Optimize(void) mEntryBlock->CheckBlocks(); #endif + #if 1 ResetVisited(); if (mEntryBlock->PeepHoleOptimizer(this, step)) changed = true; #endif - if (step == 2) { ResetVisited();