Propagate independent instructions across diamond shaped basic blocks

This commit is contained in:
drmortalwombat 2022-06-04 20:56:28 +02:00
parent f9eb91e980
commit 36a5eaae00
5 changed files with 185 additions and 17 deletions

View File

@ -12,7 +12,7 @@ enum SIDFXState
static struct SIDFXChannel static struct SIDFXChannel
{ {
SIDFX * com; const SIDFX * com;
byte delay, cnt, priority; byte delay, cnt, priority;
volatile SIDFXState state; volatile SIDFXState state;
unsigned freq, pwm; unsigned freq, pwm;
@ -29,7 +29,7 @@ void sidfx_init(void)
} }
} }
void sidfx_play(byte chn, SIDFX * fx, byte cnt) void sidfx_play(byte chn, const SIDFX * fx, byte cnt)
{ {
SIDFXState ns = channels[chn].state; SIDFXState ns = channels[chn].state;

View File

@ -14,7 +14,7 @@ struct SIDFX
void sidfx_init(void); void sidfx_init(void);
inline void sidfx_play(byte chn, SIDFX * fx, byte cnt); inline void sidfx_play(byte chn, const SIDFX * fx, byte cnt);
void sidfx_stop(byte chn); void sidfx_stop(byte chn);

View File

@ -7817,6 +7817,34 @@ void InterCodeBasicBlock::MarkRelevantStatics(void)
} }
} }
bool InterCodeBasicBlock::CanMoveInstructionBehindBlock(int ii) const
{
InterInstruction* ins = mInstructions[ii];
if (ins->mCode == IC_LOAD)
{
for (int i = ii + 1; i < mInstructions.Size(); i++)
if (!CanBypassLoad(ins, mInstructions[i]))
return false;
}
else if (ins->mCode == IC_STORE)
{
return false;
}
else if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE || ins->mCode == IC_COPY || ins->mCode == IC_PUSH_FRAME || ins->mCode == IC_POP_FRAME ||
ins->mCode == IC_RETURN || ins->mCode == IC_RETURN_STRUCT || ins->mCode == IC_RETURN_VALUE)
return false;
else
{
for (int i = ii + 1; i < mInstructions.Size(); i++)
if (!CanBypass(ins, mInstructions[i]))
return false;
}
return true;
}
bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii) const bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii) const
{ {
InterInstruction* ins = mInstructions[ii]; InterInstruction* ins = mInstructions[ii];
@ -7923,10 +7951,51 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void)
{ {
mVisited = true; mVisited = true;
if (mTrueJump && mTrueJump == mFalseJump)
{
mFalseJump = nullptr;
mInstructions[mInstructions.Size() - 1]->mCode = IC_JUMP;
mInstructions[mInstructions.Size() - 1]->mNumOperands = 0;
mTrueJump->mNumEntries--;
changed = true;
}
if (mTrueJump && mFalseJump) if (mTrueJump && mFalseJump)
{ {
InterCodeBasicBlock* tblock = nullptr, * fblock = nullptr; InterCodeBasicBlock* tblock = nullptr, * fblock = nullptr;
if (mTrueJump != mFalseJump && mTrueJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump->mTrueJump && mTrueJump->mFalseJump == mFalseJump->mFalseJump)
{
if (mTrueJump->mInstructions.Size() == 1)
{
tblock = mTrueJump;
fblock = mFalseJump;
}
else if (mFalseJump->mInstructions.Size() == 1)
{
fblock = mTrueJump;
tblock = mFalseJump;
}
if (fblock && tblock)
{
if (tblock->mInstructions[0]->IsEqual(fblock->mInstructions.Last()) && !fblock->mLocalModifiedTemps[tblock->mInstructions[0]->mSrc[0].mTemp])
{
fblock->mTrueJump = tblock;
fblock->mFalseJump = nullptr;
fblock->mInstructions[fblock->mInstructions.Size() - 1]->mCode = IC_JUMP;
fblock->mInstructions[fblock->mInstructions.Size() - 1]->mNumOperands = 0;
tblock->mNumEntries++;
tblock->mFalseJump->mNumEntries--;
tblock->mTrueJump->mNumEntries--;
changed = true;
}
}
fblock = nullptr;
tblock = nullptr;
}
if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump) if (!mTrueJump->mFalseJump && mTrueJump->mTrueJump == mFalseJump)
{ {
tblock = mTrueJump; tblock = mTrueJump;
@ -7982,6 +8051,51 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void)
} }
} }
} }
#if 1
else if ((mins->mCode == IC_BINARY_OPERATOR || mins->mCode == IC_LEA) && (mins->mSrc[1].mTemp < 0 || mins->mSrc[0].mTemp < 0) || mins->mCode == IC_UNARY_OPERATOR || mins->mCode == IC_CONVERSION_OPERATOR)
{
int ttemp = mins->mDst.mTemp;
int stemp = ((mins->mCode == IC_BINARY_OPERATOR || mins->mCode == IC_LEA) && mins->mSrc[0].mTemp < 0) ? mins->mSrc[1].mTemp : mins->mSrc[0].mTemp;
if (!tblock->mLocalRequiredTemps[ttemp] && !tblock->mLocalModifiedTemps[stemp] && !tblock->mLocalModifiedTemps[ttemp] && !IsTempReferencedOnPath(ttemp, i + 1) && !IsTempModifiedOnPath(stemp, i + 1))
{
tblock->mEntryRequiredTemps += stemp;
tblock->mExitRequiredTemps += stemp;
fblock->mEntryRequiredTemps += stemp;
mExitRequiredTemps += stemp;
fblock->mInstructions.Insert(0, mins);
mInstructions.Remove(i);
changed = true;
}
}
#endif
else if (mins->mCode == IC_LOAD)
{
int ttemp = mins->mDst.mTemp;
int stemp = mins->mSrc[0].mTemp;
if (!tblock->mLocalRequiredTemps[ttemp] && (stemp < 0 || !tblock->mLocalModifiedTemps[stemp]) &&
!tblock->mLocalModifiedTemps[ttemp] && !IsTempReferencedOnPath(ttemp, i + 1) && (stemp < 0 || !IsTempModifiedOnPath(stemp, i + 1)) &&
CanMoveInstructionBehindBlock(i))
{
if (stemp >= 0)
{
tblock->mEntryRequiredTemps += stemp;
tblock->mExitRequiredTemps += stemp;
fblock->mEntryRequiredTemps += stemp;
mExitRequiredTemps += stemp;
}
fblock->mInstructions.Insert(0, mins);
mInstructions.Remove(i);
changed = true;
}
}
} }
} }
} }
@ -8008,6 +8122,24 @@ bool InterCodeBasicBlock::IsTempModifiedOnPath(int temp, int at) const
return false; return false;
} }
bool InterCodeBasicBlock::IsTempReferencedOnPath(int temp, int at) const
{
while (at < mInstructions.Size())
{
const InterInstruction * ins = mInstructions[at];
if (ins->mDst.mTemp == temp)
return true;
for (int i = 0; i < ins->mNumOperands; i++)
if (ins->mSrc[i].mTemp == temp)
return true;
at++;
}
return false;
}
bool InterCodeBasicBlock::PushSinglePathResultInstructions(void) bool InterCodeBasicBlock::PushSinglePathResultInstructions(void)
{ {
int i; int i;
@ -11246,6 +11378,11 @@ void InterCodeProcedure::Close(void)
ResetVisited(); ResetVisited();
mEntryBlock->DropUnreachable(); mEntryBlock->DropUnreachable();
BuildDataFlowSets();
ResetVisited();
mEntryBlock->CollectLocalUsedTemps(mTemporaries.Size());
ResetVisited(); ResetVisited();
mEntryBlock->ForwardDiamondMovedTemp(); mEntryBlock->ForwardDiamondMovedTemp();
DisassembleDebug("Diamond move forwarding"); DisassembleDebug("Diamond move forwarding");
@ -11351,6 +11488,20 @@ void InterCodeProcedure::Close(void)
} while (changed); } while (changed);
#endif #endif
#if 1
BuildDataFlowSets();
ResetVisited();
mEntryBlock->CollectLocalUsedTemps(mTemporaries.Size());
ResetVisited();
mEntryBlock->ForwardDiamondMovedTemp();
DisassembleDebug("Diamond move forwarding 2");
TempForwarding();
RemoveUnusedInstructions();
#endif
#if 1 #if 1
ResetVisited(); ResetVisited();

View File

@ -455,9 +455,11 @@ public:
void RemoveNonRelevantStatics(void); void RemoveNonRelevantStatics(void);
bool IsTempModifiedOnPath(int temp, int at) const; bool IsTempModifiedOnPath(int temp, int at) const;
bool IsTempReferencedOnPath(int temp, int at) const;
bool PushSinglePathResultInstructions(void); bool PushSinglePathResultInstructions(void);
bool CanMoveInstructionBeforeBlock(int ii) const; bool CanMoveInstructionBeforeBlock(int ii) const;
bool CanMoveInstructionBehindBlock(int ii) const;
bool MergeCommonPathInstructions(void); bool MergeCommonPathInstructions(void);
void PeepholeOptimization(const GrowingVariableArray& staticVars); void PeepholeOptimization(const GrowingVariableArray& staticVars);

View File

@ -13381,9 +13381,14 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
mTrueJump->mIns[0].SameEffectiveAddress(mFalseJump->mIns[0]) && mTrueJump->mIns[1].SameEffectiveAddress(mFalseJump->mIns[1]) && mTrueJump->mIns[0].SameEffectiveAddress(mFalseJump->mIns[0]) && mTrueJump->mIns[1].SameEffectiveAddress(mFalseJump->mIns[1]) &&
HasAsmInstructionMode(ASMIT_LDX, mTrueJump->mIns[0].mMode) && HasAsmInstructionMode(ASMIT_STX, mTrueJump->mIns[1].mMode)) HasAsmInstructionMode(ASMIT_LDX, mTrueJump->mIns[0].mMode) && HasAsmInstructionMode(ASMIT_STX, mTrueJump->mIns[1].mMode))
{ {
uint32 live = mIns[s - 1].mLive;
if (mIns[s - 1].RequiresYReg())
live |= LIVE_CPU_REG_Y;
mTrueJump->mIns[0].mType = ASMIT_LDX; mTrueJump->mIns[0].mType = ASMIT_LDX;
mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X; mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X | live;
mTrueJump->mIns[1].mType = ASMIT_STX; mTrueJump->mIns[1].mType = ASMIT_STX;
mTrueJump->mIns[1].mLive |= live;
mIns.Insert(s - 1, mTrueJump->mIns[0]); mIns.Insert(s - 1, mTrueJump->mIns[0]);
mIns.Insert(s, mTrueJump->mIns[1]); mIns.Insert(s, mTrueJump->mIns[1]);
@ -13391,6 +13396,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0);
mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0);
CheckLive();
changed = true; changed = true;
} }
} }
@ -13406,9 +13413,15 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
HasAsmInstructionMode(ASMIT_LDX, mTrueJump->mIns[0].mMode) && HasAsmInstructionMode(ASMIT_STX, mTrueJump->mIns[1].mMode) && HasAsmInstructionMode(ASMIT_LDX, mTrueJump->mIns[0].mMode) && HasAsmInstructionMode(ASMIT_STX, mTrueJump->mIns[1].mMode) &&
!mIns[s - 1].MayBeChangedOnAddress(mTrueJump->mIns[1])) !mIns[s - 1].MayBeChangedOnAddress(mTrueJump->mIns[1]))
{ {
uint32 live = mIns[s - 1].mLive;
if (mIns[s - 1].RequiresYReg())
live |= LIVE_CPU_REG_Y;
mTrueJump->mIns[0].mType = ASMIT_LDX; mTrueJump->mIns[0].mType = ASMIT_LDX;
mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X; mTrueJump->mIns[0].mLive |= LIVE_CPU_REG_X | live;
mTrueJump->mIns[1].mType = ASMIT_STX; mTrueJump->mIns[1].mType = ASMIT_STX;
mTrueJump->mIns[1].mLive |= live;
mIns.Insert(s - 1, mTrueJump->mIns[0]); mIns.Insert(s - 1, mTrueJump->mIns[0]);
mIns.Insert(s, mTrueJump->mIns[1]); mIns.Insert(s, mTrueJump->mIns[1]);
@ -13416,6 +13429,8 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0);
mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0); mFalseJump->mIns.Remove(0);
CheckLive();
changed = true; changed = true;
} }
} }
@ -22238,7 +22253,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
{ {
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_INY; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mType = ASMIT_INY; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Y;
if (mIns[i + 2].mAddress == 2) if (mIns[i + 2].mAddress == 2)
mIns[i + 3].mType = ASMIT_INY; mIns[i + 3].mType = ASMIT_INY;
else else
@ -22254,7 +22269,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
{ {
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_DEY; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mType = ASMIT_DEY; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Y;
if (mIns[i + 2].mAddress == 2) if (mIns[i + 2].mAddress == 2)
mIns[i + 3].mType = ASMIT_DEY; mIns[i + 3].mType = ASMIT_DEY;
else else
@ -22271,12 +22286,12 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C))) !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C)))
{ {
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_INX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_INX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X;
if (mIns[i + 2].mAddress == 2) if (mIns[i + 2].mAddress == 2)
mIns[i + 2].mType = ASMIT_INX; mIns[i + 2].mType = ASMIT_INX;
else else
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP;
mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_X;
mIns[i + 3].mType = ASMIT_STX; mIns[i + 3].mType = ASMIT_STX;
progress = true; progress = true;
} }
@ -22288,12 +22303,12 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C))) !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C)))
{ {
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X;
if (mIns[i + 2].mAddress == 2) if (mIns[i + 2].mAddress == 2)
mIns[i + 2].mType = ASMIT_DEX; mIns[i + 2].mType = ASMIT_DEX;
else else
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP;
mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_X;
mIns[i + 3].mType = ASMIT_STX; mIns[i + 3].mType = ASMIT_STX;
progress = true; progress = true;
} }
@ -22324,12 +22339,12 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_C))) !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_C)))
{ {
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_Y;
if (mIns[i + 2].mAddress == 2) if (mIns[i + 2].mAddress == 2)
mIns[i + 2].mType = ASMIT_DEY; mIns[i + 2].mType = ASMIT_DEY;
else else
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP;
mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mLive |= LIVE_CPU_REG_Y;
mIns[i + 3].mType = ASMIT_STY; mIns[i + 3].mType = ASMIT_STY;
progress = true; progress = true;
} }
@ -22342,7 +22357,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_C))) !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_C)))
{ {
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_DEY; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_Y;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
mIns[i + 3].mType = ASMIT_STY; mIns[i + 3].mType = ASMIT_STY;
progress = true; progress = true;
@ -22355,7 +22370,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C))) !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_X | LIVE_CPU_REG_C)))
{ {
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_DEX; mIns[i + 1].mMode = ASMIM_IMPLIED; mIns[i + 1].mLive |= LIVE_CPU_REG_X;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
mIns[i + 3].mType = ASMIT_STX; mIns[i + 3].mType = ASMIT_STX;
progress = true; progress = true;