Eliminate duplicate loop counting variables

This commit is contained in:
drmortalwombat 2024-07-05 10:12:55 +02:00
parent c0e524cd82
commit 301431f12a
4 changed files with 402 additions and 30 deletions

View File

@ -15106,6 +15106,189 @@ void InterCodeBasicBlock::ConstLoopOptimization(void)
} }
} }
void InterCodeBasicBlock::EliminateDoubleLoopCounter(void)
{
if (!mVisited)
{
mVisited = true;
if (mLoopHead && mEntryBlocks.Size() == 2 && mLoopPrefix->mEntryBlocks.Size() == 1)
{
ExpandingArray<InterCodeBasicBlock*> body, path;
body.Push(this);
bool innerLoop = true;
for (int i = 0; i < mEntryBlocks.Size(); i++)
{
if (mEntryBlocks[i] != mLoopPrefix)
{
if (!mEntryBlocks[i]->CollectLoopBody(this, body))
innerLoop = false;
}
}
if (innerLoop)
{
InterCodeBasicBlock* eblock;
if (mEntryBlocks[0] == mLoopPrefix)
eblock = mEntryBlocks[1];
else
eblock = mEntryBlocks[0];
struct LoopCounter
{
InterInstruction * mInit, * mInc, * mCmp;
int64 mStart, mEnd, mStep;
bool mReferenced;
};
ExpandingArray<LoopCounter> lcs;
for (int i = 0; i < eblock->mInstructions.Size(); i++)
{
InterInstruction* ins(eblock->mInstructions[i]);
LoopCounter lc;
lc.mInc = nullptr;
lc.mInit = nullptr;
lc.mCmp = nullptr;
lc.mReferenced = false;
if (ins->mCode == IC_BINARY_OPERATOR && ins->mOperator == IA_ADD)
{
if (ins->mDst.mTemp == ins->mSrc[0].mTemp && ins->mSrc[1].mTemp < 0 ||
ins->mDst.mTemp == ins->mSrc[1].mTemp && ins->mSrc[0].mTemp < 0)
{
lc.mInc = ins;
}
}
else if (ins->mCode == IC_LEA && ins->mDst.mTemp == ins->mSrc[1].mTemp && ins->mSrc[0].mTemp < 0)
{
lc.mInc = ins;
}
if (lc.mInc)
{
int temp = lc.mInc->mDst.mTemp;
if (!eblock->IsTempModifiedInRange(0, i, temp))
{
int sz = eblock->mInstructions.Size();
int rz = sz - 1;
if (eblock->mInstructions[sz - 1]->mCode == IC_BRANCH &&
eblock->mInstructions[sz - 2]->mCode == IC_RELATIONAL_OPERATOR && eblock->mInstructions[sz - 1]->mSrc[0].mTemp == eblock->mInstructions[sz - 2]->mDst.mTemp &&
((eblock->mInstructions[sz - 2]->mSrc[0].mTemp == temp && eblock->mInstructions[sz - 2]->mSrc[1].mTemp < 0) ||
(eblock->mInstructions[sz - 2]->mSrc[1].mTemp == temp && eblock->mInstructions[sz - 2]->mSrc[0].mTemp < 0)))
{
InterInstruction* ci = eblock->mInstructions[sz - 2];
if (ci->mOperator == IA_CMPEQ && eblock->mFalseJump == this ||
ci->mOperator == IA_CMPNE && eblock->mTrueJump == this)
{
if (ci->mSrc[0].mTemp < 0)
lc.mEnd = ci->mSrc[0].mIntConst;
else
lc.mEnd = ci->mSrc[1].mIntConst;
lc.mCmp = eblock->mInstructions[sz - 2];
rz--;
}
}
if (!eblock->IsTempModifiedInRange(i + 1, sz, temp))
{
if (eblock->IsTempReferencedInRange(0, i, temp) || eblock->IsTempReferencedInRange(i + 1, rz, temp))
lc.mReferenced = true;
for (int k = 0; k < body.Size(); k++)
{
if (body[k] != eblock && body[k]->IsTempReferenced(temp))
lc.mReferenced = true;
}
int k = 0;
while (k < body.Size() && (body[k] == eblock || !body[k]->IsTempModified(lc.mInc->mDst.mTemp)))
k++;
if (k == body.Size())
{
lc.mInit = mLoopPrefix->mEntryBlocks[0]->FindTempOrigin(lc.mInc->mDst.mTemp);
if (lc.mInit && lc.mInit->mCode == IC_CONSTANT)
{
lc.mStart = lc.mInit->mConst.mIntConst;
if (lc.mInc->mSrc[0].mTemp < 0)
lc.mStep = lc.mInc->mSrc[0].mIntConst;
else
lc.mStep = lc.mInc->mSrc[1].mIntConst;
lcs.Push(lc);
}
}
}
}
}
}
if (lcs.Size() >= 2)
{
int loop = -1;
int k = 0;
while (k < lcs.Size() && !lcs[k].mCmp)
k++;
if (k < lcs.Size())
{
int64 start = lcs[k].mStart;
int64 end = lcs[k].mEnd;
int64 step = lcs[k].mStep;
if (step > 0 && end > start || step < 0 && end < start)
loop = (end - start) / step;
}
if (loop > 0)
{
if (!lcs[k].mReferenced)
{
int j = 0;
while (j < lcs.Size() && !(lcs[j].mReferenced && lcs[j].mInc->mCode == IC_BINARY_OPERATOR && lcs[j].mStart + lcs[j].mStep * loop < 65536))
j++;
// Pointer compare with constants only in native code path
if (j == lcs.Size() && mProc->mNativeProcedure)
{
j = 0;
while (j < lcs.Size() && !(lcs[j].mReferenced && lcs[j].mInc->mCode == IC_LEA && (lcs[j].mInit->mConst.mMemory == IM_GLOBAL || lcs[j].mInit->mConst.mMemory == IM_ABSOLUTE) &&
lcs[j].mStart + lcs[j].mStep * loop < 65536))
j++;
}
if (j < lcs.Size())
{
int ci = 0, ti = 1;
if (lcs[k].mCmp->mSrc[1].mTemp < 0)
{
ci = 1;
ti = 0;
}
lcs[k].mCmp->mSrc[ti] = lcs[j].mInc->mDst;
lcs[k].mCmp->mSrc[ci] = lcs[j].mInit->mConst;
lcs[k].mCmp->mSrc[ci].mIntConst += loop * lcs[j].mStep;
lcs[k].mInc->mCode = IC_NONE;
lcs[k].mInc->mNumOperands = 0;
lcs[k].mInit->mConst.mIntConst += loop * lcs[k].mStep;
}
}
}
}
}
}
if (mTrueJump)
mTrueJump->EliminateDoubleLoopCounter();
if (mFalseJump)
mFalseJump->EliminateDoubleLoopCounter();
}
}
void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams) void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams)
{ {
if (!mVisited) if (!mVisited)
@ -20635,6 +20818,18 @@ void InterCodeProcedure::MoveConditionsOutOfLoop(void)
} }
} }
void InterCodeProcedure::EliminateDoubleLoopCounter(void)
{
BuildTraces(false);
BuildLoopPrefix();
ResetEntryBlocks();
ResetVisited();
mEntryBlock->CollectEntryBlocks(nullptr);
ResetVisited();
mEntryBlock->EliminateDoubleLoopCounter();
}
void InterCodeProcedure::PropagateMemoryAliasingInfo(void) void InterCodeProcedure::PropagateMemoryAliasingInfo(void)
{ {
@ -22171,6 +22366,8 @@ void InterCodeProcedure::Close(void)
BuildDataFlowSets(); BuildDataFlowSets();
TempForwarding(false, true); TempForwarding(false, true);
EliminateDoubleLoopCounter();
ResetVisited(); ResetVisited();
mEntryBlock->SingleLoopCountZeroCheck(); mEntryBlock->SingleLoopCountZeroCheck();

View File

@ -594,6 +594,7 @@ public:
void CollectLoopPath(const ExpandingArray<InterCodeBasicBlock*>& body, ExpandingArray<InterCodeBasicBlock*>& path); void CollectLoopPath(const ExpandingArray<InterCodeBasicBlock*>& body, ExpandingArray<InterCodeBasicBlock*>& path);
void InnerLoopOptimization(const NumberSet& aliasedParams); void InnerLoopOptimization(const NumberSet& aliasedParams);
void ConstLoopOptimization(void); void ConstLoopOptimization(void);
void EliminateDoubleLoopCounter(void);
void PushMoveOutOfLoop(void); void PushMoveOutOfLoop(void);
bool MoveConditionOutOfLoop(void); bool MoveConditionOutOfLoop(void);
void SingleLoopCountZeroCheck(void); void SingleLoopCountZeroCheck(void);
@ -755,6 +756,7 @@ protected:
void PropagateMemoryAliasingInfo(void); void PropagateMemoryAliasingInfo(void);
void MoveConditionsOutOfLoop(void); void MoveConditionsOutOfLoop(void);
void ShortcutConstBranches(void); void ShortcutConstBranches(void);
void EliminateDoubleLoopCounter(void);
void CollapseDispatch(void); void CollapseDispatch(void);

View File

@ -5212,12 +5212,13 @@ int NativeCodeBasicBlock::PutBranch(NativeCodeProcedure* proc, NativeCodeBasicBl
} }
} }
void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const InterInstruction * ins, InterType type, int reg) void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure* proc, const InterInstruction* ins, const InterOperand& op, InterType type, int reg)
{ {
if (type == IT_FLOAT) if (type == IT_FLOAT)
{ {
union { float f; unsigned int v; } cc; union { float f; unsigned int v; } cc;
cc.f = float(ins->mConst.mFloatConst); cc.f = float(op.mFloatConst);
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, cc.v & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
@ -5230,33 +5231,33 @@ void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const In
} }
else if (type == IT_POINTER) else if (type == IT_POINTER)
{ {
if (ins->mConst.mMemory == IM_GLOBAL) if (op.mMemory == IM_GLOBAL)
{ {
if (ins->mConst.mIntConst < 0 || ins->mConst.mIntConst > ins->mConst.mLinkerObject->mSize) if (op.mIntConst < 0 || op.mIntConst > op.mLinkerObject->mSize)
proc->mModule->mErrors->Error(ins->mLocation, EWARN_UNDEFINED_POINTER_ARITHMETIC, "Undefined constant pointer arithmetic"); proc->mModule->mErrors->Error(ins->mLocation, EWARN_UNDEFINED_POINTER_ARITHMETIC, "Undefined constant pointer arithmetic");
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mConst.mIntConst, ins->mConst.mLinkerObject, NCIF_LOWER)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, op.mIntConst, op.mLinkerObject, NCIF_LOWER));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mConst.mIntConst, ins->mConst.mLinkerObject, NCIF_UPPER)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, op.mIntConst, op.mLinkerObject, NCIF_UPPER));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
} }
else if (ins->mConst.mMemory == IM_ABSOLUTE) else if (op.mMemory == IM_ABSOLUTE)
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mConst.mIntConst & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, op.mIntConst & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
} }
else if (ins->mConst.mMemory == IM_FPARAM || ins->mConst.mMemory == IM_FFRAME) else if (op.mMemory == IM_FPARAM || op.mMemory == IM_FFRAME)
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, BC_REG_FPARAMS + ins->mConst.mVarIndex + ins->mConst.mIntConst)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, BC_REG_FPARAMS + op.mVarIndex + op.mIntConst));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
} }
else if (ins->mConst.mMemory == IM_FRAME) else if (op.mMemory == IM_FRAME)
{ {
int index = ins->mConst.mVarIndex + int(ins->mConst.mIntConst) + 2; int index = op.mVarIndex + int(op.mIntConst) + 2;
mIns.Push(NativeCodeInstruction(ins, ASMIT_CLC, ASMIM_IMPLIED)); mIns.Push(NativeCodeInstruction(ins, ASMIT_CLC, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_STACK));
@ -5266,14 +5267,14 @@ void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const In
mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
} }
else if (ins->mConst.mMemory == IM_LOCAL || ins->mConst.mMemory == IM_PARAM) else if (op.mMemory == IM_LOCAL || op.mMemory == IM_PARAM)
{ {
int index = int(ins->mConst.mIntConst); int index = int(op.mIntConst);
int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS; int areg = mNoFrame ? BC_REG_STACK : BC_REG_LOCALS;
if (ins->mConst.mMemory == IM_LOCAL) if (op.mMemory == IM_LOCAL)
index += proc->mLocalVars[ins->mConst.mVarIndex]->mOffset; index += proc->mLocalVars[op.mVarIndex]->mOffset;
else else
index += ins->mConst.mVarIndex + proc->mLocalSize + 2; index += op.mVarIndex + proc->mLocalSize + 2;
index += mFrameOffset; index += mFrameOffset;
CheckFrameIndex(ins, areg, index, 2); CheckFrameIndex(ins, areg, index, 2);
@ -5288,10 +5289,10 @@ void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const In
mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_ADC, ASMIM_IMMEDIATE, (index >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
} }
else if (ins->mConst.mMemory == IM_PROCEDURE) else if (op.mMemory == IM_PROCEDURE)
{ {
NativeCodeInstruction lins(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mConst.mLinkerObject, NCIF_LOWER); NativeCodeInstruction lins(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, op.mIntConst, op.mLinkerObject, NCIF_LOWER);
NativeCodeInstruction hins(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, ins->mSrc[0].mIntConst, ins->mConst.mLinkerObject, NCIF_UPPER); NativeCodeInstruction hins(ins, ASMIT_LDA, ASMIM_IMMEDIATE_ADDRESS, op.mIntConst, op.mLinkerObject, NCIF_UPPER);
mIns.Push(lins); mIns.Push(lins);
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
@ -5301,26 +5302,30 @@ void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const In
} }
else if (type == IT_INT32) else if (type == IT_INT32)
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mConst.mIntConst & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, op.mIntConst & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 16) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 16) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 2));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 24) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 24) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 3));
} }
else else
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, ins->mConst.mIntConst & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, op.mIntConst & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
if (InterTypeSize[ins->mDst.mType] > 1) if (InterTypeSize[type] > 1)
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (ins->mConst.mIntConst >> 8) & 0xff)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, (op.mIntConst >> 8) & 0xff));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
} }
} }
}
void NativeCodeBasicBlock::LoadConstantToReg(InterCodeProcedure * proc, const InterInstruction * ins, InterType type, int reg)
{
LoadConstantToReg(proc, ins, ins->mConst, type, reg);
} }
void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins) void NativeCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins)
@ -12319,6 +12324,86 @@ void NativeCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const In
break; break;
} }
} }
else if (ins->mSrc[0].mType == IT_POINTER)
{
int li = 1, ri = 0;
if (op == IA_CMPLEU || op == IA_CMPGU || op == IA_CMPLES || op == IA_CMPGS)
{
li = 0; ri = 1;
}
int lreg = ins->mSrc[li].mTemp, rreg = ins->mSrc[ri].mTemp;
if (lreg < 0)
{
lreg = BC_REG_ACCU;
LoadConstantToReg(proc, ins, ins->mSrc[li], IT_POINTER, lreg);
}
else
lreg = BC_REG_TMP + proc->mTempOffset[lreg];
if (rreg < 0)
{
rreg = BC_REG_ACCU;
LoadConstantToReg(proc, ins, ins->mSrc[ri], IT_POINTER, rreg);
}
else
rreg = BC_REG_TMP + proc->mTempOffset[rreg];
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
NativeCodeBasicBlock* nblock = nproc->AllocateBlock();
if (op == IA_CMPEQ || op == IA_CMPNE)
{
// Lower byte compare more likely to miss on not equal with first
// compare
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, lreg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_CMP, ASMIM_ZERO_PAGE, rreg));
Close(ins, nblock, eblock, ASMIT_BNE);
eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, lreg + 1));
eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_CMP, ASMIM_ZERO_PAGE, rreg + 1));
}
else
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, lreg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_CMP, ASMIM_ZERO_PAGE, rreg + 1));
Close(ins, nblock, eblock, ASMIT_BNE);
eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, lreg));
eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_CMP, ASMIM_ZERO_PAGE, rreg));
}
switch (op)
{
case IA_CMPEQ:
nblock->Close(ins, falseJump, nullptr, ASMIT_JMP);
eblock->Close(ins, trueJump, falseJump, ASMIT_BEQ);
break;
case IA_CMPNE:
nblock->Close(ins, trueJump, nullptr, ASMIT_JMP);
eblock->Close(ins, falseJump, trueJump, ASMIT_BEQ);
break;
case IA_CMPLU:
case IA_CMPLS:
case IA_CMPGU:
case IA_CMPGS:
eblock->Close(ins, nblock, nullptr, ASMIT_JMP);
nblock->Close(ins, trueJump, falseJump, ASMIT_BCC);
break;
case IA_CMPLEU:
case IA_CMPLES:
case IA_CMPGEU:
case IA_CMPGES:
eblock->Close(ins, nblock, nullptr, ASMIT_JMP);
nblock->Close(ins, falseJump, trueJump, ASMIT_BCC);
break;
}
}
else if (ins->mSrc[0].mType == IT_INT32) else if (ins->mSrc[0].mType == IT_INT32)
{ {
int li = 1, ri = 0; int li = 1, ri = 0;
@ -36722,6 +36807,93 @@ bool NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc
CheckLive(); CheckLive();
#if 1
// Exchange Y against low byte of pointer
if (!ChangesYReg() && !mEntryRequiredRegs[CPU_REG_A] && !mExitRequiredRegs[CPU_REG_A])
{
int rind = -1;
for (int i = 0; i < mIns.Size(); i++)
{
if (mIns[i].mMode == ASMIM_INDIRECT_Y)
{
if (rind == -1)
rind = mIns[i].mAddress;
else if (rind != mIns[i].mAddress)
{
rind = -2;
break;
}
}
else if (mIns[i].ReferencesYReg())
{
rind = -2;
break;
}
}
if (rind >= 0)
{
for (int i = 0; i < mIns.Size(); i++)
{
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == rind)
{
if (mIns[i].mType == ASMIT_LDA || mIns[i].mType == ASMIT_STA)
;
else
{
rind = -2;
break;
}
}
else if (mIns[i].mMode == ASMIM_INDIRECT_Y)
;
else if (mIns[i].ReferencesZeroPage(rind))
{
rind = -2;
break;
}
}
if (rind >= 0)
{
if (!prevBlock)
return OptimizeSimpleLoopInvariant(proc, full);
prevBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_LDA, ASMIM_ZERO_PAGE, rind));
prevBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, rind));
prevBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_TAY));
exitBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_LDA, ASMIM_ZERO_PAGE, rind));
exitBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, rind));
exitBlock->mIns.Push(NativeCodeInstruction(mBranchIns, ASMIT_TAY));
for (int i = 0; i < mIns.Size(); i++)
{
mIns[i].mLive |= LIVE_CPU_REG_Y;
if (mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == rind)
{
if (mIns[i].mType == ASMIT_LDA)
{
mIns[i].mType = ASMIT_TYA;
mIns[i].mMode = ASMIM_IMPLIED;
}
else if (mIns[i].mType == ASMIT_STA)
{
mIns[i].mType = ASMIT_TAY;
mIns[i].mMode = ASMIM_IMPLIED;
}
}
}
prevBlock->mExitRequiredRegs += CPU_REG_Y;
mEntryRequiredRegs += CPU_REG_Y;
mExitRequiredRegs += CPU_REG_Y;
exitBlock->mEntryRequiredRegs += CPU_REG_Y;
changed = true;
}
}
}
#endif
return changed; return changed;
} }
@ -49225,7 +49397,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mInterProc = proc; mInterProc = proc;
mInterProc->mLinkerObject->mNativeProc = this; mInterProc->mLinkerObject->mNativeProc = this;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "enemies_check"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "main");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];

View File

@ -351,7 +351,8 @@ public:
void CheckFrameIndex(const InterInstruction * ins, int & reg, int & index, int size, int treg = 0); void CheckFrameIndex(const InterInstruction * ins, int & reg, int & index, int size, int treg = 0);
void LoadValueToReg(InterCodeProcedure* proc, const InterInstruction * ins, int reg, const NativeCodeInstruction * ainsl, const NativeCodeInstruction* ainsh); void LoadValueToReg(InterCodeProcedure* proc, const InterInstruction * ins, int reg, const NativeCodeInstruction * ainsl, const NativeCodeInstruction* ainsh);
void LoadConstantToReg(InterCodeProcedure* proc, const InterInstruction * ins, InterType type, int reg); void LoadConstantToReg(InterCodeProcedure* proc, const InterInstruction* ins, InterType type, int reg);
void LoadConstantToReg(InterCodeProcedure* proc, const InterInstruction* ins, const InterOperand & op, InterType type, int reg);
void LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins); void LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins);
void StoreValue(InterCodeProcedure* proc, const InterInstruction * ins); void StoreValue(InterCodeProcedure* proc, const InterInstruction * ins);