diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 0a688bb..8533e92 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -14203,27 +14203,32 @@ void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, NativeCodeProc } +void NativeCodeBasicBlock::DisassembleBody(FILE* file) +{ + fprintf(file, "L%d:\n", mIndex); + for (int i = 0; i < mIns.Size(); i++) + { + fprintf(file, "%03d ", i); + mIns[i].Disassemble(file); + fprintf(file, "\n"); + } + fprintf(file, "%03d %s", mIns.Size(), AsmInstructionNames[mBranch]); + if (mTrueJump) + { + fprintf(file, " L%d", mTrueJump->mIndex); + if (mFalseJump) + fprintf(file, ", L%d", mFalseJump->mIndex); + } + fprintf(file, "\n"); +} + void NativeCodeBasicBlock::Disassemble(FILE* file) { if (!mVisited) { mVisited = true; - fprintf(file, "L%d:\n", mIndex); - for (int i = 0; i < mIns.Size(); i++) - { - fprintf(file, "%03d ", i); - mIns[i].Disassemble(file); - fprintf(file, "\n"); - } - fprintf(file, "%03d %s", mIns.Size(), AsmInstructionNames[mBranch]); - if (mTrueJump) - { - fprintf(file, " L%d", mTrueJump->mIndex); - if (mFalseJump) - fprintf(file, ", L%d", mFalseJump->mIndex); - } - fprintf(file, "\n"); + DisassembleBody(file); if (mTrueJump) mTrueJump->Disassemble(file); if (mFalseJump) mFalseJump->Disassemble(file); @@ -40316,6 +40321,133 @@ bool NativeCodeBasicBlock::OptimizeXYSimpleLoop(void) } +bool NativeCodeBasicBlock::OptimizeSimpleForLoop(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + if (mLoopHead && mFalseJump && mNumEntries == 2) + { + NativeCodeBasicBlock* lbody = nullptr, * eblock = nullptr, *pblock = nullptr; + + if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump == this) + { + lbody = mTrueJump; + eblock = mFalseJump; + } + else if (!mFalseJump->mFalseJump && mFalseJump->mTrueJump == this) + { + lbody = mFalseJump; + eblock = mTrueJump; + } + + if (lbody) + { + if (mEntryBlocks[0] == lbody) + pblock = mEntryBlocks[1]; + else + pblock = mEntryBlocks[0]; + + if (!pblock->mFalseJump && eblock->mNumEntries == 1) + { + if (mIns.Size() == 2 && mIns[0].mType == ASMIT_LDA && mIns[0].mMode == ASMIM_ZERO_PAGE && mIns[1].mType == ASMIT_CMP && HasAsmInstructionMode(ASMIT_CPY, mIns[1].mMode) && !(mIns[0].mLive & LIVE_CPU_REG_Y) && !lbody->ReferencesYReg()) + { + int reg = mIns[0].mAddress; + bool fail = false; + + for (int i = 0; !fail && i < lbody->mIns.Size(); i++) + { + const NativeCodeInstruction& ins(lbody->mIns[i]); + if (ins.ReferencesZeroPage(reg)) + { + if (ins.mType == ASMIT_LDA || ins.mType == ASMIT_INC || ins.mType == ASMIT_DEC) + ; + else if (ins.mType == ASMIT_LDX) + { + if (i + 1 < lbody->mIns.Size()) + { + if (lbody->mIns[i + 1].mMode == ASMIM_ABSOLUTE_X && !(lbody->mIns[i + 1].mLive & LIVE_CPU_REG_X) && HasAsmInstructionMode(lbody->mIns[i + 1].mType, ASMIM_ABSOLUTE_Y)) + ; + else + fail = true; + } + else + fail = true; + } + else + fail = true; + } + } + + if (!fail) + { + mIns[0].mType = ASMIT_NOP; mIns[0].mMode = ASMIM_IMPLIED; + mIns[1].mType = ASMIT_CPY; mIns[1].mLive |= LIVE_CPU_REG_Y; + mEntryRequiredRegs += CPU_REG_Y; + mExitRequiredRegs += CPU_REG_Y; + + lbody->mEntryRequiredRegs += CPU_REG_Y; + lbody->mExitRequiredRegs += CPU_REG_Y; + + for (int i = 0; i < lbody->mIns.Size(); i++) + { + NativeCodeInstruction& ins(lbody->mIns[i]); + ins.mLive |= LIVE_CPU_REG_Y; + + if (ins.ReferencesZeroPage(reg)) + { + if (ins.mType == ASMIT_LDA) + { + ins.mType = ASMIT_TYA; + ins.mMode = ASMIM_IMPLIED; + } + else if (ins.mType == ASMIT_INC) + { + ins.mType = ASMIT_INY; + ins.mMode = ASMIM_IMPLIED; + } + else if (ins.mType == ASMIT_DEC) + { + ins.mType = ASMIT_DEY; + ins.mMode = ASMIM_IMPLIED; + } + else if (ins.mType == ASMIT_LDX) + { + ins.mType = ASMIT_NOP; ins.mMode = ASMIM_IMPLIED; + lbody->mIns[i + 1].mMode = ASMIM_ABSOLUTE_Y; + } + } + } + + eblock->mEntryRequiredRegs += CPU_REG_Y; + pblock->mExitRequiredRegs += CPU_REG_Y; + + pblock->mIns.Push(NativeCodeInstruction(mIns[0].mIns, ASMIT_LDY, ASMIM_ZERO_PAGE, reg)); + eblock->mIns.Insert(0, NativeCodeInstruction(mIns[0].mIns, ASMIT_STY, ASMIM_ZERO_PAGE, reg)); + + changed = true; + + } + } + else if (mIns.Size() == 2 && mIns[0].mType == ASMIT_LDA && mIns[0].mMode == ASMIM_ZERO_PAGE && mIns[1].mType == ASMIT_CMP && HasAsmInstructionMode(ASMIT_CPX, mIns[1].mMode) && !(mIns[0].mLive & LIVE_CPU_REG_X) && !lbody->ReferencesXReg()) + { + } + } + } + } + + if (mTrueJump && mTrueJump->OptimizeSimpleForLoop()) + changed = true; + if (mFalseJump && mFalseJump->OptimizeSimpleForLoop()) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc, bool full) { if (!mVisited) @@ -54884,6 +55016,13 @@ void NativeCodeProcedure::Optimize(void) } #endif + if (step == 4) + { + ResetVisited(); + if (mEntryBlock->OptimizeSimpleForLoop()) + changed = true; + } + if (step > 6 && !changed) { ResetVisited(); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 214fe86..fc78c6c 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -278,6 +278,7 @@ public: NativeCodeInstruction mALSIns, mXLSIns, mYLSIns; void Disassemble(FILE* file); + void DisassembleBody(FILE* file); NativeCodeInstruction DecodeNative(const InterInstruction* ins, LinkerObject * lobj, int& offset) const; @@ -349,6 +350,7 @@ public: bool OptimizeSingleEntryLoop(NativeCodeProcedure* proc); bool OptimizeSimpleLoop(NativeCodeProcedure* proc, bool full); + bool OptimizeSimpleForLoop(void); bool SimpleLoopReversal(NativeCodeProcedure* proc); bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, ExpandingArray& blocks); bool OptimizeXYSimpleLoop(void); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 5ffe530..96be63d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -10268,30 +10268,43 @@ Expression* Parser::ParseStatement(void) if ((initExp->mType == EX_ASSIGNMENT || initExp->mType == EX_INITIALIZATION) && initExp->mLeft->mType == EX_VARIABLE && initExp->mRight->mType == EX_CONSTANT && (iterateExp->mType == EX_POSTINCDEC || iterateExp->mType == EX_PREINCDEC || iterateExp->mType == EX_ASSIGNMENT && iterateExp->mToken == TK_ASSIGN_ADD && iterateExp->mRight->mType == EX_CONSTANT) && iterateExp->mLeft->IsSame(initExp->mLeft) && - conditionExp->mType == EX_RELATIONAL && (conditionExp->mToken == TK_LESS_THAN || conditionExp->mToken == TK_GREATER_THAN || conditionExp->mToken == TK_LESS_EQUAL || conditionExp->mToken == TK_GREATER_EQUAL) && conditionExp->mLeft->IsSame(initExp->mLeft) && conditionExp->mRight->mType == EX_CONSTANT) + (conditionExp->mType == EX_RELATIONAL && + (conditionExp->mToken == TK_LESS_THAN || conditionExp->mToken == TK_GREATER_THAN || conditionExp->mToken == TK_LESS_EQUAL || conditionExp->mToken == TK_GREATER_EQUAL) && + conditionExp->mLeft->IsSame(initExp->mLeft) && + conditionExp->mRight->mType == EX_CONSTANT || + conditionExp->IsSame(initExp->mLeft))) { - if (initExp->mRight->mDecValue->mType == DT_CONST_INTEGER && conditionExp->mRight->mDecValue->mType == DT_CONST_INTEGER) + if (initExp->mRight->mDecValue->mType == DT_CONST_INTEGER && (conditionExp->mType == EX_VARIABLE || conditionExp->mRight->mDecValue->mType == DT_CONST_INTEGER)) { int startValue = int(initExp->mRight->mDecValue->mInteger); - int endValue = int(conditionExp->mRight->mDecValue->mInteger); + int endValue = 0; int stepValue = 1; - if (conditionExp->mToken == TK_LESS_EQUAL) - { - endValue++; - conditionExp->mToken = TK_LESS_THAN; - } - else if (conditionExp->mToken == TK_GREATER_EQUAL) - { - endValue--; - conditionExp->mToken = TK_GREATER_THAN; - } - if (iterateExp->mType == EX_ASSIGNMENT) stepValue = int(iterateExp->mRight->mDecValue->mInteger); else if (iterateExp->mToken == TK_DEC) stepValue = -1; + if (conditionExp->mType == EX_RELATIONAL) + { + endValue = int(conditionExp->mRight->mDecValue->mInteger); + + if (conditionExp->mToken == TK_LESS_EQUAL) + { + endValue++; + conditionExp->mToken = TK_LESS_THAN; + } + else if (conditionExp->mToken == TK_GREATER_EQUAL) + { + endValue--; + conditionExp->mToken = TK_GREATER_THAN; + } + } + else if (stepValue > 0 && startValue >= 0) + { + endValue = 1 << (initExp->mLeft->mDecValue->mSize * 8); + } + if (unrollPage) { int numLoops = (endValue - startValue + 255) / 256; @@ -10349,7 +10362,22 @@ Expression* Parser::ParseStatement(void) bexp = bexp->mRight; bexp->mLeft = dexp; - conditionExp->mRight->mDecValue = conditionExp->mRight->mDecValue->Clone(); + if (conditionExp->mType == EX_RELATIONAL) + { + conditionExp->mRight->mDecValue = conditionExp->mRight->mDecValue->Clone(); + } + else + { + conditionExp = new Expression(conditionExp->mLocation, EX_RELATIONAL); + conditionExp->mDecType = TheBoolTypeDeclaration; + conditionExp->mToken = stepValue < 0 ? TK_GREATER_THAN : TK_LESS_THAN; + conditionExp->mLeft = initExp->mLeft; + conditionExp->mRight = new Expression(conditionExp->mLocation, EX_CONSTANT); + conditionExp->mRight->mDecType = conditionExp->mDecType; + conditionExp->mRight->mDecValue = new Declaration(conditionExp->mLocation, DT_CONST_INTEGER); + conditionExp->mRight->mDecValue->mBase = conditionExp->mRight->mDecType; + } + conditionExp->mRight->mDecValue->mInteger = numIterations; if (remain) @@ -10377,7 +10405,21 @@ Expression* Parser::ParseStatement(void) int remain = numSteps % unrollLoop; endValue -= remain * stepValue; - conditionExp->mRight->mDecValue = conditionExp->mRight->mDecValue->Clone(); + if (conditionExp->mType == EX_RELATIONAL) + { + conditionExp->mRight->mDecValue = conditionExp->mRight->mDecValue->Clone(); + } + else + { + conditionExp = new Expression(conditionExp->mLocation, EX_RELATIONAL); + conditionExp->mDecType = TheBoolTypeDeclaration; + conditionExp->mToken = stepValue < 0 ? TK_GREATER_THAN : TK_LESS_THAN; + conditionExp->mLeft = initExp->mLeft; + conditionExp->mRight = new Expression(conditionExp->mLocation, EX_CONSTANT); + conditionExp->mRight->mDecType = conditionExp->mDecType; + conditionExp->mRight->mDecValue = new Declaration(conditionExp->mLocation, DT_CONST_INTEGER); + conditionExp->mRight->mDecValue->mBase = conditionExp->mRight->mDecType; + } conditionExp->mRight->mDecValue->mInteger = endValue; Expression* unrollBody = new Expression(mScanner->mLocation, EX_SEQUENCE);