Eliminate duplicate loop counting variables
This commit is contained in:
parent
c0e524cd82
commit
301431f12a
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue