Join common branch code sequences
This commit is contained in:
parent
eec4ed45d1
commit
57537cd43a
|
@ -680,17 +680,21 @@ __native unsigned long ldiv16f16(unsigned long x, unsigned long y)
|
||||||
|
|
||||||
__native long ldiv16f16s(long x, long y)
|
__native long ldiv16f16s(long x, long y)
|
||||||
{
|
{
|
||||||
|
bool sign = false;
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
{
|
{
|
||||||
if (y < 0)
|
x = -x;
|
||||||
return ldiv16f16(-x, -y);
|
sign = true;
|
||||||
else
|
|
||||||
return -ldiv16f16(-x, y);
|
|
||||||
}
|
}
|
||||||
else if (y < 0)
|
if (y < 0)
|
||||||
{
|
{
|
||||||
return -ldiv16f16(x, -y);
|
y = -y;
|
||||||
|
sign = !sign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x = ldiv16f16(x, y);
|
||||||
|
if (sign)
|
||||||
|
return -x;
|
||||||
else
|
else
|
||||||
return ldiv16f16(x, y);
|
return x;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9137,6 +9137,10 @@ bool InterCodeBasicBlock::RemoveUnusedIndirectStoreInstructions(void)
|
||||||
stores.Push(ins);
|
stores.Push(ins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE)
|
||||||
|
{
|
||||||
|
stores.SetSize(0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
@ -11406,30 +11410,33 @@ bool InterCodeBasicBlock::MergeCommonPathInstructions(void)
|
||||||
if (mTrueJump->CanMoveInstructionBeforeBlock(ti) && mFalseJump->CanMoveInstructionBeforeBlock(fi))
|
if (mTrueJump->CanMoveInstructionBeforeBlock(ti) && mFalseJump->CanMoveInstructionBeforeBlock(fi))
|
||||||
{
|
{
|
||||||
int tindex = mInstructions.Size() - 1;
|
int tindex = mInstructions.Size() - 1;
|
||||||
if (mInstructions.Size() >= 2 && mInstructions[tindex - 1]->mDst.mTemp == mInstructions[tindex]->mSrc[0].mTemp &&
|
if (mInstructions[tindex]->mCode != IC_BRANCH || tins->mDst.mTemp != mInstructions[tindex]->mSrc[0].mTemp)
|
||||||
CanSwapInstructions(mInstructions[tindex - 1], tins))
|
|
||||||
// CanBypassUp(tins, mInstructions[tindex - 1]))
|
|
||||||
tindex--;
|
|
||||||
|
|
||||||
mInstructions.Insert(tindex, tins);
|
|
||||||
tindex++;
|
|
||||||
if (tins->mDst.mTemp != -1)
|
|
||||||
{
|
{
|
||||||
if (fins->mDst.mTemp != tins->mDst.mTemp)
|
if (mInstructions.Size() >= 2 && mInstructions[tindex - 1]->mDst.mTemp == mInstructions[tindex]->mSrc[0].mTemp &&
|
||||||
|
CanSwapInstructions(mInstructions[tindex - 1], tins))
|
||||||
|
// CanBypassUp(tins, mInstructions[tindex - 1]))
|
||||||
|
tindex--;
|
||||||
|
|
||||||
|
mInstructions.Insert(tindex, tins);
|
||||||
|
tindex++;
|
||||||
|
if (tins->mDst.mTemp != -1)
|
||||||
{
|
{
|
||||||
InterInstruction* nins = new InterInstruction(tins->mLocation, IC_LOAD_TEMPORARY);
|
if (fins->mDst.mTemp != tins->mDst.mTemp)
|
||||||
nins->mDst.mTemp = fins->mDst.mTemp;
|
{
|
||||||
nins->mDst.mType = fins->mDst.mType;
|
InterInstruction* nins = new InterInstruction(tins->mLocation, IC_LOAD_TEMPORARY);
|
||||||
nins->mSrc[0].mTemp = tins->mDst.mTemp;
|
nins->mDst.mTemp = fins->mDst.mTemp;
|
||||||
nins->mSrc[0].mType = tins->mDst.mType;
|
nins->mDst.mType = fins->mDst.mType;
|
||||||
assert(nins->mSrc[0].mTemp >= 0);
|
nins->mSrc[0].mTemp = tins->mDst.mTemp;
|
||||||
mFalseJump->mInstructions.Insert(0, nins);
|
nins->mSrc[0].mType = tins->mDst.mType;
|
||||||
fi++;
|
assert(nins->mSrc[0].mTemp >= 0);
|
||||||
|
mFalseJump->mInstructions.Insert(0, nins);
|
||||||
|
fi++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mTrueJump->mInstructions.Remove(ti);
|
||||||
|
mFalseJump->mInstructions.Remove(fi);
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
mTrueJump->mInstructions.Remove(ti);
|
|
||||||
mFalseJump->mInstructions.Remove(fi);
|
|
||||||
changed = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18163,6 +18170,8 @@ void InterCodeProcedure::RemoveUnusedStoreInstructions(InterMemory paramMemory)
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->RemoveUnusedIndirectStoreInstructions();
|
mEntryBlock->RemoveUnusedIndirectStoreInstructions();
|
||||||
|
|
||||||
|
DisassembleDebug("RemoveUnusedIndirectStoreInstructions");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18538,7 +18547,9 @@ void InterCodeProcedure::PropagateConstOperationsUp(void)
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (mEntryBlock->SplitSingleBranchUseConst())
|
if (mEntryBlock->SplitSingleBranchUseConst())
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
|
DisassembleDebug("SplitSingleBranchUseConst");
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (mEntryBlock->CommonTailCodeMerge())
|
if (mEntryBlock->CommonTailCodeMerge())
|
||||||
{
|
{
|
||||||
|
@ -18546,6 +18557,8 @@ void InterCodeProcedure::PropagateConstOperationsUp(void)
|
||||||
BuildDataFlowSets();
|
BuildDataFlowSets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisassembleDebug("CommonTailCodeMerge");
|
||||||
|
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->BuildConstTempSets();
|
mEntryBlock->BuildConstTempSets();
|
||||||
|
|
||||||
|
@ -18594,7 +18607,7 @@ void InterCodeProcedure::Close(void)
|
||||||
{
|
{
|
||||||
GrowingTypeArray tstack(IT_NONE);
|
GrowingTypeArray tstack(IT_NONE);
|
||||||
|
|
||||||
CheckFunc = !strcmp(mIdent->mString, "interpret_expression");
|
CheckFunc = !strcmp(mIdent->mString, "parse_expression");
|
||||||
CheckCase = false;
|
CheckCase = false;
|
||||||
|
|
||||||
mEntryBlock = mBlocks[0];
|
mEntryBlock = mBlocks[0];
|
||||||
|
|
|
@ -20,6 +20,8 @@ static const uint32 LIVE_CPU_REG_X = 0x00000002;
|
||||||
static const uint32 LIVE_CPU_REG_Y = 0x00000004;
|
static const uint32 LIVE_CPU_REG_Y = 0x00000004;
|
||||||
static const uint32 LIVE_CPU_REG_C = 0x00000008;
|
static const uint32 LIVE_CPU_REG_C = 0x00000008;
|
||||||
static const uint32 LIVE_CPU_REG_Z = 0x00000010;
|
static const uint32 LIVE_CPU_REG_Z = 0x00000010;
|
||||||
|
static const uint32 LIVE_CPU_REG = 0x0000001f;
|
||||||
|
|
||||||
static const uint32 LIVE_MEM = 0x00000020;
|
static const uint32 LIVE_MEM = 0x00000020;
|
||||||
|
|
||||||
static const uint32 LIVE_ALL = 0x000000ff;
|
static const uint32 LIVE_ALL = 0x000000ff;
|
||||||
|
@ -1542,8 +1544,15 @@ bool NativeCodeInstruction::MayBeMovedBefore(const NativeCodeInstruction& ins)
|
||||||
return false;
|
return false;
|
||||||
if (RequiresCarry() && ins.ChangesCarry() || ins.RequiresCarry() && ChangesCarry())
|
if (RequiresCarry() && ins.ChangesCarry() || ins.RequiresCarry() && ChangesCarry())
|
||||||
return false;
|
return false;
|
||||||
|
if ((mLive & LIVE_CPU_REG_A) && ins.ChangesAccu())
|
||||||
if ((ins.mLive & LIVE_CPU_REG_Z) && ChangesZFlag())
|
return false;
|
||||||
|
if ((mLive & LIVE_CPU_REG_X) && ins.ChangesXReg())
|
||||||
|
return false;
|
||||||
|
if ((mLive & LIVE_CPU_REG_Y) && ins.ChangesYReg())
|
||||||
|
return false;
|
||||||
|
if ((mLive & LIVE_CPU_REG_C) && ins.ChangesCarry())
|
||||||
|
return false;
|
||||||
|
if ((mLive & LIVE_CPU_REG_Z) && ins.ChangesZFlag())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -19674,6 +19683,35 @@ bool NativeCodeBasicBlock::CanForward16BitAddSubImmediate(int sreg, int dreg, in
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::CanForwardLoadStore(const NativeCodeInstruction& lins, const NativeCodeInstruction& sins, int& index) const
|
||||||
|
{
|
||||||
|
int i = mIns.Size() - 1;
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
if (lins.MayBeChangedOnAddress(mIns[i]))
|
||||||
|
return false;
|
||||||
|
if (mIns[i].MayBeSameAddress(sins))
|
||||||
|
{
|
||||||
|
index = i - 1;
|
||||||
|
if (mIns[i].mType == ASMIT_STA && mIns[i - 1].mType == ASMIT_LDA && !(mIns[i].mLive & LIVE_CPU_REG_A) ||
|
||||||
|
mIns[i].mType == ASMIT_STX && mIns[i - 1].mType == ASMIT_LDX && !(mIns[i].mLive & LIVE_CPU_REG_X) ||
|
||||||
|
mIns[i].mType == ASMIT_STY && mIns[i - 1].mType == ASMIT_LDY && !(mIns[i].mLive & LIVE_CPU_REG_Y))
|
||||||
|
{
|
||||||
|
if (!(mIns[i].mLive & LIVE_CPU_REG_Z) && mIns[i].SameEffectiveAddress(sins) && mIns[i - 1].SameEffectiveAddress(lins))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mIns[i].mType == ASMIT_JSR)
|
||||||
|
return false;
|
||||||
|
if (sins.MayBeChangedOnAddress(mIns[i]))
|
||||||
|
return false;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::CanForwardZPMove(int saddr, int daddr, int & index) const
|
bool NativeCodeBasicBlock::CanForwardZPMove(int saddr, int daddr, int & index) const
|
||||||
{
|
{
|
||||||
int i = mIns.Size() - 1;
|
int i = mIns.Size() - 1;
|
||||||
|
@ -20627,6 +20665,51 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if 1
|
||||||
|
if (!changed && !mEntryRequiredRegs[CPU_REG_Z] && (!mEntryRequiredRegs[CPU_REG_A] || !mEntryRequiredRegs[CPU_REG_X] || !mEntryRequiredRegs[CPU_REG_Y]))
|
||||||
|
{
|
||||||
|
for (int i = eb->mIns.Size() - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
if ((eb->mIns[i - 1].mType == ASMIT_LDA && eb->mIns[i - 0].mType == ASMIT_STA ||
|
||||||
|
eb->mIns[i - 1].mType == ASMIT_LDX && eb->mIns[i - 0].mType == ASMIT_STX ||
|
||||||
|
eb->mIns[i - 1].mType == ASMIT_LDY && eb->mIns[i - 0].mType == ASMIT_STY) &&
|
||||||
|
(eb->mIns[i - 1].mMode == ASMIM_ZERO_PAGE || eb->mIns[i - 1].mMode == ASMIM_ABSOLUTE) &&
|
||||||
|
(eb->mIns[i - 0].mMode == ASMIM_ZERO_PAGE || eb->mIns[i - 0].mMode == ASMIM_ABSOLUTE))
|
||||||
|
{
|
||||||
|
int j = 0;
|
||||||
|
while (j < mEntryBlocks.Size() && mEntryBlocks[j]->CanForwardLoadStore(eb->mIns[i - 1], eb->mIns[i - 0], mEntryBlocks[j]->mTemp))
|
||||||
|
j++;
|
||||||
|
|
||||||
|
if (j == mEntryBlocks.Size())
|
||||||
|
{
|
||||||
|
const InterInstruction* iins(eb->mIns[i].mIns);
|
||||||
|
|
||||||
|
if (!mEntryRequiredRegs[CPU_REG_A])
|
||||||
|
{
|
||||||
|
mIns.Insert(0, NativeCodeInstruction(iins, ASMIT_LDA, eb->mIns[i - 1]));
|
||||||
|
mIns.Insert(1, NativeCodeInstruction(iins, ASMIT_STA, eb->mIns[i]));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (!mEntryRequiredRegs[CPU_REG_X])
|
||||||
|
{
|
||||||
|
mIns.Insert(0, NativeCodeInstruction(iins, ASMIT_LDX, eb->mIns[i - 1]));
|
||||||
|
mIns.Insert(1, NativeCodeInstruction(iins, ASMIT_STX, eb->mIns[i]));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (!mEntryRequiredRegs[CPU_REG_Y])
|
||||||
|
{
|
||||||
|
mIns.Insert(0, NativeCodeInstruction(iins, ASMIT_LDY, eb->mIns[i - 1]));
|
||||||
|
mIns.Insert(1, NativeCodeInstruction(iins, ASMIT_STY, eb->mIns[i]));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < mEntryBlocks.Size(); j++)
|
||||||
|
mEntryBlocks[j]->mIns.Remove(mEntryBlocks[j]->mTemp, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mEntryBlocks.Size() >= 1)
|
if (mEntryBlocks.Size() >= 1)
|
||||||
|
@ -21918,6 +22001,246 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::MayBeMovedBeforeBlock(int at)
|
||||||
|
{
|
||||||
|
int i = at;
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
if (!mIns[at].MayBeMovedBefore(mIns[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end)
|
||||||
|
{
|
||||||
|
uint32 changes = 0;
|
||||||
|
uint32 requires = 0;
|
||||||
|
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
const NativeCodeInstruction& ins(block->mIns[i]);
|
||||||
|
if (ins.RequiresAccu() && !(changes & LIVE_CPU_REG_A)) requires |= LIVE_CPU_REG_A;
|
||||||
|
if (ins.RequiresXReg() && !(changes & LIVE_CPU_REG_X)) requires |= LIVE_CPU_REG_X;
|
||||||
|
if (ins.RequiresYReg() && !(changes & LIVE_CPU_REG_Y)) requires |= LIVE_CPU_REG_Y;
|
||||||
|
if (ins.RequiresCarry() && !(changes & LIVE_CPU_REG_C)) requires |= LIVE_CPU_REG_C;
|
||||||
|
if (ins.ChangesAccu()) changes |= LIVE_CPU_REG_A;
|
||||||
|
if (ins.ChangesXReg()) changes |= LIVE_CPU_REG_X;
|
||||||
|
if (ins.ChangesYReg()) changes |= LIVE_CPU_REG_Y;
|
||||||
|
if (ins.ChangesCarry()) changes |= LIVE_CPU_REG_C;
|
||||||
|
if (ins.ChangesZFlag()) changes |= LIVE_CPU_REG_Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 live = 0;
|
||||||
|
if (mBranch == ASMIT_BCC || mBranch == ASMIT_BCS)
|
||||||
|
live |= LIVE_CPU_REG_C;
|
||||||
|
if (mBranch == ASMIT_BEQ || mBranch == ASMIT_BNE || mBranch == ASMIT_BMI || mBranch == ASMIT_BPL)
|
||||||
|
live |= LIVE_CPU_REG_Z;
|
||||||
|
if (mExitRequiredRegs[CPU_REG_A])
|
||||||
|
live |= LIVE_CPU_REG_A;
|
||||||
|
if (mExitRequiredRegs[CPU_REG_X])
|
||||||
|
live |= LIVE_CPU_REG_X;
|
||||||
|
if (mExitRequiredRegs[CPU_REG_Y])
|
||||||
|
live |= LIVE_CPU_REG_Y;
|
||||||
|
if (mExitRequiredRegs[CPU_REG_C])
|
||||||
|
live |= LIVE_CPU_REG_C;
|
||||||
|
|
||||||
|
int at = mIns.Size();
|
||||||
|
while (at > 0)
|
||||||
|
{
|
||||||
|
if (live & changes)
|
||||||
|
{
|
||||||
|
at--;
|
||||||
|
const NativeCodeInstruction& ins(mIns[at]);
|
||||||
|
if (ins.ChangesAccu())
|
||||||
|
{
|
||||||
|
if (requires & LIVE_CPU_REG_A)
|
||||||
|
return false;
|
||||||
|
live &= ~LIVE_CPU_REG_A;
|
||||||
|
}
|
||||||
|
if (ins.ChangesXReg())
|
||||||
|
{
|
||||||
|
if (requires & LIVE_CPU_REG_X)
|
||||||
|
return false;
|
||||||
|
live &= ~LIVE_CPU_REG_X;
|
||||||
|
}
|
||||||
|
if (ins.ChangesYReg())
|
||||||
|
{
|
||||||
|
if (requires & LIVE_CPU_REG_Y)
|
||||||
|
return false;
|
||||||
|
live &= ~LIVE_CPU_REG_Y;
|
||||||
|
}
|
||||||
|
if (ins.ChangesCarry())
|
||||||
|
{
|
||||||
|
if (requires & LIVE_CPU_REG_C)
|
||||||
|
return false;
|
||||||
|
live &= ~LIVE_CPU_REG_C;
|
||||||
|
}
|
||||||
|
if (ins.ChangesZFlag()) live &= ~LIVE_CPU_REG_Z;
|
||||||
|
|
||||||
|
if (ins.RequiresAccu())
|
||||||
|
live |= LIVE_CPU_REG_A;
|
||||||
|
if (ins.RequiresXReg())
|
||||||
|
live |= LIVE_CPU_REG_X;
|
||||||
|
if (ins.RequiresYReg())
|
||||||
|
live |= LIVE_CPU_REG_Y;
|
||||||
|
if (ins.RequiresCarry())
|
||||||
|
live |= LIVE_CPU_REG_C;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
for (int j = at; j < mIns.Size(); j++)
|
||||||
|
{
|
||||||
|
if (block->mIns[i].MayBeChangedOnAddress(mIns[j]) || mIns[j].MayBeChangedOnAddress(block->mIns[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
mIns.Insert(at, block->mIns[i]);
|
||||||
|
mIns[at].mLive |= live;
|
||||||
|
at++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::MayBeMovedBeforeBlock(int start, int end)
|
||||||
|
{
|
||||||
|
uint32 changes = 0;
|
||||||
|
uint32 requires = 0;
|
||||||
|
|
||||||
|
if (start == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
const NativeCodeInstruction& ins(mIns[i]);
|
||||||
|
if (ins.RequiresAccu() && !(changes & LIVE_CPU_REG_A)) requires |= LIVE_CPU_REG_A;
|
||||||
|
if (ins.RequiresXReg() && !(changes & LIVE_CPU_REG_X)) requires |= LIVE_CPU_REG_X;
|
||||||
|
if (ins.RequiresYReg() && !(changes & LIVE_CPU_REG_Y)) requires |= LIVE_CPU_REG_Y;
|
||||||
|
if (ins.RequiresCarry() && !(changes & LIVE_CPU_REG_C)) requires |= LIVE_CPU_REG_C;
|
||||||
|
if (ins.ChangesAccu()) changes |= LIVE_CPU_REG_A;
|
||||||
|
if (ins.ChangesXReg()) changes |= LIVE_CPU_REG_X;
|
||||||
|
if (ins.ChangesYReg()) changes |= LIVE_CPU_REG_Y;
|
||||||
|
if (ins.ChangesCarry()) changes |= LIVE_CPU_REG_C;
|
||||||
|
if (ins.ChangesZFlag()) changes |= LIVE_CPU_REG_Z;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < start; i++)
|
||||||
|
{
|
||||||
|
const NativeCodeInstruction& ins(mIns[i]);
|
||||||
|
if (ins.ChangesAccu() && (requires & LIVE_CPU_REG_A))
|
||||||
|
return false;
|
||||||
|
if (ins.ChangesXReg() && (requires & LIVE_CPU_REG_X))
|
||||||
|
return false;
|
||||||
|
if (ins.ChangesYReg() && (requires & LIVE_CPU_REG_Y))
|
||||||
|
return false;
|
||||||
|
if (ins.ChangesCarry() && (requires & LIVE_CPU_REG_C))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int j = start; j < end; j++)
|
||||||
|
{
|
||||||
|
if (mIns[i].MayBeChangedOnAddress(mIns[j]) || mIns[j].MayBeChangedOnAddress(mIns[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::JoinCommonBranchCodeSequences(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
if (mTrueJump && mFalseJump && mTrueJump->mIns.Size() > 0 && mFalseJump->mIns.Size() > 0 &&
|
||||||
|
mTrueJump != this && mFalseJump != this &&
|
||||||
|
mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (i < mTrueJump->mIns.Size())
|
||||||
|
{
|
||||||
|
int j = 0;
|
||||||
|
while (j < mFalseJump->mIns.Size() && !mFalseJump->mIns[j].IsSame(mTrueJump->mIns[i]))
|
||||||
|
j++;
|
||||||
|
if (j < mFalseJump->mIns.Size())
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
while (i + n < mTrueJump->mIns.Size() && j + n < mFalseJump->mIns.Size() && ((mTrueJump->mIns[i + n].mLive & LIVE_CPU_REG) || (mFalseJump->mIns[j + n].mLive & LIVE_CPU_REG)))
|
||||||
|
n++;
|
||||||
|
|
||||||
|
if (i + n < mTrueJump->mIns.Size() && j + n < mFalseJump->mIns.Size())
|
||||||
|
{
|
||||||
|
if (mTrueJump->MayBeMovedBeforeBlock(i, i + n + 1) && mFalseJump->MayBeMovedBeforeBlock(j, j + n + 1))
|
||||||
|
{
|
||||||
|
if (SafeInjectSequenceFromBack(mTrueJump, i, i + n + 1))
|
||||||
|
{
|
||||||
|
for (int k = 0; k < i; k++)
|
||||||
|
mTrueJump->mIns[k].mLive |= mTrueJump->mIns[i].mLive;
|
||||||
|
for (int k = 0; k < j; k++)
|
||||||
|
mFalseJump->mIns[k].mLive |= mFalseJump->mIns[j].mLive;
|
||||||
|
if (mTrueJump->mIns[i].mLive & LIVE_CPU_REG_A)
|
||||||
|
{
|
||||||
|
mTrueJump->mEntryRequiredRegs += CPU_REG_A;
|
||||||
|
mFalseJump->mEntryRequiredRegs += CPU_REG_A;
|
||||||
|
}
|
||||||
|
if (mTrueJump->mIns[i].mLive & LIVE_CPU_REG_X)
|
||||||
|
{
|
||||||
|
mTrueJump->mEntryRequiredRegs += CPU_REG_X;
|
||||||
|
mFalseJump->mEntryRequiredRegs += CPU_REG_X;
|
||||||
|
}
|
||||||
|
if (mTrueJump->mIns[i].mLive & LIVE_CPU_REG_Y)
|
||||||
|
{
|
||||||
|
mTrueJump->mEntryRequiredRegs += CPU_REG_Y;
|
||||||
|
mFalseJump->mEntryRequiredRegs += CPU_REG_Y;
|
||||||
|
}
|
||||||
|
if (mTrueJump->mIns[i].mLive & LIVE_CPU_REG_C)
|
||||||
|
{
|
||||||
|
mTrueJump->mEntryRequiredRegs += CPU_REG_C;
|
||||||
|
mFalseJump->mEntryRequiredRegs += CPU_REG_C;
|
||||||
|
}
|
||||||
|
|
||||||
|
mTrueJump->mIns.Remove(i, n + 1);
|
||||||
|
mFalseJump->mIns.Remove(j, n + 1);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckLive();
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->JoinCommonBranchCodeSequences())
|
||||||
|
changed = true;
|
||||||
|
if (mFalseJump && mFalseJump->JoinCommonBranchCodeSequences())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
void NativeCodeBasicBlock::DoCrossBlockAShortcut(int addr)
|
void NativeCodeBasicBlock::DoCrossBlockAShortcut(int addr)
|
||||||
{
|
{
|
||||||
mExitRequiredRegs += CPU_REG_A;
|
mExitRequiredRegs += CPU_REG_A;
|
||||||
|
@ -23457,15 +23780,18 @@ bool NativeCodeBasicBlock::PatchCrossBlock16BitFloodExit(const NativeCodeBasicBl
|
||||||
{
|
{
|
||||||
NativeCodeInstruction& ins(mIns[at]);
|
NativeCodeInstruction& ins(mIns[at]);
|
||||||
|
|
||||||
if (ins.mAddress == dreg)
|
if (ins.mMode == ASMIM_ZERO_PAGE || ins.mMode == ASMIM_ZERO_PAGE_X || ins.mMode == ASMIM_ZERO_PAGE_Y || ins.mMode == ASMIM_INDIRECT_X || ins.mMode == ASMIM_INDIRECT_Y)
|
||||||
{
|
{
|
||||||
ins.mAddress = sreg;
|
if (ins.mAddress == dreg)
|
||||||
changed = true;
|
{
|
||||||
}
|
ins.mAddress = sreg;
|
||||||
else if (ins.mAddress == dreg + 1)
|
changed = true;
|
||||||
{
|
}
|
||||||
ins.mAddress = sreg + 1;
|
else if (ins.mAddress == dreg + 1)
|
||||||
changed = true;
|
{
|
||||||
|
ins.mAddress = sreg + 1;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
at--;
|
at--;
|
||||||
|
@ -26862,6 +27188,54 @@ bool NativeCodeBasicBlock::MoveZeroPageCrossBlockUp(int at, const NativeCodeInst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::ShortcutCrossBlockCondition(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
int sz = mIns.Size();
|
||||||
|
if (sz > 0 && mIns[sz - 1].mType == ASMIT_LDA && mIns[sz - 1].mMode == ASMIM_IMMEDIATE && !mFalseJump)
|
||||||
|
{
|
||||||
|
if (mTrueJump->mIns.Size() == 2 && mTrueJump->mIns[0].mType == ASMIT_STA &&
|
||||||
|
mTrueJump->mIns[1].mType == ASMIT_ORA && mTrueJump->mIns[1].mMode == ASMIM_IMMEDIATE && mTrueJump->mIns[1].mAddress == 0 &&
|
||||||
|
(mTrueJump->mBranch == ASMIT_BEQ || mTrueJump->mBranch == ASMIT_BNE))
|
||||||
|
{
|
||||||
|
mIns.Push(mTrueJump->mIns[0]);
|
||||||
|
|
||||||
|
mTrueJump->mNumEntries--;
|
||||||
|
mTrueJump->mEntryBlocks.Remove(mTrueJump->mEntryBlocks.IndexOf(this));
|
||||||
|
if (mTrueJump->mBranch == ASMIT_BEQ)
|
||||||
|
{
|
||||||
|
if (mIns[sz - 1].mAddress == 0)
|
||||||
|
mTrueJump = mTrueJump->mTrueJump;
|
||||||
|
else
|
||||||
|
mTrueJump = mTrueJump->mFalseJump;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mIns[sz - 1].mAddress != 0)
|
||||||
|
mTrueJump = mTrueJump->mTrueJump;
|
||||||
|
else
|
||||||
|
mTrueJump = mTrueJump->mFalseJump;
|
||||||
|
}
|
||||||
|
mTrueJump->mNumEntries++;
|
||||||
|
mTrueJump->mEntryBlocks.Push(this);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->ShortcutCrossBlockCondition())
|
||||||
|
changed = true;
|
||||||
|
if (mFalseJump && mFalseJump->ShortcutCrossBlockCondition())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::ShortcutCrossBlockMoves(NativeCodeProcedure* proc)
|
bool NativeCodeBasicBlock::ShortcutCrossBlockMoves(NativeCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -40445,6 +40819,20 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
|
||||||
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
|
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
|
||||||
|
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (
|
||||||
|
mIns[i + 0].mType == ASMIT_LDA &&
|
||||||
|
mIns[i + 1].mType == ASMIT_STA &&
|
||||||
|
mIns[i + 2].mType == ASMIT_CLC &&
|
||||||
|
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 255 &&
|
||||||
|
mIns[i + 4].mType == ASMIT_STA && mIns[i + 4].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 4].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)) &&
|
||||||
|
HasAsmInstructionMode(ASMIT_DEC, mIns[i + 0].mMode))
|
||||||
|
{
|
||||||
|
mIns[i + 4].mType = ASMIT_DEC;
|
||||||
|
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
|
||||||
|
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -42803,7 +43191,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
mInterProc = proc;
|
mInterProc = proc;
|
||||||
|
|
||||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "interpret_expression");
|
CheckFunc = !strcmp(mInterProc->mIdent->mString, "dungeon_init");
|
||||||
|
|
||||||
int nblocks = proc->mBlocks.Size();
|
int nblocks = proc->mBlocks.Size();
|
||||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||||
|
@ -43711,6 +44099,14 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (step > 6 && !changed)
|
||||||
|
{
|
||||||
|
ResetVisited();
|
||||||
|
if (mEntryBlock->ShortcutCrossBlockCondition())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->CheckBlocks(true);
|
mEntryBlock->CheckBlocks(true);
|
||||||
|
@ -43731,6 +44127,16 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (step > 2 && !changed)
|
||||||
|
{
|
||||||
|
ResetVisited();
|
||||||
|
if (mEntryBlock->JoinCommonBranchCodeSequences())
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
BuildDataFlowSets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (step > 4)
|
if (step > 4)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
|
|
|
@ -459,6 +459,7 @@ public:
|
||||||
|
|
||||||
bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins);
|
bool MoveZeroPageCrossBlockUp(int at, const NativeCodeInstruction & lins, const NativeCodeInstruction & sins);
|
||||||
bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc);
|
bool ShortcutCrossBlockMoves(NativeCodeProcedure* proc);
|
||||||
|
bool ShortcutCrossBlockCondition(void);
|
||||||
|
|
||||||
bool CanReplaceYRegWithXReg(int start, int end);
|
bool CanReplaceYRegWithXReg(int start, int end);
|
||||||
bool CanReplaceXRegWithYReg(int start, int end);
|
bool CanReplaceXRegWithYReg(int start, int end);
|
||||||
|
@ -518,6 +519,11 @@ public:
|
||||||
bool HasTailSTY(int& addr, int& index) const;
|
bool HasTailSTY(int& addr, int& index) const;
|
||||||
bool HasTailSTAX16(int& addr, int& index0) const;
|
bool HasTailSTAX16(int& addr, int& index0) const;
|
||||||
|
|
||||||
|
bool MayBeMovedBeforeBlock(int at);
|
||||||
|
bool MayBeMovedBeforeBlock(int start, int end);
|
||||||
|
bool SafeInjectSequenceFromBack(NativeCodeBasicBlock* block, int start, int end);
|
||||||
|
bool JoinCommonBranchCodeSequences(void);
|
||||||
|
|
||||||
bool CanJoinEntryLoadStoreZP(int saddr, int daddr);
|
bool CanJoinEntryLoadStoreZP(int saddr, int daddr);
|
||||||
bool DoJoinEntryLoadStoreZP(int saddr, int daddr);
|
bool DoJoinEntryLoadStoreZP(int saddr, int daddr);
|
||||||
bool JoinEntryLoadStoreZP(void);
|
bool JoinEntryLoadStoreZP(void);
|
||||||
|
@ -621,8 +627,8 @@ public:
|
||||||
bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex);
|
bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex);
|
||||||
bool PropagateCommonSubExpression(void);
|
bool PropagateCommonSubExpression(void);
|
||||||
|
|
||||||
bool ForwardAbsoluteLoadStores(void);
|
|
||||||
bool CanForwardZPMove(int saddr, int daddr, int & index) const;
|
bool CanForwardZPMove(int saddr, int daddr, int & index) const;
|
||||||
|
bool CanForwardLoadStore(const NativeCodeInstruction & lins, const NativeCodeInstruction & sins, int& index) const;
|
||||||
bool Is16BitAddSubImmediate(int at, int& sreg, int &dreg, int& offset) const;
|
bool Is16BitAddSubImmediate(int at, int& sreg, int &dreg, int& offset) const;
|
||||||
bool CanForward16BitAddSubImmediate(int sreg, int dreg, int offset, int & index) const;
|
bool CanForward16BitAddSubImmediate(int sreg, int dreg, int offset, int & index) const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue