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);
|
||||
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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue