More native code common subexpression elimination

This commit is contained in:
drmortalwombat 2023-03-24 20:23:10 +01:00
parent 55a2c25b44
commit c2c0244990
4 changed files with 288 additions and 26 deletions

View File

@ -823,6 +823,26 @@ InterOperator InvertRelational(InterOperator oper)
} }
static bool IsStrictUnsignedRelational(InterOperator oper)
{
return
oper == IA_CMPLEU ||
oper == IA_CMPGEU ||
oper == IA_CMPLU ||
oper == IA_CMPGU;
}
static bool IsSignedRelational(InterOperator oper)
{
return
oper == IA_CMPEQ ||
oper == IA_CMPNE ||
oper == IA_CMPLES ||
oper == IA_CMPGES ||
oper == IA_CMPLS ||
oper == IA_CMPGS;
}
InterOperator MirrorRelational(InterOperator oper) InterOperator MirrorRelational(InterOperator oper)
{ {
switch (oper) switch (oper)
@ -7343,7 +7363,7 @@ bool InterCodeBasicBlock::CalculateSingleAssignmentTemps(FastNumberSet& tassigne
return changed; return changed;
} }
void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwardingTable, bool reverse) void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwardingTable, bool reverse, bool checkloops)
{ {
int i; int i;
@ -7362,6 +7382,38 @@ void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwa
mMergeForwardingTable.Destroy(i); mMergeForwardingTable.Destroy(i);
} }
} }
else if (mLoopPrefix && checkloops)
{
GrowingArray<InterCodeBasicBlock*> body(nullptr);
body.Push(this);
bool innerLoop = true;
for (int i = 0; i < mEntryBlocks.Size(); i++)
{
if (mEntryBlocks[i] != mLoopPrefix)
{
if (!mEntryBlocks[i]->CollectLoopBody(this, body))
innerLoop = false;
}
}
if (innerLoop)
{
mMergeForwardingTable = forwardingTable;
assert(mMergeForwardingTable.Size() == mLocalModifiedTemps.Size());
for (int j = 0; j < body.Size(); j++)
{
for (int i = 0; i < mLocalModifiedTemps.Size(); i++)
{
if (body[j]->mLocalModifiedTemps[i])
mMergeForwardingTable.Destroy(i);
}
}
}
else
mMergeForwardingTable.SetSize(forwardingTable.Size());
}
else else
mMergeForwardingTable.SetSize(forwardingTable.Size()); mMergeForwardingTable.SetSize(forwardingTable.Size());
} }
@ -7385,8 +7437,8 @@ void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwa
mInstructions[i]->PerformTempForwarding(mMergeForwardingTable, reverse); mInstructions[i]->PerformTempForwarding(mMergeForwardingTable, reverse);
} }
if (mTrueJump) mTrueJump->PerformTempForwarding(mMergeForwardingTable, reverse); if (mTrueJump) mTrueJump->PerformTempForwarding(mMergeForwardingTable, reverse, checkloops);
if (mFalseJump) mFalseJump->PerformTempForwarding(mMergeForwardingTable, reverse); if (mFalseJump) mFalseJump->PerformTempForwarding(mMergeForwardingTable, reverse, checkloops);
} }
} }
@ -13149,6 +13201,33 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
mInstructions[i + 0]->mCode = IC_NONE; mInstructions[i + 0]->mNumOperands = 0; mInstructions[i + 0]->mCode = IC_NONE; mInstructions[i + 0]->mNumOperands = 0;
changed = true; changed = true;
} }
else if (
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_ADD && mInstructions[i + 0]->mSrc[0].mTemp < 0 && mInstructions[i + 0]->mDst.mType == IT_INT16 &&
mInstructions[i + 1]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal && mInstructions[i + 1]->mSrc[0].mTemp < 0 &&
mInstructions[i + 0]->mDst.mIntConst >= 0 &&
mInstructions[i + 0]->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND && mInstructions[i + 0]->mSrc[1].mRange.mMaxValue + mInstructions[i + 0]->mSrc[0].mIntConst < 32767 &&
(IsSignedRelational(mInstructions[i + 1]->mOperator) || mInstructions[i + 0]->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND && mInstructions[i + 0]->mSrc[1].mRange.mMinValue >= 0) &&
mInstructions[i + 1]->mSrc[0].mIntConst - mInstructions[i + 0]->mSrc[0].mIntConst >= (IsSignedRelational(mInstructions[i + 1]->mOperator) ? 0 : -32768) &&
mInstructions[i + 1]->mSrc[0].mIntConst - mInstructions[i + 0]->mSrc[0].mIntConst <= 32767)
{
mInstructions[i + 1]->mSrc[0].mIntConst -= mInstructions[i + 0]->mSrc[0].mIntConst;
mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1];
mInstructions[i + 0]->mSrc[1].mFinal = false;
changed = true;
}
else if (
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_SUB && mInstructions[i + 0]->mSrc[0].mTemp < 0 && mInstructions[i + 0]->mDst.mType == IT_INT16 &&
mInstructions[i + 0]->mDst.mIntConst >= 0 &&
mInstructions[i + 0]->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND && mInstructions[i + 0]->mSrc[1].mRange.mMinValue - mInstructions[i + 0]->mSrc[0].mIntConst >= (IsSignedRelational(mInstructions[i + 1]->mOperator) ? -32768 : 0) &&
mInstructions[i + 1]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal && mInstructions[i + 1]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mSrc[0].mIntConst + mInstructions[i + 0]->mSrc[0].mIntConst >= (IsSignedRelational(mInstructions[i + 1]->mOperator) ? -32768 : 0) &&
mInstructions[i + 1]->mSrc[0].mIntConst + mInstructions[i + 0]->mSrc[0].mIntConst <= 32767)
{
mInstructions[i + 1]->mSrc[0].mIntConst += mInstructions[i + 0]->mSrc[0].mIntConst;
mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1];
mInstructions[i + 0]->mSrc[1].mFinal = false;
changed = true;
}
#if 1 #if 1
if (i + 2 < mInstructions.Size() && if (i + 2 < mInstructions.Size() &&
@ -14419,7 +14498,7 @@ void InterCodeProcedure::WarnUsedUndefinedVariables(void)
} }
void InterCodeProcedure::TempForwarding(bool reverse) void InterCodeProcedure::TempForwarding(bool reverse, bool checkloops)
{ {
int numTemps = mTemporaries.Size(); int numTemps = mTemporaries.Size();
@ -14428,6 +14507,15 @@ void InterCodeProcedure::TempForwarding(bool reverse)
ValueSet valueSet; ValueSet valueSet;
FastNumberSet tvalidSet(numTemps); FastNumberSet tvalidSet(numTemps);
if (checkloops)
{
BuildLoopPrefix();
ResetEntryBlocks();
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
}
// //
// Now remove needless temporary moves, that apear due to // Now remove needless temporary moves, that apear due to
// stack evaluation // stack evaluation
@ -14436,11 +14524,15 @@ void InterCodeProcedure::TempForwarding(bool reverse)
mTempForwardingTable.Reset(); mTempForwardingTable.Reset();
ResetVisited(); ResetVisited();
mEntryBlock->PerformTempForwarding(mTempForwardingTable, reverse); mEntryBlock->PerformTempForwarding(mTempForwardingTable, reverse, checkloops);
DisassembleDebug("temp forwarding"); if (checkloops)
DisassembleDebug("loop temp forwarding");
else
DisassembleDebug("temp forwarding");
} }
void InterCodeProcedure::RemoveUnusedInstructions(void) void InterCodeProcedure::RemoveUnusedInstructions(void)
{ {
int numTemps = mTemporaries.Size(); int numTemps = mTemporaries.Size();
@ -14974,7 +15066,7 @@ void InterCodeProcedure::Close(void)
mTempForwardingTable.SetSize(numTemps); mTempForwardingTable.SetSize(numTemps);
ResetVisited(); ResetVisited();
mEntryBlock->PerformTempForwarding(mTempForwardingTable, false); mEntryBlock->PerformTempForwarding(mTempForwardingTable, false, false);
DisassembleDebug("temp forwarding 2"); DisassembleDebug("temp forwarding 2");
@ -15508,6 +15600,8 @@ void InterCodeProcedure::Close(void)
DisassembleDebug("PushMoveOutOfLoop"); DisassembleDebug("PushMoveOutOfLoop");
TempForwarding(false, true);
#endif #endif
#if 1 #if 1

View File

@ -438,7 +438,7 @@ public:
void GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries); void GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries);
void CheckValueUsage(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, const GrowingVariableArray& staticVars, FastNumberSet& fsingle); void CheckValueUsage(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, const GrowingVariableArray& staticVars, FastNumberSet& fsingle);
void PerformTempForwarding(const TempForwardingTable& forwardingTable, bool reverse); void PerformTempForwarding(const TempForwardingTable& forwardingTable, bool reverse, bool checkloops);
void PerformValueForwarding(const GrowingInstructionPtrArray& tvalue, const ValueSet& values, FastNumberSet& tvalid, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, int & spareTemps, const GrowingVariableArray& staticVars); void PerformValueForwarding(const GrowingInstructionPtrArray& tvalue, const ValueSet& values, FastNumberSet& tvalid, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, int & spareTemps, const GrowingVariableArray& staticVars);
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars, FastNumberSet& fsingle); void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars, FastNumberSet& fsingle);
bool EliminateDeadBranches(void); bool EliminateDeadBranches(void);
@ -599,7 +599,7 @@ protected:
void BuildTraces(bool expand, bool dominators = true, bool compact = false); void BuildTraces(bool expand, bool dominators = true, bool compact = false);
void BuildDataFlowSets(void); void BuildDataFlowSets(void);
void RenameTemporaries(void); void RenameTemporaries(void);
void TempForwarding(bool reverse = false); void TempForwarding(bool reverse = false, bool checkloops = false);
void RemoveUnusedInstructions(void); void RemoveUnusedInstructions(void);
bool GlobalConstantPropagation(void); bool GlobalConstantPropagation(void);
bool PropagateNonLocalUsedTemps(void); bool PropagateNonLocalUsedTemps(void);

View File

@ -3184,7 +3184,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
} }
else else
{ {
if (mMode != ASMIM_ZERO_PAGE && mMode != ASMIM_ABSOLUTE) if (mMode != ASMIM_ZERO_PAGE && mMode != ASMIM_ABSOLUTE && mMode != ASMIM_ABSOLUTE_Y)
data.mRegs[CPU_REG_X].Reset(); data.mRegs[CPU_REG_X].Reset();
data.mRegs[CPU_REG_Z].Reset(); data.mRegs[CPU_REG_Z].Reset();
} }
@ -3215,7 +3215,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
} }
else else
{ {
if (mMode != ASMIM_ZERO_PAGE && mMode != ASMIM_ABSOLUTE) if (mMode != ASMIM_ZERO_PAGE && mMode != ASMIM_ABSOLUTE && mMode != ASMIM_ABSOLUTE_X)
data.mRegs[CPU_REG_Y].Reset(); data.mRegs[CPU_REG_Y].Reset();
data.mRegs[CPU_REG_Z].Reset(); data.mRegs[CPU_REG_Z].Reset();
} }
@ -3827,6 +3827,27 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
else else
data.mRegs[CPU_REG_A].Reset(); data.mRegs[CPU_REG_A].Reset();
} }
else if (mType == ASMIT_LDY)
{
if (!(mFlags & NCIF_VOLATILE))
{
if (data.mRegs[CPU_REG_Y].mMode == NRDM_ABSOLUTE_X && data.mRegs[CPU_REG_Y].mLinkerObject == mLinkerObject && data.mRegs[CPU_REG_Y].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{
mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true;
}
else
{
data.mRegs[CPU_REG_Y].mMode = NRDM_ABSOLUTE_X;
data.mRegs[CPU_REG_Y].mLinkerObject = mLinkerObject;
data.mRegs[CPU_REG_Y].mValue = mAddress;
data.mRegs[CPU_REG_Y].mFlags = mFlags;
}
}
else
data.mRegs[CPU_REG_Y].Reset();
}
if (ChangesAddress()) if (ChangesAddress())
data.ResetIndirect(mAddress); data.ResetIndirect(mAddress);
@ -3863,6 +3884,27 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
else else
data.mRegs[CPU_REG_A].Reset(); data.mRegs[CPU_REG_A].Reset();
} }
else if (mType == ASMIT_LDX)
{
if (!(mFlags & NCIF_VOLATILE))
{
if (data.mRegs[CPU_REG_X].mMode == NRDM_ABSOLUTE_Y && data.mRegs[CPU_REG_X].mLinkerObject == mLinkerObject && data.mRegs[CPU_REG_X].mValue == mAddress && !(mLive & LIVE_CPU_REG_Z))
{
mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
changed = true;
}
else
{
data.mRegs[CPU_REG_X].mMode = NRDM_ABSOLUTE_Y;
data.mRegs[CPU_REG_X].mLinkerObject = mLinkerObject;
data.mRegs[CPU_REG_X].mValue = mAddress;
data.mRegs[CPU_REG_X].mFlags = mFlags;
}
}
else
data.mRegs[CPU_REG_X].Reset();
}
if (ChangesAddress()) if (ChangesAddress())
data.ResetIndirect(mAddress); data.ResetIndirect(mAddress);
@ -13841,14 +13883,17 @@ bool NativeCodeBasicBlock::CanGlobalSwapXY(void)
bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpression& ex) bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpression& ex)
{ {
ex.mIndex = at;
if (at + 2 < mIns.Size()) if (at + 2 < mIns.Size())
{ {
if (mIns[at + 0].mType == ASMIT_LDA && (mIns[at + 0].mMode == ASMIM_ZERO_PAGE || mIns[at + 0].mMode == ASMIM_ABSOLUTE) && if (mIns[at + 0].mType == ASMIT_LDA && (mIns[at + 0].mMode == ASMIM_ZERO_PAGE || mIns[at + 0].mMode == ASMIM_ABSOLUTE) &&
mIns[at + 2].mType == ASMIT_STA && mIns[at + 2].mMode == ASMIM_ZERO_PAGE && mIns[at + 2].mType == ASMIT_STA && mIns[at + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[at + 1].mMode == ASMIM_IMMEDIATE && (mIns[at + 1].mType == ASMIT_AND || mIns[at + 1].mType == ASMIT_ORA || mIns[at + 1].mType == ASMIT_EOR)) (mIns[at + 1].mMode == ASMIM_IMMEDIATE || mIns[at + 1].mMode == ASMIM_ZERO_PAGE) && (mIns[at + 1].mType == ASMIT_AND || mIns[at + 1].mType == ASMIT_ORA || mIns[at + 1].mType == ASMIT_EOR))
{ {
ex.mType = mIns[at + 1].mType; ex.mType = mIns[at + 1].mType;
ex.mValue = mIns[at + 1].mAddress; ex.mValue = mIns[at + 1].mAddress;
ex.mMode = mIns[at + 1].mMode;
ex.mOp = &(mIns[at + 1]); ex.mOp = &(mIns[at + 1]);
ex.mSrc = &(mIns[at + 0]); ex.mSrc = &(mIns[at + 0]);
ex.mDst = &(mIns[at + 2]); ex.mDst = &(mIns[at + 2]);
@ -13859,12 +13904,13 @@ bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpressi
{ {
if (mIns[at + 0].mType == ASMIT_LDA && (mIns[at + 0].mMode == ASMIM_ZERO_PAGE || mIns[at + 0].mMode == ASMIM_ABSOLUTE) && if (mIns[at + 0].mType == ASMIT_LDA && (mIns[at + 0].mMode == ASMIM_ZERO_PAGE || mIns[at + 0].mMode == ASMIM_ABSOLUTE) &&
mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE && mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE &&
mIns[at + 2].mMode == ASMIM_IMMEDIATE && (mIns[at + 2].mMode == ASMIM_IMMEDIATE || mIns[at + 2].mMode == ASMIM_ZERO_PAGE) &&
(mIns[at + 1].mType == ASMIT_CLC && mIns[at + 2].mType == ASMIT_ADC || mIns[at + 1].mType == ASMIT_SEC && mIns[at + 2].mType == ASMIT_SBC) && (mIns[at + 1].mType == ASMIT_CLC && mIns[at + 2].mType == ASMIT_ADC || mIns[at + 1].mType == ASMIT_SEC && mIns[at + 2].mType == ASMIT_SBC) &&
!(mIns[at + 2].mLive & LIVE_CPU_REG_C)) !(mIns[at + 2].mLive & LIVE_CPU_REG_C))
{ {
ex.mType = mIns[at + 2].mType; ex.mType = mIns[at + 2].mType;
ex.mValue = mIns[at + 2].mAddress; ex.mValue = mIns[at + 2].mAddress;
ex.mMode = mIns[at + 2].mMode;
ex.mSrc = &(mIns[at + 0]); ex.mSrc = &(mIns[at + 0]);
ex.mOp = &(mIns[at + 2]); ex.mOp = &(mIns[at + 2]);
ex.mDst = &(mIns[at + 3]); ex.mDst = &(mIns[at + 3]);
@ -13875,12 +13921,13 @@ bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpressi
{ {
if (mIns[at + 1].mType == ASMIT_LDA && (mIns[at + 1].mMode == ASMIM_ZERO_PAGE || mIns[at + 1].mMode == ASMIM_ABSOLUTE) && if (mIns[at + 1].mType == ASMIT_LDA && (mIns[at + 1].mMode == ASMIM_ZERO_PAGE || mIns[at + 1].mMode == ASMIM_ABSOLUTE) &&
mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE && mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE &&
mIns[at + 2].mMode == ASMIM_IMMEDIATE && (mIns[at + 2].mMode == ASMIM_IMMEDIATE || mIns[at + 2].mMode == ASMIM_ZERO_PAGE) &&
(mIns[at + 0].mType == ASMIT_CLC && mIns[at + 2].mType == ASMIT_ADC || mIns[at + 0].mType == ASMIT_SEC && mIns[at + 2].mType == ASMIT_SBC) && (mIns[at + 0].mType == ASMIT_CLC && mIns[at + 2].mType == ASMIT_ADC || mIns[at + 0].mType == ASMIT_SEC && mIns[at + 2].mType == ASMIT_SBC) &&
!(mIns[at + 2].mLive & LIVE_CPU_REG_C)) !(mIns[at + 2].mLive & LIVE_CPU_REG_C))
{ {
ex.mType = mIns[at + 2].mType; ex.mType = mIns[at + 2].mType;
ex.mValue = mIns[at + 2].mAddress; ex.mValue = mIns[at + 2].mAddress;
ex.mMode = mIns[at + 2].mMode;
ex.mSrc = &(mIns[at + 1]); ex.mSrc = &(mIns[at + 1]);
ex.mOp = &(mIns[at + 2]); ex.mOp = &(mIns[at + 2]);
ex.mDst = &(mIns[at + 3]); ex.mDst = &(mIns[at + 3]);
@ -13891,12 +13938,13 @@ bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpressi
{ {
if (mIns[at + 0].mType == ASMIT_STA && mIns[at + 0].mMode == ASMIM_ZERO_PAGE && if (mIns[at + 0].mType == ASMIT_STA && mIns[at + 0].mMode == ASMIM_ZERO_PAGE &&
mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE && mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE &&
mIns[at + 2].mMode == ASMIM_IMMEDIATE && (mIns[at + 2].mMode == ASMIM_IMMEDIATE || mIns[at + 2].mMode == ASMIM_ZERO_PAGE) &&
(mIns[at + 1].mType == ASMIT_CLC && mIns[at + 2].mType == ASMIT_ADC || mIns[at + 1].mType == ASMIT_SEC && mIns[at + 2].mType == ASMIT_SBC) && (mIns[at + 1].mType == ASMIT_CLC && mIns[at + 2].mType == ASMIT_ADC || mIns[at + 1].mType == ASMIT_SEC && mIns[at + 2].mType == ASMIT_SBC) &&
!(mIns[at + 2].mLive & LIVE_CPU_REG_C)) !(mIns[at + 2].mLive & LIVE_CPU_REG_C))
{ {
ex.mType = mIns[at + 2].mType; ex.mType = mIns[at + 2].mType;
ex.mValue = mIns[at + 2].mAddress; ex.mValue = mIns[at + 2].mAddress;
ex.mMode = mIns[at + 2].mMode;
ex.mSrc = &(mIns[at + 0]); ex.mSrc = &(mIns[at + 0]);
ex.mOp = &(mIns[at + 2]); ex.mOp = &(mIns[at + 2]);
ex.mDst = &(mIns[at + 3]); ex.mDst = &(mIns[at + 3]);
@ -13911,6 +13959,7 @@ bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpressi
{ {
ex.mType = ASMIT_ADC; ex.mType = ASMIT_ADC;
ex.mValue = 1; ex.mValue = 1;
ex.mMode = ASMIM_IMMEDIATE;
ex.mOp = &(mIns[at + 1]); ex.mOp = &(mIns[at + 1]);
ex.mSrc = &(mIns[at + 0]); ex.mSrc = &(mIns[at + 0]);
ex.mDst = &(mIns[at + 2]); ex.mDst = &(mIns[at + 2]);
@ -13925,11 +13974,29 @@ bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpressi
{ {
ex.mType = ASMIT_ADC; ex.mType = ASMIT_ADC;
ex.mValue = 1; ex.mValue = 1;
ex.mMode = ASMIM_IMMEDIATE;
ex.mOp = &(mIns[at + 1]); ex.mOp = &(mIns[at + 1]);
ex.mSrc = &(mIns[at + 0]); ex.mSrc = &(mIns[at + 0]);
ex.mDst = &(mIns[at + 2]); ex.mDst = &(mIns[at + 2]);
return true; return true;
} }
}
if (at + 3 < mIns.Size())
{
if (mIns[at + 0].mType == ASMIT_LDA && (mIns[at + 0].mMode == ASMIM_ZERO_PAGE || mIns[at + 0].mMode == ASMIM_ABSOLUTE || mIns[at + 0].mMode == ASMIM_ABSOLUTE_X) &&
mIns[at + 3].mType == ASMIT_TAY &&
(mIns[at + 2].mMode == ASMIM_IMMEDIATE || mIns[at + 2].mMode == ASMIM_ZERO_PAGE) &&
(mIns[at + 1].mType == ASMIT_CLC && mIns[at + 2].mType == ASMIT_ADC || mIns[at + 1].mType == ASMIT_SEC && mIns[at + 2].mType == ASMIT_SBC) &&
!(mIns[at + 2].mLive & LIVE_CPU_REG_C))
{
ex.mType = mIns[at + 2].mType;
ex.mValue = mIns[at + 2].mAddress;
ex.mMode = mIns[at + 2].mMode;
ex.mSrc = &(mIns[at + 0]);
ex.mOp = &(mIns[at + 2]);
ex.mDst = &(mIns[at + 3]);
return true;
}
} }
return false; return false;
@ -13941,25 +14008,61 @@ int NativeSimpleSubExpressions::FindCommon(const NativeSimpleSubExpression& ex)
{ {
for (int i = 0; i < mExps.Size(); i++) for (int i = 0; i < mExps.Size(); i++)
{ {
if (mExps[i].mType == ex.mType && mExps[i].mValue == ex.mValue && ex.mSrc->SameEffectiveAddress(*(mExps[i].mSrc))) if (mExps[i].mType == ex.mType && mExps[i].mMode == ex.mMode && mExps[i].mValue == ex.mValue && ex.mSrc->SameEffectiveAddress(*(mExps[i].mSrc)))
return i; {
if (mExps[i].mDst->mMode == ASMIM_IMPLIED)
{
if (mExps[i].mDst->mType == ex.mDst->mType)
return i;
}
else
return i;
}
} }
} }
return -1; return -1;
} }
bool NativeSimpleSubExpression::MayBeChangedBy(const NativeCodeInstruction& ins)
{
if (ins.ChangesAddress())
{
if (mSrc->MayBeChangedOnAddress(ins))
return true;
if (&ins != mDst && mDst->MayBeChangedOnAddress(ins))
return true;
if (mMode == ASMIM_ZERO_PAGE && ins.ChangesZeroPage(mValue))
return true;
}
if (ins.ChangesYReg())
{
if (&ins != mDst && mDst->mType == ASMIT_TAY)
return true;
if (mSrc->mType == ASMIM_ABSOLUTE_Y)
return true;
}
if (ins.ChangesXReg())
{
if (&ins != mDst && mDst->mType == ASMIT_TAX)
return true;
if (mSrc->mType == ASMIM_ABSOLUTE_X)
return true;
}
return false;
}
void NativeSimpleSubExpressions::Filter(const NativeCodeInstruction& ins) void NativeSimpleSubExpressions::Filter(const NativeCodeInstruction& ins)
{ {
if (ins.mType == ASMIT_JSR) if (ins.mType == ASMIT_JSR)
mExps.SetSize(0); mExps.SetSize(0);
else if (ins.ChangesAddress()) else
{ {
int i = 0; int i = 0;
while (i < mExps.Size()) while (i < mExps.Size())
{ {
if (mExps[i].mSrc->MayBeChangedOnAddress(ins) || if (mExps[i].MayBeChangedBy(ins))
&ins != mExps[i].mDst && mExps[i].mDst->MayBeChangedOnAddress(ins))
mExps.Remove(i); mExps.Remove(i);
else else
i++; i++;
@ -13986,10 +14089,27 @@ bool NativeCodeBasicBlock::PropagateCommonSubExpression(void)
int j = exps.FindCommon(ex); int j = exps.FindCommon(ex);
if (j >= 0) if (j >= 0)
{ {
*ex.mSrc = NativeCodeInstruction(ex.mSrc->mType, *(exps.mExps[j].mDst)); if (ex.mDst->mType == ASMIT_TAY)
ex.mSrc = exps.mExps[j].mSrc; {
ex.mOp->mType = ASMIT_NOP; for (int k = exps.mExps[j].mIndex; k < i + 2; k++)
ex.mOp->mMode = ASMIM_IMPLIED; mIns[k].mLive |= LIVE_CPU_REG_Y;
ex.mOp->mLive |= LIVE_CPU_REG_Y;
ex.mDst->mType = ASMIT_NOP;
}
else if (ex.mDst->mType == ASMIT_TAX)
{
for (int k = exps.mExps[j].mIndex; k < i + 2; k++)
mIns[k].mLive |= LIVE_CPU_REG_X;
ex.mOp->mLive |= LIVE_CPU_REG_Y;
ex.mDst->mType = ASMIT_NOP;
}
else
{
*ex.mSrc = NativeCodeInstruction(ex.mSrc->mType, *(exps.mExps[j].mDst));
ex.mSrc = exps.mExps[j].mSrc;
ex.mOp->mType = ASMIT_NOP;
ex.mOp->mMode = ASMIM_IMPLIED;
}
changed = true; changed = true;
} }
exps.mExps.Push(ex); exps.mExps.Push(ex);
@ -27411,6 +27531,50 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
} }
} }
ei = mIns.Size() - 1;
while (ei > si && !mIns[ei].ReferencesYReg())
ei--;
if (si < ei && mIns[si].mType == ASMIT_TYA && mIns[ei].mType == ASMIT_TAY)
{
int i = 0;
while (i < si && !mIns[i].ChangesYReg())
i++;
if (i == si)
{
i = ei + 1;
while (i < mIns.Size() && !mIns[i].ChangesAccu())
i++;
if (i == mIns.Size())
{
if (!prevBlock)
return OptimizeSimpleLoopInvariant(proc, full);
i = 0;
while (i < si)
{
mIns[i].mLive |= LIVE_CPU_REG_A;
i++;
}
i = ei;
while (i < mIns.Size())
{
mIns[i].mLive |= LIVE_CPU_REG_A;
i++;
}
prevBlock->mIns.Push(mIns[si]);
mIns.Remove(si);
CheckLive();
return true;
}
}
}
if (si + 2 < ei && if (si + 2 < ei &&
mIns[si + 0].mType == ASMIT_LDA && mIns[si + 0].mType == ASMIT_LDA &&
mIns[si + 1].mType == ASMIT_CLC && mIns[si + 1].mType == ASMIT_CLC &&
@ -38574,7 +38738,7 @@ void NativeCodeProcedure::Optimize(void)
changed = true; changed = true;
} }
if (step == 5) if (step == 3 || step == 5 || step == 9)
{ {
ResetVisited(); ResetVisited();
if (mEntryBlock->PropagateCommonSubExpression()) if (mEntryBlock->PropagateCommonSubExpression())

View File

@ -71,8 +71,12 @@ struct NativeRegisterSum16Info
struct NativeSimpleSubExpression struct NativeSimpleSubExpression
{ {
AsmInsType mType; AsmInsType mType;
AsmInsMode mMode;
int mValue; int mValue;
NativeCodeInstruction * mSrc, * mDst, * mOp; NativeCodeInstruction * mSrc, * mDst, * mOp;
int mIndex;
bool MayBeChangedBy(const NativeCodeInstruction& ins);
}; };
struct NativeSimpleSubExpressions struct NativeSimpleSubExpressions