Fix infinite optimizer loop

This commit is contained in:
drmortalwombat 2025-01-31 18:43:01 +01:00
parent 28ea8ef24f
commit 0126dd53a3
3 changed files with 117 additions and 6 deletions

View File

@ -14056,6 +14056,9 @@ bool InterCodeBasicBlock::PushSinglePathResultInstructions(void)
{ {
if (mTrueJump->mNumEntries == 1 && trueExitRequiredTemps[dtemp] && !falseExitRequiredTems[dtemp]) if (mTrueJump->mNumEntries == 1 && trueExitRequiredTemps[dtemp] && !falseExitRequiredTems[dtemp])
{ {
if (ins->mDst.mTemp >= 0 && mTrueJump->mEntryValueRange.Size() > ins->mDst.mTemp)
mTrueJump->mEntryValueRange[ins->mDst.mTemp].Reset();
for (int j = 0; j < ins->mNumOperands; j++) for (int j = 0; j < ins->mNumOperands; j++)
{ {
if (ins->mSrc[j].mTemp >= 0) if (ins->mSrc[j].mTemp >= 0)
@ -14073,6 +14076,9 @@ bool InterCodeBasicBlock::PushSinglePathResultInstructions(void)
} }
else if (mFalseJump->mNumEntries == 1 && !trueExitRequiredTemps[dtemp] && falseExitRequiredTems[dtemp]) else if (mFalseJump->mNumEntries == 1 && !trueExitRequiredTemps[dtemp] && falseExitRequiredTems[dtemp])
{ {
if (ins->mDst.mTemp >= 0 && mFalseJump->mEntryValueRange.Size() > ins->mDst.mTemp)
mFalseJump->mEntryValueRange[ins->mDst.mTemp].Reset();
for (int j = 0; j < ins->mNumOperands; j++) for (int j = 0; j < ins->mNumOperands; j++)
{ {
if (ins->mSrc[j].mTemp >= 0) if (ins->mSrc[j].mTemp >= 0)
@ -14116,6 +14122,9 @@ bool InterCodeBasicBlock::PushSinglePathResultInstructions(void)
if (ins->mCode != IC_LOAD || j == mFalseJump->mInstructions.Size()) if (ins->mCode != IC_LOAD || j == mFalseJump->mInstructions.Size())
{ {
if (ins->mDst.mTemp >= 0 && joinedBlock->mEntryValueRange.Size() > ins->mDst.mTemp)
joinedBlock->mEntryValueRange[ins->mDst.mTemp].Reset();
for (int j = 0; j < ins->mNumOperands; j++) for (int j = 0; j < ins->mNumOperands; j++)
{ {
if (ins->mSrc[j].mTemp >= 0) if (ins->mSrc[j].mTemp >= 0)
@ -19673,6 +19682,7 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
mInstructions[i + 1]->mSrc[0].mIntConst >>= shift; mInstructions[i + 1]->mSrc[0].mIntConst >>= shift;
mInstructions[i + 0]->mOperator = IA_AND; mInstructions[i + 0]->mOperator = IA_AND;
mInstructions[i + 0]->mSrc[0].mIntConst = ~((1LL << shift) - 1); mInstructions[i + 0]->mSrc[0].mIntConst = ~((1LL << shift) - 1);
mInstructions[i + 0]->mDst.mRange.Reset();
changed = true; changed = true;
} }
else if ( else if (
@ -19685,6 +19695,7 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
mInstructions[i + 1]->mSrc[1].mIntConst >>= shift; mInstructions[i + 1]->mSrc[1].mIntConst >>= shift;
mInstructions[i + 0]->mOperator = IA_AND; mInstructions[i + 0]->mOperator = IA_AND;
mInstructions[i + 0]->mSrc[0].mIntConst = ~((1LL << shift) - 1); mInstructions[i + 0]->mSrc[0].mIntConst = ~((1LL << shift) - 1);
mInstructions[i + 0]->mDst.mRange.Reset();
changed = true; changed = true;
} }
else if ( else if (
@ -23216,7 +23227,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "runner_entering"); CheckFunc = !strcmp(mIdent->mString, "player_move");
CheckCase = false; CheckCase = false;
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];

View File

@ -1793,7 +1793,7 @@ bool NativeCodeInstruction::IsSameLS(const NativeCodeInstruction& ins) const
return false; return false;
} }
bool NativeCodeInstruction::MayBeMovedBefore(const NativeCodeInstruction& ins) bool NativeCodeInstruction::MayBeMovedBefore(const NativeCodeInstruction& ins) const
{ {
if ((ChangesAddress() || ins.ChangesAddress()) && MayBeSameAddress(ins)) if ((ChangesAddress() || ins.ChangesAddress()) && MayBeSameAddress(ins))
return false; return false;
@ -19196,6 +19196,83 @@ bool NativeCodeBasicBlock::Split16BitLoopCount(NativeCodeProcedure* proc)
return changed; return changed;
} }
bool NativeCodeBasicBlock::MoveStoresBeforeDiamond(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (mTrueJump && mFalseJump)
{
NativeCodeBasicBlock* dblock = nullptr, * eblock = nullptr;
if (mTrueJump->mTrueJump == mFalseJump && !mTrueJump->mFalseJump && mFalseJump->mNumEntries == 2 && mTrueJump->mNumEntries == 1)
{
dblock = mTrueJump;
eblock = mFalseJump;
}
else if (mFalseJump->mTrueJump == mTrueJump && !mFalseJump->mFalseJump && mTrueJump->mNumEntries == 2 && mFalseJump->mNumEntries == 1)
{
dblock = mFalseJump;
eblock = mTrueJump;
}
if (eblock)
{
bool avalid = eblock->mEntryRequiredRegs[CPU_REG_A] && !dblock->ChangesAccu();
bool xvalid = eblock->mEntryRequiredRegs[CPU_REG_X] && !dblock->ChangesXReg();
bool yvalid = eblock->mEntryRequiredRegs[CPU_REG_Y] && !dblock->ChangesYReg();
int i = 0;
while (i < eblock->mIns.Size())
{
NativeCodeInstruction& ins(eblock->mIns[i]);
bool move = false;
if (avalid)
{
if (ins.mType == ASMIT_STA)
move = true;
else if (ins.ChangesAccu())
avalid = false;
}
else if (xvalid)
{
if (ins.mType == ASMIT_STX)
move = true;
else if (ins.ChangesXReg())
xvalid = false;
}
else if (yvalid)
{
if (ins.mType == ASMIT_STY)
move = true;
else if (ins.ChangesYReg())
yvalid = false;
}
else
break;
if (move && eblock->MayBeMovedBeforeBlock(i, ins) && dblock->MayBeMovedBeforeBlock(dblock->mIns.Size(), ins))
{
ins.mLive = LIVE_ALL;
mIns.Push(ins);
eblock->mIns.Remove(i);
changed = true;
}
else
i++;
}
}
}
if (mTrueJump && mTrueJump->MoveStoresBeforeDiamond()) changed = true;
if (mFalseJump && mFalseJump->MoveStoresBeforeDiamond()) changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::CrossBlockFlagsForwarding(void) bool NativeCodeBasicBlock::CrossBlockFlagsForwarding(void)
{ {
bool changed = false; bool changed = false;
@ -26346,6 +26423,19 @@ bool NativeCodeBasicBlock::MayBeMovedBeforeBlock(int at)
return true; return true;
} }
bool NativeCodeBasicBlock::MayBeMovedBeforeBlock(int at, const NativeCodeInstruction& ins)
{
int i = at;
while (i > 0)
{
i--;
if (!ins.MayBeMovedBefore(mIns[i]))
return false;
}
return true;
}
bool NativeCodeBasicBlock::SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end) bool NativeCodeBasicBlock::SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end)
{ {
uint32 changes = 0; uint32 changes = 0;
@ -38734,12 +38824,13 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
if (rind >= 0) if (rind >= 0)
{ {
bool found = false;
for (int i = 0; i < mIns.Size(); i++) for (int i = 0; i < mIns.Size(); i++)
{ {
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == rind) if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == rind)
{ {
if (mIns[i].mType == ASMIT_LDA || mIns[i].mType == ASMIT_STA) if (mIns[i].mType == ASMIT_LDA || mIns[i].mType == ASMIT_STA)
; found = true;
else else
{ {
rind = -2; rind = -2;
@ -38755,7 +38846,7 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
} }
} }
if (rind >= 0) if (rind >= 0 && found)
{ {
if (!prevBlock) if (!prevBlock)
return OptimizeSimpleLoopInvariant(proc, full); return OptimizeSimpleLoopInvariant(proc, full);
@ -52485,7 +52576,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mInterProc->mLinkerObject->mNativeProc = this; mInterProc->mLinkerObject->mNativeProc = this;
CheckFunc = !strcmp(mIdent->mString, "f"); CheckFunc = !strcmp(mIdent->mString, "player_move");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];
@ -54282,6 +54373,13 @@ void NativeCodeProcedure::Optimize(void)
} }
if (step == 19)
{
ResetVisited();
if (mEntryBlock->MoveStoresBeforeDiamond())
changed = true;
}
#if _DEBUG #if _DEBUG
ResetVisited(); ResetVisited();
mEntryBlock->CheckAsmCode(); mEntryBlock->CheckAsmCode();

View File

@ -211,7 +211,7 @@ public:
bool IsShift(void) const; bool IsShift(void) const;
bool IsShiftOrInc(void) const; bool IsShiftOrInc(void) const;
bool IsSimpleJSR(void) const; bool IsSimpleJSR(void) const;
bool MayBeMovedBefore(const NativeCodeInstruction& ins); bool MayBeMovedBefore(const NativeCodeInstruction& ins) const;
bool ReplaceYRegWithXReg(void); bool ReplaceYRegWithXReg(void);
bool ReplaceXRegWithYReg(void); bool ReplaceXRegWithYReg(void);
@ -603,6 +603,7 @@ public:
bool HasTailSTAX16(int& addr, int& index0) const; bool HasTailSTAX16(int& addr, int& index0) const;
bool MayBeMovedBeforeBlock(int at); bool MayBeMovedBeforeBlock(int at);
bool MayBeMovedBeforeBlock(int at, const NativeCodeInstruction & ins);
bool MayBeMovedBeforeBlock(int start, int end); bool MayBeMovedBeforeBlock(int start, int end);
bool SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end); bool SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end);
bool JoinCommonBranchCodeSequences(void); bool JoinCommonBranchCodeSequences(void);
@ -706,6 +707,7 @@ public:
bool EliminateDeadLoops(void); bool EliminateDeadLoops(void);
bool LoopRegisterWrapAround(void); bool LoopRegisterWrapAround(void);
bool CrossBlockFlagsForwarding(void); bool CrossBlockFlagsForwarding(void);
bool MoveStoresBeforeDiamond(void);
bool SinglePathRegisterForwardY(NativeCodeBasicBlock* path, int yreg); bool SinglePathRegisterForwardY(NativeCodeBasicBlock* path, int yreg);
bool SinglePathRegisterForward(void); bool SinglePathRegisterForward(void);