Integer value range optimizations

This commit is contained in:
drmortalwombat 2022-01-04 22:26:44 +01:00
parent a86a19fc8c
commit 2b7c7300d7
4 changed files with 219 additions and 59 deletions

View File

@ -41,6 +41,44 @@ bool IntegerValueRange::Same(const IntegerValueRange& range) const
return false;
}
void IntegerValueRange::LimitMin(int64 value)
{
if (mMinState != S_BOUND || mMinValue < value)
{
mMinState = S_BOUND;
mMinValue = value;
}
}
void IntegerValueRange::LimitMax(int64 value)
{
if (mMaxState != S_BOUND || mMaxValue > value)
{
mMaxState = S_BOUND;
mMaxValue = value;
}
}
void IntegerValueRange::LimitMinWeak(int64 value)
{
if (mMinState == S_UNBOUND || mMinValue < value)
{
mMinState = S_BOUND;
mMinValue = value;
}
}
void IntegerValueRange::LimitMaxWeak(int64 value)
{
if (mMaxState == S_UNBOUND || mMaxValue > value)
{
mMaxState = S_BOUND;
mMaxValue = value;
}
}
bool IntegerValueRange::Merge(const IntegerValueRange& range)
{
bool changed = false;
@ -3367,6 +3405,10 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void)
if (mInstructions[sz - 2]->mSrc[1].IsUnsigned())
mInstructions[sz - 2]->mOperator = IA_CMPLU;
}
else if (mInstructions[sz - 2]->mSrc[0].IsUnsigned() && mInstructions[sz - 2]->mSrc[1].IsUnsigned())
{
mInstructions[sz - 2]->mOperator = IA_CMPLU;
}
}
}
#endif
@ -3427,6 +3469,32 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(void)
return changed;
}
static int64 SignedTypeMin(InterType type)
{
switch (type)
{
case IT_INT8:
return -128;
case IT_INT16:
return -32768;
default:
return -0x80000000LL;
}
}
static int64 SignedTypeMax(InterType type)
{
switch (type)
{
case IT_INT8:
return 127;
case IT_INT16:
return 32767;
default:
return 0x7fffffff;
}
}
void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
{
mLocalValueRange = mEntryValueRange;
@ -3793,14 +3861,28 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
{
if (mInstructions[sz - 2]->mOperator == IA_CMPLS)
{
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1;
int s1 = mInstructions[sz - 2]->mSrc[1].mTemp, s0 = mInstructions[sz - 2]->mSrc[0].mTemp;
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
if (s0 < 0)
{
mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
mTrueValueRange[s1].LimitMinWeak(SignedTypeMin(mInstructions[sz - 2]->mSrc[1].mType));
mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
}
else if (s1 < 0)
{
mTrueValueRange[s0].LimitMin(mInstructions[sz - 2]->mSrc[1].mIntConst + 1);
mTrueValueRange[s0].LimitMaxWeak(SignedTypeMax(mInstructions[sz - 2]->mSrc[0].mType));
mFalseValueRange[s0].LimitMax(mInstructions[sz - 2]->mSrc[1].mIntConst);
}
else
{
if (mLocalValueRange[s0].mMaxState == IntegerValueRange::S_BOUND)
mTrueValueRange[s1].LimitMax(mLocalValueRange[s0].mMaxValue - 1);
if (mLocalValueRange[s0].mMinState == IntegerValueRange::S_BOUND)
mFalseValueRange[s1].LimitMin(mLocalValueRange[s0].mMinValue);
}
}
else if (mInstructions[sz - 2]->mOperator == IA_CMPLES)
@ -3808,11 +3890,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst + 1;
mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
}
}
else if (mInstructions[sz - 2]->mOperator == IA_CMPGS)
@ -3820,11 +3899,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst + 1;
mFalseValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
}
}
else if (mInstructions[sz - 2]->mOperator == IA_CMPGES)
@ -3832,11 +3908,8 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
mFalseValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1;
mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
}
}
else if (mInstructions[sz - 2]->mOperator == IA_CMPLU)
@ -3846,28 +3919,22 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1;
mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMinValue = 0;
mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
mTrueValueRange[t].LimitMin(0);
if (mFalseValueRange[t].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[t].mMinValue >= 0)
{
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
}
}
else if (mInstructions[sz - 2]->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND)
{
mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue - 1;
mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMinValue = 0;
mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue - 1);
mTrueValueRange[t].LimitMin(0);
if (mFalseValueRange[t].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[t].mMinValue >= 0)
{
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue;
mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue);
}
}
}
@ -3877,15 +3944,12 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMinValue = 0;
mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
mTrueValueRange[t].LimitMin(0);
if (mFalseValueRange[t].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[t].mMinValue >= 0)
{
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst + 1;
mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
}
}
}
@ -3896,14 +3960,11 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
// if (mTrueValueRange[t].mMinState == IntegerValueRange::S_BOUND && mTrueValueRange[t].mMinValue >= 0)
{
mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst + 1;
mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
}
mFalseValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMinValue = 0;
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[t].LimitMin(0);
}
}
else if (mInstructions[sz - 2]->mOperator == IA_CMPGEU)
@ -3913,14 +3974,11 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
if (mTrueValueRange[t].mMinState == IntegerValueRange::S_BOUND && mTrueValueRange[t].mMinValue >= 0)
{
mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mTrueValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
}
mFalseValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1;
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[t].mMinValue = 0;
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
mFalseValueRange[t].LimitMin(0);
}
}
}
@ -6928,7 +6986,12 @@ void InterCodeProcedure::SingleAssignmentForwarding(void)
ResetVisited();
mEntryBlock->SingleAssignmentTempForwarding(tunified, tvalues);
BuildDataFlowSets();
TempForwarding();
RemoveUnusedInstructions();
DisassembleDebug("single assignment forwarding");
}
void InterCodeProcedure::TempForwarding(void)
@ -7277,6 +7340,7 @@ void InterCodeProcedure::Close(void)
DisassembleDebug("Peephole optimized");
bool changed = false;
#if 1
do
{
BuildDataFlowSets();
@ -7287,7 +7351,7 @@ void InterCodeProcedure::Close(void)
DisassembleDebug("Pushed single path result");
} while (changed);
#endif
BuildDataFlowSets();
@ -7341,7 +7405,7 @@ void InterCodeProcedure::Close(void)
mEntryBlock->CollectEntryBlocks(nullptr);
BuildDataFlowSets();
#if 1
ResetVisited();
mEntryBlock->BuildLocalIntegerRangeSets(mTemporaries.Size());
@ -7357,7 +7421,7 @@ void InterCodeProcedure::Close(void)
mEntryBlock->SimplifyIntegerRangeRelops();
DisassembleDebug("Simplified range limited relational ops");
#endif
MapVariables();
DisassembleDebug("mapped variabled");

View File

@ -146,6 +146,12 @@ public:
bool Same(const IntegerValueRange& range) const;
bool Merge(const IntegerValueRange& range);
void LimitMin(int64 value);
void LimitMax(int64 value);
void LimitMinWeak(int64 value);
void LimitMaxWeak(int64 value);
};

View File

@ -6037,6 +6037,15 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
if (InterTypeSize[ins->mDst.mType] > 1)
{
#if 1
if (ins->mDst.IsUByte())
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
}
else
#endif
{
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
mIns.Push(NativeCodeInstruction(atype, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
@ -6044,6 +6053,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
}
}
}
}
} break;
case IA_SUB:
{
@ -7708,9 +7718,11 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mSrc[1].mIntConst >> 8) & 0xff));
#if 1
if (ins->mSrc[0].IsUByte())
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
else
#endif
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
}
@ -7720,9 +7732,11 @@ void NativeCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mSrc[1].mLinkerObject, NCIF_UPPER));
#if 1
if (ins->mSrc[0].IsUByte())
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_IMMEDIATE, 0));
else
#endif
mIns.Push(NativeCodeInstruction(ASMIT_ADC, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
}
@ -9975,6 +9989,43 @@ bool NativeCodeBasicBlock::MoveLoadAddZPStoreUp(int at)
return false;
}
bool NativeCodeBasicBlock::MoveCLCLoadAddZPStoreDown(int at)
{
int j = at + 4;
while (j < mIns.Size())
{
if (mIns[j].mType == ASMIT_LDA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at + 3].mAddress)
{
if (j == at + 4)
return false;
if (mIns[j].mLive & LIVE_CPU_REG_C)
return false;
mIns.Insert(j, mIns[at + 3]); // STA
mIns.Insert(j, mIns[at + 2]); // ADC
mIns.Insert(j, mIns[at + 1]); // LDA
mIns.Insert(j, mIns[at + 0]); // CLC
mIns[at + 0].mType = ASMIT_NOP; mIns[at + 0].mMode = ASMIM_IMPLIED;
mIns[at + 1].mType = ASMIT_NOP; mIns[at + 1].mMode = ASMIM_IMPLIED;
mIns[at + 2].mType = ASMIT_NOP; mIns[at + 2].mMode = ASMIM_IMPLIED;
mIns[at + 3].mType = ASMIT_NOP; mIns[at + 3].mMode = ASMIM_IMPLIED;
return true;
}
if (mIns[j].ChangesZeroPage(mIns[at + 1].mAddress))
return false;
if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress))
return false;
if (mIns[j].UsesZeroPage(mIns[at + 3].mAddress))
return false;
j++;
}
return false;
}
bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bool global)
{
bool changed = false;
@ -10148,6 +10199,8 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock* prevBlock, NativeCodeBasicBlock* exitBlock)
{
return false;
bool changed = false;
int ai = 0;
@ -11354,6 +11407,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(void)
carryClear = carrySet = false;
}
#if 1
if (carryClear || carrySet)
{
int i = 0;
@ -11367,7 +11421,7 @@ void NativeCodeBasicBlock::BlockSizeReduction(void)
mIns.Remove(i);
}
}
#endif
if (mTrueJump)
mTrueJump->BlockSizeReduction();
if (mFalseJump)
@ -11515,6 +11569,26 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
}
#endif
#if 1
// move simple add down to consumer
if (!changed)
{
for (int i = 0; i + 4 < mIns.Size(); i++)
{
if (
mIns[i + 0].mType == ASMIT_CLC &&
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && (mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_C)) == 0)
{
if (MoveCLCLoadAddZPStoreDown(i))
changed = true;
}
}
}
#endif
//
// shorten x/y register livetime
@ -12978,6 +13052,21 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
progress = true;
}
#endif
#if 1
else if (
mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_IMMEDIATE &&
mIns[i + 1].mType == ASMIT_ADC &&
mIns[i + 2].mType == ASMIT_CLC &&
mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && !(mIns[i + 3].mLive & LIVE_CPU_REG_C))
{
mIns[i + 0].mAddress += mIns[i + 3].mAddress;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
progress = true;
}
#endif
else if (
mIns[i + 0].mType == ASMIT_LDA &&
mIns[i + 3].mType == ASMIT_STA && mIns[i + 0].SameEffectiveAddress(mIns[i + 3]) &&

View File

@ -206,6 +206,7 @@ public:
bool MoveLoadAddImmStoreUp(int at);
bool MoveCLCLoadAddZPStoreUp(int at);
bool MoveLoadAddZPStoreUp(int at);
bool MoveCLCLoadAddZPStoreDown(int at);
bool FindDirectAddressSumY(int at, int reg, int& apos, int& breg);
bool PatchDirectAddressSumY(int at, int reg, int apos, int breg);
bool FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg);