Optimize loop unrolling

This commit is contained in:
drmortalwombat 2025-04-18 17:16:56 +02:00
parent 323589a484
commit e95b51609c
3 changed files with 214 additions and 31 deletions

View File

@ -14203,12 +14203,8 @@ void NativeCodeBasicBlock::CallFunction(InterCodeProcedure* proc, NativeCodeProc
}
void NativeCodeBasicBlock::Disassemble(FILE* file)
void NativeCodeBasicBlock::DisassembleBody(FILE* file)
{
if (!mVisited)
{
mVisited = true;
fprintf(file, "L%d:\n", mIndex);
for (int i = 0; i < mIns.Size(); i++)
{
@ -14224,6 +14220,15 @@ void NativeCodeBasicBlock::Disassemble(FILE* file)
fprintf(file, ", L%d", mFalseJump->mIndex);
}
fprintf(file, "\n");
}
void NativeCodeBasicBlock::Disassemble(FILE* file)
{
if (!mVisited)
{
mVisited = true;
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();

View File

@ -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<NativeCodeBasicBlock*>& blocks);
bool OptimizeXYSimpleLoop(void);

View File

@ -10268,14 +10268,27 @@ 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 (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++;
@ -10286,11 +10299,11 @@ Expression* Parser::ParseStatement(void)
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;
}
else if (stepValue > 0 && startValue >= 0)
{
endValue = 1 << (initExp->mLeft->mDecValue->mSize * 8);
}
if (unrollPage)
{
@ -10349,7 +10362,22 @@ Expression* Parser::ParseStatement(void)
bexp = bexp->mRight;
bexp->mLeft = dexp;
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;
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);