Optimize loop unrolling
This commit is contained in:
parent
323589a484
commit
e95b51609c
|
@ -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);
|
fprintf(file, "L%d:\n", mIndex);
|
||||||
for (int i = 0; i < mIns.Size(); i++)
|
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, ", L%d", mFalseJump->mIndex);
|
||||||
}
|
}
|
||||||
fprintf(file, "\n");
|
fprintf(file, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void NativeCodeBasicBlock::Disassemble(FILE* file)
|
||||||
|
{
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
DisassembleBody(file);
|
||||||
|
|
||||||
if (mTrueJump) mTrueJump->Disassemble(file);
|
if (mTrueJump) mTrueJump->Disassemble(file);
|
||||||
if (mFalseJump) mFalseJump->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)
|
bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc, bool full)
|
||||||
{
|
{
|
||||||
if (!mVisited)
|
if (!mVisited)
|
||||||
|
@ -54884,6 +55016,13 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (step == 4)
|
||||||
|
{
|
||||||
|
ResetVisited();
|
||||||
|
if (mEntryBlock->OptimizeSimpleForLoop())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (step > 6 && !changed)
|
if (step > 6 && !changed)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
|
|
|
@ -278,6 +278,7 @@ public:
|
||||||
NativeCodeInstruction mALSIns, mXLSIns, mYLSIns;
|
NativeCodeInstruction mALSIns, mXLSIns, mYLSIns;
|
||||||
|
|
||||||
void Disassemble(FILE* file);
|
void Disassemble(FILE* file);
|
||||||
|
void DisassembleBody(FILE* file);
|
||||||
|
|
||||||
NativeCodeInstruction DecodeNative(const InterInstruction* ins, LinkerObject * lobj, int& offset) const;
|
NativeCodeInstruction DecodeNative(const InterInstruction* ins, LinkerObject * lobj, int& offset) const;
|
||||||
|
|
||||||
|
@ -349,6 +350,7 @@ public:
|
||||||
bool OptimizeSingleEntryLoop(NativeCodeProcedure* proc);
|
bool OptimizeSingleEntryLoop(NativeCodeProcedure* proc);
|
||||||
|
|
||||||
bool OptimizeSimpleLoop(NativeCodeProcedure* proc, bool full);
|
bool OptimizeSimpleLoop(NativeCodeProcedure* proc, bool full);
|
||||||
|
bool OptimizeSimpleForLoop(void);
|
||||||
bool SimpleLoopReversal(NativeCodeProcedure* proc);
|
bool SimpleLoopReversal(NativeCodeProcedure* proc);
|
||||||
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, ExpandingArray<NativeCodeBasicBlock*>& blocks);
|
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, ExpandingArray<NativeCodeBasicBlock*>& blocks);
|
||||||
bool OptimizeXYSimpleLoop(void);
|
bool OptimizeXYSimpleLoop(void);
|
||||||
|
|
|
@ -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 &&
|
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->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) &&
|
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 startValue = int(initExp->mRight->mDecValue->mInteger);
|
||||||
int endValue = int(conditionExp->mRight->mDecValue->mInteger);
|
int endValue = 0;
|
||||||
int stepValue = 1;
|
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)
|
if (conditionExp->mToken == TK_LESS_EQUAL)
|
||||||
{
|
{
|
||||||
endValue++;
|
endValue++;
|
||||||
|
@ -10286,11 +10299,11 @@ Expression* Parser::ParseStatement(void)
|
||||||
endValue--;
|
endValue--;
|
||||||
conditionExp->mToken = TK_GREATER_THAN;
|
conditionExp->mToken = TK_GREATER_THAN;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (iterateExp->mType == EX_ASSIGNMENT)
|
else if (stepValue > 0 && startValue >= 0)
|
||||||
stepValue = int(iterateExp->mRight->mDecValue->mInteger);
|
{
|
||||||
else if (iterateExp->mToken == TK_DEC)
|
endValue = 1 << (initExp->mLeft->mDecValue->mSize * 8);
|
||||||
stepValue = -1;
|
}
|
||||||
|
|
||||||
if (unrollPage)
|
if (unrollPage)
|
||||||
{
|
{
|
||||||
|
@ -10349,7 +10362,22 @@ Expression* Parser::ParseStatement(void)
|
||||||
bexp = bexp->mRight;
|
bexp = bexp->mRight;
|
||||||
bexp->mLeft = dexp;
|
bexp->mLeft = dexp;
|
||||||
|
|
||||||
|
if (conditionExp->mType == EX_RELATIONAL)
|
||||||
|
{
|
||||||
conditionExp->mRight->mDecValue = conditionExp->mRight->mDecValue->Clone();
|
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;
|
conditionExp->mRight->mDecValue->mInteger = numIterations;
|
||||||
|
|
||||||
if (remain)
|
if (remain)
|
||||||
|
@ -10377,7 +10405,21 @@ Expression* Parser::ParseStatement(void)
|
||||||
int remain = numSteps % unrollLoop;
|
int remain = numSteps % unrollLoop;
|
||||||
endValue -= remain * stepValue;
|
endValue -= remain * stepValue;
|
||||||
|
|
||||||
|
if (conditionExp->mType == EX_RELATIONAL)
|
||||||
|
{
|
||||||
conditionExp->mRight->mDecValue = conditionExp->mRight->mDecValue->Clone();
|
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;
|
conditionExp->mRight->mDecValue->mInteger = endValue;
|
||||||
|
|
||||||
Expression* unrollBody = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
Expression* unrollBody = new Expression(mScanner->mLocation, EX_SEQUENCE);
|
||||||
|
|
Loading…
Reference in New Issue