From 301431f12a3e58d0a70d6203a95e3f48737a8204 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Fri, 5 Jul 2024 10:12:55 +0200 Subject: [PATCH] Eliminate duplicate loop counting variables --- oscar64/InterCode.cpp | 197 +++++++++++++++++++++++++++ oscar64/InterCode.h | 2 + oscar64/NativeCodeGenerator.cpp | 230 ++++++++++++++++++++++++++++---- oscar64/NativeCodeGenerator.h | 3 +- 4 files changed, 402 insertions(+), 30 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index dde82c6..6a83dde 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -15106,6 +15106,189 @@ void InterCodeBasicBlock::ConstLoopOptimization(void) } } +void InterCodeBasicBlock::EliminateDoubleLoopCounter(void) +{ + if (!mVisited) + { + mVisited = true; + + if (mLoopHead && mEntryBlocks.Size() == 2 && mLoopPrefix->mEntryBlocks.Size() == 1) + { + ExpandingArray body, path; + body.Push(this); + bool innerLoop = true; + + for (int i = 0; i < mEntryBlocks.Size(); i++) + { + if (mEntryBlocks[i] != mLoopPrefix) + { + if (!mEntryBlocks[i]->CollectLoopBody(this, body)) + innerLoop = false; + } + } + + if (innerLoop) + { + InterCodeBasicBlock* eblock; + if (mEntryBlocks[0] == mLoopPrefix) + eblock = mEntryBlocks[1]; + else + eblock = mEntryBlocks[0]; + + struct LoopCounter + { + InterInstruction * mInit, * mInc, * mCmp; + int64 mStart, mEnd, mStep; + bool mReferenced; + }; + + ExpandingArray lcs; + + for (int i = 0; i < eblock->mInstructions.Size(); i++) + { + InterInstruction* ins(eblock->mInstructions[i]); + + LoopCounter lc; + lc.mInc = nullptr; + lc.mInit = nullptr; + lc.mCmp = nullptr; + lc.mReferenced = false; + + if (ins->mCode == IC_BINARY_OPERATOR && ins->mOperator == IA_ADD) + { + if (ins->mDst.mTemp == ins->mSrc[0].mTemp && ins->mSrc[1].mTemp < 0 || + ins->mDst.mTemp == ins->mSrc[1].mTemp && ins->mSrc[0].mTemp < 0) + { + lc.mInc = ins; + } + } + else if (ins->mCode == IC_LEA && ins->mDst.mTemp == ins->mSrc[1].mTemp && ins->mSrc[0].mTemp < 0) + { + lc.mInc = ins; + } + + if (lc.mInc) + { + int temp = lc.mInc->mDst.mTemp; + + if (!eblock->IsTempModifiedInRange(0, i, temp)) + { + int sz = eblock->mInstructions.Size(); + int rz = sz - 1; + if (eblock->mInstructions[sz - 1]->mCode == IC_BRANCH && + eblock->mInstructions[sz - 2]->mCode == IC_RELATIONAL_OPERATOR && eblock->mInstructions[sz - 1]->mSrc[0].mTemp == eblock->mInstructions[sz - 2]->mDst.mTemp && + ((eblock->mInstructions[sz - 2]->mSrc[0].mTemp == temp && eblock->mInstructions[sz - 2]->mSrc[1].mTemp < 0) || + (eblock->mInstructions[sz - 2]->mSrc[1].mTemp == temp && eblock->mInstructions[sz - 2]->mSrc[0].mTemp < 0))) + { + InterInstruction* ci = eblock->mInstructions[sz - 2]; + + if (ci->mOperator == IA_CMPEQ && eblock->mFalseJump == this || + ci->mOperator == IA_CMPNE && eblock->mTrueJump == this) + { + if (ci->mSrc[0].mTemp < 0) + lc.mEnd = ci->mSrc[0].mIntConst; + else + lc.mEnd = ci->mSrc[1].mIntConst; + lc.mCmp = eblock->mInstructions[sz - 2]; + rz--; + } + } + + if (!eblock->IsTempModifiedInRange(i + 1, sz, temp)) + { + if (eblock->IsTempReferencedInRange(0, i, temp) || eblock->IsTempReferencedInRange(i + 1, rz, temp)) + lc.mReferenced = true; + + for (int k = 0; k < body.Size(); k++) + { + if (body[k] != eblock && body[k]->IsTempReferenced(temp)) + lc.mReferenced = true; + } + + int k = 0; + while (k < body.Size() && (body[k] == eblock || !body[k]->IsTempModified(lc.mInc->mDst.mTemp))) + k++; + + if (k == body.Size()) + { + lc.mInit = mLoopPrefix->mEntryBlocks[0]->FindTempOrigin(lc.mInc->mDst.mTemp); + if (lc.mInit && lc.mInit->mCode == IC_CONSTANT) + { + lc.mStart = lc.mInit->mConst.mIntConst; + if (lc.mInc->mSrc[0].mTemp < 0) + lc.mStep = lc.mInc->mSrc[0].mIntConst; + else + lc.mStep = lc.mInc->mSrc[1].mIntConst; + lcs.Push(lc); + } + } + } + } + } + } + + if (lcs.Size() >= 2) + { + int loop = -1; + int k = 0; + while (k < lcs.Size() && !lcs[k].mCmp) + k++; + if (k < lcs.Size()) + { + int64 start = lcs[k].mStart; + int64 end = lcs[k].mEnd; + int64 step = lcs[k].mStep; + + if (step > 0 && end > start || step < 0 && end < start) + loop = (end - start) / step; + } + + if (loop > 0) + { + if (!lcs[k].mReferenced) + { + int j = 0; + while (j < lcs.Size() && !(lcs[j].mReferenced && lcs[j].mInc->mCode == IC_BINARY_OPERATOR && lcs[j].mStart + lcs[j].mStep * loop < 65536)) + j++; + + // Pointer compare with constants only in native code path + if (j == lcs.Size() && mProc->mNativeProcedure) + { + j = 0; + while (j < lcs.Size() && !(lcs[j].mReferenced && lcs[j].mInc->mCode == IC_LEA && (lcs[j].mInit->mConst.mMemory == IM_GLOBAL || lcs[j].mInit->mConst.mMemory == IM_ABSOLUTE) && + lcs[j].mStart + lcs[j].mStep * loop < 65536)) + j++; + } + + if (j < lcs.Size()) + { + int ci = 0, ti = 1; + if (lcs[k].mCmp->mSrc[1].mTemp < 0) + { + ci = 1; + ti = 0; + } + + lcs[k].mCmp->mSrc[ti] = lcs[j].mInc->mDst; + lcs[k].mCmp->mSrc[ci] = lcs[j].mInit->mConst; + lcs[k].mCmp->mSrc[ci].mIntConst += loop * lcs[j].mStep; + + lcs[k].mInc->mCode = IC_NONE; + lcs[k].mInc->mNumOperands = 0; + lcs[k].mInit->mConst.mIntConst += loop * lcs[k].mStep; + } + } + } + } + } + } + + if (mTrueJump) + mTrueJump->EliminateDoubleLoopCounter(); + if (mFalseJump) + mFalseJump->EliminateDoubleLoopCounter(); + } +} void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) { if (!mVisited) @@ -20635,6 +20818,18 @@ void InterCodeProcedure::MoveConditionsOutOfLoop(void) } } +void InterCodeProcedure::EliminateDoubleLoopCounter(void) +{ + BuildTraces(false); + BuildLoopPrefix(); + ResetEntryBlocks(); + ResetVisited(); + mEntryBlock->CollectEntryBlocks(nullptr); + + ResetVisited(); + mEntryBlock->EliminateDoubleLoopCounter(); +} + void InterCodeProcedure::PropagateMemoryAliasingInfo(void) { @@ -22171,6 +22366,8 @@ void InterCodeProcedure::Close(void) BuildDataFlowSets(); TempForwarding(false, true); + EliminateDoubleLoopCounter(); + ResetVisited(); mEntryBlock->SingleLoopCountZeroCheck(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index f6b0bf2..e46b396 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -594,6 +594,7 @@ public: void CollectLoopPath(const ExpandingArray& body, ExpandingArray& path); void InnerLoopOptimization(const NumberSet& aliasedParams); void ConstLoopOptimization(void); + void EliminateDoubleLoopCounter(void); void PushMoveOutOfLoop(void); bool MoveConditionOutOfLoop(void); void SingleLoopCountZeroCheck(void); @@ -755,6 +756,7 @@ protected: void PropagateMemoryAliasingInfo(void); void MoveConditionsOutOfLoop(void); void ShortcutConstBranches(void); + void EliminateDoubleLoopCounter(void); void CollapseDispatch(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index af99741..004fffd 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -5212,12 +5212,13 @@ int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBl } } -void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const InterInstruction * ins, InterType type, int reg) +void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure* proc, const InterInstruction* ins, const InterOperand& op, InterType type, int reg) { + if (type == IT_FLOAT) { union { float f; unsigned int v; } cc; - cc.f = float(ins->mConst.mFloatConst); + cc.f = float(op.mFloatConst); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); @@ -5230,33 +5231,33 @@ void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const In } else if (type == IT_POINTER) { - if (ins->mConst.mMemory == IM_GLOBAL) + if (op.mMemory == IM_GLOBAL) { - if (ins->mConst.mIntConst < 0 || ins->mConst.mIntConst > ins->mConst.mLinkerObject->mSize) + if (op.mIntConst < 0 || op.mIntConst > op.mLinkerObject->mSize) proc->mModule->mErrors->Error(ins->mLocation, EWARN_UNDEFINED_POINTER_ARITHMETIC, "Undefined constant pointer arithmetic"); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mConst.mIntConst, ins->mConst.mLinkerObject, NCIF_LOWER)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, op.mIntConst, op.mLinkerObject, NCIF_LOWER)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mConst.mIntConst, ins->mConst.mLinkerObject, NCIF_UPPER)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, op.mIntConst, op.mLinkerObject, NCIF_UPPER)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } - else if (ins->mConst.mMemory == IM_ABSOLUTE) + else if (op.mMemory == IM_ABSOLUTE) { - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mConst.mIntConst & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, op.mIntConst & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } - else if (ins->mConst.mMemory == IM_FPARAM || ins->mConst.mMemory == IM_FFRAME) + else if (op.mMemory == IM_FPARAM || op.mMemory == IM_FFRAME) { - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, BC_REG_FPARAMS + ins->mConst.mVarIndex + ins->mConst.mIntConst)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, BC_REG_FPARAMS + op.mVarIndex + op.mIntConst)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } - else if (ins->mConst.mMemory == IM_FRAME) + else if (op.mMemory == IM_FRAME) { - int index = ins->mConst.mVarIndex + int(ins->mConst.mIntConst) + 2; + int index = op.mVarIndex + int(op.mIntConst) + 2; mIns.Push(NativeCodeInstruction(ins, ASMIT_CLC, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); @@ -5266,14 +5267,14 @@ void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const In mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } - else if (ins->mConst.mMemory == IM_LOCAL || ins->mConst.mMemory == IM_PARAM) + else if (op.mMemory == IM_LOCAL || op.mMemory == IM_PARAM) { - int index = int(ins->mConst.mIntConst); + int index = int(op.mIntConst); int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS; - if (ins->mConst.mMemory == IM_LOCAL) - index += proc->mLocalVars[ins->mConst.mVarIndex]->mOffset; + if (op.mMemory == IM_LOCAL) + index += proc->mLocalVars[op.mVarIndex]->mOffset; else - index += ins->mConst.mVarIndex + proc->mLocalSize + 2; + index += op.mVarIndex + proc->mLocalSize + 2; index += mFrameOffset; CheckFrameIndex(ins, areg, index, 2); @@ -5288,10 +5289,10 @@ void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const In mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } - else if (ins->mConst.mMemory == IM_PROCEDURE) + else if (op.mMemory == IM_PROCEDURE) { - NativeCodeInstruction lins(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mConst.mLinkerObject, NCIF_LOWER); - NativeCodeInstruction hins(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mConst.mLinkerObject, NCIF_UPPER); + NativeCodeInstruction lins(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, op.mIntConst, op.mLinkerObject, NCIF_LOWER); + NativeCodeInstruction hins(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, op.mIntConst, op.mLinkerObject, NCIF_UPPER); mIns.Push(lins); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); @@ -5301,26 +5302,30 @@ void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const In } else if (type == IT_INT32) { - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mConst.mIntConst & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, op.mIntConst & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 16) & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 16) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2)); - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 24) & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 24) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3)); } else { - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mConst.mIntConst & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, op.mIntConst & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); - if (InterTypeSize[ins->mDst.mType] > 1) + if (InterTypeSize[type] > 1) { - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 8) & 0xff)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); } } +} +void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const InterInstruction * ins, InterType type, int reg) +{ + LoadConstantToReg(proc, ins, ins->mConst, type, reg); } void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins) @@ -12319,6 +12324,86 @@ void NativeCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const In break; } } + else if (ins->mSrc[0].mType == IT_POINTER) + { + int li = 1, ri = 0; + if (op == IA_CMPLEU || op == IA_CMPGU || op == IA_CMPLES || op == IA_CMPGS) + { + li = 0; ri = 1; + } + + int lreg = ins->mSrc[li].mTemp, rreg = ins->mSrc[ri].mTemp; + if (lreg < 0) + { + lreg = BC_REG_ACCU; + LoadConstantToReg(proc, ins, ins->mSrc[li], IT_POINTER, lreg); + } + else + lreg = BC_REG_TMP + proc->mTempOffset[lreg]; + + if (rreg < 0) + { + rreg = BC_REG_ACCU; + LoadConstantToReg(proc, ins, ins->mSrc[ri], IT_POINTER, rreg); + } + else + rreg = BC_REG_TMP + proc->mTempOffset[rreg]; + + NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* nblock = nproc->AllocateBlock(); + + + if (op == IA_CMPEQ || op == IA_CMPNE) + { + // Lower byte compare more likely to miss on not equal with first + // compare + + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, lreg)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_CMP, ASMIM_ZERO_PAGE, rreg)); + + Close(ins, nblock, eblock, ASMIT_BNE); + + eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, lreg + 1)); + eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_CMP, ASMIM_ZERO_PAGE, rreg + 1)); + } + else + { + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, lreg + 1)); + mIns.Push(NativeCodeInstruction(ins, ASMIT_CMP, ASMIM_ZERO_PAGE, rreg + 1)); + + Close(ins, nblock, eblock, ASMIT_BNE); + + eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, lreg)); + eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_CMP, ASMIM_ZERO_PAGE, rreg)); + } + + switch (op) + { + case IA_CMPEQ: + nblock->Close(ins, falseJump, nullptr, ASMIT_JMP); + eblock->Close(ins, trueJump, falseJump, ASMIT_BEQ); + break; + case IA_CMPNE: + nblock->Close(ins, trueJump, nullptr, ASMIT_JMP); + eblock->Close(ins, falseJump, trueJump, ASMIT_BEQ); + break; + case IA_CMPLU: + case IA_CMPLS: + case IA_CMPGU: + case IA_CMPGS: + eblock->Close(ins, nblock, nullptr, ASMIT_JMP); + nblock->Close(ins, trueJump, falseJump, ASMIT_BCC); + break; + case IA_CMPLEU: + case IA_CMPLES: + case IA_CMPGEU: + case IA_CMPGES: + eblock->Close(ins, nblock, nullptr, ASMIT_JMP); + nblock->Close(ins, falseJump, trueJump, ASMIT_BCC); + break; + + } + } else if (ins->mSrc[0].mType == IT_INT32) { int li = 1, ri = 0; @@ -36722,6 +36807,93 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc CheckLive(); +#if 1 + // Exchange Y against low byte of pointer + if (!ChangesYReg() && !mEntryRequiredRegs[CPU_REG_A] && !mExitRequiredRegs[CPU_REG_A]) + { + int rind = -1; + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].mMode == ASMIM_INDIRECT_Y) + { + if (rind == -1) + rind = mIns[i].mAddress; + else if (rind != mIns[i].mAddress) + { + rind = -2; + break; + } + } + else if (mIns[i].ReferencesYReg()) + { + rind = -2; + break; + } + } + + if (rind >= 0) + { + for (int i = 0; i < mIns.Size(); i++) + { + if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == rind) + { + if (mIns[i].mType == ASMIT_LDA || mIns[i].mType == ASMIT_STA) + ; + else + { + rind = -2; + break; + } + } + else if (mIns[i].mMode == ASMIM_INDIRECT_Y) + ; + else if (mIns[i].ReferencesZeroPage(rind)) + { + rind = -2; + break; + } + } + + if (rind >= 0) + { + if (!prevBlock) + return OptimizeSimpleLoopInvariant(proc, full); + + prevBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_LDA, ASMIM_ZERO_PAGE, rind)); + prevBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, rind)); + prevBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_TAY)); + + exitBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_LDA, ASMIM_ZERO_PAGE, rind)); + exitBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, rind)); + exitBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_TAY)); + + for (int i = 0; i < mIns.Size(); i++) + { + mIns[i].mLive |= LIVE_CPU_REG_Y; + if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == rind) + { + if (mIns[i].mType == ASMIT_LDA) + { + mIns[i].mType = ASMIT_TYA; + mIns[i].mMode = ASMIM_IMPLIED; + } + else if (mIns[i].mType == ASMIT_STA) + { + mIns[i].mType = ASMIT_TAY; + mIns[i].mMode = ASMIM_IMPLIED; + } + } + } + + prevBlock->mExitRequiredRegs += CPU_REG_Y; + mEntryRequiredRegs += CPU_REG_Y; + mExitRequiredRegs += CPU_REG_Y; + exitBlock->mEntryRequiredRegs += CPU_REG_Y; + changed = true; + } + } + } +#endif return changed; } @@ -49225,7 +49397,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) mInterProc = proc; mInterProc->mLinkerObject->mNativeProc = this; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "enemies_check"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index ab50027..55c0ff5 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -351,7 +351,8 @@ public: void CheckFrameIndex(const InterInstruction * ins, int & reg, int & index, int size, int treg = 0); void LoadValueToReg(InterCodeProcedure* proc, const InterInstruction * ins, int reg, const NativeCodeInstruction * ainsl, const NativeCodeInstruction* ainsh); - void LoadConstantToReg(InterCodeProcedure* proc, const InterInstruction * ins, InterType type, int reg); + void LoadConstantToReg(InterCodeProcedure* proc, const InterInstruction* ins, InterType type, int reg); + void LoadConstantToReg(InterCodeProcedure* proc, const InterInstruction* ins, const InterOperand & op, InterType type, int reg); void LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins); void StoreValue(InterCodeProcedure* proc, const InterInstruction * ins);