Optimize cross block constant propagation
This commit is contained in:
parent
9e3b014927
commit
0f5e933002
|
@ -16219,6 +16219,153 @@ static int TempUseDelta(const InterInstruction* ins)
|
|||
return d;
|
||||
}
|
||||
|
||||
bool InterCodeBasicBlock::IsConstExitTemp(int temp) const
|
||||
{
|
||||
int n = mInstructions.Size() - 1;
|
||||
while (n >= 0 && mInstructions[n]->mDst.mTemp != temp)
|
||||
n--;
|
||||
return n >= 0 && mInstructions[n]->mCode == IC_CONSTANT;
|
||||
}
|
||||
|
||||
bool InterCodeBasicBlock::SplitSingleBranchUseConst(void)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (!mVisited)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
if (!mLoopHead && mFalseJump)
|
||||
{
|
||||
for (int i = 0; i + 1 < mInstructions.Size(); i++)
|
||||
{
|
||||
InterInstruction* ins = mInstructions[i];
|
||||
|
||||
if (ins->mCode == IC_CONSTANT)
|
||||
{
|
||||
if (CanMoveInstructionBehindBlock(i))
|
||||
{
|
||||
InterCodeBasicBlock* tblock = nullptr;
|
||||
|
||||
if (mTrueJump->mEntryRequiredTemps[ins->mDst.mTemp] && !mFalseJump->mEntryRequiredTemps[ins->mDst.mTemp])
|
||||
tblock = mTrueJump;
|
||||
else if (!mTrueJump->mEntryRequiredTemps[ins->mDst.mTemp] && mFalseJump->mEntryRequiredTemps[ins->mDst.mTemp])
|
||||
tblock = mFalseJump;
|
||||
|
||||
if (tblock)
|
||||
{
|
||||
if (tblock->mNumEntries > 1)
|
||||
{
|
||||
InterCodeBasicBlock* nblock = new InterCodeBasicBlock(mProc);
|
||||
|
||||
nblock->mEntryRequiredTemps = tblock->mEntryRequiredTemps;
|
||||
nblock->mExitRequiredTemps = tblock->mEntryRequiredTemps;
|
||||
|
||||
mExitRequiredTemps -= ins->mDst.mTemp;
|
||||
nblock->mEntryRequiredTemps -= ins->mDst.mTemp;
|
||||
|
||||
tblock->mEntryBlocks.RemoveAll(this);
|
||||
tblock->mEntryBlocks.Push(nblock);
|
||||
|
||||
if (tblock == mTrueJump)
|
||||
mTrueJump = nblock;
|
||||
else
|
||||
mFalseJump = nblock;
|
||||
|
||||
InterInstruction* jins = new InterInstruction(mInstructions.Last()->mLocation, IC_JUMP);
|
||||
nblock->mInstructions.Push(jins);
|
||||
nblock->Close(tblock, nullptr);
|
||||
|
||||
nblock->mEntryBlocks.Push(this);
|
||||
nblock->mNumEntries = 1;
|
||||
|
||||
tblock = nblock;
|
||||
}
|
||||
|
||||
tblock->mInstructions.Insert(0, ins);
|
||||
mInstructions.Remove(i);
|
||||
i--;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mTrueJump && mTrueJump->SplitSingleBranchUseConst())
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->SplitSingleBranchUseConst())
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
bool InterCodeBasicBlock::CommonTailCodeMerge(void)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (!mVisited)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
if (!mLoopHead)
|
||||
{
|
||||
for (int i = 0; i + 1 < mInstructions.Size(); i++)
|
||||
{
|
||||
InterInstruction* ins = mInstructions[i];
|
||||
|
||||
if (CanMoveInstructionBeforeBlock(i))
|
||||
{
|
||||
bool aconst = true, aany = false;
|
||||
for (int j = 0; j < ins->mNumOperands; j++)
|
||||
{
|
||||
if (ins->mSrc[j].mTemp >= 0)
|
||||
{
|
||||
aany = true;
|
||||
int k = 0;
|
||||
while (k < mEntryBlocks.Size() && mEntryBlocks[k]->IsConstExitTemp(ins->mSrc[j].mTemp) && !mEntryBlocks[k]->mFalseJump)
|
||||
k++;
|
||||
if (k < mEntryBlocks.Size())
|
||||
{
|
||||
aconst = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aconst && aany)
|
||||
{
|
||||
for (int j = 0; j < mEntryBlocks.Size(); j++)
|
||||
{
|
||||
InterCodeBasicBlock* eblock = mEntryBlocks[j];
|
||||
eblock->mInstructions.Insert(eblock->mInstructions.Size() - 1, ins->Clone());
|
||||
if (ins->mDst.mTemp >= 0)
|
||||
eblock->mExitRequiredTemps += ins->mDst.mTemp;
|
||||
}
|
||||
if (ins->mDst.mTemp >= 0)
|
||||
mEntryRequiredTemps += ins->mDst.mTemp;
|
||||
ins->mCode = IC_NONE;
|
||||
ins->mNumOperands = 0;
|
||||
ins->mDst.mTemp = -1;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->CommonTailCodeMerge())
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->CommonTailCodeMerge())
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& staticVars)
|
||||
{
|
||||
int i;
|
||||
|
@ -18021,6 +18168,17 @@ void InterCodeProcedure::PropagateConstOperationsUp(void)
|
|||
do {
|
||||
changed = false;
|
||||
|
||||
ResetVisited();
|
||||
if (mEntryBlock->SplitSingleBranchUseConst())
|
||||
changed = true;
|
||||
|
||||
ResetVisited();
|
||||
if (mEntryBlock->CommonTailCodeMerge())
|
||||
{
|
||||
changed = true;
|
||||
BuildDataFlowSets();
|
||||
}
|
||||
|
||||
ResetVisited();
|
||||
mEntryBlock->BuildConstTempSets();
|
||||
|
||||
|
@ -18069,7 +18227,7 @@ void InterCodeProcedure::Close(void)
|
|||
{
|
||||
GrowingTypeArray tstack(IT_NONE);
|
||||
|
||||
CheckFunc = !strcmp(mIdent->mString, "setspr");
|
||||
CheckFunc = !strcmp(mIdent->mString, "dungeon_rand_path");
|
||||
CheckCase = false;
|
||||
|
||||
mEntryBlock = mBlocks[0];
|
||||
|
@ -18775,15 +18933,11 @@ void InterCodeProcedure::Close(void)
|
|||
#if 1
|
||||
do {
|
||||
DisassembleDebug("InConstP");
|
||||
CheckFinal();
|
||||
TempForwarding();
|
||||
CheckFinal();
|
||||
} while (GlobalConstantPropagation());
|
||||
CheckFinal();
|
||||
|
||||
BuildTraces(false);
|
||||
DisassembleDebug("Rebuilt traces");
|
||||
CheckFinal();
|
||||
|
||||
|
||||
PeepholeOptimization();
|
||||
|
|
|
@ -555,6 +555,10 @@ public:
|
|||
void CheckFinal(void);
|
||||
void CheckBlocks(void);
|
||||
|
||||
bool IsConstExitTemp(int temp) const;
|
||||
bool CommonTailCodeMerge(void);
|
||||
bool SplitSingleBranchUseConst(void);
|
||||
|
||||
void PeepholeOptimization(const GrowingVariableArray& staticVars);
|
||||
bool PeepholeReplaceOptimization(const GrowingVariableArray& staticVars);
|
||||
|
||||
|
|
|
@ -1283,6 +1283,31 @@ bool Linker::WriteMapFile(const char* filename)
|
|||
}
|
||||
}
|
||||
|
||||
fprintf(file, "\nobjects by size\n");
|
||||
ExpandingArray<const LinkerObject*> so;
|
||||
for (int i = 0; i < mObjects.Size(); i++)
|
||||
{
|
||||
LinkerObject* obj = mObjects[i];
|
||||
|
||||
if ((obj->mFlags & LOBJF_REFERENCED) && obj->mIdent)
|
||||
{
|
||||
int k = so.Size();
|
||||
so.Push(obj);
|
||||
while (k > 0 && so[k - 1]->mSize < obj->mSize)
|
||||
{
|
||||
so[k] = so[k - 1];
|
||||
k--;
|
||||
}
|
||||
so[k] = obj;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < so.Size(); i++)
|
||||
{
|
||||
const LinkerObject* obj = so[i];
|
||||
fprintf(file, "%04x (%04x) : %s, %s:%s\n", obj->mAddress, obj->mSize, obj->mIdent->mString, LinkerObjectTypeNames[obj->mType], obj->mSection->mIdent->mString);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -18844,6 +18844,63 @@ void NativeCodeBasicBlock::PrependInstruction(const NativeCodeInstruction& ins)
|
|||
mIns[0].mLive |= LIVE_CPU_REG_C;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::ShortcutBlockExit(void)
|
||||
{
|
||||
bool changed = false;
|
||||
if (!mVisited)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
if (!mLoopHead && mTrueJump && mFalseJump && !mTrueJump->mLoopHead && !mFalseJump->mLoopHead)
|
||||
{
|
||||
for (int i = 0; i < mTrueJump->mEntryBlocks.Size(); i++)
|
||||
{
|
||||
NativeCodeBasicBlock* eblock = mTrueJump->mEntryBlocks[i];
|
||||
if (eblock != this)
|
||||
{
|
||||
if (eblock->mTrueJump == mTrueJump && eblock->mFalseJump == mFalseJump && eblock->mBranch == mBranch)
|
||||
{
|
||||
int n = mIns.Size(), m = eblock->mIns.Size();
|
||||
if (m > 0 && n >= m)
|
||||
{
|
||||
while (m > 0 && mIns[n - 1].IsSame(eblock->mIns[m - 1]))
|
||||
{
|
||||
n--;
|
||||
m--;
|
||||
}
|
||||
|
||||
if (m == 0)
|
||||
{
|
||||
mTrueJump->mNumEntries--;
|
||||
mTrueJump->mEntryBlocks.RemoveAll(this);
|
||||
mFalseJump->mNumEntries--;
|
||||
mFalseJump->mEntryBlocks.RemoveAll(this);
|
||||
mFalseJump = nullptr;
|
||||
mTrueJump = eblock;
|
||||
eblock->mNumEntries++;
|
||||
eblock->mEntryBlocks.Push(this);
|
||||
|
||||
mIns.SetSize(n);
|
||||
mBranch = ASMIT_JMP;
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->ShortcutBlockExit())
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->ShortcutBlockExit())
|
||||
changed = true;
|
||||
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::PropagateSinglePath(void)
|
||||
{
|
||||
bool changed = false;
|
||||
|
@ -41965,7 +42022,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
|||
{
|
||||
mInterProc = proc;
|
||||
|
||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "mat4_mmul");
|
||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "cursor_joy_exit");
|
||||
|
||||
int nblocks = proc->mBlocks.Size();
|
||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||
|
@ -42892,6 +42949,14 @@ void NativeCodeProcedure::Optimize(void)
|
|||
if (mEntryBlock->PropagateSinglePath())
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (step > 4)
|
||||
{
|
||||
ResetVisited();
|
||||
if (mEntryBlock->ShortcutBlockExit())
|
||||
changed = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if _DEBUG
|
||||
|
|
|
@ -515,6 +515,7 @@ public:
|
|||
bool IsExitXRegZP(int addr, int& index) const;
|
||||
bool IsExitARegZP(int addr, int& index) const;
|
||||
|
||||
bool ShortcutBlockExit(void);
|
||||
bool PropagateSinglePath(void);
|
||||
|
||||
bool CanChangeTailZPStoreToX(int addr, const NativeCodeBasicBlock * nblock, const NativeCodeBasicBlock* fblock = nullptr) const;
|
||||
|
|
Loading…
Reference in New Issue