Optimize conditional select of const values

This commit is contained in:
drmortalwombat 2024-09-10 22:26:34 +02:00
parent 1f9226255a
commit f0f174e439
4 changed files with 199 additions and 2 deletions

View File

@ -72,10 +72,10 @@ inline void sidfx_loop_ch(byte ch)
sid.voices[ch].ctrl = 0; sid.voices[ch].ctrl = 0;
sid.voices[ch].attdec = 0; sid.voices[ch].attdec = 0;
sid.voices[ch].susrel = 0; sid.voices[ch].susrel = 0;
channels[ch].state = SIDFX_RESET_1; channels[ch].state = SIDFX_READY;
break; break;
case SIDFX_RESET_1: case SIDFX_RESET_1:
sid.voices[ch].ctrl = SID_CTRL_TEST; // sid.voices[ch].ctrl = SID_CTRL_TEST;
channels[ch].state = SIDFX_READY; channels[ch].state = SIDFX_READY;
break; break;
case SIDFX_READY: case SIDFX_READY:

View File

@ -11034,6 +11034,12 @@ void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArra
if (ins->mCode == IC_BINARY_OPERATOR && ins->mOperator == IA_MUL && ins->mDst.mType == IT_INT16 && spareTemps + 1 < tvalid.Size()) if (ins->mCode == IC_BINARY_OPERATOR && ins->mOperator == IA_MUL && ins->mDst.mType == IT_INT16 && spareTemps + 1 < tvalid.Size())
{ {
InterInstruction* mi0 = ltvalue[ins->mSrc[0].mTemp], * mi1 = ltvalue[ins->mSrc[1].mTemp]; InterInstruction* mi0 = ltvalue[ins->mSrc[0].mTemp], * mi1 = ltvalue[ins->mSrc[1].mTemp];
InterInstruction* mci0 = nullptr;
InterInstruction* mci1 = nullptr;
if (mi0 && mi0->mCode == IC_CONVERSION_OPERATOR)
mci0 = ltvalue[mi0->mSrc[0].mTemp];
if (mi1 && mi1->mCode == IC_CONVERSION_OPERATOR)
mci1 = ltvalue[mi1->mSrc[0].mTemp];
if (mi0 && mi1 && mi1->mCode == IC_CONSTANT && mi0->mCode == IC_BINARY_OPERATOR && mi0->mOperator == IA_ADD) if (mi0 && mi1 && mi1->mCode == IC_CONSTANT && mi0->mCode == IC_BINARY_OPERATOR && mi0->mOperator == IA_ADD)
{ {
@ -11178,6 +11184,41 @@ void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArra
ins->mSrc[0].mTemp = cai->mDst.mTemp; ins->mSrc[0].mTemp = cai->mDst.mTemp;
} }
} }
#endif
#if 1
else if (mi0 && mci1 && mci1->mCode == IC_RELATIONAL_OPERATOR)
{
InterInstruction* cai = new InterInstruction(ins->mLocation, IC_CONSTANT);
cai->mDst.mTemp = spareTemps++;
cai->mDst.mType = ins->mDst.mType;
cai->mConst.mIntConst = 0;
cai->mConst.mFloatConst = 0;
mInstructions.Insert(i, cai);
ins->mCode = IC_SELECT;
ins->mNumOperands = 3;
ins->mSrc[2] = mci1->mDst;
ins->mSrc[1] = ins->mSrc[0];
ins->mSrc[0].mTemp = cai->mDst.mTemp;
ltvalue[cai->mDst.mTemp] = nullptr;
}
else if (mci0 && mi1 && mci0->mCode == IC_RELATIONAL_OPERATOR)
{
InterInstruction* cai = new InterInstruction(ins->mLocation, IC_CONSTANT);
cai->mDst.mTemp = spareTemps++;
cai->mDst.mType = ins->mDst.mType;
cai->mConst.mIntConst = 0;
cai->mConst.mFloatConst = 0;
mInstructions.Insert(i, cai);
ins->mCode = IC_SELECT;
ins->mNumOperands = 3;
ins->mSrc[2] = mci0->mDst;
ins->mSrc[0].mTemp = cai->mDst.mTemp;
ltvalue[cai->mDst.mTemp] = nullptr;
}
#endif #endif
} }
#endif #endif

View File

@ -1624,6 +1624,12 @@ bool NativeCodeInstruction::IsCommutative(void) const
return mType == ASMIT_ADC || mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR; return mType == ASMIT_ADC || mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR;
} }
bool NativeCodeInstruction::IsLogic(void) const
{
return mType == ASMIT_AND || mType == ASMIT_ORA || mType == ASMIT_EOR;
}
bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const
{ {
@ -26516,6 +26522,60 @@ bool NativeCodeBasicBlock::EliminateMicroBlocks(void)
return changed; return changed;
} }
bool NativeCodeBasicBlock::CombineAlternateLoads(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (mTrueJump && mFalseJump && (mBranch == ASMIT_BCC || mBranch == ASMIT_BCS) &&
mTrueJump->mIns.Size() == 1 && mFalseJump->mIns.Size() == 1 &&
mTrueJump->mTrueJump == mFalseJump->mTrueJump &&
!mTrueJump->mFalseJump && !mFalseJump->mFalseJump &&
mTrueJump->mNumEntries == 1 && mFalseJump->mNumEntries == 1)
{
if (mTrueJump->mIns[0].mType == ASMIT_LDA && mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE &&
mFalseJump->mIns[0].mType == ASMIT_LDA && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE)
{
mFalseJump->mIns[0].mLive |= LIVE_CPU_REG_C;
mIns.Push(mFalseJump->mIns[0]);
mFalseJump->mIns.Remove(0);
mExitRequiredRegs += CPU_REG_A;
mFalseJump->mEntryRequiredRegs += CPU_REG_A;
changed = true;
}
else if (mTrueJump->mIns[0].mType == ASMIT_LDX && mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE &&
mFalseJump->mIns[0].mType == ASMIT_LDX && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE)
{
mFalseJump->mIns[0].mLive |= LIVE_CPU_REG_C;
mIns.Push(mFalseJump->mIns[0]);
mFalseJump->mIns.Remove(0);
mExitRequiredRegs += CPU_REG_X;
mFalseJump->mEntryRequiredRegs += CPU_REG_X;
changed = true;
}
else if (mTrueJump->mIns[0].mType == ASMIT_LDY && mTrueJump->mIns[0].mMode == ASMIM_IMMEDIATE &&
mFalseJump->mIns[0].mType == ASMIT_LDY && mFalseJump->mIns[0].mMode == ASMIM_IMMEDIATE)
{
mFalseJump->mIns[0].mLive |= LIVE_CPU_REG_C;
mIns.Push(mFalseJump->mIns[0]);
mFalseJump->mIns.Remove(0);
mExitRequiredRegs += CPU_REG_Y;
mFalseJump->mEntryRequiredRegs += CPU_REG_Y;
changed = true;
}
}
if (mTrueJump && mTrueJump->CombineAlternateLoads())
changed = true;
if (mFalseJump && mFalseJump->CombineAlternateLoads())
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::FoldLoopEntry(void) bool NativeCodeBasicBlock::FoldLoopEntry(void)
{ {
bool changed = false; bool changed = false;
@ -33394,6 +33454,58 @@ bool NativeCodeBasicBlock::MoveLoadAddImmStoreAbsXUp(int at)
return false; return false;
} }
bool NativeCodeBasicBlock::MoveLoadLogicStoreAbsUp(int at)
{
// at + 0 : LDA zp
// at + 1 : ORA zp / imm
// at + 2 : STA abs / abs,x / abs,y
int j = at - 1;
while (j >= 0)
{
if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress)
{
while (j + 1 < mIns.Size() && mIns[j + 1].mType == ASMIT_STA)
j++;
if (mIns[j].mLive & LIVE_CPU_REG_A)
return false;
mIns[j].mLive |= LIVE_CPU_REG_A;
for (int i = j + 1; i < at; i++)
mIns[i].mLive |= LIVE_CPU_REG_C;
mIns[at + 1].mLive |= mIns[j].mLive;
mIns[at + 2].mLive |= mIns[j].mLive;
mIns.Insert(j + 1, mIns[at + 2]); // STA
mIns.Insert(j + 1, mIns[at + 2]); // ORA
mIns[at + 2].mType = ASMIT_NOP; mIns[at + 2].mMode = ASMIM_IMPLIED;
mIns[at + 3].mType = ASMIT_NOP; mIns[at + 3].mMode = ASMIM_IMPLIED;
mIns[at + 4].mType = ASMIT_NOP; mIns[at + 4].mMode = ASMIM_IMPLIED;
return true;
}
if (mIns[j].ChangesZeroPage(mIns[at + 0].mAddress))
return false;
if (mIns[at + 1].mType == ASMIM_ZERO_PAGE && mIns[j].ChangesZeroPage(mIns[at + 1].mAddress))
return false;
if (mIns[j].UsesMemoryOf(mIns[at + 2]))
return false;
if (mIns[at + 2].mMode == ASMIM_ABSOLUTE_X && mIns[j].ChangesXReg())
return false;
if (mIns[at + 2].mMode == ASMIM_ABSOLUTE_Y && mIns[j].ChangesYReg())
return false;
j--;
}
return false;
}
bool NativeCodeBasicBlock::MoveLoadAddImmStoreUp(int at) bool NativeCodeBasicBlock::MoveLoadAddImmStoreUp(int at)
{ {
@ -42101,6 +42213,27 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerShuffle(int pass)
#endif #endif
#if 1
// move load - add # - store up to initial store
//
for (int i = 1; i + 2 < mIns.Size(); i++)
{
if (
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 1].IsLogic() && (mIns[i + 1].mMode == ASMIM_IMMEDIATE || mIns[i + 1].mMode == ASMIM_ZERO_PAGE) &&
mIns[i + 2].mType == ASMIT_STA && (mIns[i + 2].mMode == ASMIM_ZERO_PAGE || mIns[i + 2].mMode == ASMIM_ABSOLUTE || mIns[i + 2].mMode == ASMIM_ABSOLUTE_X || mIns[i + 2].mMode == ASMIM_ABSOLUTE_Y) &&
(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)) == 0)
{
if (MoveLoadLogicStoreAbsUp(i))
changed = true;
}
}
CheckLive();
#endif
#if 1 #if 1
// move load - ora/and/eor # - store up to initial store // move load - ora/and/eor # - store up to initial store
// //
@ -47266,6 +47399,21 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerIterate6(int i, int pass)
mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED; mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED;
return true; return true;
} }
else if (
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 &&
mIns[i + 1].mType == ASMIT_ROL && mIns[i + 1].mMode == ASMIM_IMPLIED &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 3].mType == ASMIT_LDA && !mIns[i + 3].MayBeSameAddress(mIns[i + 2]) &&
mIns[i + 4].mType == ASMIT_ASL && mIns[i + 4].mMode == ASMIM_IMPLIED &&
mIns[i + 5].mType == ASMIT_ORA && mIns[i + 5].SameEffectiveAddress(mIns[i + 2]) && !(mIns[i + 5].mLive & LIVE_MEM))
{
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
mIns[i + 4].mType = ASMIT_ROL;
mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED;
return true;
}
if (pass == 0 && if (pass == 0 &&
mIns[i + 0].mType == ASMIT_CLC && mIns[i + 0].mType == ASMIT_CLC &&
@ -52349,6 +52497,10 @@ void NativeCodeProcedure::Optimize(void)
} while (changed); } while (changed);
#if 1
ResetVisited();
mEntryBlock->CombineAlternateLoads();
#endif
#if 1 #if 1
ResetVisited(); ResetVisited();
mEntryBlock->ReduceLocalYPressure(); mEntryBlock->ReduceLocalYPressure();

View File

@ -198,6 +198,7 @@ public:
bool IsSame(const NativeCodeInstruction& ins) const; bool IsSame(const NativeCodeInstruction& ins) const;
bool IsSameLS(const NativeCodeInstruction& ins) const; bool IsSameLS(const NativeCodeInstruction& ins) const;
bool IsCommutative(void) const; bool IsCommutative(void) const;
bool IsLogic(void) const;
bool IsShift(void) const; bool IsShift(void) const;
bool IsShiftOrInc(void) const; bool IsShiftOrInc(void) const;
bool IsSimpleJSR(void) const; bool IsSimpleJSR(void) const;
@ -463,6 +464,8 @@ public:
bool MoveTYADCStoreDown(int at); bool MoveTYADCStoreDown(int at);
bool MoveShiftZeroPageUp(int at); bool MoveShiftZeroPageUp(int at);
bool MoveLoadLogicStoreAbsUp(int at);
bool MoveLDSTXOutOfRange(int at); bool MoveLDSTXOutOfRange(int at);
bool MoveCLCLoadAddZPStoreDown(int at); bool MoveCLCLoadAddZPStoreDown(int at);
@ -617,6 +620,7 @@ public:
bool BypassRegisterConditionBlock(void); bool BypassRegisterConditionBlock(void);
bool FoldLoopEntry(void); bool FoldLoopEntry(void);
bool CombineAlternateLoads(void);
bool Is16BitImmSum(int at, int & val, int& reg) const; bool Is16BitImmSum(int at, int & val, int& reg) const;