Move conditions out of loops
This commit is contained in:
parent
8fd560a643
commit
cf28c1a618
|
@ -628,6 +628,178 @@ unsigned long lmul16f16(unsigned long x, unsigned long y)
|
||||||
return ll;
|
return ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
long lmul16f16s(long x, long y)
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
lda #0
|
||||||
|
// fractional
|
||||||
|
sta __tmp + 0
|
||||||
|
sta __tmp + 1
|
||||||
|
|
||||||
|
// result
|
||||||
|
sta __accu + 0
|
||||||
|
sta __accu + 1
|
||||||
|
sta __accu + 2
|
||||||
|
sta __accu + 3
|
||||||
|
|
||||||
|
lda x + 0
|
||||||
|
ora x + 1
|
||||||
|
ora y + 0
|
||||||
|
ora y + 1
|
||||||
|
bne w0b
|
||||||
|
|
||||||
|
l2:
|
||||||
|
|
||||||
|
lsr x + 2
|
||||||
|
bcc ws1
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda y + 2
|
||||||
|
adc __accu + 2
|
||||||
|
sta __accu + 2
|
||||||
|
lda y + 3
|
||||||
|
adc __accu + 3
|
||||||
|
sta __accu + 3
|
||||||
|
ws1:
|
||||||
|
|
||||||
|
lsr x + 3
|
||||||
|
bcc ws2
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda y + 2
|
||||||
|
adc __accu + 3
|
||||||
|
sta __accu + 3
|
||||||
|
ws2:
|
||||||
|
|
||||||
|
asl y + 2
|
||||||
|
rol y + 3
|
||||||
|
|
||||||
|
lda x + 2
|
||||||
|
ora x + 3
|
||||||
|
bne l2
|
||||||
|
rts
|
||||||
|
|
||||||
|
w0b:
|
||||||
|
|
||||||
|
lda y + 3
|
||||||
|
and #$80
|
||||||
|
beq w0
|
||||||
|
lda #$ff
|
||||||
|
w0:
|
||||||
|
// overflow
|
||||||
|
sta __tmp + 2
|
||||||
|
sta __tmp + 3
|
||||||
|
|
||||||
|
lda x + 3
|
||||||
|
bpl w0a
|
||||||
|
|
||||||
|
sec
|
||||||
|
lda #0
|
||||||
|
sbc y + 0
|
||||||
|
sta __accu + 2
|
||||||
|
lda #0
|
||||||
|
sbc y + 1
|
||||||
|
sta __accu + 3
|
||||||
|
w0a:
|
||||||
|
|
||||||
|
ldx #8
|
||||||
|
|
||||||
|
l1:
|
||||||
|
lsr x + 0
|
||||||
|
bcc w1
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda y + 0
|
||||||
|
adc __tmp + 0
|
||||||
|
sta __tmp + 0
|
||||||
|
lda y + 1
|
||||||
|
adc __tmp + 1
|
||||||
|
sta __tmp + 1
|
||||||
|
lda y + 2
|
||||||
|
adc __accu + 0
|
||||||
|
sta __accu + 0
|
||||||
|
lda y + 3
|
||||||
|
adc __accu + 1
|
||||||
|
sta __accu + 1
|
||||||
|
lda __tmp + 2
|
||||||
|
adc __accu + 2
|
||||||
|
sta __accu + 2
|
||||||
|
lda __tmp + 3
|
||||||
|
adc __accu + 3
|
||||||
|
sta __accu + 3
|
||||||
|
w1:
|
||||||
|
|
||||||
|
lsr x + 1
|
||||||
|
bcc w2
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda y + 0
|
||||||
|
adc __tmp + 1
|
||||||
|
sta __tmp + 1
|
||||||
|
lda y + 1
|
||||||
|
adc __accu + 0
|
||||||
|
sta __accu + 0
|
||||||
|
lda y + 2
|
||||||
|
adc __accu + 1
|
||||||
|
sta __accu + 1
|
||||||
|
lda y + 3
|
||||||
|
adc __accu + 2
|
||||||
|
sta __accu + 2
|
||||||
|
lda __tmp + 2
|
||||||
|
adc __accu + 3
|
||||||
|
sta __accu + 3
|
||||||
|
w2:
|
||||||
|
|
||||||
|
lsr x + 2
|
||||||
|
bcc w3
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda y + 0
|
||||||
|
adc __accu + 0
|
||||||
|
sta __accu + 0
|
||||||
|
lda y + 1
|
||||||
|
adc __accu + 1
|
||||||
|
sta __accu + 1
|
||||||
|
lda y + 2
|
||||||
|
adc __accu + 2
|
||||||
|
sta __accu + 2
|
||||||
|
lda y + 3
|
||||||
|
adc __accu + 3
|
||||||
|
sta __accu + 3
|
||||||
|
w3:
|
||||||
|
|
||||||
|
lsr x + 3
|
||||||
|
bcc w4
|
||||||
|
|
||||||
|
clc
|
||||||
|
lda y + 0
|
||||||
|
adc __accu + 1
|
||||||
|
sta __accu + 1
|
||||||
|
lda y + 1
|
||||||
|
adc __accu + 2
|
||||||
|
sta __accu + 2
|
||||||
|
lda y + 2
|
||||||
|
adc __accu + 3
|
||||||
|
sta __accu + 3
|
||||||
|
w4:
|
||||||
|
|
||||||
|
asl y + 0
|
||||||
|
rol y + 1
|
||||||
|
rol y + 2
|
||||||
|
rol y + 3
|
||||||
|
rol __tmp + 2
|
||||||
|
rol __tmp + 3
|
||||||
|
|
||||||
|
dex
|
||||||
|
beq w5
|
||||||
|
jmp l1
|
||||||
|
w5:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
__native long lmul16f16s(long x, long y)
|
__native long lmul16f16s(long x, long y)
|
||||||
{
|
{
|
||||||
unsigned lox = x;
|
unsigned lox = x;
|
||||||
|
@ -656,6 +828,7 @@ __native long lmul16f16s(long x, long y)
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
__native unsigned long ldiv16f16(unsigned long x, unsigned long y)
|
__native unsigned long ldiv16f16(unsigned long x, unsigned long y)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4847,6 +4847,14 @@ InterCodeBasicBlock::~InterCodeBasicBlock(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InterCodeBasicBlock* InterCodeBasicBlock::Clone(void)
|
||||||
|
{
|
||||||
|
InterCodeBasicBlock* nblock = new InterCodeBasicBlock(mProc);
|
||||||
|
for (int i = 0; i < mInstructions.Size(); i++)
|
||||||
|
nblock->mInstructions.Push(mInstructions[i]->Clone());
|
||||||
|
return nblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterCodeBasicBlock::Append(InterInstruction * code)
|
void InterCodeBasicBlock::Append(InterInstruction * code)
|
||||||
{
|
{
|
||||||
|
@ -14007,6 +14015,143 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool IsTempModifiedInBlocks(const ExpandingArray<InterCodeBasicBlock*>& body, int temp)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < body.Size(); j++)
|
||||||
|
if (body[j]->IsTempModified(temp))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsInsSrcModifiedInBlocks(const ExpandingArray<InterCodeBasicBlock*>& body, const InterInstruction * ins)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ins->mNumOperands; i++)
|
||||||
|
{
|
||||||
|
if (ins->mSrc[i].mTemp >= 0 && IsTempModifiedInBlocks(body, ins->mSrc[i].mTemp))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InterCodeBasicBlock::MoveConditionOutOfLoop(void)
|
||||||
|
{
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
if (mLoopHead)
|
||||||
|
{
|
||||||
|
ExpandingArray<InterCodeBasicBlock*> body, path;
|
||||||
|
body.Push(this);
|
||||||
|
bool innerLoop = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||||
|
{
|
||||||
|
if (mEntryBlocks[i] != mLoopPrefix)
|
||||||
|
{
|
||||||
|
if (!mEntryBlocks[i]->CollectLoopBody(this, body))
|
||||||
|
innerLoop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (innerLoop)
|
||||||
|
{
|
||||||
|
// Find all conditions based on invariants
|
||||||
|
for (int i = 0; i < body.Size(); i++)
|
||||||
|
{
|
||||||
|
InterCodeBasicBlock* block = body[i];
|
||||||
|
int nins = block->mInstructions.Size();
|
||||||
|
if (block->mFalseJump && block->mInstructions[nins-1]->mCode == IC_BRANCH && body.Contains(block->mFalseJump) && body.Contains(block->mTrueJump))
|
||||||
|
{
|
||||||
|
int ncins = 0;
|
||||||
|
if (!IsInsSrcModifiedInBlocks(body, block->mInstructions[nins - 1]))
|
||||||
|
ncins = 1;
|
||||||
|
else if (nins > 1 && block->mInstructions[nins - 2]->mCode == IC_RELATIONAL_OPERATOR &&
|
||||||
|
block->mInstructions[nins - 1]->mSrc[0].mTemp == block->mInstructions[nins - 2]->mDst.mTemp && block->mInstructions[nins - 1]->mSrc[0].mFinal &&
|
||||||
|
!IsInsSrcModifiedInBlocks(body, block->mInstructions[nins - 2]))
|
||||||
|
ncins = 2;
|
||||||
|
|
||||||
|
if (ncins > 0)
|
||||||
|
{
|
||||||
|
// The condition is not modified on the path
|
||||||
|
// Now check the number of instructions in the conditional section
|
||||||
|
|
||||||
|
int ninside = 0, noutside = 0;
|
||||||
|
for (int i = 0; i < body.Size(); i++)
|
||||||
|
{
|
||||||
|
bool tdom = block->mTrueJump->IsDirectDominatorBlock(body[i]);
|
||||||
|
bool fdom = block->mFalseJump->IsDirectDominatorBlock(body[i]);
|
||||||
|
if (tdom != fdom)
|
||||||
|
ninside += body[i]->mInstructions.Size();
|
||||||
|
else
|
||||||
|
noutside += body[i]->mInstructions.Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less than four instructions outside of condition, or twice as many
|
||||||
|
// inside as outside is the trigger
|
||||||
|
if (noutside - ncins < 4 || ninside > 2 * (noutside - ncins))
|
||||||
|
{
|
||||||
|
// Now clone the loop into a true and a false branch
|
||||||
|
|
||||||
|
GrowingArray<InterCodeBasicBlock*> copies(nullptr);
|
||||||
|
for (int i = 0; i < body.Size(); i++)
|
||||||
|
{
|
||||||
|
InterCodeBasicBlock* nblock = body[i]->Clone();
|
||||||
|
copies[body[i]->mIndex] = nblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < body.Size(); i++)
|
||||||
|
{
|
||||||
|
InterCodeBasicBlock* rblock = body[i];
|
||||||
|
InterCodeBasicBlock* nblock = copies[rblock->mIndex];
|
||||||
|
if (rblock->mTrueJump)
|
||||||
|
{
|
||||||
|
InterCodeBasicBlock* tblock = copies[rblock->mTrueJump->mIndex];
|
||||||
|
if (tblock)
|
||||||
|
nblock->mTrueJump = tblock;
|
||||||
|
else
|
||||||
|
nblock->mTrueJump = rblock->mTrueJump;
|
||||||
|
}
|
||||||
|
if (rblock->mFalseJump)
|
||||||
|
{
|
||||||
|
InterCodeBasicBlock* tblock = copies[rblock->mFalseJump->mIndex];
|
||||||
|
if (tblock)
|
||||||
|
nblock->mFalseJump = tblock;
|
||||||
|
else
|
||||||
|
nblock->mFalseJump = rblock->mFalseJump;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mLoopPrefix->mInstructions.Pop();
|
||||||
|
for (int i = 0; i < ncins; i++)
|
||||||
|
mLoopPrefix->mInstructions.Push(block->mInstructions[nins - ncins + i]->Clone());
|
||||||
|
|
||||||
|
block->mInstructions[nins - 1]->mSrc[0].mTemp = -1;
|
||||||
|
block->mInstructions[nins - 1]->mSrc[0].mIntConst = 1;
|
||||||
|
|
||||||
|
mLoopPrefix->mFalseJump = copies[mLoopPrefix->mTrueJump->mIndex];
|
||||||
|
|
||||||
|
InterCodeBasicBlock* nblock = copies[block->mIndex];
|
||||||
|
nblock->mInstructions[nins - 1]->mSrc[0].mTemp = -1;
|
||||||
|
nblock->mInstructions[nins - 1]->mSrc[0].mIntConst = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->MoveConditionOutOfLoop())
|
||||||
|
return true;
|
||||||
|
if (mFalseJump && mFalseJump->MoveConditionOutOfLoop())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void InterCodeBasicBlock::PushMoveOutOfLoop(void)
|
void InterCodeBasicBlock::PushMoveOutOfLoop(void)
|
||||||
{
|
{
|
||||||
|
@ -17977,6 +18122,38 @@ void InterCodeProcedure::CheckUsedDefinedTemps(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterCodeProcedure::MoveConditionsOutOfLoop(void)
|
||||||
|
{
|
||||||
|
BuildTraces(false);
|
||||||
|
BuildLoopPrefix();
|
||||||
|
ResetEntryBlocks();
|
||||||
|
ResetVisited();
|
||||||
|
mEntryBlock->CollectEntryBlocks(nullptr);
|
||||||
|
|
||||||
|
Disassemble("PreMoveConditionOutOfLoop");
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
while (mEntryBlock->MoveConditionOutOfLoop())
|
||||||
|
{
|
||||||
|
Disassemble("MoveConditionOutOfLoop");
|
||||||
|
|
||||||
|
BuildDataFlowSets();
|
||||||
|
TempForwarding();
|
||||||
|
RemoveUnusedInstructions();
|
||||||
|
|
||||||
|
BuildTraces(false);
|
||||||
|
BuildLoopPrefix();
|
||||||
|
ResetEntryBlocks();
|
||||||
|
ResetVisited();
|
||||||
|
mEntryBlock->CollectEntryBlocks(nullptr);
|
||||||
|
|
||||||
|
Disassemble("PostMoveConditionOutOfLoop");
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterCodeProcedure::PropagateMemoryAliasingInfo(void)
|
void InterCodeProcedure::PropagateMemoryAliasingInfo(void)
|
||||||
{
|
{
|
||||||
GrowingInstructionPtrArray tvalue(nullptr);
|
GrowingInstructionPtrArray tvalue(nullptr);
|
||||||
|
@ -18607,7 +18784,7 @@ void InterCodeProcedure::Close(void)
|
||||||
{
|
{
|
||||||
GrowingTypeArray tstack(IT_NONE);
|
GrowingTypeArray tstack(IT_NONE);
|
||||||
|
|
||||||
CheckFunc = !strcmp(mIdent->mString, "parse_expression");
|
CheckFunc = !strcmp(mIdent->mString, "main");
|
||||||
CheckCase = false;
|
CheckCase = false;
|
||||||
|
|
||||||
mEntryBlock = mBlocks[0];
|
mEntryBlock = mBlocks[0];
|
||||||
|
@ -19258,6 +19435,11 @@ void InterCodeProcedure::Close(void)
|
||||||
|
|
||||||
RemoveUnusedLocalStoreInstructions();
|
RemoveUnusedLocalStoreInstructions();
|
||||||
|
|
||||||
|
if (mCompilerOptions & COPT_OPTIMIZE_BASIC)
|
||||||
|
{
|
||||||
|
MoveConditionsOutOfLoop();
|
||||||
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
|
|
||||||
|
|
|
@ -398,6 +398,8 @@ public:
|
||||||
InterCodeBasicBlock(InterCodeProcedure * proc);
|
InterCodeBasicBlock(InterCodeProcedure * proc);
|
||||||
~InterCodeBasicBlock(void);
|
~InterCodeBasicBlock(void);
|
||||||
|
|
||||||
|
InterCodeBasicBlock* Clone(void);
|
||||||
|
|
||||||
void Append(InterInstruction * code);
|
void Append(InterInstruction * code);
|
||||||
const InterInstruction* FindByDst(int dst) const;
|
const InterInstruction* FindByDst(int dst) const;
|
||||||
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
|
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
|
||||||
|
@ -576,6 +578,7 @@ public:
|
||||||
void CollectLoopPath(const ExpandingArray<InterCodeBasicBlock*>& body, ExpandingArray<InterCodeBasicBlock*>& path);
|
void CollectLoopPath(const ExpandingArray<InterCodeBasicBlock*>& body, ExpandingArray<InterCodeBasicBlock*>& path);
|
||||||
void InnerLoopOptimization(const NumberSet& aliasedParams);
|
void InnerLoopOptimization(const NumberSet& aliasedParams);
|
||||||
void PushMoveOutOfLoop(void);
|
void PushMoveOutOfLoop(void);
|
||||||
|
bool MoveConditionOutOfLoop(void);
|
||||||
|
|
||||||
void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue);
|
void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue);
|
||||||
void RemoveUnusedMallocs(void);
|
void RemoveUnusedMallocs(void);
|
||||||
|
@ -716,6 +719,7 @@ protected:
|
||||||
void CheckUsedDefinedTemps(void);
|
void CheckUsedDefinedTemps(void);
|
||||||
void WarnUsedUndefinedVariables(void);
|
void WarnUsedUndefinedVariables(void);
|
||||||
void PropagateMemoryAliasingInfo(void);
|
void PropagateMemoryAliasingInfo(void);
|
||||||
|
void MoveConditionsOutOfLoop(void);
|
||||||
|
|
||||||
void PeepholeOptimization(void);
|
void PeepholeOptimization(void);
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,25 @@ void NativeRegisterDataSet::ResetAbsolute(LinkerObject* linkerObject, int addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeRegisterDataSet::ResetAbsoluteXY(LinkerObject* linkerObject, int addr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_REGS; i++)
|
||||||
|
{
|
||||||
|
if (mRegs[i].mMode == NRDM_ABSOLUTE)
|
||||||
|
{
|
||||||
|
if (mRegs[i].mLinkerObject == linkerObject && mRegs[i].mValue < addr + 256 && mRegs[i].mValue >= addr)
|
||||||
|
mRegs[i].Reset();
|
||||||
|
}
|
||||||
|
else if (mRegs[i].mMode == NRDM_ABSOLUTE_X || mRegs[i].mMode == NRDM_ABSOLUTE_Y)
|
||||||
|
{
|
||||||
|
if (mRegs[i].mLinkerObject == linkerObject && mRegs[i].mValue < addr + 256 && mRegs[i].mValue + 256 > addr)
|
||||||
|
mRegs[i].Reset();
|
||||||
|
}
|
||||||
|
else if (mRegs[i].mMode == NRDM_INDIRECT_Y)
|
||||||
|
mRegs[i].Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NativeRegisterDataSet::ResetX(void)
|
void NativeRegisterDataSet::ResetX(void)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NUM_REGS; i++)
|
for (int i = 0; i < NUM_REGS; i++)
|
||||||
|
@ -4047,7 +4066,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ChangesAddress())
|
if (ChangesAddress())
|
||||||
data.ResetIndirect(mAddress);
|
data.ResetAbsoluteXY(mLinkerObject, mAddress);
|
||||||
}
|
}
|
||||||
else if (mMode == ASMIM_ABSOLUTE_Y)
|
else if (mMode == ASMIM_ABSOLUTE_Y)
|
||||||
{
|
{
|
||||||
|
@ -4111,7 +4130,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ChangesAddress())
|
if (ChangesAddress())
|
||||||
data.ResetIndirect(mAddress);
|
data.ResetAbsoluteXY(mLinkerObject, mAddress);
|
||||||
}
|
}
|
||||||
else if (mMode == ASMIM_ABSOLUTE)
|
else if (mMode == ASMIM_ABSOLUTE)
|
||||||
{
|
{
|
||||||
|
@ -15404,6 +15423,57 @@ bool NativeCodeBasicBlock::PropagateCommonSubExpression(void)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::LocalSwapXY(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
int pre = -1;
|
||||||
|
|
||||||
|
if (mEntryRequiredRegs[CPU_REG_X] || mEntryRequiredRegs[CPU_REG_Y])
|
||||||
|
pre = -2;
|
||||||
|
|
||||||
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
|
{
|
||||||
|
uint32 live = mIns[i].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Y);
|
||||||
|
if (live)
|
||||||
|
{
|
||||||
|
if (pre == -1)
|
||||||
|
pre = i;
|
||||||
|
}
|
||||||
|
else if (!live)
|
||||||
|
{
|
||||||
|
if (pre >= 0)
|
||||||
|
{
|
||||||
|
int k = pre;
|
||||||
|
while (k <= i && mIns[k].CanSwapXYReg())
|
||||||
|
k++;
|
||||||
|
if (k > i)
|
||||||
|
{
|
||||||
|
for (int k = pre; k <= i; k++)
|
||||||
|
{
|
||||||
|
if (mIns[k].SwapXYReg())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pre = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->LocalSwapXY())
|
||||||
|
changed = true;
|
||||||
|
if (mFalseJump && mFalseJump->LocalSwapXY())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::GlobalSwapXY(void)
|
bool NativeCodeBasicBlock::GlobalSwapXY(void)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -15498,6 +15568,66 @@ bool NativeCodeBasicBlock::GlobalSwapXY(void)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::UntangleXYUsage(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
int xins = -1, yins = -1;
|
||||||
|
for (int i = 0; i + 1 < mIns.Size(); i++)
|
||||||
|
{
|
||||||
|
NativeCodeInstruction& ins(mIns[i]);
|
||||||
|
NativeCodeInstruction& nins(mIns[i + 1]);
|
||||||
|
|
||||||
|
if (ins.mType == ASMIT_LDX)
|
||||||
|
{
|
||||||
|
if (yins >= 0 && mIns[yins].SameEffectiveAddress(ins) && nins.mMode == ASMIM_ABSOLUTE_X && HasAsmInstructionMode(nins.mType, ASMIM_ABSOLUTE_Y))
|
||||||
|
{
|
||||||
|
mIns.Insert(i, NativeCodeInstruction(nins.mIns, nins.mType, ASMIM_ABSOLUTE_Y, nins.mAddress, nins.mLinkerObject, nins.mFlags));
|
||||||
|
mIns[i + 1].mLive |= mIns[i].mLive;
|
||||||
|
mIns.Remove(i + 2);
|
||||||
|
for (int j = yins; j < i; j++)
|
||||||
|
mIns[j].mLive |= LIVE_CPU_REG_Y;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
xins = i;
|
||||||
|
}
|
||||||
|
else if (ins.mType == ASMIT_LDY)
|
||||||
|
{
|
||||||
|
if (xins >= 0 && mIns[xins].SameEffectiveAddress(ins) && nins.mMode == ASMIM_ABSOLUTE_Y && HasAsmInstructionMode(nins.mType, ASMIM_ABSOLUTE_X))
|
||||||
|
{
|
||||||
|
mIns.Insert(i, NativeCodeInstruction(nins.mIns, nins.mType, ASMIM_ABSOLUTE_X, nins.mAddress, nins.mLinkerObject, nins.mFlags));
|
||||||
|
mIns[i + 1].mLive |= mIns[i].mLive;
|
||||||
|
mIns.Remove(i + 2);
|
||||||
|
for (int j = xins; j < i; j++)
|
||||||
|
mIns[j].mLive |= LIVE_CPU_REG_X;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
yins = i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (xins >= 0 && (mIns[xins].MayBeChangedOnAddress(ins) || ins.ChangesXReg()))
|
||||||
|
xins = -1;
|
||||||
|
if (yins >= 0 && (mIns[yins].MayBeChangedOnAddress(ins) || ins.ChangesYReg()))
|
||||||
|
yins = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->UntangleXYUsage())
|
||||||
|
changed = true;
|
||||||
|
if (mFalseJump && mFalseJump->UntangleXYUsage())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::OptimizeXYPairUsage(void)
|
bool NativeCodeBasicBlock::OptimizeXYPairUsage(void)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -16514,6 +16644,7 @@ bool NativeCodeBasicBlock::EliminateDeadLoops(void)
|
||||||
mTrueJump = eblock;
|
mTrueJump = eblock;
|
||||||
mBranch = ASMIT_JMP;
|
mBranch = ASMIT_JMP;
|
||||||
mEntryBlocks.RemoveAll(this);
|
mEntryBlocks.RemoveAll(this);
|
||||||
|
mFalseJump = nullptr;
|
||||||
mNumEntries--;
|
mNumEntries--;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -16526,6 +16657,7 @@ bool NativeCodeBasicBlock::EliminateDeadLoops(void)
|
||||||
mTrueJump = eblock;
|
mTrueJump = eblock;
|
||||||
mBranch = ASMIT_JMP;
|
mBranch = ASMIT_JMP;
|
||||||
mEntryBlocks.RemoveAll(this);
|
mEntryBlocks.RemoveAll(this);
|
||||||
|
mFalseJump = nullptr;
|
||||||
mNumEntries--;
|
mNumEntries--;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -26649,6 +26781,68 @@ bool NativeCodeBasicBlock::MoveIndirectLoadStoreDown(int at)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::MoveLDXUp(int at)
|
||||||
|
{
|
||||||
|
NativeCodeInstruction& lins(mIns[at]);
|
||||||
|
|
||||||
|
int i = at;
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
NativeCodeInstruction& ins(mIns[i]);
|
||||||
|
if (ins.mType == ASMIT_STA && ins.SameEffectiveAddress(lins))
|
||||||
|
{
|
||||||
|
if (ins.mLive & LIVE_CPU_REG_Z)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mIns.Insert(i + 1, NativeCodeInstruction(lins.mIns, ASMIT_TAX));
|
||||||
|
mIns.Remove(at + 1);
|
||||||
|
|
||||||
|
while (i < at)
|
||||||
|
{
|
||||||
|
mIns[i].mLive |= LIVE_CPU_REG_X;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (ins.ReferencesXReg() || lins.MayBeChangedOnAddress(ins))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::MoveLDYUp(int at)
|
||||||
|
{
|
||||||
|
NativeCodeInstruction& lins(mIns[at]);
|
||||||
|
|
||||||
|
int i = at;
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
NativeCodeInstruction& ins(mIns[i]);
|
||||||
|
if (ins.mType == ASMIT_STA && ins.SameEffectiveAddress(lins))
|
||||||
|
{
|
||||||
|
if (ins.mLive & LIVE_CPU_REG_Z)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mIns.Insert(i + 1, NativeCodeInstruction(lins.mIns, ASMIT_TAY));
|
||||||
|
mIns.Remove(at + 1);
|
||||||
|
|
||||||
|
while (i < at)
|
||||||
|
{
|
||||||
|
mIns[i].mLive |= LIVE_CPU_REG_Y;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (ins.ReferencesYReg() || lins.MayBeChangedOnAddress(ins))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::MoveIndirectLoadStoreDownY(int at)
|
bool NativeCodeBasicBlock::MoveIndirectLoadStoreDownY(int at)
|
||||||
{
|
{
|
||||||
int j = at + 3;
|
int j = at + 3;
|
||||||
|
@ -35270,6 +35464,17 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen
|
||||||
j += 2;
|
j += 2;
|
||||||
i += 4;
|
i += 4;
|
||||||
}
|
}
|
||||||
|
else if (i + 4 < mIns.Size() &&
|
||||||
|
mIns[i + 0].mType == ASMIT_SEC &&
|
||||||
|
mIns[i + 1].mType == ASMIT_LDA &&
|
||||||
|
mIns[i + 2].mType == ASMIT_SBC &&
|
||||||
|
mIns[i + 3].mType == ASMIT_SEC &&
|
||||||
|
mIns[i + 4].mType == ASMIT_SBC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0x01)
|
||||||
|
{
|
||||||
|
mIns[j + 0] = NativeCodeInstruction(mIns[i + 0].mIns, ASMIT_CLC);
|
||||||
|
j += 3;
|
||||||
|
i += 5;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (i + 1 < mIns.Size() &&
|
else if (i + 1 < mIns.Size() &&
|
||||||
mIns[i + 0].ChangesZFlag() && mIns[i + 1].mType == ASMIT_LDA && mIns[i + 0].SameEffectiveAddress(mIns[i + 1]) && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
mIns[i + 0].ChangesZFlag() && mIns[i + 1].mType == ASMIT_LDA && mIns[i + 0].SameEffectiveAddress(mIns[i + 1]) && !(mIns[i + 1].mLive & LIVE_CPU_REG_A))
|
||||||
|
@ -35929,6 +36134,27 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Move LDX/LDY up to STA of same address
|
||||||
|
#if 1
|
||||||
|
if (pass >= 9)
|
||||||
|
{
|
||||||
|
for (int i = 2; i < mIns.Size(); i++)
|
||||||
|
{
|
||||||
|
if (mIns[i].mType == ASMIT_LDX && (mIns[i].mMode == ASMIM_ZERO_PAGE || mIns[i].mMode == ASMIM_ABSOLUTE) && !(mIns[i].mLive & LIVE_CPU_REG_Z))
|
||||||
|
{
|
||||||
|
if (MoveLDXUp(i))
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (mIns[i].mType == ASMIT_LDY && (mIns[i].mMode == ASMIM_ZERO_PAGE || mIns[i].mMode == ASMIM_ABSOLUTE) && !(mIns[i].mLive & LIVE_CPU_REG_Z))
|
||||||
|
{
|
||||||
|
if (MoveLDYUp(i))
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CheckLive();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// move ORA #imm up a shift chain to an LDA #imm
|
// move ORA #imm up a shift chain to an LDA #imm
|
||||||
|
|
||||||
|
@ -37813,6 +38039,43 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (mIns[i + 0].ChangesAccuAndFlag() && mIns[i + 1].mType == ASMIT_TAX && !(mIns[i + 1].mLive & LIVE_CPU_REG_X))
|
||||||
|
{
|
||||||
|
mIns[i + 0].mLive |= (mIns[i + 1].mLive & LIVE_CPU_REG_Z);
|
||||||
|
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (mIns[i + 0].ChangesAccuAndFlag() && mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_Y))
|
||||||
|
{
|
||||||
|
mIns[i + 0].mLive |= (mIns[i + 1].mLive & LIVE_CPU_REG_Z);
|
||||||
|
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (mIns[i + 0].mType == ASMIT_LDX && mIns[i + 1].mType == ASMIT_CPX && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X)))
|
||||||
|
{
|
||||||
|
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 1].mType = ASMIT_CMP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 1].mType == ASMIT_CPY && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y)))
|
||||||
|
{
|
||||||
|
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 1].mType = ASMIT_CMP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (mIns[i + 0].mType == ASMIT_LDX && mIns[i + 1].mType == ASMIT_STX && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X)))
|
||||||
|
{
|
||||||
|
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 1].mType = ASMIT_STA;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 1].mType == ASMIT_STY && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y)))
|
||||||
|
{
|
||||||
|
mIns[i + 0].mType = ASMIT_LDA; mIns[i + 0].mLive |= LIVE_CPU_REG_A;
|
||||||
|
mIns[i + 1].mType = ASMIT_STA;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 0].mType == ASMIT_INC && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
mIns[i + 0].mType == ASMIT_INC && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
@ -43264,7 +43527,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
mInterProc = proc;
|
mInterProc = proc;
|
||||||
|
|
||||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "board_draw_item");
|
CheckFunc = !strcmp(mInterProc->mIdent->mString, "interpret_expression");
|
||||||
|
|
||||||
int nblocks = proc->mBlocks.Size();
|
int nblocks = proc->mBlocks.Size();
|
||||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||||
|
@ -44448,9 +44711,11 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
if (mEntryBlock->OptimizeXYPairUsage())
|
if (mEntryBlock->OptimizeXYPairUsage())
|
||||||
changed = true;
|
changed = true;
|
||||||
|
ResetVisited();
|
||||||
|
if (mEntryBlock->UntangleXYUsage())
|
||||||
|
changed = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->CheckBlocks();
|
mEntryBlock->CheckBlocks();
|
||||||
|
@ -44653,6 +44918,18 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (step == 11)
|
||||||
|
{
|
||||||
|
if (changed)
|
||||||
|
swappedXY = false;
|
||||||
|
else if (!swappedXY)
|
||||||
|
{
|
||||||
|
ResetVisited();
|
||||||
|
changed = mEntryBlock->LocalSwapXY();
|
||||||
|
swappedXY = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
|
@ -44673,7 +44950,7 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
if (!changed && step < 11)
|
if (!changed && step < 12)
|
||||||
{
|
{
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
step++;
|
step++;
|
||||||
|
|
|
@ -47,6 +47,7 @@ struct NativeRegisterDataSet
|
||||||
void ResetZeroPage(int addr);
|
void ResetZeroPage(int addr);
|
||||||
void ResetZeroPageRange(int addr, int num);
|
void ResetZeroPageRange(int addr, int num);
|
||||||
void ResetAbsolute(LinkerObject * linkerObject, int addr);
|
void ResetAbsolute(LinkerObject * linkerObject, int addr);
|
||||||
|
void ResetAbsoluteXY(LinkerObject* linkerObject, int addr);
|
||||||
int FindAbsolute(LinkerObject* linkerObject, int addr);
|
int FindAbsolute(LinkerObject* linkerObject, int addr);
|
||||||
void ResetIndirect(int reg);
|
void ResetIndirect(int reg);
|
||||||
void ResetX(void);
|
void ResetX(void);
|
||||||
|
@ -407,6 +408,10 @@ public:
|
||||||
bool MoveIndirectLoadStoreDown(int at);
|
bool MoveIndirectLoadStoreDown(int at);
|
||||||
bool MoveIndirectLoadStoreDownY(int at);
|
bool MoveIndirectLoadStoreDownY(int at);
|
||||||
|
|
||||||
|
bool MoveLDXUp(int at);
|
||||||
|
bool MoveLDYUp(int at);
|
||||||
|
|
||||||
|
|
||||||
bool MoveIndirectLoadStoreUp(int at);
|
bool MoveIndirectLoadStoreUp(int at);
|
||||||
bool MoveAbsoluteLoadStoreUp(int at);
|
bool MoveAbsoluteLoadStoreUp(int at);
|
||||||
bool MoveLoadStoreOutOfXYRangeUp(int at);
|
bool MoveLoadStoreOutOfXYRangeUp(int at);
|
||||||
|
@ -624,6 +629,8 @@ public:
|
||||||
bool OptimizeXYPairUsage(void);
|
bool OptimizeXYPairUsage(void);
|
||||||
bool CanGlobalSwapXY(void);
|
bool CanGlobalSwapXY(void);
|
||||||
bool GlobalSwapXY(void);
|
bool GlobalSwapXY(void);
|
||||||
|
bool LocalSwapXY(void);
|
||||||
|
bool UntangleXYUsage(void);
|
||||||
|
|
||||||
bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex);
|
bool IsSimpleSubExpression(int at, NativeSimpleSubExpression & ex);
|
||||||
bool PropagateCommonSubExpression(void);
|
bool PropagateCommonSubExpression(void);
|
||||||
|
|
Loading…
Reference in New Issue