Propagate sign and zero information cross branches
This commit is contained in:
parent
612e88456c
commit
f0c36c6400
|
@ -6022,7 +6022,9 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
|
||||||
if (s0 < 0)
|
if (s0 < 0)
|
||||||
{
|
{
|
||||||
mTrueValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
|
mTrueValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
|
||||||
|
mTrueValueRange[s1].LimitMaxWeak(SignedTypeMax(mInstructions[sz - 2]->mSrc[1].mType));
|
||||||
mFalseValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
|
mFalseValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
|
||||||
|
mFalseValueRange[s1].LimitMinWeak(SignedTypeMin(mInstructions[sz - 2]->mSrc[1].mType));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IA_CMPGES:
|
case IA_CMPGES:
|
||||||
|
|
|
@ -2083,7 +2083,36 @@ bool NativeCodeInstruction::BitFieldForwarding(NativeRegisterDataSet& data, AsmI
|
||||||
switch (mType)
|
switch (mType)
|
||||||
{
|
{
|
||||||
case ASMIT_JSR:
|
case ASMIT_JSR:
|
||||||
data.ResetMask();
|
data.mRegs[CPU_REG_C].ResetMask();
|
||||||
|
data.mRegs[CPU_REG_Z].ResetMask();
|
||||||
|
data.mRegs[CPU_REG_A].ResetMask();
|
||||||
|
data.mRegs[CPU_REG_X].ResetMask();
|
||||||
|
data.mRegs[CPU_REG_Y].ResetMask();
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
data.mRegs[BC_REG_ACCU + i].ResetMask();
|
||||||
|
data.mRegs[BC_REG_WORK + i].ResetMask();
|
||||||
|
data.mRegs[BC_REG_ADDR + i].ResetMask();
|
||||||
|
}
|
||||||
|
data.mRegs[BC_REG_WORK_Y].ResetMask();
|
||||||
|
|
||||||
|
if (!(mFlags & NCIF_RUNTIME) || (mFlags & NCIF_FEXEC))
|
||||||
|
{
|
||||||
|
if (mLinkerObject && mLinkerObject->mProc)
|
||||||
|
{
|
||||||
|
for (int i = BC_REG_TMP; i < BC_REG_TMP + mLinkerObject->mProc->mCallerSavedTemps; i++)
|
||||||
|
data.mRegs[i].ResetMask();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = BC_REG_TMP; i < BC_REG_TMP_SAVED; i++)
|
||||||
|
data.mRegs[i].ResetMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = BC_REG_FPARAMS; i < BC_REG_FPARAMS_END; i++)
|
||||||
|
data.mRegs[i].ResetMask();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ASMIT_CLC:
|
case ASMIT_CLC:
|
||||||
data.mRegs[CPU_REG_C].mMask = 1;
|
data.mRegs[CPU_REG_C].mMask = 1;
|
||||||
|
@ -19082,6 +19111,8 @@ bool NativeCodeBasicBlock::MoveCLCLoadAddZPStoreDown(int at)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static bool PeepCheck = false;
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::BitFieldForwarding(const NativeRegisterDataSet& data)
|
bool NativeCodeBasicBlock::BitFieldForwarding(const NativeRegisterDataSet& data)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
@ -19121,12 +19152,132 @@ bool NativeCodeBasicBlock::BitFieldForwarding(const NativeRegisterDataSet& data)
|
||||||
if (carryop != ASMIT_NOP)
|
if (carryop != ASMIT_NOP)
|
||||||
mIns.Insert(i + 1, NativeCodeInstruction(carryop));
|
mIns.Insert(i + 1, NativeCodeInstruction(carryop));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (mFalseJump)
|
if (mFalseJump)
|
||||||
{
|
{
|
||||||
mFDataSet = mNDataSet;
|
mFDataSet = mNDataSet;
|
||||||
|
|
||||||
|
if (mIns.Size() > 0)
|
||||||
|
{
|
||||||
|
const NativeCodeInstruction& lins(mIns[mIns.Size() - 1]);
|
||||||
|
|
||||||
|
if (lins.mMode == ASMIM_ZERO_PAGE && lins.mType == ASMIT_LDA)
|
||||||
|
{
|
||||||
|
switch (mBranch)
|
||||||
|
{
|
||||||
|
case ASMIT_BEQ:
|
||||||
|
if (mNDataSet.mRegs[lins.mAddress].mMask == 0xff)
|
||||||
|
{
|
||||||
|
if (mNDataSet.mRegs[lins.mAddress].mValue != 0)
|
||||||
|
{
|
||||||
|
mTrueJump->RemoveEntryBlock(this);
|
||||||
|
mTrueJump = mFalseJump;
|
||||||
|
mFalseJump = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mFalseJump->RemoveEntryBlock(this);
|
||||||
|
mFalseJump = nullptr;
|
||||||
|
}
|
||||||
|
mBranch = ASMIT_JMP;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mNDataSet.mRegs[CPU_REG_A].mMask = 0xff;
|
||||||
|
mNDataSet.mRegs[CPU_REG_A].mValue = 0x00;
|
||||||
|
mNDataSet.mRegs[lins.mAddress].mMask = 0xff;
|
||||||
|
mNDataSet.mRegs[lins.mAddress].mValue = 0x00;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ASMIT_BNE:
|
||||||
|
if (mNDataSet.mRegs[lins.mAddress].mMask == 0xff)
|
||||||
|
{
|
||||||
|
if (mNDataSet.mRegs[lins.mAddress].mValue == 0)
|
||||||
|
{
|
||||||
|
mTrueJump->RemoveEntryBlock(this);
|
||||||
|
mTrueJump = mFalseJump;
|
||||||
|
mFalseJump = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mFalseJump->RemoveEntryBlock(this);
|
||||||
|
mFalseJump = nullptr;
|
||||||
|
}
|
||||||
|
mBranch = ASMIT_JMP;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mFDataSet.mRegs[CPU_REG_A].mMask = 0xff;
|
||||||
|
mFDataSet.mRegs[CPU_REG_A].mValue = 0x00;
|
||||||
|
mFDataSet.mRegs[lins.mAddress].mMask = 0xff;
|
||||||
|
mFDataSet.mRegs[lins.mAddress].mValue = 0x00;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ASMIT_BPL:
|
||||||
|
if (mNDataSet.mRegs[lins.mAddress].mMask & 0x80)
|
||||||
|
{
|
||||||
|
if (mNDataSet.mRegs[lins.mAddress].mValue & 0x80)
|
||||||
|
{
|
||||||
|
mTrueJump->RemoveEntryBlock(this);
|
||||||
|
mTrueJump = mFalseJump;
|
||||||
|
mFalseJump = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mFalseJump->RemoveEntryBlock(this);
|
||||||
|
mFalseJump = nullptr;
|
||||||
|
}
|
||||||
|
mBranch = ASMIT_JMP;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mNDataSet.mRegs[CPU_REG_A].mMask |= 0x80;
|
||||||
|
mNDataSet.mRegs[CPU_REG_A].mValue &= 0x7f;
|
||||||
|
mFDataSet.mRegs[CPU_REG_A].mMask |= 0x80;
|
||||||
|
mFDataSet.mRegs[CPU_REG_A].mValue |= 0x80;
|
||||||
|
|
||||||
|
mNDataSet.mRegs[lins.mAddress].mMask |= 0x80;
|
||||||
|
mNDataSet.mRegs[lins.mAddress].mValue &= 0x7f;
|
||||||
|
mFDataSet.mRegs[lins.mAddress].mMask |= 0x80;
|
||||||
|
mFDataSet.mRegs[lins.mAddress].mValue |= 0x80;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ASMIT_BMI:
|
||||||
|
if (mNDataSet.mRegs[lins.mAddress].mMask & 0x80)
|
||||||
|
{
|
||||||
|
if (!(mNDataSet.mRegs[lins.mAddress].mValue & 0x80))
|
||||||
|
{
|
||||||
|
mTrueJump->RemoveEntryBlock(this);
|
||||||
|
mTrueJump = mFalseJump;
|
||||||
|
mFalseJump = nullptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mFalseJump->RemoveEntryBlock(this);
|
||||||
|
mFalseJump = nullptr;
|
||||||
|
}
|
||||||
|
mBranch = ASMIT_JMP;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mFDataSet.mRegs[CPU_REG_A].mMask |= 0x80;
|
||||||
|
mFDataSet.mRegs[CPU_REG_A].mValue &= 0x7f;
|
||||||
|
mNDataSet.mRegs[CPU_REG_A].mMask |= 0x80;
|
||||||
|
mNDataSet.mRegs[CPU_REG_A].mValue |= 0x80;
|
||||||
|
|
||||||
|
mFDataSet.mRegs[lins.mAddress].mMask |= 0x80;
|
||||||
|
mFDataSet.mRegs[lins.mAddress].mValue &= 0x7f;
|
||||||
|
mNDataSet.mRegs[lins.mAddress].mMask |= 0x80;
|
||||||
|
mNDataSet.mRegs[lins.mAddress].mValue |= 0x80;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(mIndex == 1000 || mNumEntries == mEntryBlocks.Size());
|
assert(mIndex == 1000 || mNumEntries == mEntryBlocks.Size());
|
||||||
|
@ -23731,6 +23882,42 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
|
|
||||||
CheckLive();
|
CheckLive();
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
for (int i = 0; i + 4 < mIns.Size(); i++)
|
||||||
|
{
|
||||||
|
if (mIns[i + 0].mType == ASMIT_LSR && mIns[i + 0].mMode == ASMIM_IMPLIED &&
|
||||||
|
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress != mIns[i + 2].mAddress &&
|
||||||
|
mIns[i + 3].mType == ASMIT_ROR && mIns[i + 3].mMode == ASMIM_IMPLIED)
|
||||||
|
{
|
||||||
|
int j = 2;
|
||||||
|
while (i + 3 + j < mIns.Size() &&
|
||||||
|
mIns[i + 2 + j].mType == ASMIT_LSR && mIns[i + 2 + j].mMode == ASMIM_ZERO_PAGE && mIns[i + 2 + j].mAddress == mIns[i + 1].mAddress &&
|
||||||
|
mIns[i + 3 + j].mType == ASMIT_ROR && mIns[i + 3 + j].mMode == ASMIM_IMPLIED)
|
||||||
|
{
|
||||||
|
j += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 2 + j < mIns.Size() && mIns[i + 2 + j].mType == ASMIT_STA && mIns[i + 2 + j].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[i + 2 + j].mAddress == mIns[i + 2].mAddress && !(mIns[i + 2 + j].mLive & LIVE_CPU_REG_A))
|
||||||
|
{
|
||||||
|
int addrl = mIns[i + 2].mAddress, addrh = mIns[i + 1].mAddress;
|
||||||
|
for (int k = 0; k < j; k += 2)
|
||||||
|
{
|
||||||
|
mIns[i + k + 0] = NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED);
|
||||||
|
mIns[i + k + 1] = NativeCodeInstruction(ASMIT_ROR, ASMIM_ZERO_PAGE, addrl);
|
||||||
|
}
|
||||||
|
mIns[i + j] = NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, addrh);
|
||||||
|
mIns[i + j + 1].mType = ASMIT_NOP; mIns[i + j + 1].mMode = ASMIM_IMPLIED;
|
||||||
|
mIns[i + j + 2].mType = ASMIT_NOP; mIns[i + j + 2].mMode = ASMIM_IMPLIED;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckLive();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
bool progress = false;
|
bool progress = false;
|
||||||
do {
|
do {
|
||||||
|
@ -28061,6 +28248,13 @@ void NativeCodeBasicBlock::Close(NativeCodeBasicBlock* trueJump, NativeCodeBasic
|
||||||
this->mBranch = branch;
|
this->mBranch = branch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeCodeBasicBlock::RemoveEntryBlock(NativeCodeBasicBlock* block)
|
||||||
|
{
|
||||||
|
int i = mEntryBlocks.IndexOf(block);
|
||||||
|
assert(i >= 0);
|
||||||
|
mEntryBlocks.Remove(i);
|
||||||
|
mNumEntries--;
|
||||||
|
}
|
||||||
|
|
||||||
NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void)
|
NativeCodeBasicBlock* NativeCodeBasicBlock::BypassEmptyBlocks(void)
|
||||||
{
|
{
|
||||||
|
@ -28983,7 +29177,7 @@ void NativeCodeProcedure::RebuildEntry(void)
|
||||||
|
|
||||||
void NativeCodeProcedure::Optimize(void)
|
void NativeCodeProcedure::Optimize(void)
|
||||||
{
|
{
|
||||||
//PeepChecker = !strcmp(mInterProc->mIdent->mString, "ghostUnit");
|
// PeepCheck = !strcmp(mInterProc->mIdent->mString, "main");
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
int step = 0;
|
int step = 0;
|
||||||
|
@ -29030,6 +29224,13 @@ void NativeCodeProcedure::Optimize(void)
|
||||||
do {
|
do {
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
bchanged = mEntryBlock->BitFieldForwarding(data);
|
bchanged = mEntryBlock->BitFieldForwarding(data);
|
||||||
|
|
||||||
|
if (!bchanged)
|
||||||
|
{
|
||||||
|
ResetPatched();
|
||||||
|
mEntryBlock->CheckVisited();
|
||||||
|
}
|
||||||
|
|
||||||
} while (bchanged);
|
} while (bchanged);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -179,6 +179,7 @@ public:
|
||||||
int BranchByteSize(int from, int to);
|
int BranchByteSize(int from, int to);
|
||||||
|
|
||||||
NativeCodeBasicBlock* BypassEmptyBlocks(void);
|
NativeCodeBasicBlock* BypassEmptyBlocks(void);
|
||||||
|
void RemoveEntryBlock(NativeCodeBasicBlock* block);
|
||||||
|
|
||||||
int LeadsInto(NativeCodeBasicBlock* block, int dist);
|
int LeadsInto(NativeCodeBasicBlock* block, int dist);
|
||||||
void BuildPlacement(GrowingArray<NativeCodeBasicBlock*>& placement);
|
void BuildPlacement(GrowingArray<NativeCodeBasicBlock*>& placement);
|
||||||
|
|
Loading…
Reference in New Issue