Optimize jump to rts and simple loop invariants in native code generator

This commit is contained in:
drmortalwombat 2021-12-11 23:04:38 +01:00
parent f7a5c94229
commit fefa2e7d9a
2 changed files with 95 additions and 29 deletions

View File

@ -2523,8 +2523,15 @@ static AsmInsType TransposeBranchCondition(AsmInsType code)
}
int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, int offset)
int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target)
{
if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS)
{
PutByte(0x60);
return 1;
}
else
{
PutByte(0x4c);
LinkerReference rl;
@ -2532,13 +2539,23 @@ int NativeCodeBasicBlock::PutJump(NativeCodeProcedure* proc, int offset)
rl.mOffset = mCode.Size();
rl.mFlags = LREF_LOWBYTE | LREF_HIGHBYTE;
rl.mRefObject = nullptr;
rl.mRefOffset = mOffset + mCode.Size() + offset - 1;
rl.mRefOffset = target->mOffset;
mRelocations.Push(rl);
PutWord(0);
return 3;
}
}
int NativeCodeBasicBlock::JumpByteSize(NativeCodeBasicBlock* target)
{
if (target->mIns.Size() == 1 && target->mIns[0].mType == ASMIT_RTS)
return 1;
else
return 3;
}
int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset)
{
if (offset >= -126 && offset <= 129)
@ -4443,6 +4460,8 @@ void NativeCodeBasicBlock::ShiftRegisterLeft(InterCodeProcedure* proc, int reg,
int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins, const InterInstruction* sins, int index, int mul)
{
mul &= 0xffff;
if (sins)
LoadValueToReg(proc, sins, BC_REG_ACCU, nullptr, nullptr);
else
@ -4573,11 +4592,24 @@ int NativeCodeBasicBlock::ShortMultiply(InterCodeProcedure* proc, NativeCodeProc
#endif
#endif
default:
if (mul & 0xff00)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, mul & 0xff));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, mul >> 8));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 1));
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("mul16")));
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME));
}
else
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, mul));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_WORK + 0));
NativeCodeGenerator::Runtime& rt(nproc->mGenerator->ResolveRuntime(Ident::Unique("mul16by8")));
mIns.Push(NativeCodeInstruction(ASMIT_JSR, ASMIM_ABSOLUTE, rt.mOffset, rt.mLinkerObject, NCIF_RUNTIME));
}
return BC_REG_WORK + 2;
}
@ -5531,13 +5563,13 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
{
int reg = BC_REG_ACCU;
if (ins->mOperator == IA_MUL && ins->mSrc[1].mTemp < 0 && (ins->mSrc[1].mIntConst & ~0xff) == 0)
if (ins->mOperator == IA_MUL && ins->mSrc[1].mTemp < 0)
{
reg = ShortMultiply(proc, nproc, ins, sins0, 0, ins->mSrc[1].mIntConst & 0xff);
reg = ShortMultiply(proc, nproc, ins, sins0, 0, ins->mSrc[1].mIntConst);
}
else if (ins->mOperator == IA_MUL && ins->mSrc[0].mTemp < 0 && (ins->mSrc[0].mIntConst & ~0xff) == 0)
else if (ins->mOperator == IA_MUL && ins->mSrc[0].mTemp < 0)
{
reg = ShortMultiply(proc, nproc, ins, sins1, 1, ins->mSrc[0].mIntConst & 0xff);
reg = ShortMultiply(proc, nproc, ins, sins1, 1, ins->mSrc[0].mIntConst);
}
else
{
@ -8860,6 +8892,32 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
return changed;
}
void NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock* lblock)
{
if (lblock->mIns[0].mType == ASMIT_LDA && lblock->mIns[0].mMode == ASMIM_IMMEDIATE)
{
int i = 1;
while (i < lblock->mIns.Size() && !lblock->mIns[i].ChangesAccu())
i++;
if (i == lblock->mIns.Size())
{
mIns.Push(lblock->mIns[0]);
lblock->mIns.Remove(0);
}
}
else if (lblock->mIns[0].mType == ASMIT_LDA && lblock->mIns[0].mMode == ASMIM_ZERO_PAGE)
{
int i = 1;
while (i < lblock->mIns.Size() && !lblock->mIns[i].ChangesAccu() && !lblock->mIns[i].ChangesZeroPage(lblock->mIns[0].mAddress))
i++;
if (i == lblock->mIns.Size())
{
mIns.Push(lblock->mIns[0]);
lblock->mIns.Remove(0);
}
}
}
bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
{
if (!mVisited)
@ -8953,6 +9011,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock;
mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock);
changed = true;
assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV);
@ -8985,6 +9045,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock;
mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock);
changed = true;
assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV);
@ -9041,6 +9103,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock;
mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock);
changed = true;
assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV);
@ -9121,6 +9185,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock;
mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock);
changed = true;
assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV);
@ -9153,6 +9219,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoop(NativeCodeProcedure * proc)
mTrueJump = lblock;
mFalseJump = nullptr;
OptimizeSimpleLoopInvariant(proc, lblock);
changed = true;
assert(mIns.Size() == 0 || mIns[0].mType != ASMIT_INV);
@ -11369,11 +11437,6 @@ static int BranchByteSize(int from, int to)
return 5;
}
static int JumpByteSize(int from, int to)
{
return 3;
}
NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void)
{
if (mBypassed)
@ -11480,13 +11543,13 @@ bool NativeCodeBasicBlock::CalculateOffset(int& total)
else
{
total += BranchByteSize(total, mTrueJump->mOffset);
total += JumpByteSize(total, mFalseJump->mOffset);
total += JumpByteSize(mFalseJump);
}
}
else if (mTrueJump)
{
if (mTrueJump->mPlace != mPlace + 1)
total += JumpByteSize(total, mTrueJump->mOffset);
total += JumpByteSize(mTrueJump);
}
if (mOffset + mSize != total)
@ -11515,13 +11578,13 @@ void NativeCodeBasicBlock::CopyCode(NativeCodeProcedure * proc, uint8* target)
else
{
end += PutBranch(proc, mBranch, mTrueJump->mOffset - end);
end += PutJump(proc, mFalseJump->mOffset - end);
end += PutJump(proc, mFalseJump);
}
}
else if (mTrueJump)
{
if (mTrueJump->mPlace != mPlace + 1)
end += PutJump(proc, mTrueJump->mOffset - end);
end += PutJump(proc, mTrueJump);
}
assert(end == next);

View File

@ -113,7 +113,8 @@ public:
NativeRegisterDataSet mDataSet, mNDataSet;
int PutBranch(NativeCodeProcedure* proc, AsmInsType code, int offset);
int PutJump(NativeCodeProcedure* proc, int offset);
int PutJump(NativeCodeProcedure* proc, NativeCodeBasicBlock* target);
int JumpByteSize(NativeCodeBasicBlock * target);
NativeCodeBasicBlock* BypassEmptyBlocks(void);
@ -128,6 +129,8 @@ public:
bool RemoveNops(void);
bool PeepHoleOptimizer(int pass);
void BlockSizeReduction(void);
void OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock * lblock);
bool OptimizeSimpleLoop(NativeCodeProcedure* proc);
bool OptimizeInnerLoop(NativeCodeProcedure* proc, NativeCodeBasicBlock* head, NativeCodeBasicBlock* tail, GrowingArray<NativeCodeBasicBlock*>& blocks);