Peephole optimizations

This commit is contained in:
drmortalwombat 2024-09-26 09:15:09 +02:00 committed by John Schneiderman
parent 4b2c02fe26
commit bdd25cbb1d
5 changed files with 229 additions and 13 deletions

View File

@ -11082,6 +11082,47 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra
} }
} }
} }
else if (ins->mSrc[0].mTemp >= 0 && ins->mSrc[1].mTemp >= 0 &&
ltvalue[ins->mSrc[0].mTemp] && ltvalue[ins->mSrc[1].mTemp] &&
ins->mSrc[0].mFinal && ins->mSrc[1].mFinal)
{
InterInstruction* ai0 = ltvalue[ins->mSrc[0].mTemp], * ai1 = ltvalue[ins->mSrc[1].mTemp];
if (ai0->mCode == IC_BINARY_OPERATOR && ai0->mOperator == IA_SUB && ai0->mSrc[0].mTemp < 0 && ai0->mSrc[1].mFinal &&
ai1->mCode == IC_BINARY_OPERATOR && ai1->mOperator == IA_SUB && ai1->mSrc[0].mTemp < 0 && ai1->mSrc[1].mFinal)
{
if (spareTemps + 2 >= ltvalue.Size())
return true;
InterInstruction* sins = new InterInstruction(ins->mLocation, IC_BINARY_OPERATOR);
sins->mOperator = IA_SUB;
sins->mDst = ins->mDst;
sins->mSrc[1].mType = IT_INT16;
sins->mSrc[1].mTemp = spareTemps++;
sins->mSrc[1].mFinal = true;
sins->mSrc[0] = ai0->mSrc[0];
sins->mSrc[0].mIntConst += ai1->mSrc[0].mIntConst;
sins->mSrc[0].mRange.AddConstValue(IT_INT16, -ai1->mSrc[0].mIntConst);
mInstructions.Insert(i + 1, sins);
ins->mDst = sins->mSrc[1];
ai0->mCode = IC_LOAD_TEMPORARY;
ai0->mSrc[0] = ai0->mSrc[1];
ai0->mDst.mRange = ai0->mSrc[0].mRange;
ai0->mNumOperands = 1;
ai1->mCode = IC_LOAD_TEMPORARY;
ai1->mSrc[0] = ai1->mSrc[1];
ai1->mDst.mRange = ai1->mSrc[0].mRange;
ai1->mNumOperands = 1;
ins->mSrc[0].mRange = ai0->mDst.mRange;
ins->mSrc[1].mRange = ai1->mDst.mRange;
changed = true;
}
}
break; break;
#endif #endif
@ -20749,6 +20790,28 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
mInstructions[i + 0] = ins; mInstructions[i + 0] = ins;
changed = true; changed = true;
} }
#if 1
else if (i + 2 < mInstructions.Size() && mInstructions[i + 0]->mCode == IC_STORE && mInstructions[i + 2]->mCode == IC_STORE &&
mInstructions[i + 1]->mCode == IC_LOAD &&
CanSwapInstructions(mInstructions[i + 0], mInstructions[i + 1]) &&
mInstructions[i + 1]->mDst.mTemp == mInstructions[i + 2]->mSrc[0].mTemp && mInstructions[i + 2]->mSrc[0].mFinal &&
!mInstructions[i + 0]->mVolatile && !mInstructions[i + 2]->mVolatile &&
SameMemRegion(mInstructions[i + 0]->mSrc[1], mInstructions[i + 2]->mSrc[1]) &&
(mInstructions[i + 0]->mSrc[1].mVarIndex > mInstructions[i + 2]->mSrc[1].mVarIndex ||
mInstructions[i + 0]->mSrc[1].mVarIndex == mInstructions[i + 2]->mSrc[1].mVarIndex &&
mInstructions[i + 0]->mSrc[1].mIntConst > mInstructions[i + 2]->mSrc[1].mIntConst))
{
InterInstruction* ins = mInstructions[i + 0];
SwapInstructions(ins, mInstructions[i + 1]);
mInstructions[i + 0] = mInstructions[i + 1];
SwapInstructions(ins, mInstructions[i + 2]);
mInstructions[i + 1] = mInstructions[i + 2];
mInstructions[i + 2] = ins;
changed = true;
}
#endif
} }
} while (changed); } while (changed);
@ -22491,7 +22554,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "main"); CheckFunc = !strcmp(mIdent->mString, "bm_init");
CheckCase = false; CheckCase = false;
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];

View File

@ -2,6 +2,7 @@
#include "CompilerTypes.h" #include "CompilerTypes.h"
#define JUMP_TO_BRANCH 1 #define JUMP_TO_BRANCH 1
#define CHECK_NULLPTR 0
static bool CheckFunc; static bool CheckFunc;
static bool CheckCase; static bool CheckCase;
@ -21083,7 +21084,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
if (mFalseJump->mFalseJump == mTrueJump) if (mFalseJump->mFalseJump == mTrueJump)
{ {
mBranch = ASMIT_BCS; mBranch = ASMIT_BCS;
mFalseJump = mFalseJump->mFalseJump; mFalseJump = mFalseJump->mTrueJump;
changed = true; changed = true;
} }
} }
@ -21092,7 +21093,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
if (mFalseJump->mTrueJump == mTrueJump) if (mFalseJump->mTrueJump == mTrueJump)
{ {
mBranch = ASMIT_BCS; mBranch = ASMIT_BCS;
mFalseJump = mFalseJump->mTrueJump; mFalseJump = mFalseJump->mFalseJump;
changed = true; changed = true;
} }
} }
@ -32863,6 +32864,88 @@ bool NativeCodeBasicBlock::Propagate16BitSum(const ExpandingArray<NativeRegister
return changed; return changed;
} }
bool NativeCodeBasicBlock::FindAccuExitValue(int& at)
{
int i = mIns.Size() - 1;
while (i >= 0)
{
if ((mIns[i].mType == ASMIT_LDA || mIns[i].mType == ASMIT_STA) && (mIns[i].mMode == ASMIM_ZERO_PAGE || mIns[i].mMode == ASMIM_ABSOLUTE))
{
at = i;
i++;
while (i < mIns.Size())
{
if (mIns[at].MayBeChangedOnAddress(mIns[i]))
return false;
i++;
}
return true;
}
else if (mIns[i].ChangesAccu())
return false;
i--;
}
return false;
}
bool NativeCodeBasicBlock::MoveLoadXAbsUpCrossBlock(int at)
{
int i = at - 1;
while (i >= 0)
{
if ((mIns[i].mType == ASMIT_STA || mIns[i].mType == ASMIT_LDA) && mIns[i].SameEffectiveAddress(mIns[at]))
{
mIns[i].mLive |= LIVE_CPU_REG_A;
i++;
mIns.Insert(i, NativeCodeInstruction(mIns[at].mIns, ASMIT_TAX));
mIns[at + 1].mType = ASMIT_NOP;
mIns[at + 1].mMode = ASMIM_IMPLIED;
while (i < at + 1)
{
mIns[i].mLive |= LIVE_CPU_REG_X;
i++;
}
return true;
}
if (mIns[i].RequiresXReg() || mIns[i].ChangesXReg() || (mIns[i].mLive & LIVE_CPU_REG_X))
return false;
if (mIns[at].MayBeChangedOnAddress(mIns[i]))
return false;
i--;
}
if (mEntryBlocks.Size() == 1)
{
NativeCodeBasicBlock* eb = mEntryBlocks[0];
if (eb->FindAccuExitValue(i) && eb->mIns[i].SameEffectiveAddress(mIns[at]))
{
while (i < eb->mIns.Size())
{
eb->mIns[i].mLive |= LIVE_CPU_REG_A;
i++;
}
eb->mExitRequiredRegs += CPU_REG_A;
mEntryRequiredRegs += CPU_REG_A;
mIns.Insert(0, NativeCodeInstruction(mIns[at].mIns, ASMIT_TAX));
mIns[at + 1].mType = ASMIT_NOP;
mIns[at + 1].mMode = ASMIM_IMPLIED;
i = 0;
while (i < at + 1)
{
mIns[i].mLive |= LIVE_CPU_REG_X;
i++;
}
return true;
}
}
return false;
}
bool NativeCodeBasicBlock::MoveLoadXUp(int at) bool NativeCodeBasicBlock::MoveLoadXUp(int at)
{ {
@ -42680,6 +42763,23 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerShuffle(int pass)
#endif #endif
#if 1
if (pass > 10)
{
for (int i = 0; i < mIns.Size(); i++)
{
if (!(mIns[i].mFlags & NCIF_VOLATILE))
{
if (mIns[i].mType == ASMIT_LDX && (mIns[i].mMode == ASMIM_ZERO_PAGE || mIns[i].mMode == ASMIM_ABSOLUTE) && !(mIns[i].mLive & LIVE_CPU_REG_Z))
{
if (MoveLoadXAbsUpCrossBlock(i))
changed = true;
}
}
}
CheckLive();
}
#endif
#if 1 #if 1
// move ldy, sty down if live // move ldy, sty down if live
@ -49923,6 +50023,58 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerExits(int pass)
} }
#endif #endif
#if 1
if (sz > 0 && mFalseJump && mIns[sz - 1].ChangesAccuAndFlag() && mBranch == ASMIT_BMI)
{
if (mFalseJump->mIns.Size() == 1 && mFalseJump->mIns[0].mType == ASMIT_CMP && mFalseJump->mBranch == ASMIT_BCS && mFalseJump->mTrueJump == mTrueJump)
{
mTrueJump->RemEntryBlock(this);
mTrueJump = mFalseJump;
mFalseJump = nullptr;
mBranch = ASMIT_JMP;
changed = true;
}
}
#endif
#if 1
if (pass > 15 && sz > 0 && (mIns[sz - 1].mType == ASMIT_CMP || mIns[sz - 1].mType == ASMIT_CPX || mIns[sz - 1].mType == ASMIT_CPY))
{
if (mTrueJump && mTrueJump->mEntryBlocks.Size() == 1 && mTrueJump->mIns.Size() > 0 && mTrueJump->mIns[0].IsSame(mIns[sz - 1]))
{
mTrueJump->mIns[0].mType = ASMIT_NOP; mTrueJump->mIns[0].mMode = ASMIM_IMPLIED;
if (mTrueJump->mIns[0].mLive & LIVE_CPU_REG_Z)
{
mExitRequiredRegs += CPU_REG_Z;
mTrueJump->mEntryRequiredRegs += CPU_REG_Z;
mIns[sz - 1].mLive |= LIVE_CPU_REG_Z;
}
if (mTrueJump->mIns[0].mLive & LIVE_CPU_REG_C)
{
mExitRequiredRegs += CPU_REG_C;
mTrueJump->mEntryRequiredRegs += CPU_REG_C;
mIns[sz - 1].mLive |= LIVE_CPU_REG_C;
}
changed = true;
}
if (mFalseJump && mFalseJump->mEntryBlocks.Size() == 1 && mFalseJump->mIns.Size() > 0 && mFalseJump->mIns[0].IsSame(mIns[sz - 1]))
{
mFalseJump->mIns[0].mType = ASMIT_NOP; mFalseJump->mIns[0].mMode = ASMIM_IMPLIED;
if (mFalseJump->mIns[0].mLive & LIVE_CPU_REG_Z)
{
mExitRequiredRegs += CPU_REG_Z;
mFalseJump->mEntryRequiredRegs += CPU_REG_Z;
mIns[sz - 1].mLive |= LIVE_CPU_REG_Z;
}
if (mFalseJump->mIns[0].mLive & LIVE_CPU_REG_C)
{
mExitRequiredRegs += CPU_REG_C;
mFalseJump->mEntryRequiredRegs += CPU_REG_C;
mIns[sz - 1].mLive |= LIVE_CPU_REG_C;
}
changed = true;
}
}
#endif
CheckLive(); CheckLive();
if (mTrueJump) if (mTrueJump)
mTrueJump->CheckLive(); mTrueJump->CheckLive();
@ -50101,8 +50253,10 @@ void NativeCodeBasicBlock::CheckAsmCode(void)
assert(HasAsmInstructionMode(mIns[j].mType, ASMIM_IMMEDIATE)); assert(HasAsmInstructionMode(mIns[j].mType, ASMIM_IMMEDIATE));
else else
assert(HasAsmInstructionMode(mIns[j].mType, mIns[j].mMode)); assert(HasAsmInstructionMode(mIns[j].mType, mIns[j].mMode));
#if CHECK_NULLPTR
if (mIns[j].mMode == ASMIM_ABSOLUTE || mIns[j].mMode == ASMIM_ABSOLUTE_Y || mIns[j].mMode == ASMIM_ABSOLUTE_X) if (mIns[j].mMode == ASMIM_ABSOLUTE || mIns[j].mMode == ASMIM_ABSOLUTE_Y || mIns[j].mMode == ASMIM_ABSOLUTE_X)
assert(mIns[j].mLinkerObject != nullptr || mIns[j].mAddress > 0); assert(mIns[j].mLinkerObject != nullptr || mIns[j].mAddress > 0);
#endif
} }
if (mTrueJump) mTrueJump->CheckAsmCode(); if (mTrueJump) mTrueJump->CheckAsmCode();
@ -50189,9 +50343,10 @@ void NativeCodeBasicBlock::CheckLive(void)
else else
assert(HasAsmInstructionMode(mIns[j].mType, mIns[j].mMode)); assert(HasAsmInstructionMode(mIns[j].mType, mIns[j].mMode));
#if CHECK_NULLPTR
if (mIns[j].mMode == ASMIM_ABSOLUTE || mIns[j].mMode == ASMIM_ZERO_PAGE || mIns[j].mMode == ASMIM_ABSOLUTE_X || mIns[j].mMode == ASMIM_ABSOLUTE_Y) if (mIns[j].mMode == ASMIM_ABSOLUTE || mIns[j].mMode == ASMIM_ZERO_PAGE || mIns[j].mMode == ASMIM_ABSOLUTE_X || mIns[j].mMode == ASMIM_ABSOLUTE_Y)
assert(mIns[j].mLinkerObject != nullptr || mIns[j].mAddress > 0); assert(mIns[j].mLinkerObject != nullptr || mIns[j].mAddress > 0);
#endif
if (mIns[j].mType != ASMIT_NOP) if (mIns[j].mType != ASMIT_NOP)
{ {
assert(!(live & ~mIns[j].mLive)); assert(!(live & ~mIns[j].mLive));
@ -50943,7 +51098,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mInterProc = proc; mInterProc = proc;
mInterProc->mLinkerObject->mNativeProc = this; mInterProc->mLinkerObject->mNativeProc = this;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "a"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "particle_add");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];

View File

@ -504,6 +504,9 @@ public:
bool MoveTXADCDown(int at); bool MoveTXADCDown(int at);
bool FoldShiftORAIntoLoadImmUp(int at); bool FoldShiftORAIntoLoadImmUp(int at);
bool FindAccuExitValue(int& at);
bool MoveLoadXAbsUpCrossBlock(int at);
bool MoveSimpleADCToINCDECDown(int at); bool MoveSimpleADCToINCDECDown(int at);
bool MoveTAXADCSTADown(int at); bool MoveTAXADCSTADown(int at);

View File

@ -1974,14 +1974,9 @@ Expression* Parser::ParseInitExpression(Declaration* dtype, bool inner)
} }
else if (exp->mDecValue->mType == DT_CONST_INTEGER && exp->mDecValue->mInteger == 0) else if (exp->mDecValue->mType == DT_CONST_INTEGER && exp->mDecValue->mInteger == 0)
{ {
Declaration * ndec = new Declaration(exp->mDecValue->mLocation, DT_CONST_ADDRESS);
ndec->mBase = TheVoidPointerTypeDeclaration;
ndec->mInteger = 0;
dec = ndec;
Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTANT); Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTANT);
nexp->mDecValue = ndec; nexp->mDecValue = TheNullptrConstDeclaration;
nexp->mDecType = ndec->mBase; nexp->mDecType = TheNullPointerTypeDeclaration;
exp = nexp; exp = nexp;
} }
else else

View File

@ -1,4 +1,4 @@
call ..\..\bin\oscar64 -n fireworks_ptr.c call ..\..\bin\oscar64 -n fireworks_ptr.c
call ..\..\bin\oscar64 -n fireworks_hires.c call ..\..\bin\oscar64 -n fireworks_hires.c
call ..\..\bin\oscar64 -n fireworks_stripe.c call ..\..\bin\oscar64 -n fireworks_stripe.c -O2