diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 96a7ade..f5b78c4 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -16166,6 +16166,97 @@ bool InterCodeBasicBlock::SingleBlockLoopPointerSplit(int& spareTemps) return changed; } +bool InterCodeBasicBlock::PostDecLoopOptimization(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + if (mLoopHead && mNumEntries == 2 && mFalseJump && (mTrueJump == this || mFalseJump == this) && mInstructions.Size() > 3) + { + int nins = mInstructions.Size(); + + InterCodeBasicBlock* pblock = mEntryBlocks[0], * eblock = mFalseJump; + if (pblock == this) + pblock = mEntryBlocks[1]; + if (eblock == this) + eblock = mTrueJump; + + InterInstruction* movins = nullptr, * decins = nullptr; + int ctemp = -1; + + if (mInstructions[nins - 1]->mCode == IC_BRANCH && !pblock->mFalseJump) + { + ctemp = mInstructions[nins - 1]->mSrc->mTemp; + if (mInstructions[nins - 2]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[nins - 2]->mDst.mTemp == ctemp) + { + if (mInstructions[nins - 2]->mSrc[0].mTemp < 0) + ctemp = mInstructions[nins - 2]->mSrc[1].mTemp; + else + ctemp = mInstructions[nins - 2]->mSrc[0].mTemp; + } + + if (ctemp >= 0) + { + int movi = nins - 1; + while (movi >= 0 && mInstructions[movi]->mDst.mTemp != ctemp) + movi--; + + if (movi >= 0) + { + int ltemp = mInstructions[movi]->mSrc->mTemp; + int inci = movi; + while (inci < nins && mInstructions[inci]->mDst.mTemp != ltemp) + inci++; + if (inci < nins) + { + if (mInstructions[inci]->mCode == IC_BINARY_OPERATOR && mInstructions[inci]->mOperator == IA_ADD) + { + int inco = -1; + if (mInstructions[inci]->mSrc[0].mTemp == ltemp && mInstructions[inci]->mSrc[1].mTemp < 0) + inco = 1; + else if (mInstructions[inci]->mSrc[1].mTemp == ltemp && mInstructions[inci]->mSrc[0].mTemp < 0) + inco = 0; + + if (inco >= 0 && !IsTempReferencedInRange(0, movi, ltemp) && !IsTempReferencedInRange(movi + 1, inci, ltemp) && !IsTempReferencedInRange(inci + 1, nins, ltemp)) + { + if (!eblock->mEntryRequiredTemps[ltemp]) + { + InterInstruction* ins = mInstructions[inci]; + + int v = ins->mSrc[inco].mIntConst; + + if (ins->mDst.mRange.mMaxState == IntegerValueRange::S_BOUND) + ins->mDst.mRange.mMaxValue -= v; + if (ins->mSrc[1 - inco].mRange.mMinState == IntegerValueRange::S_BOUND) + ins->mSrc[1 - inco].mRange.mMinValue -= v; + + mInstructions.Remove(inci); + mInstructions.Insert(movi, ins); + InterInstruction* pins = ins->Clone(); + pins->mSrc[inco].mIntConst = -v; + pblock->mInstructions.Insert(pblock->mInstructions.Size() - 1, pins); + changed = true; + } + } + } + } + } + } + } + } + + if (mTrueJump && mTrueJump->PostDecLoopOptimization()) + changed = true; + if (mFalseJump && mFalseJump->PostDecLoopOptimization()) + changed = true; + } + + return changed; +} + void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars) { if (!mVisited) @@ -20285,7 +20376,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "palette_draw"); + CheckFunc = !strcmp(mIdent->mString, "test3"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -20696,6 +20787,11 @@ void InterCodeProcedure::Close(void) BuildDataFlowSets(); + ResetVisited(); + mEntryBlock->PostDecLoopOptimization(); + + DisassembleDebug("PostDecLoopOptimization"); + ResetVisited(); mEntryBlock->SingleBlockLoopOptimisation(mParamAliasedSet, mModule->mGlobalVars); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 2e7b336..8adc51f 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -585,6 +585,7 @@ public: void PushMoveOutOfLoop(void); bool MoveConditionOutOfLoop(void); void SingleLoopCountZeroCheck(void); + bool PostDecLoopOptimization(void); void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue); void RemoveUnusedMallocs(void); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 40d7fc4..3c8b1e7 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -17075,9 +17075,15 @@ bool NativeCodeBasicBlock::SimplifyLoopEnd(NativeCodeProcedure* proc) { mIns.Push(mTrueJump->mIns[0]); mBranch = mTrueJump->mBranch; + + mTrueJump->RemEntryBlock(this); + mFalseJump = mTrueJump->mFalseJump; mTrueJump = mTrueJump->mTrueJump; + mTrueJump->AddEntryBlock(this); + mFalseJump->AddEntryBlock(this); + changed = true; } } @@ -46397,7 +46403,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "player_check"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "test3"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -47714,8 +47720,8 @@ void NativeCodeProcedure::Optimize(void) mEntryBlock->CheckBlocks(); #endif } -#endif +#endif if (step >= 6) { ResetVisited(); @@ -47921,6 +47927,7 @@ void NativeCodeProcedure::Optimize(void) else cnt++; + } while (changed); #if 1