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)
|
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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue