Basic block tail merging
This commit is contained in:
parent
2fc414ed6b
commit
bffef3e9dd
|
@ -12,7 +12,7 @@ int main(void)
|
||||||
|
|
||||||
for(i=0; i<50; i++)
|
for(i=0; i<50; i++)
|
||||||
{
|
{
|
||||||
// printf("%d %f %f %f\n", i, i * c, a, i * c - a);
|
printf("%d %f %f %f\n", i, i * c, a, i * c - a);
|
||||||
assert(i * c == a);
|
assert(i * c == a);
|
||||||
a += c;
|
a += c;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ int main(void)
|
||||||
|
|
||||||
for(i=1; i<50; i++)
|
for(i=1; i<50; i++)
|
||||||
{
|
{
|
||||||
// printf("%d %f %f %f\n", i, i * d, a, fabs(i * d - a) / i);
|
printf("%d %f %f %f\n", i, i * d, a, fabs(i * d - a) / i);
|
||||||
assert(fabs(i * d - a) < i * 1.0e-6);
|
assert(fabs(i * d - a) < i * 1.0e-6);
|
||||||
a += d;
|
a += d;
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,32 @@ bool ByteCodeInstruction::IsCommutative(void) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ByteCodeInstruction::IsLocalStore(void) const
|
||||||
|
{
|
||||||
|
return mCode >= BC_STORE_LOCAL_8 && mCode <= BC_STORE_LOCAL_32;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteCodeInstruction::IsLocalLoad(void) const
|
||||||
|
{
|
||||||
|
return mCode >= BC_LOAD_LOCAL_8 && mCode <= BC_LOAD_LOCAL_32 || mCode == BC_COPY;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteCodeInstruction::IsLocalAccess(void) const
|
||||||
|
{
|
||||||
|
return IsLocalStore() || IsLocalLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ByteCodeInstruction::IsSame(const ByteCodeInstruction& ins) const
|
||||||
|
{
|
||||||
|
if (mCode == ins.mCode && mValue == ins.mValue && mRegister == ins.mRegister && mLinkerObject == ins.mLinkerObject)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ByteCodeInstruction::StoresRegister(uint32 reg) const
|
bool ByteCodeInstruction::StoresRegister(uint32 reg) const
|
||||||
{
|
{
|
||||||
if (mRegister == reg)
|
if (mRegister == reg)
|
||||||
|
@ -529,7 +555,7 @@ int ByteCodeBasicBlock::PutBranch(ByteCodeGenerator* generator, ByteCode code, i
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteCodeBasicBlock::ByteCodeBasicBlock(void)
|
ByteCodeBasicBlock::ByteCodeBasicBlock(void)
|
||||||
: mRelocations({ 0 }), mIns(ByteCodeInstruction(BC_NOP))
|
: mRelocations({ 0 }), mIns(ByteCodeInstruction(BC_NOP)), mEntryBlocks(nullptr)
|
||||||
{
|
{
|
||||||
mTrueJump = mFalseJump = NULL;
|
mTrueJump = mFalseJump = NULL;
|
||||||
mTrueLink = mFalseLink = NULL;
|
mTrueLink = mFalseLink = NULL;
|
||||||
|
@ -2530,6 +2556,78 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p
|
||||||
this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), nullptr, BC_JUMPS);
|
this->Close(proc->CompileBlock(iproc, sblock->mTrueJump), nullptr, BC_JUMPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ByteCodeBasicBlock::CollectEntryBlocks(ByteCodeBasicBlock* block)
|
||||||
|
{
|
||||||
|
if (block)
|
||||||
|
mEntryBlocks.Push(block);
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
if (mTrueJump)
|
||||||
|
mTrueJump->CollectEntryBlocks(this);
|
||||||
|
if (mFalseJump)
|
||||||
|
mFalseJump->CollectEntryBlocks(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteCodeBasicBlock::SameTail(ByteCodeInstruction& ins)
|
||||||
|
{
|
||||||
|
if (mIns.Size() > 0)
|
||||||
|
return mIns[mIns.Size() - 1].IsSame(ins);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteCodeBasicBlock::JoinTailCodeSequences(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
if (mEntryBlocks.Size() > 1)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->mBranch == BC_JUMPS)
|
||||||
|
i++;
|
||||||
|
if (i == mEntryBlocks.Size())
|
||||||
|
{
|
||||||
|
ByteCodeBasicBlock* eb = mEntryBlocks[0];
|
||||||
|
|
||||||
|
while (eb->mIns.Size() > 0)
|
||||||
|
{
|
||||||
|
ByteCodeInstruction& ins(eb->mIns[eb->mIns.Size() - 1]);
|
||||||
|
i = 1;
|
||||||
|
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->SameTail(ins))
|
||||||
|
i++;
|
||||||
|
if (i == mEntryBlocks.Size())
|
||||||
|
{
|
||||||
|
mIns.Insert(0, ins);
|
||||||
|
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||||
|
{
|
||||||
|
ByteCodeBasicBlock* b = mEntryBlocks[i];
|
||||||
|
b->mIns.SetSize(b->mIns.Size() - 1);
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->JoinTailCodeSequences())
|
||||||
|
changed = true;
|
||||||
|
if (mFalseJump && mFalseJump->JoinTailCodeSequences())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
{
|
{
|
||||||
|
@ -2582,6 +2680,7 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 2].mCode = BC_NOP;
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
if (mIns[i + 2].mRegisterFinal)
|
if (mIns[i + 2].mRegisterFinal)
|
||||||
mIns[i].mCode = BC_NOP;
|
mIns[i].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (mIns[i].mCode == BC_STORE_REG_32 &&
|
else if (mIns[i].mCode == BC_STORE_REG_32 &&
|
||||||
!mIns[i + 1].ChangesAccu() && mIns[i + 1].mRegister != mIns[i].mRegister &&
|
!mIns[i + 1].ChangesAccu() && mIns[i + 1].mRegister != mIns[i].mRegister &&
|
||||||
|
@ -2590,6 +2689,7 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 2].mCode = BC_NOP;
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
if (mIns[i + 2].mRegisterFinal)
|
if (mIns[i + 2].mRegisterFinal)
|
||||||
mIns[i].mCode = BC_NOP;
|
mIns[i].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (mIns[i].mCode == BC_STORE_REG_16 &&
|
else if (mIns[i].mCode == BC_STORE_REG_16 &&
|
||||||
!mIns[i + 1].ChangesAccu() && mIns[i + 1].mRegister != mIns[i].mRegister &&
|
!mIns[i + 1].ChangesAccu() && mIns[i + 1].mRegister != mIns[i].mRegister &&
|
||||||
|
@ -2597,6 +2697,7 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
{
|
{
|
||||||
mIns[i].mCode = BC_NOP;
|
mIns[i].mCode = BC_NOP;
|
||||||
mIns[i + 2].mRegister = BC_REG_ACCU;
|
mIns[i + 2].mRegister = BC_REG_ACCU;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (mIns[i].mCode == BC_STORE_REG_16 &&
|
else if (mIns[i].mCode == BC_STORE_REG_16 &&
|
||||||
!mIns[i + 1].ChangesAddr() && mIns[i + 1].mRegister != mIns[i].mRegister &&
|
!mIns[i + 1].ChangesAddr() && mIns[i + 1].mRegister != mIns[i].mRegister &&
|
||||||
|
@ -2605,6 +2706,7 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i].mCode = BC_ADDR_REG;
|
mIns[i].mCode = BC_ADDR_REG;
|
||||||
mIns[i].mRegister = BC_REG_ACCU;
|
mIns[i].mRegister = BC_REG_ACCU;
|
||||||
mIns[i + 2].mCode = BC_NOP;
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 2].mCode == BC_BINOP_ADDR_16 &&
|
mIns[i + 2].mCode == BC_BINOP_ADDR_16 &&
|
||||||
|
@ -2614,6 +2716,7 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 0].mRegister = BC_REG_ACCU;
|
mIns[i + 0].mRegister = BC_REG_ACCU;
|
||||||
mIns[i + 1].mCode = mIns[i + 2].mCode;
|
mIns[i + 1].mCode = mIns[i + 2].mCode;
|
||||||
mIns[i + 2].mCode = BC_NOP;
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 2].mCode == BC_BINOP_ADDR_16 &&
|
mIns[i + 2].mCode == BC_BINOP_ADDR_16 &&
|
||||||
|
@ -2623,6 +2726,7 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 0].mCode = BC_NOP;;
|
mIns[i + 0].mCode = BC_NOP;;
|
||||||
mIns[i + 1].mCode = mIns[i + 2].mCode;
|
mIns[i + 1].mCode = mIns[i + 2].mCode;
|
||||||
mIns[i + 2].mCode = BC_NOP;
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (mIns[i].mCode == BC_STORE_REG_32 &&
|
else if (mIns[i].mCode == BC_STORE_REG_32 &&
|
||||||
mIns[i + 1].mCode == BC_LOAD_REG_32 && mIns[i + 1].mRegister != mIns[i + 2].mRegister &&
|
mIns[i + 1].mCode == BC_LOAD_REG_32 && mIns[i + 1].mRegister != mIns[i + 2].mRegister &&
|
||||||
|
@ -2633,6 +2737,7 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 1].mCode = BC_NOP;
|
mIns[i + 1].mCode = BC_NOP;
|
||||||
mIns[i + 2].mRegister = mIns[i + 1].mRegister;
|
mIns[i + 2].mRegister = mIns[i + 1].mRegister;
|
||||||
mIns[i + 2].mRegisterFinal = mIns[i + 1].mRegisterFinal;
|
mIns[i + 2].mRegisterFinal = mIns[i + 1].mRegisterFinal;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (mIns[i].mCode == BC_STORE_REG_16 &&
|
else if (mIns[i].mCode == BC_STORE_REG_16 &&
|
||||||
mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i + 1].mRegister != mIns[i + 2].mRegister &&
|
mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i + 1].mRegister != mIns[i + 2].mRegister &&
|
||||||
|
@ -2643,6 +2748,7 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 1].mCode = BC_NOP;
|
mIns[i + 1].mCode = BC_NOP;
|
||||||
mIns[i + 2].mRegister = mIns[i + 1].mRegister;
|
mIns[i + 2].mRegister = mIns[i + 1].mRegister;
|
||||||
mIns[i + 2].mRegisterFinal = mIns[i + 1].mRegisterFinal;
|
mIns[i + 2].mRegisterFinal = mIns[i + 1].mRegisterFinal;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (mIns[i + 0].mCode == BC_STORE_REG_32 &&
|
else if (mIns[i + 0].mCode == BC_STORE_REG_32 &&
|
||||||
mIns[i + 2].mCode == BC_BINOP_CMP_F32 && mIns[i + 2].mRegister == mIns[i + 0].mRegister && mIns[i + 2].mRegisterFinal &&
|
mIns[i + 2].mCode == BC_BINOP_CMP_F32 && mIns[i + 2].mRegister == mIns[i + 0].mRegister && mIns[i + 2].mRegisterFinal &&
|
||||||
|
@ -2651,24 +2757,34 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 1].mRegister = mIns[i + 0].mRegister;
|
mIns[i + 1].mRegister = mIns[i + 0].mRegister;
|
||||||
mIns[i + 0].mCode = BC_NOP;
|
mIns[i + 0].mCode = BC_NOP;
|
||||||
mBranch = TransposeBranchCondition(mBranch);
|
mBranch = TransposeBranchCondition(mBranch);
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (mIns[i + 0].mCode == BC_LOAD_REG_16 &&
|
else if (mIns[i + 0].mCode == BC_LOAD_REG_16 &&
|
||||||
mIns[i + 1].mCode == BC_STORE_REG_16 &&
|
mIns[i + 1].mCode == BC_STORE_REG_16 &&
|
||||||
mIns[i + 2].mCode == BC_LOAD_REG_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister)
|
mIns[i + 2].mCode == BC_LOAD_REG_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister)
|
||||||
{
|
{
|
||||||
mIns[i + 2].mCode = BC_NOP;
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (mIns[i + 0].mCode == BC_CONST_16 && mIns[i + 2].mCode == BC_CONST_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister && mIns[i + 0].mValue == mIns[i + 2].mValue && !mIns[i + 1].ChangesRegister(mIns[i + 0].mRegister))
|
else if (mIns[i + 0].mCode == BC_CONST_16 && mIns[i + 2].mCode == BC_CONST_16 && mIns[i + 0].mRegister == mIns[i + 2].mRegister && mIns[i + 0].mValue == mIns[i + 2].mValue && !mIns[i + 1].ChangesRegister(mIns[i + 0].mRegister))
|
||||||
{
|
{
|
||||||
mIns[i + 2].mCode = BC_NOP;
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
else if (mIns[i + 0].mCode >= BC_SET_EQ && mIns[i + 0].mCode <= BC_SET_LE &&
|
else if (mIns[i + 0].mCode >= BC_SET_EQ && mIns[i + 0].mCode <= BC_SET_LE &&
|
||||||
mIns[i + 1].mCode == BC_STORE_REG_8 &&
|
mIns[i + 1].mCode == BC_STORE_REG_8 &&
|
||||||
mIns[i + 2].mCode == BC_LOAD_REG_8 && mIns[i + 1].mRegister == mIns[i + 2].mRegister)
|
mIns[i + 2].mCode == BC_LOAD_REG_8 && mIns[i + 1].mRegister == mIns[i + 2].mRegister)
|
||||||
{
|
{
|
||||||
mIns[i + 2].mCode = BC_NOP;
|
mIns[i + 2].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (mIns[i + 0].IsLocalStore() && mIns[i + 2].IsSame(mIns[i + 0]) && !mIns[i + 1].IsLocalAccess() && mIns[i + 1].mCode != BC_JSR)
|
||||||
|
{
|
||||||
|
mIns[i + 0].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i + 1 < mIns.Size())
|
if (i + 1 < mIns.Size())
|
||||||
{
|
{
|
||||||
if (mIns[i].mCode == BC_STORE_REG_16 && mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i].mRegister == mIns[i + 1].mRegister)
|
if (mIns[i].mCode == BC_STORE_REG_16 && mIns[i + 1].mCode == BC_LOAD_REG_16 && mIns[i].mRegister == mIns[i + 1].mRegister)
|
||||||
|
@ -2756,12 +2872,30 @@ bool ByteCodeBasicBlock::PeepHoleOptimizer(void)
|
||||||
mIns[i + 1].mCode = BC_NOP;
|
mIns[i + 1].mCode = BC_NOP;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
else if (mIns[i].mCode == BC_BINOP_ADDI_16 && mIns[i + 1].mCode == BC_BINOP_ADDI_16 && mIns[i].mRegister == mIns[i + 1].mRegister)
|
||||||
|
{
|
||||||
|
mIns[i + 1].mValue += mIns[i].mValue;
|
||||||
|
mIns[i].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
else if (mIns[i].mCode == BC_BINOP_ADDI_16 && mIns[i].mValue == 0)
|
||||||
|
{
|
||||||
|
mIns[i].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mIns[i].mCode == BC_LOAD_REG_16 || mIns[i].mCode == BC_STORE_REG_16 || mIns[i].mCode == BC_LOAD_REG_32 || mIns[i].mCode == BC_STORE_REG_32) && accuTemp == mIns[i].mRegister)
|
if ((mIns[i].mCode == BC_LOAD_REG_16 || mIns[i].mCode == BC_STORE_REG_16 || mIns[i].mCode == BC_LOAD_REG_32 || mIns[i].mCode == BC_STORE_REG_32) && accuTemp == mIns[i].mRegister)
|
||||||
|
{
|
||||||
mIns[i].mCode = BC_NOP;
|
mIns[i].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (mIns[i].mCode == BC_ADDR_REG && mIns[i].mRegister == addrTemp)
|
if (mIns[i].mCode == BC_ADDR_REG && mIns[i].mRegister == addrTemp)
|
||||||
|
{
|
||||||
mIns[i].mCode = BC_NOP;
|
mIns[i].mCode = BC_NOP;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (mIns[i].ChangesAccu())
|
if (mIns[i].ChangesAccu())
|
||||||
accuTemp = -1;
|
accuTemp = -1;
|
||||||
|
@ -3072,6 +3206,32 @@ void ByteCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure
|
||||||
exitBlock = new ByteCodeBasicBlock();
|
exitBlock = new ByteCodeBasicBlock();
|
||||||
mBlocks.Push(exitBlock);
|
mBlocks.Push(exitBlock);
|
||||||
|
|
||||||
|
entryBlock->Compile(proc, this, proc->mBlocks[0]);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
bool progress = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
progress = false;
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
progress = entryBlock->PeepHoleOptimizer();
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
for (int i = 0; i < mBlocks.Size(); i++)
|
||||||
|
mBlocks[i]->mEntryBlocks.SetSize(0);
|
||||||
|
entryBlock->CollectEntryBlocks(nullptr);
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
if (entryBlock->JoinTailCodeSequences())
|
||||||
|
progress = true;
|
||||||
|
|
||||||
|
} while (progress);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
entryBlock->Assemble(generator);
|
||||||
|
|
||||||
if (!proc->mLeafProcedure)
|
if (!proc->mLeafProcedure)
|
||||||
{
|
{
|
||||||
exitBlock->PutCode(generator, BC_POP_FRAME);
|
exitBlock->PutCode(generator, BC_POP_FRAME);
|
||||||
|
@ -3079,13 +3239,6 @@ void ByteCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure
|
||||||
}
|
}
|
||||||
exitBlock->PutCode(generator, BC_RETURN); exitBlock->PutByte(tempSave); exitBlock->PutWord(proc->mLocalSize + 2 + tempSave);
|
exitBlock->PutCode(generator, BC_RETURN); exitBlock->PutByte(tempSave); exitBlock->PutWord(proc->mLocalSize + 2 + tempSave);
|
||||||
|
|
||||||
entryBlock->Compile(proc, this, proc->mBlocks[0]);
|
|
||||||
|
|
||||||
bool progress = false;
|
|
||||||
ResetVisited();
|
|
||||||
progress = entryBlock->PeepHoleOptimizer();
|
|
||||||
|
|
||||||
entryBlock->Assemble(generator);
|
|
||||||
|
|
||||||
int total;
|
int total;
|
||||||
|
|
||||||
|
|
|
@ -178,8 +178,12 @@ public:
|
||||||
bool ChangesRegister(uint32 reg) const;
|
bool ChangesRegister(uint32 reg) const;
|
||||||
bool LoadsRegister(uint32 reg) const;
|
bool LoadsRegister(uint32 reg) const;
|
||||||
bool StoresRegister(uint32 reg) const;
|
bool StoresRegister(uint32 reg) const;
|
||||||
|
bool IsLocalStore(void) const;
|
||||||
|
bool IsLocalLoad(void) const;
|
||||||
|
bool IsLocalAccess(void) const;
|
||||||
|
|
||||||
bool IsCommutative(void) const;
|
bool IsCommutative(void) const;
|
||||||
|
bool IsSame(const ByteCodeInstruction& ins) const;
|
||||||
|
|
||||||
bool ValueForwarding(ByteCodeInstruction*& accuIns, ByteCodeInstruction*& addrIns);
|
bool ValueForwarding(ByteCodeInstruction*& accuIns, ByteCodeInstruction*& addrIns);
|
||||||
};
|
};
|
||||||
|
@ -196,6 +200,7 @@ public:
|
||||||
|
|
||||||
GrowingArray<ByteCodeInstruction> mIns;
|
GrowingArray<ByteCodeInstruction> mIns;
|
||||||
GrowingArray<LinkerReference> mRelocations;
|
GrowingArray<LinkerReference> mRelocations;
|
||||||
|
GrowingArray<ByteCodeBasicBlock*> mEntryBlocks;
|
||||||
|
|
||||||
int mOffset, mSize;
|
int mOffset, mSize;
|
||||||
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mVisited;
|
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mVisited;
|
||||||
|
@ -236,6 +241,11 @@ public:
|
||||||
void BinaryIntOperator(InterCodeProcedure* proc, const InterInstruction * ins, ByteCode code);
|
void BinaryIntOperator(InterCodeProcedure* proc, const InterInstruction * ins, ByteCode code);
|
||||||
void NumericConversion(InterCodeProcedure* proc, const InterInstruction * ins);
|
void NumericConversion(InterCodeProcedure* proc, const InterInstruction * ins);
|
||||||
|
|
||||||
|
void CollectEntryBlocks(ByteCodeBasicBlock * block);
|
||||||
|
|
||||||
|
bool JoinTailCodeSequences(void);
|
||||||
|
bool SameTail(ByteCodeInstruction& ins);
|
||||||
|
|
||||||
bool PeepHoleOptimizer(void);
|
bool PeepHoleOptimizer(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3243,9 +3243,25 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
|
||||||
{
|
{
|
||||||
mVisited = true;
|
mVisited = true;
|
||||||
|
|
||||||
|
// Remove none instructions
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
for (i = 0; i < mInstructions.Size(); i++)
|
||||||
|
{
|
||||||
|
if (mInstructions[i]->mCode != IC_NONE)
|
||||||
|
{
|
||||||
|
mInstructions[j++] = mInstructions[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mInstructions.SetSize(j);
|
||||||
|
|
||||||
// shorten lifespan
|
// shorten lifespan
|
||||||
|
|
||||||
int i = mInstructions.Size() - 2;
|
int limit = mInstructions.Size() - 1;
|
||||||
|
if (limit >= 2 && mInstructions[limit]->mCode == IC_BRANCH)
|
||||||
|
limit -= 2;
|
||||||
|
|
||||||
|
int i = limit;
|
||||||
|
|
||||||
while (i >= 0)
|
while (i >= 0)
|
||||||
{
|
{
|
||||||
|
@ -3254,7 +3270,7 @@ void InterCodeBasicBlock::PeepholeOptimization(void)
|
||||||
{
|
{
|
||||||
InterInstruction * ins(mInstructions[i]);
|
InterInstruction * ins(mInstructions[i]);
|
||||||
int j = i;
|
int j = i;
|
||||||
while (j + 2 < mInstructions.Size() && CanBypassLoad(ins, mInstructions[j + 1]))
|
while (j < limit && CanBypassLoad(ins, mInstructions[j + 1]))
|
||||||
{
|
{
|
||||||
mInstructions[j] = mInstructions[j + 1];
|
mInstructions[j] = mInstructions[j + 1];
|
||||||
j++;
|
j++;
|
||||||
|
|
|
@ -495,6 +495,35 @@ bool NativeCodeInstruction::IsCommutative(void) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const
|
||||||
|
{
|
||||||
|
if (mType == ins.mType && mMode == ins.mMode)
|
||||||
|
{
|
||||||
|
switch (mMode)
|
||||||
|
{
|
||||||
|
case ASMIM_IMPLIED:
|
||||||
|
return true;
|
||||||
|
case ASMIM_IMMEDIATE:
|
||||||
|
case ASMIM_ZERO_PAGE:
|
||||||
|
case ASMIM_ZERO_PAGE_X:
|
||||||
|
case ASMIM_ZERO_PAGE_Y:
|
||||||
|
case ASMIM_INDIRECT_X:
|
||||||
|
case ASMIM_INDIRECT_Y:
|
||||||
|
return ins.mAddress == mAddress;
|
||||||
|
case ASMIM_IMMEDIATE_ADDRESS:
|
||||||
|
return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress && ins.mFlags == mFlags);
|
||||||
|
case ASMIM_ABSOLUTE:
|
||||||
|
case ASMIM_ABSOLUTE_X:
|
||||||
|
case ASMIM_ABSOLUTE_Y:
|
||||||
|
return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeInstruction::SameEffectiveAddress(const NativeCodeInstruction& ins) const
|
bool NativeCodeInstruction::SameEffectiveAddress(const NativeCodeInstruction& ins) const
|
||||||
{
|
{
|
||||||
if (mMode != ins.mMode)
|
if (mMode != ins.mMode)
|
||||||
|
@ -4124,6 +4153,79 @@ bool NativeCodeBasicBlock::MergeBasicBlocks(void)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeCodeBasicBlock::CollectEntryBlocks(NativeCodeBasicBlock* block)
|
||||||
|
{
|
||||||
|
if (block)
|
||||||
|
mEntryBlocks.Push(block);
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
if (mTrueJump)
|
||||||
|
mTrueJump->CollectEntryBlocks(this);
|
||||||
|
if (mFalseJump)
|
||||||
|
mFalseJump->CollectEntryBlocks(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::SameTail(const NativeCodeInstruction& ins) const
|
||||||
|
{
|
||||||
|
if (mIns.Size() > 0)
|
||||||
|
return mIns[mIns.Size() - 1].IsSame(ins);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::JoinTailCodeSequences(void)
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
|
{
|
||||||
|
mVisited = true;
|
||||||
|
|
||||||
|
if (mEntryBlocks.Size() > 1)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->mBranch == ASMIT_JMP)
|
||||||
|
i++;
|
||||||
|
if (i == mEntryBlocks.Size())
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* eb = mEntryBlocks[0];
|
||||||
|
|
||||||
|
while (eb->mIns.Size() > 0)
|
||||||
|
{
|
||||||
|
NativeCodeInstruction& ins(eb->mIns[eb->mIns.Size() - 1]);
|
||||||
|
i = 1;
|
||||||
|
while (i < mEntryBlocks.Size() && mEntryBlocks[i]->SameTail(ins))
|
||||||
|
i++;
|
||||||
|
if (i == mEntryBlocks.Size())
|
||||||
|
{
|
||||||
|
mIns.Insert(0, ins);
|
||||||
|
for (int i = 0; i < mEntryBlocks.Size(); i++)
|
||||||
|
{
|
||||||
|
NativeCodeBasicBlock* b = mEntryBlocks[i];
|
||||||
|
b->mIns.SetSize(b->mIns.Size() - 1);
|
||||||
|
}
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTrueJump && mTrueJump->JoinTailCodeSequences())
|
||||||
|
changed = true;
|
||||||
|
if (mFalseJump && mFalseJump->JoinTailCodeSequences())
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::FindGlobalAddress(int at, int reg, int& apos)
|
bool NativeCodeBasicBlock::FindGlobalAddress(int at, int reg, int& apos)
|
||||||
{
|
{
|
||||||
int j = at - 4;
|
int j = at - 4;
|
||||||
|
@ -4986,7 +5088,7 @@ void NativeCodeBasicBlock::CalculateOffset(int& total)
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeCodeBasicBlock::NativeCodeBasicBlock(void)
|
NativeCodeBasicBlock::NativeCodeBasicBlock(void)
|
||||||
: mIns(NativeCodeInstruction(ASMIT_INV, ASMIM_IMPLIED)), mRelocations({ 0 })
|
: mIns(NativeCodeInstruction(ASMIT_INV, ASMIM_IMPLIED)), mRelocations({ 0 }), mEntryBlocks(nullptr)
|
||||||
{
|
{
|
||||||
mTrueJump = mFalseJump = NULL;
|
mTrueJump = mFalseJump = NULL;
|
||||||
mOffset = 0x7fffffff;
|
mOffset = 0x7fffffff;
|
||||||
|
@ -5175,6 +5277,15 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
if (entryBlock->MergeBasicBlocks())
|
if (entryBlock->MergeBasicBlocks())
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
for (int i = 0; i < mBlocks.Size(); i++)
|
||||||
|
mBlocks[i]->mEntryBlocks.SetSize(0);
|
||||||
|
entryBlock->CollectEntryBlocks(nullptr);
|
||||||
|
|
||||||
|
ResetVisited();
|
||||||
|
if (entryBlock->JoinTailCodeSequences())
|
||||||
|
changed = true;
|
||||||
|
|
||||||
} while (changed);
|
} while (changed);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -48,12 +48,14 @@ public:
|
||||||
bool IsUsedResultInstructions(NumberSet& requiredTemps);
|
bool IsUsedResultInstructions(NumberSet& requiredTemps);
|
||||||
bool ValueForwarding(NativeRegisterDataSet& data);
|
bool ValueForwarding(NativeRegisterDataSet& data);
|
||||||
|
|
||||||
|
|
||||||
bool LoadsAccu(void) const;
|
bool LoadsAccu(void) const;
|
||||||
bool ChangesAccuAndFlag(void) const;
|
bool ChangesAccuAndFlag(void) const;
|
||||||
bool ChangesAddress(void) const;
|
bool ChangesAddress(void) const;
|
||||||
bool ChangesAccu(void) const;
|
bool ChangesAccu(void) const;
|
||||||
bool RequiresAccu(void) const;
|
bool RequiresAccu(void) const;
|
||||||
bool SameEffectiveAddress(const NativeCodeInstruction& ins) const;
|
bool SameEffectiveAddress(const NativeCodeInstruction& ins) const;
|
||||||
|
bool IsSame(const NativeCodeInstruction& ins) const;
|
||||||
bool IsCommutative(void) const;
|
bool IsCommutative(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,6 +74,8 @@ public:
|
||||||
GrowingArray<NativeCodeInstruction> mIns;
|
GrowingArray<NativeCodeInstruction> mIns;
|
||||||
GrowingArray<LinkerReference> mRelocations;
|
GrowingArray<LinkerReference> mRelocations;
|
||||||
|
|
||||||
|
GrowingArray<NativeCodeBasicBlock*> mEntryBlocks;
|
||||||
|
|
||||||
int mOffset, mSize, mNumEntries;
|
int mOffset, mSize, mNumEntries;
|
||||||
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited;
|
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited;
|
||||||
|
|
||||||
|
@ -132,6 +136,11 @@ public:
|
||||||
|
|
||||||
bool ValueForwarding(const NativeRegisterDataSet& data);
|
bool ValueForwarding(const NativeRegisterDataSet& data);
|
||||||
|
|
||||||
|
void CollectEntryBlocks(NativeCodeBasicBlock* block);
|
||||||
|
|
||||||
|
bool JoinTailCodeSequences(void);
|
||||||
|
bool SameTail(const NativeCodeInstruction& ins) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NativeCodeProcedure
|
class NativeCodeProcedure
|
||||||
|
|
Loading…
Reference in New Issue