Constant folding address of global and static variables

This commit is contained in:
drmortalwombat 2022-03-27 17:18:44 +02:00
parent 0aacc14287
commit d2503aaf1f
7 changed files with 454 additions and 65 deletions

View File

@ -69,6 +69,8 @@ enum RIRQCodeIndex
RIRQ_DATA_19 = 101,
RIRQ_ADDR_19 = 103,
RIRQ_SIZE_20 = 106,
};
// One raster interrupt operation, handles up to five writes
@ -79,6 +81,12 @@ typedef struct RIRQCode
byte code[RIRQ_SIZE];
} RIRQCode;
typedef struct RQIRCode20
{
RIRQCode c;
byte code[RIRQ_SIZE_20 - RIRQ_SIZE];
} RIRQCode20;
// Build one raster IRQ operation of the given size (wait + #ops) for up to 5 instructions
void rirq_build(RIRQCode * ic, byte size);

View File

@ -211,6 +211,17 @@ Expression* Expression::ConstantFold(Errors * errors)
}
}
}
#if 1
else if (mType == EX_PREFIX && mToken == TK_BINARY_AND && mLeft->mType == EX_VARIABLE && (mLeft->mDecValue->mFlags & (DTF_STATIC | DTF_GLOBAL)))
{
Expression* ex = new Expression(mLocation, EX_CONSTANT);
Declaration* dec = new Declaration(mLocation, DT_CONST_POINTER);
dec->mValue = mLeft;
ex->mDecValue = dec;
ex->mDecType = mDecType;
return ex;
}
#endif
else if (mType == EX_TYPECAST && mRight->mType == EX_CONSTANT)
{
if (mLeft->mDecType->mType == DT_TYPE_POINTER)

View File

@ -715,7 +715,7 @@ static void ConversionConstantFold(InterInstruction * ins, const InterOperand &
}
}
static void LoadConstantFold(InterInstruction* ins, InterInstruction* ains)
static void LoadConstantFold(InterInstruction* ins, InterInstruction* ains, const GrowingVariableArray& staticVars)
{
const uint8* data;
@ -752,11 +752,18 @@ static void LoadConstantFold(InterInstruction* ins, InterInstruction* ains)
i++;
if (i < lobj->mReferences.Size())
{
int j = 0;
while (j < staticVars.Size() && !(staticVars[j] && staticVars[j]->mLinkerObject == lobj->mReferences[i]->mRefObject))
j++;
ins->mConst.mLinkerObject = lobj->mReferences[i]->mRefObject;
ins->mConst.mIntConst = lobj->mReferences[i]->mRefOffset;
ins->mConst.mMemory = IM_GLOBAL;
ins->mConst.mOperandSize = ins->mConst.mLinkerObject->mSize;
ins->mConst.mVarIndex = -1;
if (j < staticVars.Size())
ins->mConst.mVarIndex = staticVars[j]->mIndex;
else
ins->mConst.mVarIndex = -1;
}
else
{
@ -1107,7 +1114,7 @@ void ValueSet::UpdateValue(InterInstruction * ins, const GrowingInstructionPtrAr
}
else if (ins->mSrc[0].mTemp >= 0 && tvalue[ins->mSrc[0].mTemp] && tvalue[ins->mSrc[0].mTemp]->mCode == IC_CONSTANT && tvalue[ins->mSrc[0].mTemp]->mConst.mMemory == IM_GLOBAL && (tvalue[ins->mSrc[0].mTemp]->mConst.mLinkerObject->mFlags & LOBJF_CONST))
{
LoadConstantFold(ins, tvalue[ins->mSrc[0].mTemp]);
LoadConstantFold(ins, tvalue[ins->mSrc[0].mTemp], staticVars);
InsertValue(ins);
}
else
@ -3430,7 +3437,7 @@ static void OptimizeAddress(InterInstruction * ins, const GrowingInstructionPtrA
}
void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue)
void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, const GrowingVariableArray& staticVars)
{
switch (ins->mCode)
{
@ -3507,7 +3514,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
OptimizeAddress(ins, tvalue, 0);
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL && (ins->mSrc[0].mLinkerObject->mFlags & LOBJF_CONST))
LoadConstantFold(ins, nullptr);
LoadConstantFold(ins, nullptr, staticVars);
break;
case IC_STORE:
@ -6179,7 +6186,7 @@ void InterCodeBasicBlock::PerformValueForwarding(const GrowingInstructionPtrArra
}
}
void InterCodeBasicBlock::PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid)
void InterCodeBasicBlock::PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars)
{
int i;
@ -6229,12 +6236,12 @@ void InterCodeBasicBlock::PerformMachineSpecificValueUsageCheck(const GrowingIns
for (i = 0; i < mInstructions.Size(); i++)
{
CheckValueUsage(mInstructions[i], ltvalue);
CheckValueUsage(mInstructions[i], ltvalue, staticVars);
mInstructions[i]->PerformValueForwarding(ltvalue, tvalid);
}
if (mTrueJump) mTrueJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid);
if (mFalseJump) mFalseJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid);
if (mTrueJump) mTrueJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid, staticVars);
if (mFalseJump) mFalseJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid, staticVars);
}
}
@ -9464,7 +9471,7 @@ void InterCodeProcedure::Close(void)
mTemporaries.SetSize(numTemps, true);
ResetVisited();
mEntryBlock->PerformMachineSpecificValueUsageCheck(mValueForwardingTable, tvalidSet);
mEntryBlock->PerformMachineSpecificValueUsageCheck(mValueForwardingTable, tvalidSet, mModule->mGlobalVars);
GlobalConstantPropagation();
@ -9911,6 +9918,43 @@ void InterCodeProcedure::MapVariables(void)
}
}
bool InterCodeBasicBlock::SameExitCode(const InterCodeBasicBlock* block) const
{
if (mInstructions.Size() > 1 && block->mInstructions.Size() > 1)
{
InterInstruction* ins0 = mInstructions[mInstructions.Size() - 2];
InterInstruction* ins1 = block->mInstructions[block->mInstructions.Size() - 2];
if (ins0->IsEqual(ins1))
{
if (ins0->mCode == IC_STORE && ins0->mSrc[1].mTemp >= 0)
{
int j0 = mInstructions.Size() - 2;
while (j0 >= 0 && mInstructions[j0]->mDst.mTemp != ins0->mSrc[1].mTemp)
j0--;
int j1 = block->mInstructions.Size() - 2;
while (j1 >= 0 && block->mInstructions[j1]->mDst.mTemp != ins0->mSrc[1].mTemp)
j1--;
if (j0 >= 0 && j1 >= 0)
{
if (!(mInstructions[j0]->IsEqual(block->mInstructions[j1])))
{
if (mInstructions[j0]->mCode == IC_LEA && mInstructions[j0]->mSrc[1].mTemp < 0)
return false;
if (block->mInstructions[j1]->mCode == IC_LEA && mInstructions[j1]->mSrc[1].mTemp < 0)
return false;
}
}
}
return true;
}
}
return false;
}
void InterCodeProcedure::MergeBasicBlocks(void)
{
ResetVisited();
@ -10017,7 +10061,7 @@ void InterCodeProcedure::MergeBasicBlocks(void)
InterInstruction* ins = eblocks[0]->mInstructions[eblocks[0]->mInstructions.Size() - 2];
int j = 1;
while (j < eblocks.Size() && eblocks[j]->mInstructions.Size() > 1 && eblocks[j]->mInstructions[eblocks[j]->mInstructions.Size() - 2]->IsEqual(ins))
while (j < eblocks.Size() && eblocks[0]->SameExitCode(eblocks[j]))
j++;
if (j == eblocks.Size())
{

View File

@ -407,10 +407,10 @@ public:
void BuildGlobalRenameRegisterTable(const GrowingIntArray& renameTable, GrowingIntArray& globalRenameTable);
void GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries);
void CheckValueUsage(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue);
void CheckValueUsage(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, const GrowingVariableArray& staticVars);
void PerformTempForwarding(TempForwardingTable& forwardingTable);
void PerformValueForwarding(const GrowingInstructionPtrArray& tvalue, const ValueSet& values, FastNumberSet& tvalid, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, int & spareTemps, const GrowingVariableArray& staticVars);
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid);
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars);
bool EliminateDeadBranches(void);
bool CalculateSingleAssignmentTemps(FastNumberSet& tassigned, GrowingInstructionPtrArray& tvalue, NumberSet& modifiedParams, InterMemory paramMemory);
@ -463,6 +463,8 @@ public:
bool CheckStaticStack(void);
void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars);
bool SameExitCode(const InterCodeBasicBlock* block) const;
};
class InterCodeModule;

View File

@ -858,6 +858,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case DT_CONST_POINTER:
{
vl = TranslateExpression(procType, proc, block, dec->mValue, breakBlock, continueBlock, inlineMapper);
vl.mReference--;
vl.mType = exp->mDecType;
return vl;
}
case DT_CONST_DATA:
@ -884,6 +886,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mDst.mTemp = proc->AddTemporary(IT_POINTER);
ins->mConst.mIntConst = 0;
ins->mConst.mVarIndex = dec->mVarIndex;
assert(dec->mVarIndex >= 0);
ins->mConst.mLinkerObject = dec->mLinkerObject;
ins->mConst.mMemory = IM_GLOBAL;
block->Append(ins);
@ -915,6 +918,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mDst.mTemp = proc->AddTemporary(IT_POINTER);
ins->mConst.mIntConst = 0;
ins->mConst.mVarIndex = dec->mVarIndex;
assert(dec->mVarIndex >= 0);
ins->mConst.mLinkerObject = dec->mLinkerObject;
ins->mConst.mMemory = IM_GLOBAL;
block->Append(ins);
@ -970,6 +974,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mConst.mMemory = IM_GLOBAL;
ins->mConst.mLinkerObject = dec->mLinkerObject;
ins->mConst.mVarIndex = dec->mVarIndex;
assert(dec->mVarIndex >= 0);
}
else
{

View File

@ -628,30 +628,39 @@ bool NativeCodeInstruction::RequiresXReg(void) const
}
void NativeCodeInstruction::ReplaceYRegWithXReg(void)
bool NativeCodeInstruction::ReplaceYRegWithXReg(void)
{
bool changed = false;
switch (mType)
{
case ASMIT_LDY:
mType = ASMIT_LDX;
changed = true;
break;
case ASMIT_STY:
mType = ASMIT_STX;
changed = true;
break;
case ASMIT_CPY:
mType = ASMIT_CPX;
changed = true;
break;
case ASMIT_TYA:
mType = ASMIT_TXA;
changed = true;
break;
case ASMIT_TAY:
mType = ASMIT_TAX;
changed = true;
break;
case ASMIT_INY:
mType = ASMIT_INX;
changed = true;
break;
case ASMIT_DEY:
mType = ASMIT_DEX;
changed = true;
break;
}
@ -660,48 +669,62 @@ void NativeCodeInstruction::ReplaceYRegWithXReg(void)
{
assert(HasAsmInstructionMode(mType, ASMIM_ABSOLUTE_X));
mMode = ASMIM_ABSOLUTE_X;
changed = true;
}
if (mLive & LIVE_CPU_REG_X)
mLive |= LIVE_CPU_REG_Y;
return changed;
}
void NativeCodeInstruction::ReplaceXRegWithYReg(void)
bool NativeCodeInstruction::ReplaceXRegWithYReg(void)
{
bool changed = false;
switch (mType)
{
case ASMIT_LDX:
mType = ASMIT_LDY;
changed = true;
break;
case ASMIT_STX:
mType = ASMIT_STY;
changed = true;
break;
case ASMIT_CPX:
mType = ASMIT_CPY;
changed = true;
break;
case ASMIT_TXA:
mType = ASMIT_TYA;
changed = true;
break;
case ASMIT_TAX:
mType = ASMIT_TAY;
changed = true;
break;
case ASMIT_INX:
mType = ASMIT_INY;
changed = true;
break;
case ASMIT_DEX:
mType = ASMIT_DEY;
changed = true;
break;
}
if (mMode == ASMIM_ABSOLUTE_X)
{
assert(HasAsmInstructionMode(mType, ASMIM_ABSOLUTE_Y));
mMode = ASMIM_ABSOLUTE_Y;
changed = true;
}
if (mLive & LIVE_CPU_REG_Y)
mLive |= LIVE_CPU_REG_X;
return changed;
}
bool NativeCodeInstruction::ChangesYReg(void) const
@ -2088,7 +2111,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
}
else
{
if (mMode != ASMIM_ZERO_PAGE)
if (mMode != ASMIM_ZERO_PAGE && mMode != ASMIM_ABSOLUTE)
data.mRegs[CPU_REG_X].Reset();
data.mRegs[CPU_REG_Z].Reset();
}
@ -2117,7 +2140,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
}
else
{
if (mMode != ASMIM_ZERO_PAGE)
if (mMode != ASMIM_ZERO_PAGE && mMode != ASMIM_ABSOLUTE)
data.mRegs[CPU_REG_Y].Reset();
data.mRegs[CPU_REG_Z].Reset();
}
@ -2534,6 +2557,52 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
else
data.mRegs[CPU_REG_A].Reset();
break;
case ASMIT_LDY:
if (!(mFlags & NCIF_VOLATILE))
{
if (data.mRegs[CPU_REG_Y].mMode == NRDM_ABSOLUTE && data.mRegs[CPU_REG_Y].mLinkerObject == mLinkerObject && data.mRegs[CPU_REG_Y].mValue == mAddress)
{
if (!(mLive & LIVE_CPU_REG_Z))
{
mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
}
changed = true;
}
else
{
data.mRegs[CPU_REG_Y].mMode = NRDM_ABSOLUTE;
data.mRegs[CPU_REG_Y].mLinkerObject = mLinkerObject;
data.mRegs[CPU_REG_Y].mValue = mAddress;
data.mRegs[CPU_REG_Y].mFlags = mFlags;
}
}
else
data.mRegs[CPU_REG_Y].Reset();
break;
case ASMIT_LDX:
if (!(mFlags & NCIF_VOLATILE))
{
if (data.mRegs[CPU_REG_X].mMode == NRDM_ABSOLUTE && data.mRegs[CPU_REG_X].mLinkerObject == mLinkerObject && data.mRegs[CPU_REG_X].mValue == mAddress)
{
if (!(mLive & LIVE_CPU_REG_Z))
{
mType = ASMIT_NOP;
mMode = ASMIM_IMPLIED;
}
changed = true;
}
else
{
data.mRegs[CPU_REG_X].mMode = NRDM_ABSOLUTE;
data.mRegs[CPU_REG_X].mLinkerObject = mLinkerObject;
data.mRegs[CPU_REG_X].mValue = mAddress;
data.mRegs[CPU_REG_X].mFlags = mFlags;
}
}
else
data.mRegs[CPU_REG_X].Reset();
break;
default:
if (ChangesAddress())
data.ResetAbsolute(mLinkerObject, mAddress);
@ -9001,6 +9070,50 @@ bool NativeCodeBasicBlock::RemoveUnusedResultInstructions(void)
return changed;
}
void NativeCodeBasicBlock::BuildDominatorTree(NativeCodeBasicBlock* from)
{
if (from == this)
return;
else if (!mDominator)
mDominator = from;
else if (from == mDominator)
return;
else
{
GrowingArray< NativeCodeBasicBlock * > d1(nullptr), d2(nullptr);
NativeCodeBasicBlock* b = mDominator;
while (b)
{
d1.Push(b);
b = b->mDominator;
}
b = from;
while (b)
{
d2.Push(b);
b = b->mDominator;
}
b = nullptr;
while (d1.Size() > 0 && d2.Size() > 0 && d1.Last() == d2.Last())
{
b = d1.Pop(); d2.Pop();
}
if (mDominator == b)
return;
mDominator = b;
}
if (mTrueJump)
mTrueJump->BuildDominatorTree(this);
if (mFalseJump)
mFalseJump->BuildDominatorTree(this);
}
void NativeCodeBasicBlock::CountEntries(NativeCodeBasicBlock * fromJump)
{
if (mVisiting)
@ -9419,13 +9532,16 @@ void NativeCodeBasicBlock::GlobalRegisterYMap(int reg)
bool NativeCodeBasicBlock::ReplaceYRegWithXReg(int start, int end)
{
bool changed = false;
for (int i = start; i < end; i++)
{
NativeCodeInstruction& ins(mIns[i]);
ins.ReplaceYRegWithXReg();
if (ins.ReplaceYRegWithXReg())
changed = true;
}
return true;
return changed;
}
bool NativeCodeBasicBlock::ReduceLocalYPressure(void)
@ -9776,15 +9892,161 @@ bool NativeCodeBasicBlock::ForwardZpXIndex(bool full)
bool NativeCodeBasicBlock::ReplaceXRegWithYReg(int start, int end)
{
bool changed = false;
for (int i = start; i < end; i++)
{
NativeCodeInstruction& ins(mIns[i]);
ins.ReplaceXRegWithYReg();
if (ins.ReplaceXRegWithYReg())
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::CanReplaceYRegWithXReg(int start, int end)
{
for (int i = start; i < end; i++)
{
NativeCodeInstruction& ins(mIns[i]);
if ((ins.mLive & LIVE_CPU_REG_X) && (ins.mLive & LIVE_CPU_REG_Y))
return false;
if (ins.mMode == ASMIM_INDIRECT_Y)
return false;
}
return true;
}
bool NativeCodeBasicBlock::CanReplaceXRegWithYReg(int start, int end)
{
for (int i = start; i < end; i++)
{
NativeCodeInstruction& ins(mIns[i]);
if ((ins.mLive & LIVE_CPU_REG_X) && (ins.mLive & LIVE_CPU_REG_Y))
return false;
if (ins.mMode == ASMIM_INDIRECT_X)
return false;
}
return true;
}
bool NativeCodeBasicBlock::AlternateXYUsage(void)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
int start = 0;
int predYPos = -1, predXPos = -1, currYPos = -1, currXPos = -1, predYEnd = -1, predXEnd = -1;
for (int start = 0; start < mIns.Size(); start++)
{
const NativeCodeInstruction& ins(mIns[start]);
if (ins.mType == ASMIT_LDY)
{
if ((ins.mMode == ASMIM_ZERO_PAGE || ins.mMode == ASMIM_ABSOLUTE) && predYPos >= 0 && ins.SameEffectiveAddress(mIns[predYPos]))
{
if (CanReplaceYRegWithXReg(predYEnd, start))
{
if (ReplaceYRegWithXReg(predYEnd, start))
changed = true;
}
}
else
{
if (currYPos >= 0)
{
predYPos = currYPos;
predYEnd = start;
}
if (ins.mMode == ASMIM_ZERO_PAGE || ins.mMode == ASMIM_ABSOLUTE)
currYPos = start;
else
currYPos = -1;
}
}
else if (ins.mType == ASMIT_LDX)
{
if ((ins.mMode == ASMIM_ZERO_PAGE || ins.mMode == ASMIM_ABSOLUTE) && predXPos >= 0 && ins.SameEffectiveAddress(mIns[predXPos]))
{
if (CanReplaceXRegWithYReg(predXEnd, start))
{
if (ReplaceXRegWithYReg(predXEnd, start))
changed = true;
}
}
else
{
if (currXPos >= 0)
{
predXPos = currXPos;
predXEnd = start;
}
if (ins.mMode == ASMIM_ZERO_PAGE || ins.mMode == ASMIM_ABSOLUTE)
currXPos = start;
else
currXPos = -1;
}
}
else if (ins.mType == ASMIT_JSR)
{
currYPos = predYPos = -1;
currXPos = predXPos = -1;
}
else if (ins.ChangesXReg())
{
if (currXPos != -1)
{
predXEnd = start;
predXPos = currXPos;
}
currXPos = -1;
}
else if (ins.ChangesYReg())
{
if (currYPos != -1)
{
predYEnd = start;
predYPos = currYPos;
}
currYPos = -1;
}
else
{
if (predYPos >= 0 && mIns[predYPos].MayBeChangedOnAddress(ins))
predYPos = -1;
if (predXPos >= 0 && mIns[predXPos].MayBeChangedOnAddress(ins))
predXPos = -1;
if (currYPos >= 0 && mIns[currYPos].MayBeChangedOnAddress(ins))
currYPos = -1;
if (currXPos >= 0 && mIns[currXPos].MayBeChangedOnAddress(ins))
currYPos = -1;
}
}
if (mTrueJump && mTrueJump->AlternateXYUsage())
changed = true;
if (mFalseJump && mFalseJump->AlternateXYUsage())
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::ReduceLocalXPressure(void)
{
bool changed = false;
@ -10599,7 +10861,7 @@ bool NativeCodeBasicBlock::FindImmediateStore(int at, int reg, const NativeCodeI
return false;
}
bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains, int cycles)
bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains, int cycles)
{
if (!mPatched)
{
@ -10611,7 +10873,14 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const Nativ
return true;
if (mNumEntries > 1)
return false;
{
if (mLoopHead)
return false;
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->IsDominatedBy(block))
return false;
}
}
while (at < mIns.Size())
@ -10664,16 +10933,16 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const Nativ
at++;
}
if (mTrueJump && !mTrueJump->CheckSingleUseGlobalLoad(reg, 0, ains, cycles))
if (mTrueJump && !mTrueJump->CheckSingleUseGlobalLoad(block, reg, 0, ains, cycles))
return false;
if (mFalseJump && !mFalseJump->CheckSingleUseGlobalLoad(reg, 0, ains, cycles))
if (mFalseJump && !mFalseJump->CheckSingleUseGlobalLoad(block, reg, 0, ains, cycles))
return false;
}
return true;
}
bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains)
bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains)
{
bool changed = false;
@ -10703,16 +10972,16 @@ bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(int reg, int at, const Nativ
at++;
}
if (mTrueJump && mTrueJump->PatchSingleUseGlobalLoad(reg, 0, ains))
if (mTrueJump && mTrueJump->PatchSingleUseGlobalLoad(block, reg, 0, ains))
changed = true;
if (mFalseJump && mFalseJump->PatchSingleUseGlobalLoad(reg, 0, ains))
if (mFalseJump && mFalseJump->PatchSingleUseGlobalLoad(block, reg, 0, ains))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int index, int at, int yval)
bool NativeCodeBasicBlock::CheckForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, int index, int at, int yval)
{
if (!mPatched)
{
@ -10724,7 +10993,12 @@ bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int index,
return true;
if (mNumEntries > 1)
{
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->IsDominatedBy(block))
return false;
yval = -1;
}
}
while (at < mIns.Size())
@ -10761,16 +11035,16 @@ bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int index,
at++;
}
if (mTrueJump && !mTrueJump->CheckForwardSumYPointer(reg, base, index, 0, yval))
if (mTrueJump && !mTrueJump->CheckForwardSumYPointer(block, reg, base, index, 0, yval))
return false;
if (mFalseJump && !mFalseJump->CheckForwardSumYPointer(reg, base, index, 0, yval))
if (mFalseJump && !mFalseJump->CheckForwardSumYPointer(block, reg, base, index, 0, yval))
return false;
}
return true;
}
bool NativeCodeBasicBlock::PatchForwardSumYPointer(int reg, int base, int index, int at, int yval)
bool NativeCodeBasicBlock::PatchForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, int index, int at, int yval)
{
bool changed = false;
@ -10821,16 +11095,36 @@ bool NativeCodeBasicBlock::PatchForwardSumYPointer(int reg, int base, int index,
at++;
}
if (mTrueJump && mTrueJump->PatchForwardSumYPointer(reg, base, index, 0, yval))
if (mTrueJump && mTrueJump->PatchForwardSumYPointer(block, reg, base, index, 0, yval))
changed = true;
if (mFalseJump && mFalseJump->PatchForwardSumYPointer(reg, base, index, 0, yval))
if (mFalseJump && mFalseJump->PatchForwardSumYPointer(block, reg, base, index, 0, yval))
changed = true;
}
return changed;
}
bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yval)
bool NativeCodeBasicBlock::IsDominatedBy(const NativeCodeBasicBlock* block) const
{
if (this == block)
return true;
else
{
NativeCodeBasicBlock* dom = mDominator;
while (dom)
{
if (dom == block)
return true;
dom = dom->mDominator;
}
return false;
}
}
bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(const NativeCodeBasicBlock * block, int reg, int at, int yval)
{
if (!mPatched)
{
@ -10842,7 +11136,12 @@ bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yv
return true;
if (mNumEntries > 1)
{
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->IsDominatedBy(block))
return false;
yval = -1;
}
}
while (at < mIns.Size())
@ -10877,16 +11176,16 @@ bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yv
at++;
}
if (mTrueJump && !mTrueJump->CheckGlobalAddressSumYPointer(reg, 0, yval))
if (mTrueJump && !mTrueJump->CheckGlobalAddressSumYPointer(block, reg, 0, yval))
return false;
if (mFalseJump && !mFalseJump->CheckGlobalAddressSumYPointer(reg, 0, yval))
if (mFalseJump && !mFalseJump->CheckGlobalAddressSumYPointer(block, reg, 0, yval))
return false;
}
return true;
}
bool NativeCodeBasicBlock::PatchGlobalAddressSumYPointer(int reg, int at, int yval, LinkerObject* lobj, int address)
bool NativeCodeBasicBlock::PatchGlobalAddressSumYPointer(const NativeCodeBasicBlock* block, int reg, int at, int yval, LinkerObject* lobj, int address)
{
bool changed = false;
@ -10933,9 +11232,9 @@ bool NativeCodeBasicBlock::PatchGlobalAddressSumYPointer(int reg, int at, int yv
at++;
}
if (mTrueJump && mTrueJump->PatchGlobalAddressSumYPointer(reg, 0, yval, lobj, address))
if (mTrueJump && mTrueJump->PatchGlobalAddressSumYPointer(block, reg, 0, yval, lobj, address))
changed = true;
if (mFalseJump && mFalseJump->PatchGlobalAddressSumYPointer(reg, 0, yval, lobj, address))
if (mFalseJump && mFalseJump->PatchGlobalAddressSumYPointer(block, reg, 0, yval, lobj, address))
changed = true;
}
@ -18194,10 +18493,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
{
proc->ResetPatched();
if (CheckSingleUseGlobalLoad(mIns[i + 1].mAddress, i + 2, mIns[i], 3))
if (CheckSingleUseGlobalLoad(this, mIns[i + 1].mAddress, i + 2, mIns[i], 3))
{
proc->ResetPatched();
if (PatchSingleUseGlobalLoad(mIns[i + 1].mAddress, i + 2, mIns[i]))
if (PatchSingleUseGlobalLoad(this, mIns[i + 1].mAddress, i + 2, mIns[i]))
progress = true;
}
}
@ -18206,10 +18505,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ABSOLUTE)
{
proc->ResetPatched();
if (CheckSingleUseGlobalLoad(mIns[i + 0].mAddress, i + 2, mIns[i + 1], 2))
if (CheckSingleUseGlobalLoad(this, mIns[i + 0].mAddress, i + 2, mIns[i + 1], 2))
{
proc->ResetPatched();
if (PatchSingleUseGlobalLoad(mIns[i + 0].mAddress, i + 2, mIns[i + 1]))
if (PatchSingleUseGlobalLoad(this, mIns[i + 0].mAddress, i + 2, mIns[i + 1]))
progress = true;
}
}
@ -18259,7 +18558,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 5].mLive & LIVE_CPU_REG_A))
{
proc->ResetPatched();
if (CheckGlobalAddressSumYPointer(mIns[i + 2].mAddress, i + 6, -1))
if (CheckGlobalAddressSumYPointer(this, mIns[i + 2].mAddress, i + 6, -1))
{
assert(mIns[i + 3].mAddress == mIns[i + 1].mAddress);
@ -18270,7 +18569,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED;
proc->ResetPatched();
if (PatchGlobalAddressSumYPointer(mIns[i + 2].mAddress, i + 6, -1, mIns[i + 3].mLinkerObject, mIns[i + 3].mAddress))
if (PatchGlobalAddressSumYPointer(this, mIns[i + 2].mAddress, i + 6, -1, mIns[i + 3].mLinkerObject, mIns[i + 3].mAddress))
progress = true;
}
}
@ -18286,14 +18585,14 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 5].mLive & LIVE_CPU_REG_A))
{
proc->ResetPatched();
if (CheckGlobalAddressSumYPointer(mIns[i + 2].mAddress, i + 6, -1))
if (CheckGlobalAddressSumYPointer(this, mIns[i + 2].mAddress, i + 6, -1))
{
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].mMode = ASMIM_IMPLIED;
mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED;
proc->ResetPatched();
if (PatchGlobalAddressSumYPointer(mIns[i + 2].mAddress, i + 6, -1, nullptr, 256 * mIns[i + 3].mAddress))
if (PatchGlobalAddressSumYPointer(this, mIns[i + 2].mAddress, i + 6, -1, nullptr, 256 * mIns[i + 3].mAddress))
progress = true;
}
}
@ -18329,7 +18628,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 6].mLive & LIVE_CPU_REG_A))
{
proc->ResetPatched();
if (CheckGlobalAddressSumYPointer(mIns[i + 3].mAddress, i + 7, -1))
if (CheckGlobalAddressSumYPointer(this, mIns[i + 3].mAddress, i + 7, -1))
{
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
@ -18339,7 +18638,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED;
proc->ResetPatched();
if (PatchGlobalAddressSumYPointer(mIns[i + 3].mAddress, i + 7, -1, mIns[i + 1].mLinkerObject, mIns[i + 1].mAddress))
if (PatchGlobalAddressSumYPointer(this, mIns[i + 3].mAddress, i + 7, -1, mIns[i + 1].mLinkerObject, mIns[i + 1].mAddress))
progress = true;
}
}
@ -18357,7 +18656,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 6].mLive & LIVE_CPU_REG_A))
{
proc->ResetPatched();
if (CheckForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 1].mAddress, mIns[i + 3].mAddress, i + 7, -1))
if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 1].mAddress, mIns[i + 3].mAddress, i + 7, -1))
{
mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
@ -18368,7 +18667,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED;
proc->ResetPatched();
if (PatchForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 1].mAddress, mIns[i + 3].mAddress, i + 7, -1))
if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 1].mAddress, mIns[i + 3].mAddress, i + 7, -1))
progress = true;
}
}
@ -18385,7 +18684,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 6].mLive & LIVE_CPU_REG_A))
{
proc->ResetPatched();
if (CheckForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 2].mAddress, mIns[i + 0].mAddress, i + 7, -1))
if (CheckForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 2].mAddress, mIns[i + 0].mAddress, i + 7, -1))
{
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
@ -18395,7 +18694,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED;
proc->ResetPatched();
if (PatchForwardSumYPointer(mIns[i + 3].mAddress, mIns[i + 2].mAddress, mIns[i + 0].mAddress, i + 7, -1))
if (PatchForwardSumYPointer(this, mIns[i + 3].mAddress, mIns[i + 2].mAddress, mIns[i + 0].mAddress, i + 7, -1))
progress = true;
}
}
@ -19069,6 +19368,7 @@ NativeCodeBasicBlock::NativeCodeBasicBlock(void)
mBypassed = false;
mAssembled = false;
mLocked = false;
mDominator = nullptr;
mLoopHeadBlock = nullptr;
}
@ -19603,9 +19903,10 @@ void NativeCodeProcedure::Optimize(void)
mBlocks[i]->mVisiting = false;
mBlocks[i]->mLoopHead = false;
mBlocks[i]->mFromJump = nullptr;
mBlocks[i]->mDominator = nullptr;
}
mEntryBlock->CountEntries(nullptr);
mEntryBlock->BuildDominatorTree(nullptr);
#if 1
do
{
@ -19785,6 +20086,13 @@ void NativeCodeProcedure::Optimize(void)
#endif
#endif
if (step == 5)
{
ResetVisited();
if (mEntryBlock->AlternateXYUsage())
changed = true;
}
#if 1
ResetVisited();
if (mEntryBlock->ForwardZpYIndex(step >= 4))

View File

@ -114,8 +114,8 @@ public:
bool IsCommutative(void) const;
bool IsShift(void) const;
void ReplaceYRegWithXReg(void);
void ReplaceXRegWithYReg(void);
bool ReplaceYRegWithXReg(void);
bool ReplaceXRegWithYReg(void);
};
class NativeCodeBasicBlock
@ -135,8 +135,10 @@ public:
GrowingArray<NativeCodeBasicBlock*> mEntryBlocks;
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset;
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched;
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset;
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched;
NativeCodeBasicBlock * mDominator;
NativeCodeBasicBlock* mLoopHeadBlock;
NativeRegisterDataSet mDataSet, mNDataSet;
@ -220,6 +222,7 @@ public:
void CountEntries(NativeCodeBasicBlock* fromJump);
bool MergeBasicBlocks(void);
void MarkLoopHead(void);
void BuildDominatorTree(NativeCodeBasicBlock * from);
bool MoveLoadStoreUp(int at);
bool MoveLoadStoreXUp(int at);
@ -258,6 +261,9 @@ public:
bool ReplaceYRegWithXReg(int start, int end);
bool ReplaceXRegWithYReg(int start, int end);
bool CanReplaceYRegWithXReg(int start, int end);
bool CanReplaceXRegWithYReg(int start, int end);
bool ForwardZpYIndex(bool full);
bool ForwardZpXIndex(bool full);
@ -296,14 +302,19 @@ public:
bool ReduceLocalYPressure(void);
bool ReduceLocalXPressure(void);
bool CheckGlobalAddressSumYPointer(int reg, int at, int yval);
bool PatchGlobalAddressSumYPointer(int reg, int at, int yval, LinkerObject * lobj, int address);
bool AlternateXYUsage(void);
bool ForwardAbsoluteLoadStores(void);
bool CheckSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains, int cycles);
bool PatchSingleUseGlobalLoad(int reg, int at, const NativeCodeInstruction& ains);
bool CheckGlobalAddressSumYPointer(const NativeCodeBasicBlock * block, int reg, int at, int yval);
bool PatchGlobalAddressSumYPointer(const NativeCodeBasicBlock* block, int reg, int at, int yval, LinkerObject * lobj, int address);
bool CheckForwardSumYPointer(int reg, int base, int index, int at, int yval);
bool PatchForwardSumYPointer(int reg, int base, int index, int at, int yval);
bool CheckSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains, int cycles);
bool PatchSingleUseGlobalLoad(const NativeCodeBasicBlock* block, int reg, int at, const NativeCodeInstruction& ains);
bool CheckForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, int index, int at, int yval);
bool PatchForwardSumYPointer(const NativeCodeBasicBlock* block, int reg, int base, int index, int at, int yval);
bool IsDominatedBy(const NativeCodeBasicBlock* block) const;
};
class NativeCodeProcedure