Combining consecutive pointer arithmetic

This commit is contained in:
drmortalwombat 2023-02-12 20:09:02 +01:00
parent 71a071fea4
commit 23091a0536
2 changed files with 709 additions and 654 deletions

View File

@ -12264,22 +12264,10 @@ void InterCodeBasicBlock::CheckBlocks(void)
}
void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& staticVars)
bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray& staticVars)
{
int i;
if (!mVisited)
{
mVisited = true;
CheckFinalLocal();
if (mTrueJump) mTrueJump->CheckFinalLocal();
if (mFalseJump) mFalseJump->CheckFinalLocal();
// Remove none instructions
int j = 0;
for (i = 0; i < mInstructions.Size(); i++)
for (int i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i]->mCode != IC_NONE)
{
@ -12288,291 +12276,9 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
}
mInstructions.SetSize(j);
// shorten lifespan
int loopTmp = -1;
int limit = mInstructions.Size() - 1;
if (limit >= 0 && mInstructions[limit]->mCode == IC_BRANCH)
{
limit--;
#if 1
// try to move conditional source down
int i = limit;
while (i >= 0 && mInstructions[i]->mDst.mTemp != mInstructions[limit + 1]->mSrc[0].mTemp)
i--;
if (i >= 0 && i != limit)
{
InterInstruction* ins(mInstructions[i]);
if (ins->mCode == IC_BINARY_OPERATOR || ins->mCode == IC_RELATIONAL_OPERATOR)
{
if (ins->mSrc[0].mTemp < 0)
{
int k = i;
while (k < limit && CanBypass(ins, mInstructions[k + 1]))
k++;
if (k == limit)
{
for (int l = i; l < limit; l++)
{
SwapInstructions(ins, mInstructions[l + 1]);
mInstructions[l] = mInstructions[l + 1];
}
mInstructions[limit] = ins;
// mInstructions.Remove(i);
// mInstructions.Insert(limit, ins);
}
}
}
}
#endif
if (limit > 0 && mInstructions[limit]->mCode == IC_RELATIONAL_OPERATOR)
{
if (mInstructions[limit]->mSrc[1].mTemp)
loopTmp = mInstructions[limit]->mSrc[1].mTemp;
else if (mInstructions[limit]->mSrc[0].mTemp)
loopTmp = mInstructions[limit]->mSrc[0].mTemp;
limit--;
if (loopTmp >= 0)
{
int i = limit;
while (i >= 0 && !(mInstructions[i]->mCode == IC_BINARY_OPERATOR && mInstructions[i]->mDst.mTemp == loopTmp))
i--;
if (i >= 0 && i < limit)
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypass(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
if (limit > 0 && mInstructions[limit]->mCode == IC_BINARY_OPERATOR && (mInstructions[limit]->mDst.mTemp == loopTmp))
limit--;
}
}
else if (limit > 0 && mInstructions[limit]->mDst.mTemp == mInstructions[limit + 1]->mSrc[0].mTemp)
limit--;
}
else if (limit >= 0 && mInstructions[limit]->mCode == IC_JUMP)
limit --;
CheckFinalLocal();
int i = limit;
#if 1
while (i >= 0)
{
// move non indirect loads down
if (mInstructions[i]->mCode == IC_LOAD && (mInstructions[i]->mSrc[0].mMemory != IM_INDIRECT || mInstructions[i]->mDst.mType != IT_INT8 || !mInstructions[i]->mSrc[0].mFinal))
{
InterInstruction * ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypassLoad(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_BINARY_OPERATOR || mInstructions[i]->mCode == IC_UNARY_OPERATOR || mInstructions[i]->mCode == IC_CONVERSION_OPERATOR || mInstructions[i]->mCode == IC_CONSTANT)
{
InterInstruction* ins(mInstructions[i]);
int k = i;
while (k < limit && CanBypass(ins, mInstructions[k + 1]))
k++;
if (k < limit)
{
while (k > i && IsChained(mInstructions[k], mInstructions[k + 1]))
k--;
}
int j = i;
while (j < k)
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_LEA && (mInstructions[i]->mSrc[0].mTemp < 0 || mInstructions[i]->mSrc[1].mTemp < 0))
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypass(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
i--;
}
CheckFinalLocal();
#endif
#if 1
// move indirect load/store pairs up
i = 0;
while (i + 1 < mInstructions.Size())
{
if (mInstructions[i + 0]->mCode == IC_LOAD && mInstructions[i + 1]->mCode == IC_STORE && mInstructions[i + 1]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mFinal)
{
if (mInstructions[i + 0]->mSrc[0].mMemory == IM_INDIRECT)
{
InterInstruction* lins(mInstructions[i + 0]);
InterInstruction* sins(mInstructions[i + 1]);
int j = i;
while (j > 0 &&
CanBypassLoadUp(lins, mInstructions[j - 1]) &&
CanBypassStore(sins, mInstructions[j - 1]))
{
SwapInstructions(mInstructions[j - 1], lins);
SwapInstructions(mInstructions[j - 1], sins);
mInstructions[j + 1] = mInstructions[j - 1];
j--;
}
if (i != j)
{
mInstructions[j + 0] = lins;
mInstructions[j + 1] = sins;
}
}
}
i++;
}
CheckFinalLocal();
#endif
#if 1
i = 0;
while (i < mInstructions.Size())
{
// move stores up
if (mInstructions[i]->mCode == IC_STORE)
{
InterInstruction * ins(mInstructions[i]);
int j = i;
while (j > 0 && CanBypassStore(ins, mInstructions[j - 1]))
{
SwapInstructions(mInstructions[j - 1], ins);
mInstructions[j] = mInstructions[j - 1];
j--;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_BINARY_OPERATOR && mInstructions[i]->mSrc[0].mTemp >= 0 && mInstructions[i]->mSrc[0].mFinal && mInstructions[i]->mSrc[1].mTemp >= 0 && mInstructions[i]->mSrc[1].mFinal)
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j > 0 && CanBypassUp(ins, mInstructions[j - 1]))
{
SwapInstructions(mInstructions[j - 1], ins);
mInstructions[j] = mInstructions[j - 1];
j--;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_LOAD && mInstructions[i]->mSrc[0].mMemory == IM_INDIRECT && mInstructions[i]->mSrc[0].mFinal && mInstructions[i]->mDst.mType == IT_INT8)
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j > 0 && CanBypassLoadUp(ins, mInstructions[j - 1]))
{
SwapInstructions(mInstructions[j - 1], ins);
mInstructions[j] = mInstructions[j - 1];
j--;
}
if (i != j)
mInstructions[j] = ins;
}
i++;
}
CheckFinalLocal();
#endif
#if 1
i = limit;
while (i >= 0)
{
// move non indirect loads down
if (mInstructions[i]->mCode == IC_LOAD && (mInstructions[i]->mSrc[0].mMemory != IM_INDIRECT || mInstructions[i]->mDst.mType != IT_INT8 || !mInstructions[i]->mSrc[0].mFinal))
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypassLoad(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_CONSTANT || (mInstructions[i]->mCode == IC_LEA && mInstructions[i]->mSrc[0].mTemp == -1))
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypass(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
i--;
}
#endif
CheckFinalLocal();
bool changed = false;
do
{
int j = 0;
for (i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i]->mCode != IC_NONE)
{
mInstructions[j++] = mInstructions[i];
}
}
mInstructions.SetSize(j);
changed = false;
for (i = 0; i < mInstructions.Size(); i++)
for (int i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i]->mCode == IC_LOAD_TEMPORARY && mInstructions[i]->mDst.mTemp == mInstructions[i]->mSrc->mTemp)
{
@ -13065,6 +12771,51 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
mInstructions[i + 1]->mCode = IC_NONE; mInstructions[i + 1]->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]->mSrc[1].mTemp >= 0 &&
mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 1]->mOperator == IA_ADD &&
mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mTemp >= 0 &&
mInstructions[i + 2]->mCode == IC_LEA && mInstructions[i + 2]->mSrc[0].mTemp == mInstructions[i + 1]->mDst.mTemp && mInstructions[i + 2]->mSrc[0].mFinal &&
mInstructions[i + 2]->mSrc[1].mTemp < 0 &&
mInstructions[i + 0]->mDst.mTemp != mInstructions[i + 0]->mSrc[1].mTemp)
{
mInstructions[i + 2]->mSrc[1].mIntConst += mInstructions[i + 0]->mSrc[0].mIntConst;
mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1];
mInstructions[i + 0]->mSrc[1].mFinal = false;
mInstructions[i + 1]->mSrc[0].mFinal = false;
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]->mSrc[1].mTemp >= 0 &&
mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 1]->mOperator == IA_ADD &&
mInstructions[i + 1]->mSrc[0].mTemp < 0 && mInstructions[i + 1]->mSrc[1].mTemp >= 0 &&
mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 2]->mOperator == IA_ADD &&
mInstructions[i + 2]->mSrc[0].mTemp == mInstructions[i + 1]->mDst.mTemp &&
mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp &&
// !mInstructions[i + 1]->ReferencesTemp(mInstructions[i + 0]->mDst.mTemp) &&
(mInstructions[i + 2]->mSrc[0].mFinal || mInstructions[i + 2]->mSrc[1].mFinal))
{
if (mInstructions[i + 2]->mSrc[0].mFinal)
{
mInstructions[i + 0]->mSrc[0].mIntConst += mInstructions[i + 1]->mSrc[0].mIntConst;
mInstructions[i + 1]->mSrc[1].mFinal = false;
mInstructions[i + 2]->mSrc[1] = mInstructions[i + 1]->mSrc[1];
}
else
{
mInstructions[i + 1]->mSrc[0].mIntConst += mInstructions[i + 0]->mSrc[0].mIntConst;
mInstructions[i + 0]->mSrc[1].mFinal = false;
mInstructions[i + 2]->mSrc[0] = mInstructions[i + 0]->mSrc[1];
}
changed = true;
}
else if (
mInstructions[i + 0]->mCode == IC_LEA && mInstructions[i + 0]->mSrc[1].mMemory == IM_GLOBAL &&
mInstructions[i + 1]->mCode == IC_LEA && mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal &&
@ -13210,7 +12961,303 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
#endif
}
} while (changed);
return changed;
}
void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& staticVars)
{
int i;
if (!mVisited)
{
mVisited = true;
CheckFinalLocal();
if (mTrueJump) mTrueJump->CheckFinalLocal();
if (mFalseJump) mFalseJump->CheckFinalLocal();
// Remove none instructions
int j = 0;
for (i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i]->mCode != IC_NONE)
{
mInstructions[j++] = mInstructions[i];
}
}
mInstructions.SetSize(j);
// shorten lifespan
int loopTmp = -1;
int limit = mInstructions.Size() - 1;
if (limit >= 0 && mInstructions[limit]->mCode == IC_BRANCH)
{
limit--;
#if 1
// try to move conditional source down
int i = limit;
while (i >= 0 && mInstructions[i]->mDst.mTemp != mInstructions[limit + 1]->mSrc[0].mTemp)
i--;
if (i >= 0 && i != limit)
{
InterInstruction* ins(mInstructions[i]);
if (ins->mCode == IC_BINARY_OPERATOR || ins->mCode == IC_RELATIONAL_OPERATOR)
{
if (ins->mSrc[0].mTemp < 0)
{
int k = i;
while (k < limit && CanBypass(ins, mInstructions[k + 1]))
k++;
if (k == limit)
{
for (int l = i; l < limit; l++)
{
SwapInstructions(ins, mInstructions[l + 1]);
mInstructions[l] = mInstructions[l + 1];
}
mInstructions[limit] = ins;
// mInstructions.Remove(i);
// mInstructions.Insert(limit, ins);
}
}
}
}
#endif
if (limit > 0 && mInstructions[limit]->mCode == IC_RELATIONAL_OPERATOR)
{
if (mInstructions[limit]->mSrc[1].mTemp)
loopTmp = mInstructions[limit]->mSrc[1].mTemp;
else if (mInstructions[limit]->mSrc[0].mTemp)
loopTmp = mInstructions[limit]->mSrc[0].mTemp;
limit--;
if (loopTmp >= 0)
{
int i = limit;
while (i >= 0 && !(mInstructions[i]->mCode == IC_BINARY_OPERATOR && mInstructions[i]->mDst.mTemp == loopTmp))
i--;
if (i >= 0 && i < limit)
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypass(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
if (limit > 0 && mInstructions[limit]->mCode == IC_BINARY_OPERATOR && (mInstructions[limit]->mDst.mTemp == loopTmp))
limit--;
}
}
else if (limit > 0 && mInstructions[limit]->mDst.mTemp == mInstructions[limit + 1]->mSrc[0].mTemp)
limit--;
}
else if (limit >= 0 && mInstructions[limit]->mCode == IC_JUMP)
limit --;
CheckFinalLocal();
int i = limit;
#if 1
while (i >= 0)
{
// move non indirect loads down
if (mInstructions[i]->mCode == IC_LOAD && (mInstructions[i]->mSrc[0].mMemory != IM_INDIRECT || mInstructions[i]->mDst.mType != IT_INT8 || !mInstructions[i]->mSrc[0].mFinal))
{
InterInstruction * ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypassLoad(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_BINARY_OPERATOR || mInstructions[i]->mCode == IC_UNARY_OPERATOR || mInstructions[i]->mCode == IC_CONVERSION_OPERATOR || mInstructions[i]->mCode == IC_CONSTANT)
{
InterInstruction* ins(mInstructions[i]);
int k = i;
while (k < limit && CanBypass(ins, mInstructions[k + 1]))
k++;
if (k < limit)
{
while (k > i && IsChained(mInstructions[k], mInstructions[k + 1]))
k--;
}
int j = i;
while (j < k)
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_LEA && (mInstructions[i]->mSrc[0].mTemp < 0 || mInstructions[i]->mSrc[1].mTemp < 0))
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypass(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
i--;
}
CheckFinalLocal();
#endif
#if 1
// move indirect load/store pairs up
i = 0;
while (i + 1 < mInstructions.Size())
{
if (mInstructions[i + 0]->mCode == IC_LOAD && mInstructions[i + 1]->mCode == IC_STORE && mInstructions[i + 1]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mFinal)
{
if (mInstructions[i + 0]->mSrc[0].mMemory == IM_INDIRECT)
{
InterInstruction* lins(mInstructions[i + 0]);
InterInstruction* sins(mInstructions[i + 1]);
int j = i;
while (j > 0 &&
CanBypassLoadUp(lins, mInstructions[j - 1]) &&
CanBypassStore(sins, mInstructions[j - 1]))
{
SwapInstructions(mInstructions[j - 1], lins);
SwapInstructions(mInstructions[j - 1], sins);
mInstructions[j + 1] = mInstructions[j - 1];
j--;
}
if (i != j)
{
mInstructions[j + 0] = lins;
mInstructions[j + 1] = sins;
}
}
}
i++;
}
CheckFinalLocal();
#endif
#if 1
i = 0;
while (i < mInstructions.Size())
{
// move stores up
if (mInstructions[i]->mCode == IC_STORE)
{
InterInstruction * ins(mInstructions[i]);
int j = i;
while (j > 0 && CanBypassStore(ins, mInstructions[j - 1]))
{
SwapInstructions(mInstructions[j - 1], ins);
mInstructions[j] = mInstructions[j - 1];
j--;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_BINARY_OPERATOR && mInstructions[i]->mSrc[0].mTemp >= 0 && mInstructions[i]->mSrc[0].mFinal && mInstructions[i]->mSrc[1].mTemp >= 0 && mInstructions[i]->mSrc[1].mFinal)
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j > 0 && CanBypassUp(ins, mInstructions[j - 1]))
{
SwapInstructions(mInstructions[j - 1], ins);
mInstructions[j] = mInstructions[j - 1];
j--;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_LOAD && mInstructions[i]->mSrc[0].mMemory == IM_INDIRECT && mInstructions[i]->mSrc[0].mFinal && mInstructions[i]->mDst.mType == IT_INT8)
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j > 0 && CanBypassLoadUp(ins, mInstructions[j - 1]))
{
SwapInstructions(mInstructions[j - 1], ins);
mInstructions[j] = mInstructions[j - 1];
j--;
}
if (i != j)
mInstructions[j] = ins;
}
i++;
}
CheckFinalLocal();
#endif
#if 1
i = limit;
while (i >= 0)
{
// move non indirect loads down
if (mInstructions[i]->mCode == IC_LOAD && (mInstructions[i]->mSrc[0].mMemory != IM_INDIRECT || mInstructions[i]->mDst.mType != IT_INT8 || !mInstructions[i]->mSrc[0].mFinal))
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypassLoad(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
else if (mInstructions[i]->mCode == IC_CONSTANT || (mInstructions[i]->mCode == IC_LEA && mInstructions[i]->mSrc[0].mTemp == -1))
{
InterInstruction* ins(mInstructions[i]);
int j = i;
while (j < limit && CanBypass(ins, mInstructions[j + 1]))
{
SwapInstructions(ins, mInstructions[j + 1]);
mInstructions[j] = mInstructions[j + 1];
j++;
}
if (i != j)
mInstructions[j] = ins;
}
i--;
}
#endif
CheckFinalLocal();
do {} while (PeepholeReplaceOptimization(staticVars));
// build trains
#if 1
@ -13256,6 +13303,8 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
// sort stores up
bool changed;
do
{
changed = false;
@ -13330,6 +13379,10 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
CheckFinalLocal();
do {} while (PeepholeReplaceOptimization(staticVars));
CheckFinalLocal();
if (mTrueJump) mTrueJump->PeepholeOptimization(staticVars);
if (mFalseJump) mFalseJump->PeepholeOptimization(staticVars);
}

View File

@ -499,6 +499,8 @@ public:
void CheckBlocks(void);
void PeepholeOptimization(const GrowingVariableArray& staticVars);
bool PeepholeReplaceOptimization(const GrowingVariableArray& staticVars);
void SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
void SingleBlockLoopUnrolling(void);
bool SingleBlockLoopPointerSplit(int& spareTemps);