Improve unrolled loops towards zero

This commit is contained in:
drmortalwombat 2024-01-20 13:49:25 +01:00
parent a19469d851
commit 8a49ffd111
6 changed files with 303 additions and 15 deletions

View File

@ -94,4 +94,24 @@ void vic_waitLine(int line)
} while ((vic.ctrl1 & VIC_CTRL1_RST8) != upper);
}
void vic_waitBelow(int line)
{
char upper = (char)(line >> 1) & VIC_CTRL1_RST8;
char lower = (char)line;
if (upper)
{
do
{
while (vic.raster <= lower)
;
} while (!(vic.ctrl1 & VIC_CTRL1_RST8));
}
else
{
while (vic.raster <= lower)
;
}
}
#pragma native(vic_waitLine)

View File

@ -115,6 +115,9 @@ void vic_waitFrames(char n);
// wait for a specific raster line
void vic_waitLine(int line);
// wait for beam to be below a line
void vic_waitBelow(int line);
// reference to the VIC chip
#define vic (*((struct VIC *)0xd000))

View File

@ -14531,6 +14531,67 @@ static bool IsInsSrcModifiedInBlocks(const ExpandingArray<InterCodeBasicBlock*>&
return false;
}
void InterCodeBasicBlock::SingleLoopCountZeroCheck(void)
{
if (!mVisited)
{
mVisited = true;
if (mLoopHead && mEntryBlocks.Size() == 2 && mFalseJump && (mTrueJump == this || mFalseJump == this) && mInstructions.Size() > 3)
{
int nins = mInstructions.Size();
InterCodeBasicBlock * pblock = mEntryBlocks[0];
if (pblock == this)
pblock = mEntryBlocks[1];
while (pblock->mInstructions.Size() == 1 && pblock->mInstructions[0]->mCode == IC_JUMP && pblock->mEntryBlocks.Size() == 1)
pblock = pblock->mEntryBlocks[0];
if (mInstructions[nins - 1]->mCode == IC_BRANCH &&
mInstructions[nins - 2]->mCode == IC_RELATIONAL_OPERATOR &&
mInstructions[nins - 3]->mCode == IC_BINARY_OPERATOR && mInstructions[nins - 3]->mOperator == IA_ADD)
{
InterInstruction* ains = mInstructions[nins - 3];
InterInstruction* cins = mInstructions[nins - 2];
InterInstruction* bins = mInstructions[nins - 1];
if (bins->mSrc[0].mTemp == cins->mDst.mTemp &&
cins->mSrc[1].mTemp == ains->mDst.mTemp &&
cins->mSrc[0].mTemp < 0 &&
ains->mSrc[1].mTemp == ains->mDst.mTemp &&
ains->mSrc[0].mTemp < 0 &&
cins->mOperator == IA_CMPGS &&
ains->mSrc[0].mIntConst < -1 &&
cins->mSrc[0].mIntConst > 0 &&
cins->mSrc[0].mIntConst < - ains->mSrc[0].mIntConst &&
!IsTempModifiedInRange(0, nins - 3, ains->mDst.mTemp))
{
int pi = pblock->mInstructions.Size() - 1;
while (pi >= 0 && pblock->mInstructions[pi]->mDst.mTemp != ains->mDst.mTemp)
pi--;
if (pi >= 0 && pblock->mInstructions[pi]->mCode == IC_CONSTANT)
{
int64 istart = pblock->mInstructions[pi]->mConst.mIntConst;
if (istart > 0)
{
int64 iend = istart % -ains->mSrc[0].mIntConst;
if (cins->mSrc[0].mIntConst < iend)
{
cins->mSrc[0].mIntConst = 0;
cins->mOperator = IA_CMPGES;
}
}
}
}
}
}
if (mTrueJump) mTrueJump->SingleLoopCountZeroCheck();
if (mFalseJump) mFalseJump->SingleLoopCountZeroCheck();
}
}
bool InterCodeBasicBlock::MoveConditionOutOfLoop(void)
{
if (!mVisited)
@ -20208,6 +20269,9 @@ void InterCodeProcedure::Close(void)
}
#endif
ResetVisited();
mEntryBlock->SingleLoopCountZeroCheck();
RemoveUnusedPartialStoreInstructions();
MapVariables();

View File

@ -579,6 +579,7 @@ public:
void InnerLoopOptimization(const NumberSet& aliasedParams);
void PushMoveOutOfLoop(void);
bool MoveConditionOutOfLoop(void);
void SingleLoopCountZeroCheck(void);
void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue);
void RemoveUnusedMallocs(void);

View File

@ -14401,6 +14401,64 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
yoffset = 2;
changed = true;
}
else if (yoffset == 0xff && i + 1 < mIns.Size() && mIns[i + 1].mType == ASMIT_DEY)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
changed = true;
}
else if (yoffset == 0xff)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_INY; mIns[i + 0].mMode = ASMIM_IMPLIED;
yoffset = 0;
changed = true;
}
else if (yoffset == 0xfe && i + 2 < mIns.Size() && mIns[i + 1].mType == ASMIT_DEY && mIns[i + 2].mType == ASMIT_DEY)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
changed = true;
}
else if (yoffset == 0xfe && i + 1 < mIns.Size() && mIns[i + 1].mType == ASMIT_DEY)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_INY;
changed = true;
}
else if (yoffset == 0xfd && i + 2 < mIns.Size() && mIns[i + 1].mType == ASMIT_DEY && mIns[i + 2].mType == ASMIT_DEY)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_INY; mIns[i + 2].mMode = ASMIM_IMPLIED;
changed = true;
}
else if (yoffset == 0xfd && i + 1 < mIns.Size() && mIns[i + 1].mType == ASMIT_DEY)
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_INY; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_INY; mIns[i + 1].mMode = ASMIM_IMPLIED;
yoffset = 0xfe;
changed = true;
}
else
yoffset = 0;
ypred = i;
@ -14419,7 +14477,7 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
mIns[j + 2].mType == ASMIT_STA && mIns[j + 2].mMode == ASMIM_ZERO_PAGE && mIns[j + 2].mAddress == yreg &&
!(mIns[j + 2].mLive & LIVE_CPU_REG_C))
{
if (mIns[j + 1].mAddress == yoffset + 1)
if (mIns[j + 1].mAddress == ((yoffset + 1) & 0xff))
{
for (int k = ypred; k < i; k++)
mIns[k].mLive |= LIVE_CPU_REG_Y;
@ -14432,6 +14490,19 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
i += 2;
changed = true;
}
else if (mIns[j + 1].mAddress == ((yoffset - 1) & 0xff))
{
for (int k = ypred; k < i; k++)
mIns[k].mLive |= LIVE_CPU_REG_Y;
mIns.Remove(j + 2);
mIns.Remove(j + 1);
mIns.Remove(j - 1);
mIns.Insert(i, NativeCodeInstruction(mIns[i].mIns, ASMIT_DEY));
mIns.Insert(i + 1, NativeCodeInstruction(mIns[i].mIns, ASMIT_STY, ASMIM_ZERO_PAGE, yreg));
i += 2;
changed = true;
}
}
}
@ -14446,7 +14517,7 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE &&
mIns[i + 3].mType == ASMIT_TAY)
{
if (mIns[i + 1].mAddress == yreg && mIns[i + 2].mAddress == yoffset + 1 && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
if (mIns[i + 1].mAddress == yreg && mIns[i + 2].mAddress == ((yoffset + 1) & 0xff) && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
@ -14456,6 +14527,16 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
mIns[i + 3].mType = ASMIT_INY;
changed = true;
}
else if (mIns[i + 1].mAddress == yreg && mIns[i + 2].mAddress == ((yoffset - 1) & 0xff) && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
{
for (int j = ypred; j < i; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
mIns[i + 3].mType = ASMIT_DEY;
changed = true;
}
else
{
yreg = mIns[i + 1].mAddress;
@ -14467,18 +14548,18 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
else if (i + 3 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == yreg &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == yoffset + 1 &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == ((yoffset + 1) & 0xff) &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
!(mIns[i + 3].mLive & (LIVE_CPU_REG_Y | LIVE_CPU_REG_C)))
{
for (int j = ypred; j < i + 3; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[j].mLive |= LIVE_CPU_REG_Y | (mIns[i + 3].mLive & LIVE_CPU_REG_Z);
mIns[i + 0].mType = ASMIT_INY;
mIns[i + 1].mType = ASMIT_STY; mIns[i + 1].mAddress = mIns[i + 3].mAddress;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
ypred = i + 1;
yoffset++;
yoffset = (yoffset + 1) & 0xff;
if (mIns[i + 3].mLive & LIVE_CPU_REG_A)
{
@ -14495,18 +14576,46 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
else if (i + 3 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == yreg &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == yoffset + 2 &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == ((yoffset - 1) & 0xff) &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
!(mIns[i + 3].mLive & (LIVE_CPU_REG_Y | LIVE_CPU_REG_C)))
{
for (int j = ypred; j < i + 3; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y;
mIns[j].mLive |= LIVE_CPU_REG_Y | (mIns[i + 3].mLive & LIVE_CPU_REG_Z);
mIns[i + 0].mType = ASMIT_DEY;
mIns[i + 1].mType = ASMIT_STY; mIns[i + 1].mAddress = mIns[i + 3].mAddress;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
ypred = i + 1;
yoffset = (yoffset - 1) & 0xff;
if (mIns[i + 3].mLive & LIVE_CPU_REG_A)
{
mIns[i + 3].mType = ASMIT_TYA;
mIns[i + 3].mMode = ASMIM_IMPLIED;
}
else
{
mIns[i + 3].mType = ASMIT_NOP;
mIns[i + 3].mMode = ASMIM_IMPLIED;
}
changed = true;
}
else if (i + 3 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress == yreg &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == ((yoffset + 2) & 0xff) &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
!(mIns[i + 3].mLive & (LIVE_CPU_REG_Y | LIVE_CPU_REG_C)))
{
for (int j = ypred; j < i + 3; j++)
mIns[j].mLive |= LIVE_CPU_REG_Y | (mIns[i + 3].mLive & LIVE_CPU_REG_Z);
mIns[i + 0].mType = ASMIT_INY;
mIns[i + 1].mType = ASMIT_INY; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_STY; mIns[i + 2].CopyMode(mIns[i + 3]);
ypred = i + 1;
yoffset++;
yoffset = (yoffset + 2) & 0xff;
if (mIns[i + 3].mLive & LIVE_CPU_REG_A)
{
@ -14531,7 +14640,7 @@ bool NativeCodeBasicBlock::ForwardZpYIndex(bool full)
mIns[i + 1].mType = ASMIT_STY;
ypred = i + 1;
yoffset++;
yoffset = (yoffset + 1) & 0xff;
changed = true;
}
@ -14898,7 +15007,7 @@ bool NativeCodeBasicBlock::JoinXYCascade(void)
mIns[i + 1].mType == ASMIT_CLC &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE)
{
if (predXPos >= 0 && !(mIns[i + 2].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_C)) && mIns[predXPos + 2].mAddress + 1 == mIns[i + 2].mAddress)
if (predXPos >= 0 && !(mIns[i + 2].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_C)) && ((mIns[predXPos + 2].mAddress + 1) & 0xff) == mIns[i + 2].mAddress)
{
// Remove add
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
@ -14918,6 +15027,26 @@ bool NativeCodeBasicBlock::JoinXYCascade(void)
changed = true;
}
else if (predXPos >= 0 && !(mIns[i + 2].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_C)) && ((mIns[predXPos + 2].mAddress - 1) & 0xff) == mIns[i + 2].mAddress)
{
// Remove add
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
// Insert DEX
mIns.Insert(i, NativeCodeInstruction(mIns[i].mIns, ASMIT_DEX));
// Insert TAX
mIns[predXPos + 2].mLive &= ~LIVE_CPU_REG_X;
mIns.Insert(predXPos + 3, NativeCodeInstruction(mIns[i].mIns, ASMIT_TAX));
// Restart
restart = true;
predXPos = -1;
predYPos = -1;
changed = true;
}
else
predXPos = i;
}
@ -14927,7 +15056,7 @@ bool NativeCodeBasicBlock::JoinXYCascade(void)
mIns[i + 1].mType == ASMIT_CLC &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE)
{
if (predYPos >= 0 && !(mIns[i + 2].mLive & (LIVE_CPU_REG_Y | LIVE_CPU_REG_C)) && mIns[predYPos + 2].mAddress + 1 == mIns[i + 2].mAddress)
if (predYPos >= 0 && !(mIns[i + 2].mLive & (LIVE_CPU_REG_Y | LIVE_CPU_REG_C)) && ((mIns[predYPos + 2].mAddress + 1) & 0xff) == mIns[i + 2].mAddress)
{
// Remove add
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
@ -14947,6 +15076,26 @@ bool NativeCodeBasicBlock::JoinXYCascade(void)
changed = true;
}
else if (predYPos >= 0 && !(mIns[i + 2].mLive & (LIVE_CPU_REG_Y | LIVE_CPU_REG_C)) && ((mIns[predYPos + 2].mAddress - 1) & 0xff) == mIns[i + 2].mAddress)
{
// Remove add
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
// Insert DEY
mIns.Insert(i, NativeCodeInstruction(mIns[i].mIns, ASMIT_DEY));
// Insert TAX
mIns[predYPos + 2].mLive &= ~LIVE_CPU_REG_Y;
mIns.Insert(predYPos + 3, NativeCodeInstruction(mIns[i].mIns, ASMIT_TAY));
// Restart
restart = true;
predXPos = -1;
predYPos = -1;
changed = true;
}
else
predYPos = i;
}
@ -41436,6 +41585,25 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 3].mType = ASMIT_NOP;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_TXA &&
mIns[i + 1].mType == ASMIT_CLC &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress >= 0xfe &&
mIns[i + 3].mType == ASMIT_TAX && !(mIns[i + 3].mLive & LIVE_CPU_REG_C))
{
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X | LIVE_CPU_REG_Z;
if (mIns[i + 2].mAddress == 0xfe)
mIns[i + 2].mType = ASMIT_DEX;
else
mIns[i + 2].mType = ASMIT_NOP;
mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_X;
if (mIns[i + 3].mLive & LIVE_CPU_REG_A)
mIns[i + 3].mType = ASMIT_TXA;
else
mIns[i + 3].mType = ASMIT_NOP;
progress = true;
}
#endif
else if (
mIns[i + 0].mType == ASMIT_TXA &&
@ -41474,6 +41642,25 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 3].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_TYA &&
mIns[i + 1].mType == ASMIT_CLC &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress >= 0xfe &&
mIns[i + 3].mType == ASMIT_TAY && !(mIns[i + 3].mLive & LIVE_CPU_REG_C))
{
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_Y | LIVE_CPU_REG_Z;
if (mIns[i + 2].mAddress == 0xfe)
mIns[i + 2].mType = ASMIT_DEY;
else
mIns[i + 2].mType = ASMIT_NOP;
mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Y;
if (mIns[i + 3].mLive & LIVE_CPU_REG_A)
mIns[i + 3].mType = ASMIT_TYA;
else
mIns[i + 3].mType = ASMIT_NOP;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_TYA &&
mIns[i + 1].mType == ASMIT_SEC &&
@ -45239,7 +45426,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
{
mInterProc = proc;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "check");
CheckFunc = !strcmp(mInterProc->mIdent->mString, "test");
int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks];
@ -47779,7 +47966,7 @@ void NativeCodeGenerator::BuildFunctionProxies(void)
{
if (ncp->mCount > 1)
{
printf("RFC %s : %d\n", ncp->mLinkerObject->mIdent->mString, ncp->mCount);
// printf("RFC %s : %d\n", ncp->mLinkerObject->mIdent->mString, ncp->mCount);
ncp->mProxyObject = mLinker->AddObject(ncp->mLinkerObject->mLocation, ncp->mLinkerObject->mIdent->Mangle("@proxy"), ncp->mLinkerObject->mSection, ncp->mLinkerObject->mType);
ExpandingArray<uint8> code;

View File

@ -8925,7 +8925,7 @@ 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->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)
{
if (initExp->mRight->mDecValue->mType == DT_CONST_INTEGER && conditionExp->mRight->mDecValue->mType == DT_CONST_INTEGER)
{
@ -8933,6 +8933,17 @@ Expression* Parser::ParseStatement(void)
int endValue = int(conditionExp->mRight->mDecValue->mInteger);
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)
@ -9018,7 +9029,7 @@ Expression* Parser::ParseStatement(void)
Expression* unrollBody = new Expression(mScanner->mLocation, EX_SEQUENCE);
unrollBody->mLeft = bodyExp;
Expression* bexp = unrollBody;
if (endValue > startValue)
if ((endValue - startValue) * stepValue > 0)
{
for (int i = 1; i < unrollLoop; i++)
{
@ -9029,6 +9040,8 @@ Expression* Parser::ParseStatement(void)
bexp = bexp->mRight;
bexp->mLeft = bodyExp;
}
conditionExp->mRight->mDecValue->mInteger = endValue - stepValue * (unrollLoop - 1);
}
if (remain)