Reduce code size by recycling nearby jmp for far branches

This commit is contained in:
drmortalwombat 2024-10-27 16:56:35 +01:00
parent 887a51b176
commit 179cc694e3
2 changed files with 110 additions and 39 deletions

View File

@ -3,6 +3,7 @@
#define JUMP_TO_BRANCH 1 #define JUMP_TO_BRANCH 1
#define CHECK_NULLPTR 0 #define CHECK_NULLPTR 0
#define REYCLE_JUMPS 1
static bool CheckFunc; static bool CheckFunc;
static bool CheckCase; static bool CheckCase;
@ -5202,7 +5203,7 @@ static AsmInsType TransposeBranchCondition(AsmInsType code)
} }
int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, int offset, AsmInsType code) int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, int from, int to, AsmInsType code)
{ {
if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS) if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS)
{ {
@ -5232,12 +5233,12 @@ int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBloc
PutWord(0); PutWord(0);
return 3; return 3;
} }
else if (offset >= -126 && offset <= 129) else if (to - from >= -126 && to - from <= 129)
{ {
if (code != ASMIT_INV) if (code != ASMIT_INV)
{ {
PutOpcode(AsmInsOpcodes[InvertBranchCondition(code)][ASMIM_RELATIVE]); PutOpcode(AsmInsOpcodes[InvertBranchCondition(code)][ASMIM_RELATIVE]);
PutByte(offset - 2); PutByte(to - from - 2);
return 2; return 2;
} }
#if JUMP_TO_BRANCH #if JUMP_TO_BRANCH
@ -5248,7 +5249,7 @@ int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBloc
else else
PutOpcode(AsmInsOpcodes[ASMIT_BCC][ASMIM_RELATIVE]); PutOpcode(AsmInsOpcodes[ASMIT_BCC][ASMIM_RELATIVE]);
PutByte(offset - 2); PutByte(to - from - 2);
return 2; return 2;
} }
else if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE) else if (mNDataSet.mRegs[CPU_REG_Z].mMode == NRDM_IMMEDIATE)
@ -5258,11 +5259,14 @@ int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBloc
else else
PutOpcode(AsmInsOpcodes[ASMIT_BEQ][ASMIM_RELATIVE]); PutOpcode(AsmInsOpcodes[ASMIT_BEQ][ASMIM_RELATIVE]);
PutByte(offset - 2); PutByte(to - from - 2);
return 2; return 2;
} }
#endif #endif
} }
target->mAsmFromJump = from;
PutByte(0x4c); PutByte(0x4c);
LinkerReference rl; LinkerReference rl;
@ -5277,7 +5281,7 @@ int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBloc
return 3; return 3;
} }
int NativeCodeBasicBlock::BranchByteSize(NativeCodeBasicBlock* target, int from, int to) int NativeCodeBasicBlock::BranchByteSize(NativeCodeBasicBlock* target, int from, int to, bool final)
{ {
if (to - from >= -126 && to - from <= 129) if (to - from >= -126 && to - from <= 129)
return 2; return 2;
@ -5285,11 +5289,23 @@ int NativeCodeBasicBlock::BranchByteSize(NativeCodeBasicBlock* target, int from,
{ {
if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS) if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS)
return 3; return 3;
return 5; if (final)
{
#if REYCLE_JUMPS
if (target->mAsmFromJump >= 0 && target->mAsmFromJump - from >= -126)
return 2;
#endif
target->mAsmFromJump = from + 2;
return 5;
}
else
{
return 5;
}
} }
} }
int NativeCodeBasicBlock::JumpByteSize(NativeCodeBasicBlock* target, int offset, bool second) int NativeCodeBasicBlock::JumpByteSize(NativeCodeBasicBlock* target, int from, int to, bool second, bool final)
{ {
if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS) if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS)
{ {
@ -5302,7 +5318,7 @@ int NativeCodeBasicBlock::JumpByteSize(NativeCodeBasicBlock* target, int offset,
{ {
return 3; return 3;
} }
else if (offset >= -126 && offset <= 129) else if (to - from >= -126 && to - from <= 129)
{ {
if (second) if (second)
return 2; return 2;
@ -5313,21 +5329,38 @@ int NativeCodeBasicBlock::JumpByteSize(NativeCodeBasicBlock* target, int offset,
return 2; return 2;
#endif #endif
else else
{
if (final)
target->mAsmFromJump = from;
return 3; return 3;
}
} }
else else
{
if (final)
target->mAsmFromJump = from;
return 3; return 3;
}
} }
int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, AsmInsType code, int offset) int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, AsmInsType code, int from, int to)
{ {
if (offset >= -126 && offset <= 129) if (to - from >= -126 && to - from <= 129)
{ {
PutOpcode(AsmInsOpcodes[code][ASMIM_RELATIVE]); PutOpcode(AsmInsOpcodes[code][ASMIM_RELATIVE]);
PutByte(offset - 2); PutByte(to - from - 2);
return 2; return 2;
} }
#if REYCLE_JUMPS
else if (target->mAsmFromJump >= 0 && target->mAsmFromJump - from >= -126)
{
PutOpcode(AsmInsOpcodes[code][ASMIM_RELATIVE]);
PutByte(target->mAsmFromJump - from - 2);
return 2;
}
#endif
else else
{ {
PutOpcode(AsmInsOpcodes[InvertBranchCondition(code)][ASMIM_RELATIVE]); PutOpcode(AsmInsOpcodes[InvertBranchCondition(code)][ASMIM_RELATIVE]);
@ -5341,6 +5374,9 @@ int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBl
else else
{ {
PutByte(3); PutByte(3);
target->mAsmFromJump = from + 2;
PutByte(0x4c); PutByte(0x4c);
LinkerReference rl; LinkerReference rl;
@ -5348,7 +5384,7 @@ int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBl
rl.mOffset = mCode.Size(); rl.mOffset = mCode.Size();
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE; rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
rl.mRefObject = nullptr; rl.mRefObject = nullptr;
rl.mRefOffset = mOffset + mCode.Size() + offset - 3; rl.mRefOffset = to;
mRelocations.Push(rl); mRelocations.Push(rl);
PutWord(0); PutWord(0);
@ -42018,6 +42054,18 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen
i += 5; i += 5;
} }
#endif #endif
else if (mIns[i + 0].mType == ASMIT_ORA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && !(mIns[i + 0].mLive & LIVE_CPU_REG_X))
{
mIns[j + 0] = NativeCodeInstruction(mIns[i + 0].mIns, ASMIT_TAX);
i++;
j++;
}
else if (mIns[i + 0].mType == ASMIT_ORA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && !(mIns[i + 0].mLive & LIVE_CPU_REG_Y))
{
mIns[j + 0] = NativeCodeInstruction(mIns[i + 0].mIns, ASMIT_TAY);
i++;
j++;
}
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))
{ {
@ -51059,6 +51107,8 @@ void NativeCodeBasicBlock::BuildPlacement(ExpandingArray<NativeCodeBasicBlock*>&
placement.Push(mTrueJump->mTrueJump); placement.Push(mTrueJump->mTrueJump);
mFalseJump->BuildPlacement(placement); mFalseJump->BuildPlacement(placement);
mTrueJump->mTrueJump->mTrueJump->BuildPlacement(placement);
mTrueJump->mTrueJump->mFalseJump->BuildPlacement(placement);
} }
else if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump && mTrueJump->mCode.Size() < 100 && mFalseJump->LeadsInto(mTrueJump->mTrueJump, 0) < 100) else if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump && mTrueJump->mCode.Size() < 100 && mFalseJump->LeadsInto(mTrueJump->mTrueJump, 0) < 100)
{ {
@ -51150,6 +51200,8 @@ void NativeCodeBasicBlock::BuildPlacement(ExpandingArray<NativeCodeBasicBlock*>&
void NativeCodeBasicBlock::InitialOffset(int& total) void NativeCodeBasicBlock::InitialOffset(int& total)
{ {
mAsmFromJump = -1;
mOffset = total; mOffset = total;
total += mCode.Size(); total += mCode.Size();
if (mFalseJump) if (mFalseJump)
@ -51167,7 +51219,7 @@ void NativeCodeBasicBlock::InitialOffset(int& total)
mSize = total - mOffset; mSize = total - mOffset;
} }
bool NativeCodeBasicBlock::CalculateOffset(int& total) bool NativeCodeBasicBlock::CalculateOffset(int& total, bool final)
{ {
bool changed = total != mOffset; bool changed = total != mOffset;
mOffset = total; mOffset = total;
@ -51177,26 +51229,26 @@ bool NativeCodeBasicBlock::CalculateOffset(int& total)
if (mFalseJump) if (mFalseJump)
{ {
if (mFalseJump->mPlace == mPlace + 1) if (mFalseJump->mPlace == mPlace + 1)
total += BranchByteSize(mTrueJump, total, mTrueJump->mOffset); total += BranchByteSize(mTrueJump, total, mTrueJump->mOffset, final);
else if (mTrueJump->mPlace == mPlace + 1) else if (mTrueJump->mPlace == mPlace + 1)
total += BranchByteSize(mFalseJump, total, mFalseJump->mOffset); total += BranchByteSize(mFalseJump, total, mFalseJump->mOffset, final);
else if (mFalseJump->mPlace < mPlace && mTrueJump->mPlace < mPlace && mPlace - mTrueJump->mPlace < 126 && else if (mFalseJump->mPlace < mPlace && mTrueJump->mPlace < mPlace && mPlace - mTrueJump->mPlace < 126 &&
mFalseJump->mIns.Size() == 1 && mFalseJump->mIns[0].mType == ASMIT_RTS) mFalseJump->mIns.Size() == 1 && mFalseJump->mIns[0].mType == ASMIT_RTS)
{ {
total += BranchByteSize(mTrueJump, total, mTrueJump->mOffset); total += BranchByteSize(mTrueJump, total, mTrueJump->mOffset, final);
total += JumpByteSize(mFalseJump, mFalseJump->mOffset - total, true); total += JumpByteSize(mFalseJump, total, mFalseJump->mOffset, true, final);
} }
else if ( else if (
mFalseJump->mPlace > mTrueJump->mPlace && mFalseJump->mPlace < mPlace || mFalseJump->mPlace > mTrueJump->mPlace && mFalseJump->mPlace < mPlace ||
mFalseJump->mPlace < mTrueJump->mPlace && mFalseJump->mPlace > mPlace) mFalseJump->mPlace < mTrueJump->mPlace && mFalseJump->mPlace > mPlace)
{ {
total += BranchByteSize(mFalseJump, total, mFalseJump->mOffset); total += BranchByteSize(mFalseJump, total, mFalseJump->mOffset, final);
total += JumpByteSize(mTrueJump, mTrueJump->mOffset - total, true); total += JumpByteSize(mTrueJump, total, mTrueJump->mOffset, true, final);
} }
else else
{ {
total += BranchByteSize(mTrueJump, total, mTrueJump->mOffset); total += BranchByteSize(mTrueJump, total, mTrueJump->mOffset, final);
total += JumpByteSize(mFalseJump, mFalseJump->mOffset - total, true); total += JumpByteSize(mFalseJump, total, mFalseJump->mOffset, true, final);
} }
} }
else if (mTrueJump) else if (mTrueJump)
@ -51211,7 +51263,7 @@ bool NativeCodeBasicBlock::CalculateOffset(int& total)
mTrueJump = nullptr; mTrueJump = nullptr;
} }
else else
total += JumpByteSize(mTrueJump, mTrueJump->mOffset - total, false); total += JumpByteSize(mTrueJump, total, mTrueJump->mOffset, false, final);
} }
} }
@ -51315,26 +51367,26 @@ void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target)
PutLocation(mBranchIns->mLocation, false); PutLocation(mBranchIns->mLocation, false);
if (mFalseJump->mPlace == mPlace + 1) if (mFalseJump->mPlace == mPlace + 1)
end += PutBranch(proc, mTrueJump, mBranch, mTrueJump->mOffset - end); end += PutBranch(proc, mTrueJump, mBranch, end, mTrueJump->mOffset);
else if (mTrueJump->mPlace == mPlace + 1) else if (mTrueJump->mPlace == mPlace + 1)
end += PutBranch(proc, mFalseJump, InvertBranchCondition(mBranch), mFalseJump->mOffset - end); end += PutBranch(proc, mFalseJump, InvertBranchCondition(mBranch), end, mFalseJump->mOffset);
else if (mFalseJump->mPlace < mPlace && mTrueJump->mPlace < mPlace && mPlace - mTrueJump->mPlace < 126 && else if (mFalseJump->mPlace < mPlace && mTrueJump->mPlace < mPlace && mPlace - mTrueJump->mPlace < 126 &&
mFalseJump->mIns.Size() == 1 && mFalseJump->mIns[0].mType == ASMIT_RTS) mFalseJump->mIns.Size() == 1 && mFalseJump->mIns[0].mType == ASMIT_RTS)
{ {
end += PutBranch(proc, mTrueJump, mBranch, mTrueJump->mOffset - end); end += PutBranch(proc, mTrueJump, mBranch, end, mTrueJump->mOffset);
end += PutJump(proc, mFalseJump, mFalseJump->mOffset - end, mBranch); end += PutJump(proc, mFalseJump, end, mFalseJump->mOffset, mBranch);
} }
else if ( else if (
mFalseJump->mPlace > mTrueJump->mPlace && mFalseJump->mPlace < mPlace || mFalseJump->mPlace > mTrueJump->mPlace && mFalseJump->mPlace < mPlace ||
mFalseJump->mPlace < mTrueJump->mPlace && mFalseJump->mPlace > mPlace) mFalseJump->mPlace < mTrueJump->mPlace && mFalseJump->mPlace > mPlace)
{ {
end += PutBranch(proc, mFalseJump, InvertBranchCondition(mBranch), mFalseJump->mOffset - end); end += PutBranch(proc, mFalseJump, InvertBranchCondition(mBranch), end, mFalseJump->mOffset);
end += PutJump(proc, mTrueJump, mTrueJump->mOffset - end, InvertBranchCondition(mBranch)); end += PutJump(proc, mTrueJump, end, mTrueJump->mOffset, InvertBranchCondition(mBranch));
} }
else else
{ {
end += PutBranch(proc, mTrueJump, mBranch, mTrueJump->mOffset - end); end += PutBranch(proc, mTrueJump, mBranch, end, mTrueJump->mOffset);
end += PutJump(proc, mFalseJump, mFalseJump->mOffset - end, mBranch); end += PutJump(proc, mFalseJump, end, mFalseJump->mOffset, mBranch);
} }
if (mBranchIns) if (mBranchIns)
@ -51347,7 +51399,7 @@ void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target)
if (mBranchIns) if (mBranchIns)
PutLocation(mBranchIns->mLocation, false); PutLocation(mBranchIns->mLocation, false);
end += PutJump(proc, mTrueJump, mTrueJump->mOffset - end); end += PutJump(proc, mTrueJump, end, mTrueJump->mOffset);
if (mBranchIns) if (mBranchIns)
PutLocation(mBranchIns->mLocation, false); PutLocation(mBranchIns->mLocation, false);
@ -52177,7 +52229,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
void NativeCodeProcedure::Assemble(void) void NativeCodeProcedure::Assemble(void)
{ {
CheckFunc = !strcmp(mInterProc->mIdent->mString, "floor_prepare"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "fighter_ai");
if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS) if (mInterProc->mCompilerOptions & COPT_OPTIMIZE_MERGE_CALLS)
{ {
@ -52208,10 +52260,27 @@ void NativeCodeProcedure::Assemble(void)
progress = false; progress = false;
total = 0; total = 0;
for (int i = 0; i < placement.Size(); i++) for (int i = 0; i < placement.Size(); i++)
if (placement[i]->CalculateOffset(total)) if (placement[i]->CalculateOffset(total, false))
progress = true; progress = true;
} while (progress); } while (progress);
// final run to recycle jumps
do {
progress = false;
for (int i = 0; i < placement.Size(); i++)
placement[i]->mAsmFromJump = -1;
total = 0;
for (int i = 0; i < placement.Size(); i++)
if (placement[i]->CalculateOffset(total, true))
progress = true;
} while (progress);
for (int i = 0; i < placement.Size(); i++)
placement[i]->mAsmFromJump = -1;
uint8* data = mInterProc->mLinkerObject->AddSpace(total); uint8* data = mInterProc->mLinkerObject->AddSpace(total);
for (int i = 0; i < placement.Size(); i++) for (int i = 0; i < placement.Size(); i++)

View File

@ -250,6 +250,8 @@ public:
bool mEntryRegA, mEntryRegX, mEntryRegY, mExitRegA, mExitRegX, mChecked; bool mEntryRegA, mEntryRegX, mEntryRegY, mExitRegA, mExitRegX, mChecked;
NativeCodeBasicBlock * mDominator, * mSameBlock; NativeCodeBasicBlock * mDominator, * mSameBlock;
int mAsmFromJump;
NativeCodeBasicBlock* mLoopHeadBlock, * mLoopTailBlock; NativeCodeBasicBlock* mLoopHeadBlock, * mLoopTailBlock;
NativeRegisterDataSet mDataSet, mNDataSet, mFDataSet; NativeRegisterDataSet mDataSet, mNDataSet, mFDataSet;
@ -264,10 +266,10 @@ public:
NativeCodeInstruction DecodeNative(const InterInstruction* ins, LinkerObject * lobj, int& offset) const; NativeCodeInstruction DecodeNative(const InterInstruction* ins, LinkerObject * lobj, int& offset) const;
int PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, AsmInsType code, int offset); int PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, AsmInsType code, int from, int to);
int PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, int offset, AsmInsType code = ASMIT_INV); int PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target, int from, int to, AsmInsType code = ASMIT_INV);
int JumpByteSize(NativeCodeBasicBlock * target, int offset, bool second); int JumpByteSize(NativeCodeBasicBlock * target, int from, int to, bool second, bool final);
int BranchByteSize(NativeCodeBasicBlock* target, int from, int to); int BranchByteSize(NativeCodeBasicBlock* target, int from, int to, bool final);
NativeCodeBasicBlock* SplitAt(int at); NativeCodeBasicBlock* SplitAt(int at);
@ -277,7 +279,7 @@ public:
NativeCodeBasicBlock* PlaceSequence(ExpandingArray<NativeCodeBasicBlock*>& placement, NativeCodeBasicBlock* block); NativeCodeBasicBlock* PlaceSequence(ExpandingArray<NativeCodeBasicBlock*>& placement, NativeCodeBasicBlock* block);
void BuildPlacement(ExpandingArray<NativeCodeBasicBlock*>& placement); void BuildPlacement(ExpandingArray<NativeCodeBasicBlock*>& placement);
void InitialOffset(int& total); void InitialOffset(int& total);
bool CalculateOffset(int& total); bool CalculateOffset(int& total, bool final);
void CopyCode(NativeCodeProcedure* proc, uint8* target); void CopyCode(NativeCodeProcedure* proc, uint8* target);
void Assemble(void); void Assemble(void);