Optimize carry propagation

This commit is contained in:
drmortalwombat 2025-05-25 17:37:52 +02:00
parent 4d9d628b67
commit 197e2a91be
3 changed files with 160 additions and 37 deletions

View File

@ -8006,6 +8006,38 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void)
mInstructions[i]->ConstantFolding(); mInstructions[i]->ConstantFolding();
} }
#endif
#if 1
// Check shortcut double jump
if (mTrueJump && mTrueJump->mInstructions.Size() == 1 && mTrueJump->mInstructions[0]->mCode == IC_BRANCH &&
mTrueJump->mInstructions[0]->mSrc[0].mTemp >= 0 &&
mTrueJump->mInstructions[0]->mSrc[0].mTemp < mTrueValueRange.Size() &&
mTrueValueRange[mTrueJump->mInstructions[0]->mSrc[0].mTemp].IsConstant())
{
mTrueJump->mNumEntries--;
mTrueJump->mEntryBlocks.RemoveAll(this);
if (mTrueValueRange[mTrueJump->mInstructions[0]->mSrc[0].mTemp].mMaxValue == 0)
mTrueJump = mTrueJump->mFalseJump;
else
mTrueJump = mTrueJump->mTrueJump;
mTrueJump->mNumEntries++;
mTrueJump->mEntryBlocks.Push(this);
}
if (mFalseJump && mFalseJump->mInstructions.Size() == 1 && mFalseJump->mInstructions[0]->mCode == IC_BRANCH &&
mFalseJump->mInstructions[0]->mSrc[0].mTemp >= 0 &&
mFalseJump->mInstructions[0]->mSrc[0].mTemp < mFalseValueRange.Size() &&
mFalseValueRange[mFalseJump->mInstructions[0]->mSrc[0].mTemp].IsConstant())
{
mFalseJump->mNumEntries--;
mFalseJump->mEntryBlocks.RemoveAll(this);
if (mFalseValueRange[mFalseJump->mInstructions[0]->mSrc[0].mTemp].mMaxValue == 0)
mFalseJump = mFalseJump->mFalseJump;
else
mFalseJump = mFalseJump->mTrueJump;
mFalseJump->mNumEntries++;
mFalseJump->mEntryBlocks.Push(this);
}
#endif #endif
} }
#endif #endif

View File

@ -2106,6 +2106,8 @@ bool NativeCodeInstruction::SameEffectiveAddress(const NativeCodeInstruction& in
case ASMIM_ABSOLUTE_X: case ASMIM_ABSOLUTE_X:
case ASMIM_ABSOLUTE_Y: case ASMIM_ABSOLUTE_Y:
return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress); return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress);
case ASMIM_IMMEDIATE_ADDRESS:
return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress && ins.mFlags == mFlags);
default: default:
return false; return false;
} }
@ -7850,6 +7852,9 @@ void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterI
{ {
if (ins->mSrc[0].mMemory == IM_GLOBAL) if (ins->mSrc[0].mMemory == IM_GLOBAL)
{ {
if (ins->mDst.IsUByte())
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, flags, 0, uint8(ins->mDst.mRange.mMinValue), uint8(ins->mDst.mRange.mMaxValue)));
else
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, flags)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ABSOLUTE, ins->mSrc[0].mIntConst, ins->mSrc[0].mLinkerObject, flags));
} }
else if (ins->mSrc[0].mMemory == IM_ABSOLUTE) else if (ins->mSrc[0].mMemory == IM_ABSOLUTE)
@ -7858,6 +7863,9 @@ void NativeCodeBasicBlock::LoadValueToReg(InterCodeProcedure* proc, const InterI
} }
else if (ins->mSrc[0].mMemory == IM_FPARAM) else if (ins->mSrc[0].mMemory == IM_FPARAM)
{ {
if (ins->mDst.IsUByte())
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst, nullptr, flags, 0, uint8(ins->mDst.mRange.mMinValue), uint8(ins->mDst.mRange.mMaxValue)));
else
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst, nullptr, flags)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_FPARAMS + ins->mSrc[0].mVarIndex + ins->mSrc[0].mIntConst, nullptr, flags));
} }
else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM) else if (ins->mSrc[0].mMemory == IM_LOCAL || ins->mSrc[0].mMemory == IM_PARAM)
@ -21373,6 +21381,48 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
break; break;
} }
#endif #endif
#if 1
if (i + 6 < mIns.Size() &&
mIns[i + 0].mType == ASMIT_TAY &&
mIns[i + 1].mType == ASMIT_ASL && mIns[i + 1].mMode == ASMIM_IMPLIED &&
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 0 &&
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0xff &&
mIns[i + 4].mType == ASMIT_EOR && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0xff &&
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 6].mType == ASMIT_TYA &&
!(mIns[i + 6].mLive & (LIVE_CPU_REG_Y | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
{
changed = true;
NativeCodeBasicBlock* eblock = proc->AllocateBlock();
NativeCodeBasicBlock* neblock = proc->AllocateBlock();
NativeCodeBasicBlock* rblock = proc->AllocateBlock();
rblock->mTrueJump = mTrueJump;
rblock->mFalseJump = mFalseJump;
rblock->mBranch = mBranch;
rblock->mBranchIns = mBranchIns;
rblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_STY, mIns[i + 5]));
for (int j = i + 7; j < mIns.Size(); j++)
rblock->mIns.Push(mIns[j]);
mIns.SetSize(i + 1);
mIns[i + 0].mType = ASMIT_ORA; mIns[i + 0].mMode = ASMIM_IMMEDIATE; mIns[i + 0].mAddress = 0x00;
mIns[i + 0].mLive |= LIVE_CPU_REG_A | LIVE_CPU_REG_Z;
mTrueJump = eblock;
mFalseJump = neblock;
mBranch = ASMIT_BPL;
mBranchIns = mIns[i + 0].mIns;
eblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDY, ASMIM_IMMEDIATE, 0x00));
neblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDY, ASMIM_IMMEDIATE, 0xff));
eblock->Close(mIns[i].mIns, rblock, nullptr, ASMIT_JMP);
neblock->Close(mIns[i].mIns, rblock, nullptr, ASMIT_JMP);
break;
}
#endif
#if 1 #if 1
if (i + 4 < mIns.Size() && if (i + 4 < mIns.Size() &&
(mIns[i + 0].mType == ASMIT_CPX || mIns[i + 0].mType == ASMIT_CPY) && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0x01 && (mIns[i + 0].mType == ASMIT_CPX || mIns[i + 0].mType == ASMIT_CPY) && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0x01 &&
@ -22588,6 +22638,33 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
} }
} }
#if 1
if (mFalseJump && mIns.Size() >= 3)
{
int sz = mIns.Size();
if (mIns[sz - 3].mType == ASMIT_CLC &&
mIns[sz - 2].mType == ASMIT_ADC &&
mIns[sz - 1].mType == ASMIT_CMP && mIns[sz - 1].SameEffectiveAddress(mIns[sz - 2]))
{
if (mTrueJump->mNumEntries == 1 && !mFalseJump->mEntryRequiredRegs[CPU_REG_A])
{
mTrueJump->mIns.Insert(0, mIns[sz - 3]);
mTrueJump->mIns.Insert(1, mIns[sz - 2]);
mIns[sz - 1].mMode = ASMIM_IMMEDIATE; mIns[sz - 1].mAddress = 0;
mIns.Remove(sz - 3, 2);
changed = true;
}
else if (mFalseJump->mNumEntries == 1 && !mTrueJump->mEntryRequiredRegs[CPU_REG_A])
{
mFalseJump->mIns.Insert(0, mIns[sz - 3]);
mFalseJump->mIns.Insert(1, mIns[sz - 2]);
mIns[sz - 1].mMode = ASMIM_IMMEDIATE; mIns[sz - 1].mAddress = 0;
mIns.Remove(sz - 3, 2);
changed = true;
}
}
}
#endif
if (mTrueJump && mTrueJump->ExpandADCToBranch(proc)) if (mTrueJump && mTrueJump->ExpandADCToBranch(proc))
changed = true; changed = true;
if (mFalseJump && mFalseJump->ExpandADCToBranch(proc)) if (mFalseJump && mFalseJump->ExpandADCToBranch(proc))
@ -43836,7 +43913,7 @@ bool NativeCodeBasicBlock::BlockSizeCopyReduction(NativeCodeProcedure* proc, int
// Size reduction violating various assumptions such as no branches in basic blocks // Size reduction violating various assumptions such as no branches in basic blocks
// must be last step before actual assembly // must be last step before actual assembly
void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xenter, int yenter) void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xenter, int yenter, int center)
{ {
if (!mVisited) if (!mVisited)
{ {
@ -44665,7 +44742,15 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen
#endif #endif
bool carrySet = false, carryClear = false; bool carrySet = false, carryClear = false;
if (mEntryBlocks.Size() == 1 && center >= 0)
{
if (center)
carrySet = true;
else
carryClear = true;
}
else
{
if (mEntryBlocks.Size() > 0) if (mEntryBlocks.Size() > 0)
{ {
carrySet = true; carrySet = true;
@ -44696,6 +44781,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen
else else
carryClear = carrySet = false; carryClear = carrySet = false;
} }
}
#if 1 #if 1
@ -45026,11 +45112,16 @@ void NativeCodeBasicBlock::BlockSizeReduction(NativeCodeProcedure* proc, int xen
} }
mIns.SetSize(j); mIns.SetSize(j);
int cval = -1;
if (carrySet)
cval = 1;
else if (carryClear)
cval = 0;
#endif #endif
if (mTrueJump) if (mTrueJump)
mTrueJump->BlockSizeReduction(proc, ximm ? xval : -1, yimm ? yval: -1); mTrueJump->BlockSizeReduction(proc, ximm ? xval : -1, yimm ? yval: -1, cval);
if (mFalseJump) if (mFalseJump)
mFalseJump->BlockSizeReduction(proc, ximm ? xval : -1, yimm ? yval : -1); mFalseJump->BlockSizeReduction(proc, ximm ? xval : -1, yimm ? yval : -1, cval);
} }
} }
@ -55276,7 +55367,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mInterProc->mLinkerObject->mNativeProc = this; mInterProc->mLinkerObject->mNativeProc = this;
CheckFunc = !strcmp(mIdent->mString, "floaters_update"); CheckFunc = !strcmp(mIdent->mString, "sprite_mobs_update_slide");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];
@ -57336,7 +57427,7 @@ void NativeCodeProcedure::Optimize(void)
#if 1 #if 1
ResetVisited(); ResetVisited();
mEntryBlock->BlockSizeReduction(this, -1, -1); mEntryBlock->BlockSizeReduction(this, -1, -1, -1);
ResetVisited(); ResetVisited();
mEntryBlock->MergeBasicBlocks(); mEntryBlock->MergeBasicBlocks();

View File

@ -345,7 +345,7 @@ public:
bool PeepHoleOptimizerIterate(int pass); bool PeepHoleOptimizerIterate(int pass);
bool PeepHoleOptimizerExits(int pass); bool PeepHoleOptimizerExits(int pass);
void BlockSizeReduction(NativeCodeProcedure* proc, int xenter, int yenter); void BlockSizeReduction(NativeCodeProcedure* proc, int xenter, int yenter, int center);
bool BlockSizeCopyReduction(NativeCodeProcedure* proc, int & si, int & di); bool BlockSizeCopyReduction(NativeCodeProcedure* proc, int & si, int & di);
bool OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, bool full); bool OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, bool full);