More native code common subexpression elimination
This commit is contained in:
parent
55a2c25b44
commit
c2c0244990
|
@ -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)
|
||||
{
|
||||
switch (oper)
|
||||
|
@ -7343,7 +7363,7 @@ bool InterCodeBasicBlock::CalculateSingleAssignmentTemps(FastNumberSet& tassigne
|
|||
return changed;
|
||||
}
|
||||
|
||||
void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwardingTable, bool reverse)
|
||||
void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwardingTable, bool reverse, bool checkloops)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -7362,6 +7382,38 @@ void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwa
|
|||
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
|
||||
mMergeForwardingTable.SetSize(forwardingTable.Size());
|
||||
}
|
||||
|
@ -7385,8 +7437,8 @@ void InterCodeBasicBlock::PerformTempForwarding(const TempForwardingTable& forwa
|
|||
mInstructions[i]->PerformTempForwarding(mMergeForwardingTable, reverse);
|
||||
}
|
||||
|
||||
if (mTrueJump) mTrueJump->PerformTempForwarding(mMergeForwardingTable, reverse);
|
||||
if (mFalseJump) mFalseJump->PerformTempForwarding(mMergeForwardingTable, reverse);
|
||||
if (mTrueJump) mTrueJump->PerformTempForwarding(mMergeForwardingTable, reverse, checkloops);
|
||||
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;
|
||||
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 (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();
|
||||
|
||||
|
@ -14428,6 +14507,15 @@ void InterCodeProcedure::TempForwarding(bool reverse)
|
|||
ValueSet valueSet;
|
||||
FastNumberSet tvalidSet(numTemps);
|
||||
|
||||
if (checkloops)
|
||||
{
|
||||
BuildLoopPrefix();
|
||||
|
||||
ResetEntryBlocks();
|
||||
ResetVisited();
|
||||
mEntryBlock->CollectEntryBlocks(nullptr);
|
||||
}
|
||||
|
||||
//
|
||||
// Now remove needless temporary moves, that apear due to
|
||||
// stack evaluation
|
||||
|
@ -14436,11 +14524,15 @@ void InterCodeProcedure::TempForwarding(bool reverse)
|
|||
|
||||
mTempForwardingTable.Reset();
|
||||
ResetVisited();
|
||||
mEntryBlock->PerformTempForwarding(mTempForwardingTable, reverse);
|
||||
|
||||
DisassembleDebug("temp forwarding");
|
||||
mEntryBlock->PerformTempForwarding(mTempForwardingTable, reverse, checkloops);
|
||||
|
||||
if (checkloops)
|
||||
DisassembleDebug("loop temp forwarding");
|
||||
else
|
||||
DisassembleDebug("temp forwarding");
|
||||
}
|
||||
|
||||
|
||||
void InterCodeProcedure::RemoveUnusedInstructions(void)
|
||||
{
|
||||
int numTemps = mTemporaries.Size();
|
||||
|
@ -14974,7 +15066,7 @@ void InterCodeProcedure::Close(void)
|
|||
mTempForwardingTable.SetSize(numTemps);
|
||||
|
||||
ResetVisited();
|
||||
mEntryBlock->PerformTempForwarding(mTempForwardingTable, false);
|
||||
mEntryBlock->PerformTempForwarding(mTempForwardingTable, false, false);
|
||||
|
||||
DisassembleDebug("temp forwarding 2");
|
||||
|
||||
|
@ -15508,6 +15600,8 @@ void InterCodeProcedure::Close(void)
|
|||
|
||||
DisassembleDebug("PushMoveOutOfLoop");
|
||||
|
||||
TempForwarding(false, true);
|
||||
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
|
|
|
@ -438,7 +438,7 @@ public:
|
|||
void GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries);
|
||||
|
||||
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 PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars, FastNumberSet& fsingle);
|
||||
bool EliminateDeadBranches(void);
|
||||
|
@ -599,7 +599,7 @@ protected:
|
|||
void BuildTraces(bool expand, bool dominators = true, bool compact = false);
|
||||
void BuildDataFlowSets(void);
|
||||
void RenameTemporaries(void);
|
||||
void TempForwarding(bool reverse = false);
|
||||
void TempForwarding(bool reverse = false, bool checkloops = false);
|
||||
void RemoveUnusedInstructions(void);
|
||||
bool GlobalConstantPropagation(void);
|
||||
bool PropagateNonLocalUsedTemps(void);
|
||||
|
|
|
@ -3184,7 +3184,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
|||
}
|
||||
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_Z].Reset();
|
||||
}
|
||||
|
@ -3215,7 +3215,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
|||
}
|
||||
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_Z].Reset();
|
||||
}
|
||||
|
@ -3827,6 +3827,27 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
|||
else
|
||||
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())
|
||||
data.ResetIndirect(mAddress);
|
||||
|
@ -3863,6 +3884,27 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
|
|||
else
|
||||
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())
|
||||
data.ResetIndirect(mAddress);
|
||||
|
@ -13841,14 +13883,17 @@ bool NativeCodeBasicBlock::CanGlobalSwapXY(void)
|
|||
|
||||
bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpression& ex)
|
||||
{
|
||||
ex.mIndex = at;
|
||||
|
||||
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) &&
|
||||
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.mValue = mIns[at + 1].mAddress;
|
||||
ex.mMode = mIns[at + 1].mMode;
|
||||
ex.mOp = &(mIns[at + 1]);
|
||||
ex.mSrc = &(mIns[at + 0]);
|
||||
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) &&
|
||||
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 + 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]);
|
||||
|
@ -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) &&
|
||||
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 + 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 + 1]);
|
||||
ex.mOp = &(mIns[at + 2]);
|
||||
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 &&
|
||||
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 + 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]);
|
||||
|
@ -13911,6 +13959,7 @@ bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpressi
|
|||
{
|
||||
ex.mType = ASMIT_ADC;
|
||||
ex.mValue = 1;
|
||||
ex.mMode = ASMIM_IMMEDIATE;
|
||||
ex.mOp = &(mIns[at + 1]);
|
||||
ex.mSrc = &(mIns[at + 0]);
|
||||
ex.mDst = &(mIns[at + 2]);
|
||||
|
@ -13925,11 +13974,29 @@ bool NativeCodeBasicBlock::IsSimpleSubExpression(int at, NativeSimpleSubExpressi
|
|||
{
|
||||
ex.mType = ASMIT_ADC;
|
||||
ex.mValue = 1;
|
||||
ex.mMode = ASMIM_IMMEDIATE;
|
||||
ex.mOp = &(mIns[at + 1]);
|
||||
ex.mSrc = &(mIns[at + 0]);
|
||||
ex.mDst = &(mIns[at + 2]);
|
||||
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;
|
||||
|
@ -13941,25 +14008,61 @@ int NativeSimpleSubExpressions::FindCommon(const NativeSimpleSubExpression& ex)
|
|||
{
|
||||
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)))
|
||||
return i;
|
||||
if (mExps[i].mType == ex.mType && mExps[i].mMode == ex.mMode && mExps[i].mValue == ex.mValue && ex.mSrc->SameEffectiveAddress(*(mExps[i].mSrc)))
|
||||
{
|
||||
if (mExps[i].mDst->mMode == ASMIM_IMPLIED)
|
||||
{
|
||||
if (mExps[i].mDst->mType == ex.mDst->mType)
|
||||
return i;
|
||||
}
|
||||
else
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (ins.mType == ASMIT_JSR)
|
||||
mExps.SetSize(0);
|
||||
else if (ins.ChangesAddress())
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
while (i < mExps.Size())
|
||||
{
|
||||
if (mExps[i].mSrc->MayBeChangedOnAddress(ins) ||
|
||||
&ins != mExps[i].mDst && mExps[i].mDst->MayBeChangedOnAddress(ins))
|
||||
if (mExps[i].MayBeChangedBy(ins))
|
||||
mExps.Remove(i);
|
||||
else
|
||||
i++;
|
||||
|
@ -13986,10 +14089,27 @@ bool NativeCodeBasicBlock::PropagateCommonSubExpression(void)
|
|||
int j = exps.FindCommon(ex);
|
||||
if (j >= 0)
|
||||
{
|
||||
*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;
|
||||
if (ex.mDst->mType == ASMIT_TAY)
|
||||
{
|
||||
for (int k = exps.mExps[j].mIndex; k < i + 2; k++)
|
||||
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;
|
||||
}
|
||||
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 &&
|
||||
mIns[si + 0].mType == ASMIT_LDA &&
|
||||
mIns[si + 1].mType == ASMIT_CLC &&
|
||||
|
@ -38574,7 +38738,7 @@ void NativeCodeProcedure::Optimize(void)
|
|||
changed = true;
|
||||
}
|
||||
|
||||
if (step == 5)
|
||||
if (step == 3 || step == 5 || step == 9)
|
||||
{
|
||||
ResetVisited();
|
||||
if (mEntryBlock->PropagateCommonSubExpression())
|
||||
|
|
|
@ -71,8 +71,12 @@ struct NativeRegisterSum16Info
|
|||
struct NativeSimpleSubExpression
|
||||
{
|
||||
AsmInsType mType;
|
||||
AsmInsMode mMode;
|
||||
int mValue;
|
||||
NativeCodeInstruction * mSrc, * mDst, * mOp;
|
||||
int mIndex;
|
||||
|
||||
bool MayBeChangedBy(const NativeCodeInstruction& ins);
|
||||
};
|
||||
|
||||
struct NativeSimpleSubExpressions
|
||||
|
|
Loading…
Reference in New Issue