Optimize cross block constant propagation

This commit is contained in:
drmortalwombat 2023-10-18 15:57:59 +02:00
parent 9e3b014927
commit 0f5e933002
5 changed files with 256 additions and 7 deletions

View File

@ -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();

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;