More simple common subexpression elimination in native code

This commit is contained in:
drmortalwombat 2023-03-17 09:32:22 +01:00
parent 9f28fdfcc0
commit 9c5e018c5a
3 changed files with 393 additions and 23 deletions

View File

@ -12685,7 +12685,19 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
mInstructions[i + 1]->mNumOperands = 0;
changed = true;
}
else if (
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && (mInstructions[i + 0]->mOperator == IA_SUB || mInstructions[i + 0]->mOperator == IA_XOR) &&
mInstructions[i + 0]->mSrc[0].mTemp >= 0 && mInstructions[i + 0]->mSrc[0].mTemp == mInstructions[i + 0]->mSrc[1].mTemp)
{
mInstructions[i + 0]->mCode = IC_CONSTANT;
mInstructions[i + 0]->mNumOperands = 0;
mInstructions[i + 0]->mConst.mType = mInstructions[i + 0]->mDst.mType;
mInstructions[i + 0]->mConst.mIntConst = 0;
mInstructions[i + 0]->mConst.mFloatConst = 0;
changed = true;
}
#endif
#if 1
else if (
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_SHR && mInstructions[i + 0]->mSrc[0].mTemp < 0 &&
@ -13137,6 +13149,96 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
changed = true;
}
#if 1
if (i + 2 < mInstructions.Size() &&
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR &&
mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR &&
mInstructions[i + 0]->mDst.mTemp != mInstructions[i + 1]->mSrc[0].mTemp &&
mInstructions[i + 0]->mDst.mTemp != mInstructions[i + 1]->mSrc[1].mTemp &&
mInstructions[i + 2]->mSrc[0].mTemp >= 0 && mInstructions[i + 2]->mSrc[1].mTemp >= 0 &&
mInstructions[i + 2]->mSrc[0].mFinal && mInstructions[i + 2]->mSrc[1].mFinal &&
mInstructions[i + 2]->mDst.mType == IT_INT16)
{
bool fail = false;
int s0, s1, c0, c1, s2 = i + 2;
if (mInstructions[i + 2]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 1]->mDst.mTemp)
{
s0 = i + 0; s1 = i + 1;
}
else if (mInstructions[i + 2]->mSrc[0].mTemp == mInstructions[i + 1]->mDst.mTemp && mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp)
{
s0 = i + 1; s1 = i + 0;
}
else
fail = true;
if (!fail)
{
if (mInstructions[s0]->mSrc[0].mTemp < 0)
c0 = 0;
else if (mInstructions[s0]->mSrc[1].mTemp < 0)
c0 = 1;
else
fail = true;
if (mInstructions[s1]->mSrc[0].mTemp < 0)
c1 = 0;
else if (mInstructions[s1]->mSrc[1].mTemp < 0)
c1 = 1;
else
fail = true;
if (!fail)
{
InterOperator o0 = mInstructions[s0]->mOperator;
InterOperator o1 = mInstructions[s1]->mOperator;
InterOperator o2 = mInstructions[s2]->mOperator;
if (o2 == IA_SUB)
{
if ((o0 == IA_ADD || o0 == IA_SUB && c0 == 0) && (o1 == IA_ADD || o1 == IA_SUB && c1 == 0))
{
int iconst =
(o1 == IA_ADD ? mInstructions[s1]->mSrc[c1].mIntConst : -mInstructions[s1]->mSrc[c1].mIntConst) -
(o0 == IA_ADD ? mInstructions[s0]->mSrc[c0].mIntConst : -mInstructions[s0]->mSrc[c0].mIntConst);
mInstructions[s0]->mSrc[0] = mInstructions[s0]->mSrc[1 - c0];
mInstructions[s0]->mSrc[1] = mInstructions[s1]->mSrc[1 - c1];
mInstructions[s0]->mDst.mRange.Reset();
mInstructions[s0]->mOperator = IA_SUB;
mInstructions[s2]->mOperator = IA_ADD;
mInstructions[s2]->mSrc[0].mRange = mInstructions[s0]->mDst.mRange;
mInstructions[s2]->mSrc[1].mTemp = -1;
mInstructions[s2]->mSrc[1].mIntConst = iconst;
changed = true;
}
}
else if (o2 == IA_ADD)
{
if ((o0 == IA_ADD || o0 == IA_SUB && c0 == 0) && (o1 == IA_ADD || o1 == IA_SUB && c1 == 0))
{
int iconst =
(o1 == IA_ADD ? mInstructions[s1]->mSrc[c1].mIntConst : -mInstructions[s1]->mSrc[c1].mIntConst) +
(o0 == IA_ADD ? mInstructions[s0]->mSrc[c0].mIntConst : -mInstructions[s0]->mSrc[c0].mIntConst);
mInstructions[s0]->mSrc[0] = mInstructions[s0]->mSrc[1 - c0];
mInstructions[s0]->mSrc[1] = mInstructions[s1]->mSrc[1 - c1];
mInstructions[s0]->mDst.mRange.Reset();
mInstructions[s0]->mOperator = IA_ADD;
mInstructions[s2]->mOperator = IA_ADD;
mInstructions[s2]->mSrc[0].mRange = mInstructions[s0]->mDst.mRange;
mInstructions[s2]->mSrc[1].mTemp = -1;
mInstructions[s2]->mSrc[1].mIntConst = iconst;
changed = true;
}
}
}
}
}
#endif
#if 1
// Postincrement artifact
if (mInstructions[i + 0]->mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&

View File

@ -1400,6 +1400,35 @@ bool NativeCodeInstruction::IsSame(const NativeCodeInstruction& ins) const
return false;
}
bool NativeCodeInstruction::IsSameLS(const NativeCodeInstruction& ins) const
{
if ((mType == ins.mType || mType == ASMIT_STA && ins.mType == ASMIT_LDA) && mMode == ins.mMode && mParam == ins.mParam)
{
switch (mMode)
{
case ASMIM_IMPLIED:
return true;
case ASMIM_IMMEDIATE:
case ASMIM_ZERO_PAGE:
case ASMIM_ZERO_PAGE_X:
case ASMIM_ZERO_PAGE_Y:
case ASMIM_INDIRECT_X:
case ASMIM_INDIRECT_Y:
return ins.mAddress == mAddress;
case ASMIM_IMMEDIATE_ADDRESS:
return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress && ins.mFlags == mFlags);
case ASMIM_ABSOLUTE:
case ASMIM_ABSOLUTE_X:
case ASMIM_ABSOLUTE_Y:
return (ins.mLinkerObject == mLinkerObject && ins.mAddress == mAddress);
default:
return false;
}
}
else
return false;
}
bool NativeCodeInstruction::MayBeMovedBefore(const NativeCodeInstruction& ins)
{
if ((ChangesAddress() || ins.ChangesAddress()) && MayBeSameAddress(ins))
@ -13824,9 +13853,26 @@ bool NativeCodeBasicBlock::IsSimpleSubExpression(int at) const
}
}
if (at >= 3 &&
mIns[at - 3].mType == ASMIT_STA && mIns[at - 3].mMode == ASMIM_ZERO_PAGE && mIns[at - 2].mType == ASMIT_CLC &&
mIns[at - 1].mType == ASMIT_ADC && mIns[at - 1].mMode == ASMIM_IMMEDIATE)
return true;
return false;
}
bool NativeCodeBasicBlock::IsSameSimpleSubExpression(int pat, int at) const
{
if (pat >= 2 && mIns[pat - 2].mType == ASMIT_LDA)
{
return mIns[pat - 2].IsSame(mIns[at - 2]) && mIns[pat - 1].IsSame(mIns[at - 1]);
}
else
{
return mIns[pat - 3].SameEffectiveAddress(mIns[at - 2]) && mIns[pat - 1].IsSame(mIns[at - 1]);
}
}
bool NativeCodeBasicBlock::PropagateCommonSubExpression(void)
{
bool changed = false;
@ -13849,7 +13895,7 @@ bool NativeCodeBasicBlock::PropagateCommonSubExpression(void)
if (IsSimpleSubExpression(i))
{
int si = cex[ins.mAddress];
if (si >= 0 && mIns[si - 2].IsSame(mIns[i - 2]) && mIns[si - 1].IsSame(mIns[i - 1]) && !(ins.mLive & LIVE_CPU_REG_C))
if (si >= 0 && IsSameSimpleSubExpression(si, i) && !(ins.mLive & LIVE_CPU_REG_C))
{
mIns[i].mType = ASMIT_LDA;
mIns[si].mLive |= LIVE_MEM;
@ -13876,8 +13922,12 @@ bool NativeCodeBasicBlock::PropagateCommonSubExpression(void)
cex[ins.mAddress] = -1;
for (int j = 0; j < 256; j++)
{
if (cex[j] >= 0 && mIns[cex[j] - 2].mAddress == ins.mAddress)
int k = cex[j];
if (k >= 0 && (
mIns[k - 2].mType == ASMIT_LDA && mIns[k - 2].mAddress == ins.mAddress || mIns[k - 3].mAddress == ins.mAddress))
{
cex[j] = -1;
}
}
}
@ -17533,6 +17583,145 @@ bool NativeCodeBasicBlock::ShortcutPointerAddForward(void)
return changed;
}
#if 0
static int NativeCodeExpressionID;
struct NativeCodeExpression
{
int mIndex;
AsmInsType mType;
NativeCodeInstruction * mIns;
int mLeft, mRight;
int mReg;
NativeCodeExpression(AsmInsType type, NativeCodeInstruction* ins)
: mIndex(NativeCodeExpressionID++), mType(type), mIns(ins), mLeft(-1), mRight(-1), mReg(-1)
{
}
NativeCodeExpression(AsmInsType type, int left, int right)
: mIndex(NativeCodeExpressionID++), mType(type), mIns(nullptr), mLeft(left), mRight(right), mReg(reg)
{
}
};
struct NativeCodeExpressions
{
ExpandingArray<NativeCodeExpression> mExps;
void KillReg(int reg);
void KillYReg(void);
void KillXReg(void);
void KillAddr(const NativeCodeInstruction& ins);
int AddLoad(const NativeCodeInstruction& ins);
};
void NativeCodeExpressions::KillReg(int reg)
{
int i = 0;
while (i < mExps.Size())
{
if (mExps[i].mReg == reg)
mExps.Remove(i);
else if (mExps[i].mIns)
{
if (reg == CPU_REG_Y && mExps[i].mIns->RequiresYReg())
mExps.Remove(i);
else if (reg == CPU_REG_X && mExps[i].mIns->RequiresXReg())
mExps.Remove(i);
else if (mExps[i].mIns->ReferencesZeroPage(reg))
mExps.Remove(i);
else
i++;
}
else
i++;
}
}
void NativeCodeExpressions::KillYReg(void)
{
int i = 0;
while (i < mExps.Size())
{
if (mExps[i].mIns && mExps[i].mIns->RequiresYReg())
mExps.Remove(i);
else
i++;
}
}
void NativeCodeExpressions::KillAddr(const NativeCodeInstruction& ins)
{
int i = 0;
while (i < mExps.Size())
{
if (mExps[i].mIns && mExps[i].mIns->MayBeChangedOnAddress(ins))
mExps.Remove(i);
else
i++;
}
}
int NativeCodeExpressions::AddLoad(const NativeCodeInstruction& ins)
{
int i = 0;
while (i < mExps.Size() && !(mExps[i].mType == ASMIT_LDA && mExps[i].mIns->SameAddress(ins))
i++;
if (i < mExps.Size())
return mExps[i].mIndex;
else
{
NativeCodeExpressions e(ASMIT_LDA, &ins);
mExps.Push(e);
return e.mIndex;
}
}
bool NativeCodeBasicBlock::CommonSubExpressionElimination(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
NativeCodeExpressions exps;
int aexp = -1, xexp = -1, yexp = -1;
for (int i = 0; i < mIns.Size(); i++)
{
NativeCodeInstruction& ins(mIns[i]);
switch (ins.mType)
{
case ASMIT_LDA:
aexp = exps.AddLoad(ins);
break;
case ASMIT_LDX:
aexp = exps.AddLoad(ins);
break;
case ASMIT_LDY:
aexp = exps.AddLoad(ins);
break;
}
}
if (mTrueJump && mTrueJump->CommonSubExpressionElimination())
changed = true;
if (mFalseJump && mFalseJump->CommonSubExpressionElimination())
changed = true;
}
return changed;
}
#endif
bool NativeCodeBasicBlock::CanChangeTailZPStoreToX(int addr, const NativeCodeBasicBlock* nblock, const NativeCodeBasicBlock* fblock) const
{
if (mExitRequiredRegs[CPU_REG_X])
@ -34466,6 +34655,56 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDX &&
mIns[i + 1].mType == ASMIT_INX && mIns[i + 2].mType == ASMIT_INX &&
mIns[i + 3].mType == ASMIT_STX && mIns[i + 3].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 3].mLive & LIVE_CPU_REG_X))
{
mIns[i + 0].mType = ASMIT_INC;
mIns[i + 3].mType = ASMIT_INC;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDX &&
mIns[i + 1].mType == ASMIT_DEX && mIns[i + 2].mType == ASMIT_DEX &&
mIns[i + 3].mType == ASMIT_STX && mIns[i + 3].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 3].mLive & LIVE_CPU_REG_X))
{
mIns[i + 0].mType = ASMIT_DEC;
mIns[i + 3].mType = ASMIT_DEC;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (pass > 10 &&
mIns[i + 0].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_INC, mIns[i + 0].mMode) &&
mIns[i + 1].mType == ASMIT_CLC &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 2 &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
{
mIns[i + 0].mType = ASMIT_INC;
mIns[i + 3].mType = ASMIT_INC;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (pass > 10 &&
mIns[i + 0].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_DEC, mIns[i + 0].mMode) &&
mIns[i + 1].mType == ASMIT_SEC &&
mIns[i + 2].mType == ASMIT_SBC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && mIns[i + 2].mAddress == 2 &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].SameEffectiveAddress(mIns[i + 0]) && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C)))
{
mIns[i + 0].mType = ASMIT_DEC;
mIns[i + 3].mType = ASMIT_DEC;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
progress = true;
}
else if (
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
!(mIns[i + 1].ChangesYReg() || mIns[i + 1].mMode == ASMIM_INDIRECT_Y || mIns[i + 1].RequiresXReg()) &&
@ -35601,30 +35840,28 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
}
}
if (i + 8 < mIns.Size() && pass > 3 &&
mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 1].mType == ASMIT_CLC &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 4].mType == ASMIT_LDA &&
mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE &&
mIns[i + 6].mType == ASMIT_STA && mIns[i + 6].mMode == ASMIM_ZERO_PAGE && mIns[i + 6].mAddress == mIns[i + 3].mAddress + 1 &&
mIns[i + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE &&
mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 3].mAddress && !(mIns[i + 8].mLive & LIVE_MEM))
if (i + 7 < mIns.Size() && pass > 3 &&
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 3].mType == ASMIT_LDA &&
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE &&
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
mIns[i + 6].mType == ASMIT_LDY && mIns[i + 6].mMode == ASMIM_IMMEDIATE &&
mIns[i + 7].mMode == ASMIM_INDIRECT_Y && mIns[i + 7].mAddress == mIns[i + 2].mAddress && !(mIns[i + 7].mLive & LIVE_MEM))
{
int total = mIns[i + 2].mAddress + mIns[i + 7].mAddress + 256 * mIns[i + 5].mAddress;
if (!(mIns[i + 8].mLive & LIVE_CPU_REG_Y) || !(mIns[i + 8].mLive & LIVE_CPU_REG_Z))
int total = mIns[i + 1].mAddress + mIns[i + 6].mAddress + 256 * mIns[i + 4].mAddress;
if (!(mIns[i + 7].mLive & LIVE_CPU_REG_Y) || !(mIns[i + 7].mLive & LIVE_CPU_REG_Z))
{
if (mIns[i + 8].mLive & LIVE_CPU_REG_Y)
mIns.Insert(i + 9, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, mIns[i + 7].mAddress));
mIns[i + 7].mAddress = total & 255;
mIns[i + 5].mAddress = total >> 8;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
if (mIns[i + 7].mLive & LIVE_CPU_REG_Y)
mIns.Insert(i + 8, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, mIns[i + 6].mAddress));
mIns[i + 6].mAddress = total & 255;
mIns[i + 4].mAddress = total >> 8;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
changed = true;
}
}
if (i + 6 < mIns.Size())
{
if (
@ -35978,6 +36215,35 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
}
}
#endif
#if 1
if (mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE &&
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 3].mType == ASMIT_LDA &&
mIns[i + 4].mType == ASMIT_STA && mIns[i + 4].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 5].mType == ASMIT_ADC && mIns[i + 5].mMode == ASMIM_IMMEDIATE &&
mIns[i + 6].mType == ASMIT_STA && mIns[i + 6].mMode == ASMIM_ZERO_PAGE && mIns[i + 6].mAddress == mIns[i + 2].mAddress + 1 &&
mIns[i + 2].mAddress != BC_REG_STACK &&
!(mIns[i + 6].mLive & LIVE_CPU_REG_A))
{
int yval = RetrieveYValue(i);
proc->ResetPatched();
if (CheckForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 2].mAddress, mIns[i + 1], i + 7, yval))
{
proc->ResetPatched();
if (PatchForwardSumYPointer(this, mIns[i + 2].mAddress, mIns[i + 2].mAddress, mIns[i + 1], i + 7, yval))
progress = true;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
if (mTrueJump)
mTrueJump->CheckLive();
if (mFalseJump)
mFalseJump->CheckLive();
}
}
#endif
#if 1
if (
mIns[i + 0].mType == ASMIT_CLC &&
@ -37821,7 +38087,7 @@ void NativeCodeProcedure::RebuildEntry(void)
void NativeCodeProcedure::Optimize(void)
{
CheckFunc = !strcmp(mInterProc->mIdent->mString, "_mapUp");
CheckFunc = !strcmp(mInterProc->mIdent->mString, "setpair");
#if 1
int step = 0;
@ -38017,7 +38283,6 @@ void NativeCodeProcedure::Optimize(void)
}
#if 1
if (step > 0)
{
@ -38453,7 +38718,6 @@ void NativeCodeProcedure::Optimize(void)
else
cnt++;
} while (changed);
#if 1

View File

@ -147,6 +147,7 @@ public:
bool MayBeChangedOnAddress(const NativeCodeInstruction& ins, bool sameXY = false) const;
bool MayBeSameAddress(const NativeCodeInstruction& ins, bool sameXY = false) const;
bool IsSame(const NativeCodeInstruction& ins) const;
bool IsSameLS(const NativeCodeInstruction& ins) const;
bool IsCommutative(void) const;
bool IsShift(void) const;
bool IsShiftOrInc(void) const;
@ -506,6 +507,7 @@ public:
bool GlobalSwapXY(void);
bool IsSimpleSubExpression(int at) const;
bool IsSameSimpleSubExpression(int pat, int at) const;
bool PropagateCommonSubExpression(void);
bool ForwardAbsoluteLoadStores(void);
@ -516,6 +518,8 @@ public:
bool CheckShortcutPointerAddForward(int at);
bool ShortcutPointerAddForward(void);
bool CommonSubExpressionElimination(void);
bool CheckPatchFailReg(const NativeCodeBasicBlock* block, int reg);
bool CheckPatchFailRegPair(const NativeCodeBasicBlock* block, int reg);
bool CheckPatchFailUse(void);