Optimize native code branch placement
This commit is contained in:
parent
4f1de9ce89
commit
0b9163afbe
|
@ -267,6 +267,7 @@ public:
|
|||
int PutBranch(ByteCodeGenerator* generator, ByteCode code, int offset);
|
||||
|
||||
ByteCodeBasicBlock* BypassEmptyBlocks(void);
|
||||
|
||||
void BuildPlacement(GrowingArray<ByteCodeBasicBlock*> & placement);
|
||||
void InitialOffset(int& total, int& linear);
|
||||
bool CalculateOffset(int & total);
|
||||
|
|
|
@ -5936,6 +5936,7 @@ void InterCodeProcedure::MergeBasicBlocks(void)
|
|||
{
|
||||
InterCodeBasicBlock* block = mBlocks[i];
|
||||
#if 0
|
||||
// too eager will need some rework
|
||||
if (block->mTrueJump && block->mFalseJump && block->mTrueJump->mNumEntries == 1 && block->mFalseJump->mNumEntries == 1)
|
||||
{
|
||||
while (block->mTrueJump->mInstructions.Size() && block->mFalseJump->mInstructions.Size() &&
|
||||
|
|
|
@ -590,6 +590,13 @@ bool NativeCodeInstruction::ChangesGlobalMemory(void) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeInstruction::RequiresCarry(void) const
|
||||
{
|
||||
return
|
||||
mType == ASMIT_ADC || mType == ASMIT_SBC ||
|
||||
mType == ASMIT_ROL || mType == ASMIT_ROR;
|
||||
}
|
||||
|
||||
bool NativeCodeInstruction::ChangesCarry(void) const
|
||||
{
|
||||
return
|
||||
|
@ -8093,6 +8100,37 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i
|
|||
j--;
|
||||
}
|
||||
|
||||
if (at >= 6 &&
|
||||
mIns[0].mType == ASMIT_CLC &&
|
||||
mIns[1].mType == ASMIT_ADC && mIns[1].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[1].mFlags & NCIF_LOWER) && mIns[1].mLinkerObject &&
|
||||
mIns[2].mType == ASMIT_STA && mIns[2].mMode == ASMIM_ZERO_PAGE && mIns[2].mAddress == reg &&
|
||||
mIns[3].mType == ASMIT_LDA && mIns[3].mMode == ASMIM_IMMEDIATE_ADDRESS && (mIns[3].mFlags & NCIF_UPPER) && mIns[3].mLinkerObject == mIns[1].mLinkerObject &&
|
||||
mIns[4].mType == ASMIT_ADC && mIns[4].mMode == ASMIM_IMMEDIATE && mIns[4].mAddress == 0 &&
|
||||
mIns[5].mType == ASMIT_STA && mIns[5].mMode == ASMIM_ZERO_PAGE && mIns[5].mAddress == reg + 1)
|
||||
{
|
||||
ains = &(mIns[1]);
|
||||
iins = nullptr;
|
||||
apos = 0;
|
||||
|
||||
if (!direct)
|
||||
return false;
|
||||
|
||||
flags = (LIVE_CPU_REG_X | LIVE_CPU_REG_Y) & ~mIns[0].mLive;
|
||||
|
||||
int k = 6;
|
||||
while (k < at)
|
||||
{
|
||||
assert(!(flags & LIVE_CPU_REG_Y) || mIns[k].mType != ASMIT_TYA);
|
||||
if (mIns[k].ChangesYReg())
|
||||
flags &= ~LIVE_CPU_REG_Y;
|
||||
if (mIns[k].ChangesXReg())
|
||||
flags &= ~LIVE_CPU_REG_X;
|
||||
k++;
|
||||
}
|
||||
|
||||
return flags != 0;
|
||||
}
|
||||
|
||||
if (mFromJump)
|
||||
{
|
||||
while (j >= -6)
|
||||
|
@ -9679,6 +9717,25 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// move clc and sec down
|
||||
for (int i = 0; i + 1 < mIns.Size(); i++)
|
||||
{
|
||||
if ((mIns[i].mType == ASMIT_CLC || mIns[i].mType == ASMIT_SEC) && !mIns[i + 1].RequiresCarry() && !mIns[i + 1].ChangesCarry())
|
||||
{
|
||||
if (i + 2 < mIns.Size() && mIns[i + 1].mType == ASMIT_LDA && (mIns[i + 1].mMode == ASMIM_IMMEDIATE || mIns[i + 1].mMode == ASMIM_IMMEDIATE_ADDRESS || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) && mIns[i + 2].RequiresCarry())
|
||||
;
|
||||
else
|
||||
{
|
||||
NativeCodeInstruction pins = mIns[i];
|
||||
mIns[i] = mIns[i + 1];
|
||||
mIns[i + 1] = pins;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
|
||||
// shortcut index
|
||||
|
@ -10516,7 +10573,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
|||
progress = true;
|
||||
}
|
||||
else if (
|
||||
mIns[i + 0].mType == ASMIT_LDA &&
|
||||
mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_IMMEDIATE || mIns[i + 0].mMode == ASMIM_IMMEDIATE_ADDRESS || mIns[i + 0].mMode == ASMIM_ZERO_PAGE) &&
|
||||
mIns[i + 1].mType == ASMIT_CLC &&
|
||||
mIns[i + 2].mType == ASMIT_ADC)
|
||||
{
|
||||
|
@ -11049,8 +11106,158 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void)
|
|||
}
|
||||
}
|
||||
|
||||
void NativeCodeBasicBlock::BuildPlacement(GrowingArray<NativeCodeBasicBlock*>& placement)
|
||||
{
|
||||
if (!mPlaced)
|
||||
{
|
||||
mPlaced = true;
|
||||
mPlace = placement.Size();
|
||||
placement.Push(this);
|
||||
|
||||
if (mFalseJump)
|
||||
{
|
||||
if (mFalseJump->mPlaced)
|
||||
mTrueJump->BuildPlacement(placement);
|
||||
else if (mTrueJump->mPlaced)
|
||||
mFalseJump->BuildPlacement(placement);
|
||||
else if (!mTrueJump->mFalseJump && !mFalseJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump)
|
||||
{
|
||||
mFalseJump->mPlaced = true;
|
||||
mFalseJump->mPlace = placement.Size();
|
||||
placement.Push(mFalseJump);
|
||||
|
||||
mTrueJump->BuildPlacement(placement);
|
||||
}
|
||||
else if (mTrueJump->mFalseJump == mFalseJump || mTrueJump->mTrueJump == mFalseJump)
|
||||
{
|
||||
mTrueJump->BuildPlacement(placement);
|
||||
mFalseJump->BuildPlacement(placement);
|
||||
}
|
||||
else if (mFalseJump->mFalseJump == mTrueJump || mFalseJump->mTrueJump == mTrueJump)
|
||||
{
|
||||
mFalseJump->BuildPlacement(placement);
|
||||
mTrueJump->BuildPlacement(placement);
|
||||
}
|
||||
else if (
|
||||
!mTrueJump->mFalseJump && mTrueJump->mTrueJump && mTrueJump->mTrueJump->mPlaced && mTrueJump->mCode.Size() < 120 ||
|
||||
mTrueJump->mFalseJump && mTrueJump->mTrueJump && mTrueJump->mFalseJump->mPlaced && mTrueJump->mTrueJump->mPlaced && mTrueJump->mCode.Size() < 120)
|
||||
{
|
||||
mTrueJump->BuildPlacement(placement);
|
||||
mFalseJump->BuildPlacement(placement);
|
||||
}
|
||||
else
|
||||
{
|
||||
mFalseJump->BuildPlacement(placement);
|
||||
mTrueJump->BuildPlacement(placement);
|
||||
}
|
||||
}
|
||||
else if (mTrueJump)
|
||||
{
|
||||
mTrueJump->BuildPlacement(placement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NativeCodeBasicBlock::InitialOffset(int& total)
|
||||
{
|
||||
mOffset = total;
|
||||
total += mCode.Size();
|
||||
if (mFalseJump)
|
||||
{
|
||||
total += 5;
|
||||
if (mFalseJump->mPlace != mPlace + 1 && mTrueJump->mPlace != mPlace + 1)
|
||||
total += 3;
|
||||
}
|
||||
else if (mTrueJump)
|
||||
{
|
||||
if (mTrueJump->mPlace != mPlace + 1)
|
||||
total += 3;
|
||||
}
|
||||
|
||||
mSize = total - mOffset;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::CalculateOffset(int& total)
|
||||
{
|
||||
bool changed = total != mOffset;
|
||||
mOffset = total;
|
||||
|
||||
total += mCode.Size();
|
||||
|
||||
if (mFalseJump)
|
||||
{
|
||||
if (mFalseJump->mPlace == mPlace + 1)
|
||||
total += BranchByteSize(total, mTrueJump->mOffset);
|
||||
else if (mTrueJump->mPlace == mPlace + 1)
|
||||
total += BranchByteSize(total, mFalseJump->mOffset);
|
||||
else
|
||||
{
|
||||
total += BranchByteSize(total, mTrueJump->mOffset);
|
||||
total += JumpByteSize(total, mFalseJump->mOffset);
|
||||
}
|
||||
}
|
||||
else if (mTrueJump)
|
||||
{
|
||||
if (mTrueJump->mPlace != mPlace + 1)
|
||||
total += JumpByteSize(total, mTrueJump->mOffset);
|
||||
}
|
||||
|
||||
if (mOffset + mSize != total)
|
||||
changed = true;
|
||||
|
||||
mSize = total - mOffset;
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target)
|
||||
{
|
||||
int i;
|
||||
int next, end;
|
||||
|
||||
#if 1
|
||||
end = mOffset + mCode.Size();
|
||||
next = mOffset + mSize;
|
||||
|
||||
if (mFalseJump)
|
||||
{
|
||||
if (mFalseJump->mPlace == mPlace + 1)
|
||||
end += PutBranch(proc, mBranch, mTrueJump->mOffset - end);
|
||||
else if (mTrueJump->mPlace == mPlace + 1)
|
||||
end += PutBranch(proc, InvertBranchCondition(mBranch), mFalseJump->mOffset - end);
|
||||
else
|
||||
{
|
||||
end += PutBranch(proc, mBranch, mTrueJump->mOffset - end);
|
||||
end += PutJump(proc, mFalseJump->mOffset - end);
|
||||
}
|
||||
}
|
||||
else if (mTrueJump)
|
||||
{
|
||||
if (mTrueJump->mPlace != mPlace + 1)
|
||||
end += PutJump(proc, mTrueJump->mOffset - end);
|
||||
}
|
||||
|
||||
assert(end == next);
|
||||
|
||||
for (int i = 0; i < mRelocations.Size(); i++)
|
||||
{
|
||||
LinkerReference& rl(mRelocations[i]);
|
||||
rl.mOffset += mOffset;
|
||||
if (rl.mFlags & LREF_INBLOCK)
|
||||
{
|
||||
rl.mRefOffset += mOffset;
|
||||
rl.mFlags &= ~LREF_INBLOCK;
|
||||
}
|
||||
proc->mRelocations.Push(rl);
|
||||
}
|
||||
|
||||
for (i = 0; i < mCode.Size(); i++)
|
||||
{
|
||||
target[i + mOffset] = mCode[i];
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
int i;
|
||||
int next;
|
||||
int pos, at;
|
||||
|
@ -11113,8 +11320,9 @@ void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target)
|
|||
if (mTrueJump) mTrueJump->CopyCode(proc, target);
|
||||
if (mFalseJump) mFalseJump->CopyCode(proc, target);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
void NativeCodeBasicBlock::CalculateOffset(int& total)
|
||||
{
|
||||
int next;
|
||||
|
@ -11245,12 +11453,14 @@ void NativeCodeBasicBlock::CalculateOffset(int& total)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NativeCodeBasicBlock::NativeCodeBasicBlock(void)
|
||||
: mIns(NativeCodeInstruction(ASMIT_INV, ASMIM_IMPLIED)), mRelocations({ 0 }), mEntryBlocks(nullptr), mCode(0)
|
||||
{
|
||||
mTrueJump = mFalseJump = NULL;
|
||||
mOffset = 0x7fffffff;
|
||||
mOffset = -1;
|
||||
mPlaced = false;
|
||||
mCopied = false;
|
||||
mKnownShortBranch = false;
|
||||
mBypassed = false;
|
||||
|
@ -11564,15 +11774,34 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
|
||||
mEntryBlock->Assemble();
|
||||
|
||||
int total, base;
|
||||
|
||||
NativeCodeBasicBlock* lentryBlock = mEntryBlock->BypassEmptyBlocks();
|
||||
|
||||
total = 0;
|
||||
lentryBlock->CalculateOffset(total);
|
||||
|
||||
proc->mLinkerObject->mType = LOT_NATIVE_CODE;
|
||||
lentryBlock->CopyCode(this, proc->mLinkerObject->AddSpace(total));
|
||||
|
||||
GrowingArray<NativeCodeBasicBlock*> placement(nullptr);
|
||||
|
||||
int total;
|
||||
total = 0;
|
||||
|
||||
lentryBlock->BuildPlacement(placement);
|
||||
|
||||
for (int i = 0; i < placement.Size(); i++)
|
||||
placement[i]->InitialOffset(total);
|
||||
|
||||
bool progress;
|
||||
do {
|
||||
progress = false;
|
||||
total = 0;
|
||||
for (int i = 0; i < placement.Size(); i++)
|
||||
if (placement[i]->CalculateOffset(total))
|
||||
progress = true;
|
||||
} while (progress);
|
||||
|
||||
uint8* data = proc->mLinkerObject->AddSpace(total);
|
||||
|
||||
for (int i = 0; i < placement.Size(); i++)
|
||||
placement[i]->CopyCode(this, data);
|
||||
|
||||
|
||||
for (int i = 0; i < mRelocations.Size(); i++)
|
||||
{
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
bool ChangesAccu(void) const;
|
||||
bool UsesAccu(void) const;
|
||||
bool ChangesCarry(void) const;
|
||||
bool RequiresCarry(void) const;
|
||||
bool RequiresAccu(void) const;
|
||||
bool RequiresYReg(void) const;
|
||||
bool RequiresXReg(void) const;
|
||||
|
@ -105,7 +106,7 @@ public:
|
|||
|
||||
GrowingArray<NativeCodeBasicBlock*> mEntryBlocks;
|
||||
|
||||
int mOffset, mSize, mNumEntries, mNumEntered, mFrameOffset;
|
||||
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset;
|
||||
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked;
|
||||
NativeCodeBasicBlock* mLoopHeadBlock;
|
||||
|
||||
|
@ -115,7 +116,10 @@ public:
|
|||
int PutJump(NativeCodeProcedure* proc, int offset);
|
||||
|
||||
NativeCodeBasicBlock* BypassEmptyBlocks(void);
|
||||
void CalculateOffset(int& total);
|
||||
|
||||
void BuildPlacement(GrowingArray<NativeCodeBasicBlock*>& placement);
|
||||
void InitialOffset(int& total);
|
||||
bool CalculateOffset(int& total);
|
||||
|
||||
void CopyCode(NativeCodeProcedure* proc, uint8* target);
|
||||
void Assemble(void);
|
||||
|
|
Loading…
Reference in New Issue