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_DATA_19 = 101,
RIRQ_ADDR_19 = 103, RIRQ_ADDR_19 = 103,
RIRQ_SIZE_20 = 106,
}; };
// One raster interrupt operation, handles up to five writes // One raster interrupt operation, handles up to five writes
@ -79,6 +81,12 @@ typedef struct RIRQCode
byte code[RIRQ_SIZE]; byte code[RIRQ_SIZE];
} RIRQCode; } 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 // Build one raster IRQ operation of the given size (wait + #ops) for up to 5 instructions
void rirq_build(RIRQCode * ic, byte size); 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) else if (mType == EX_TYPECAST && mRight->mType == EX_CONSTANT)
{ {
if (mLeft->mDecType->mType == DT_TYPE_POINTER) 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; const uint8* data;
@ -752,10 +752,17 @@ static void LoadConstantFold(InterInstruction* ins, InterInstruction* ains)
i++; i++;
if (i < lobj->mReferences.Size()) 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.mLinkerObject = lobj->mReferences[i]->mRefObject;
ins->mConst.mIntConst = lobj->mReferences[i]->mRefOffset; ins->mConst.mIntConst = lobj->mReferences[i]->mRefOffset;
ins->mConst.mMemory = IM_GLOBAL; ins->mConst.mMemory = IM_GLOBAL;
ins->mConst.mOperandSize = ins->mConst.mLinkerObject->mSize; ins->mConst.mOperandSize = ins->mConst.mLinkerObject->mSize;
if (j < staticVars.Size())
ins->mConst.mVarIndex = staticVars[j]->mIndex;
else
ins->mConst.mVarIndex = -1; ins->mConst.mVarIndex = -1;
} }
else 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)) 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); InsertValue(ins);
} }
else 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) switch (ins->mCode)
{ {
@ -3507,7 +3514,7 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI
OptimizeAddress(ins, tvalue, 0); OptimizeAddress(ins, tvalue, 0);
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mMemory == IM_GLOBAL && (ins->mSrc[0].mLinkerObject->mFlags & LOBJF_CONST)) 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; break;
case IC_STORE: 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; int i;
@ -6229,12 +6236,12 @@ void InterCodeBasicBlock::PerformMachineSpecificValueUsageCheck(const GrowingIns
for (i = 0; i < mInstructions.Size(); i++) for (i = 0; i < mInstructions.Size(); i++)
{ {
CheckValueUsage(mInstructions[i], ltvalue); CheckValueUsage(mInstructions[i], ltvalue, staticVars);
mInstructions[i]->PerformValueForwarding(ltvalue, tvalid); mInstructions[i]->PerformValueForwarding(ltvalue, tvalid);
} }
if (mTrueJump) mTrueJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid); if (mTrueJump) mTrueJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid, staticVars);
if (mFalseJump) mFalseJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid); if (mFalseJump) mFalseJump->PerformMachineSpecificValueUsageCheck(ltvalue, tvalid, staticVars);
} }
} }
@ -9464,7 +9471,7 @@ void InterCodeProcedure::Close(void)
mTemporaries.SetSize(numTemps, true); mTemporaries.SetSize(numTemps, true);
ResetVisited(); ResetVisited();
mEntryBlock->PerformMachineSpecificValueUsageCheck(mValueForwardingTable, tvalidSet); mEntryBlock->PerformMachineSpecificValueUsageCheck(mValueForwardingTable, tvalidSet, mModule->mGlobalVars);
GlobalConstantPropagation(); 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) void InterCodeProcedure::MergeBasicBlocks(void)
{ {
ResetVisited(); ResetVisited();
@ -10017,7 +10061,7 @@ void InterCodeProcedure::MergeBasicBlocks(void)
InterInstruction* ins = eblocks[0]->mInstructions[eblocks[0]->mInstructions.Size() - 2]; InterInstruction* ins = eblocks[0]->mInstructions[eblocks[0]->mInstructions.Size() - 2];
int j = 1; 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++; j++;
if (j == eblocks.Size()) if (j == eblocks.Size())
{ {

View File

@ -407,10 +407,10 @@ public:
void BuildGlobalRenameRegisterTable(const GrowingIntArray& renameTable, GrowingIntArray& globalRenameTable); void BuildGlobalRenameRegisterTable(const GrowingIntArray& renameTable, GrowingIntArray& globalRenameTable);
void GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries); 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 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 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 EliminateDeadBranches(void);
bool CalculateSingleAssignmentTemps(FastNumberSet& tassigned, GrowingInstructionPtrArray& tvalue, NumberSet& modifiedParams, InterMemory paramMemory); bool CalculateSingleAssignmentTemps(FastNumberSet& tassigned, GrowingInstructionPtrArray& tvalue, NumberSet& modifiedParams, InterMemory paramMemory);
@ -463,6 +463,8 @@ public:
bool CheckStaticStack(void); bool CheckStaticStack(void);
void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars); void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars);
bool SameExitCode(const InterCodeBasicBlock* block) const;
}; };
class InterCodeModule; class InterCodeModule;

View File

@ -858,6 +858,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case DT_CONST_POINTER: case DT_CONST_POINTER:
{ {
vl = TranslateExpression(procType, proc, block, dec->mValue, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, dec->mValue, breakBlock, continueBlock, inlineMapper);
vl.mReference--;
vl.mType = exp->mDecType;
return vl; return vl;
} }
case DT_CONST_DATA: case DT_CONST_DATA:
@ -884,6 +886,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mDst.mTemp = proc->AddTemporary(IT_POINTER); ins->mDst.mTemp = proc->AddTemporary(IT_POINTER);
ins->mConst.mIntConst = 0; ins->mConst.mIntConst = 0;
ins->mConst.mVarIndex = dec->mVarIndex; ins->mConst.mVarIndex = dec->mVarIndex;
assert(dec->mVarIndex >= 0);
ins->mConst.mLinkerObject = dec->mLinkerObject; ins->mConst.mLinkerObject = dec->mLinkerObject;
ins->mConst.mMemory = IM_GLOBAL; ins->mConst.mMemory = IM_GLOBAL;
block->Append(ins); block->Append(ins);
@ -915,6 +918,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mDst.mTemp = proc->AddTemporary(IT_POINTER); ins->mDst.mTemp = proc->AddTemporary(IT_POINTER);
ins->mConst.mIntConst = 0; ins->mConst.mIntConst = 0;
ins->mConst.mVarIndex = dec->mVarIndex; ins->mConst.mVarIndex = dec->mVarIndex;
assert(dec->mVarIndex >= 0);
ins->mConst.mLinkerObject = dec->mLinkerObject; ins->mConst.mLinkerObject = dec->mLinkerObject;
ins->mConst.mMemory = IM_GLOBAL; ins->mConst.mMemory = IM_GLOBAL;
block->Append(ins); block->Append(ins);
@ -970,6 +974,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mConst.mMemory = IM_GLOBAL; ins->mConst.mMemory = IM_GLOBAL;
ins->mConst.mLinkerObject = dec->mLinkerObject; ins->mConst.mLinkerObject = dec->mLinkerObject;
ins->mConst.mVarIndex = dec->mVarIndex; ins->mConst.mVarIndex = dec->mVarIndex;
assert(dec->mVarIndex >= 0);
} }
else 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) switch (mType)
{ {
case ASMIT_LDY: case ASMIT_LDY:
mType = ASMIT_LDX; mType = ASMIT_LDX;
changed = true;
break; break;
case ASMIT_STY: case ASMIT_STY:
mType = ASMIT_STX; mType = ASMIT_STX;
changed = true;
break; break;
case ASMIT_CPY: case ASMIT_CPY:
mType = ASMIT_CPX; mType = ASMIT_CPX;
changed = true;
break; break;
case ASMIT_TYA: case ASMIT_TYA:
mType = ASMIT_TXA; mType = ASMIT_TXA;
changed = true;
break; break;
case ASMIT_TAY: case ASMIT_TAY:
mType = ASMIT_TAX; mType = ASMIT_TAX;
changed = true;
break; break;
case ASMIT_INY: case ASMIT_INY:
mType = ASMIT_INX; mType = ASMIT_INX;
changed = true;
break; break;
case ASMIT_DEY: case ASMIT_DEY:
mType = ASMIT_DEX; mType = ASMIT_DEX;
changed = true;
break; break;
} }
@ -660,48 +669,62 @@ void NativeCodeInstruction::ReplaceYRegWithXReg(void)
{ {
assert(HasAsmInstructionMode(mType, ASMIM_ABSOLUTE_X)); assert(HasAsmInstructionMode(mType, ASMIM_ABSOLUTE_X));
mMode = ASMIM_ABSOLUTE_X; mMode = ASMIM_ABSOLUTE_X;
changed = true;
} }
if (mLive & LIVE_CPU_REG_X) if (mLive & LIVE_CPU_REG_X)
mLive |= LIVE_CPU_REG_Y; mLive |= LIVE_CPU_REG_Y;
return changed;
} }
void NativeCodeInstruction::ReplaceXRegWithYReg(void) bool NativeCodeInstruction::ReplaceXRegWithYReg(void)
{ {
bool changed = false;
switch (mType) switch (mType)
{ {
case ASMIT_LDX: case ASMIT_LDX:
mType = ASMIT_LDY; mType = ASMIT_LDY;
changed = true;
break; break;
case ASMIT_STX: case ASMIT_STX:
mType = ASMIT_STY; mType = ASMIT_STY;
changed = true;
break; break;
case ASMIT_CPX: case ASMIT_CPX:
mType = ASMIT_CPY; mType = ASMIT_CPY;
changed = true;
break; break;
case ASMIT_TXA: case ASMIT_TXA:
mType = ASMIT_TYA; mType = ASMIT_TYA;
changed = true;
break; break;
case ASMIT_TAX: case ASMIT_TAX:
mType = ASMIT_TAY; mType = ASMIT_TAY;
changed = true;
break; break;
case ASMIT_INX: case ASMIT_INX:
mType = ASMIT_INY; mType = ASMIT_INY;
changed = true;
break; break;
case ASMIT_DEX: case ASMIT_DEX:
mType = ASMIT_DEY; mType = ASMIT_DEY;
changed = true;
break; break;
} }
if (mMode == ASMIM_ABSOLUTE_X) if (mMode == ASMIM_ABSOLUTE_X)
{ {
assert(HasAsmInstructionMode(mType, ASMIM_ABSOLUTE_Y)); assert(HasAsmInstructionMode(mType, ASMIM_ABSOLUTE_Y));
mMode = ASMIM_ABSOLUTE_Y; mMode = ASMIM_ABSOLUTE_Y;
changed = true;
} }
if (mLive & LIVE_CPU_REG_Y) if (mLive & LIVE_CPU_REG_Y)
mLive |= LIVE_CPU_REG_X; mLive |= LIVE_CPU_REG_X;
return changed;
} }
bool NativeCodeInstruction::ChangesYReg(void) const bool NativeCodeInstruction::ChangesYReg(void) const
@ -2088,7 +2111,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
} }
else else
{ {
if (mMode != ASMIM_ZERO_PAGE) if (mMode != ASMIM_ZERO_PAGE && mMode != ASMIM_ABSOLUTE)
data.mRegs[CPU_REG_X].Reset(); data.mRegs[CPU_REG_X].Reset();
data.mRegs[CPU_REG_Z].Reset(); data.mRegs[CPU_REG_Z].Reset();
} }
@ -2117,7 +2140,7 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
} }
else else
{ {
if (mMode != ASMIM_ZERO_PAGE) if (mMode != ASMIM_ZERO_PAGE && mMode != ASMIM_ABSOLUTE)
data.mRegs[CPU_REG_Y].Reset(); data.mRegs[CPU_REG_Y].Reset();
data.mRegs[CPU_REG_Z].Reset(); data.mRegs[CPU_REG_Z].Reset();
} }
@ -2534,6 +2557,52 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT
else else
data.mRegs[CPU_REG_A].Reset(); data.mRegs[CPU_REG_A].Reset();
break; 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: default:
if (ChangesAddress()) if (ChangesAddress())
data.ResetAbsolute(mLinkerObject, mAddress); data.ResetAbsolute(mLinkerObject, mAddress);
@ -9001,6 +9070,50 @@ bool NativeCodeBasicBlock::RemoveUnusedResultInstructions(void)
return changed; 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) void NativeCodeBasicBlock::CountEntries(NativeCodeBasicBlock * fromJump)
{ {
if (mVisiting) if (mVisiting)
@ -9419,13 +9532,16 @@ void NativeCodeBasicBlock::GlobalRegisterYMap(int reg)
bool NativeCodeBasicBlock::ReplaceYRegWithXReg(int start, int end) bool NativeCodeBasicBlock::ReplaceYRegWithXReg(int start, int end)
{ {
bool changed = false;
for (int i = start; i < end; i++) for (int i = start; i < end; i++)
{ {
NativeCodeInstruction& ins(mIns[i]); NativeCodeInstruction& ins(mIns[i]);
ins.ReplaceYRegWithXReg(); if (ins.ReplaceYRegWithXReg())
changed = true;
} }
return true; return changed;
} }
bool NativeCodeBasicBlock::ReduceLocalYPressure(void) bool NativeCodeBasicBlock::ReduceLocalYPressure(void)
@ -9776,15 +9892,161 @@ bool NativeCodeBasicBlock::ForwardZpXIndex(bool full)
bool NativeCodeBasicBlock::ReplaceXRegWithYReg(int start, int end) bool NativeCodeBasicBlock::ReplaceXRegWithYReg(int start, int end)
{ {
bool changed = false;
for (int i = start; i < end; i++) for (int i = start; i < end; i++)
{ {
NativeCodeInstruction& ins(mIns[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; 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 NativeCodeBasicBlock::ReduceLocalXPressure(void)
{ {
bool changed = false; bool changed = false;
@ -10599,7 +10861,7 @@ bool NativeCodeBasicBlock::FindImmediateStore(int at, int reg, const NativeCodeI
return false; 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) if (!mPatched)
{ {
@ -10611,7 +10873,14 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const Nativ
return true; return true;
if (mNumEntries > 1) if (mNumEntries > 1)
{
if (mLoopHead)
return false; return false;
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->IsDominatedBy(block))
return false;
}
} }
while (at < mIns.Size()) while (at < mIns.Size())
@ -10664,16 +10933,16 @@ bool NativeCodeBasicBlock::CheckSingleUseGlobalLoad(int reg, int at, const Nativ
at++; at++;
} }
if (mTrueJump && !mTrueJump->CheckSingleUseGlobalLoad(reg, 0, ains, cycles)) if (mTrueJump && !mTrueJump->CheckSingleUseGlobalLoad(block, reg, 0, ains, cycles))
return false; return false;
if (mFalseJump && !mFalseJump->CheckSingleUseGlobalLoad(reg, 0, ains, cycles)) if (mFalseJump && !mFalseJump->CheckSingleUseGlobalLoad(block, reg, 0, ains, cycles))
return false; return false;
} }
return true; 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; bool changed = false;
@ -10703,16 +10972,16 @@ bool NativeCodeBasicBlock::PatchSingleUseGlobalLoad(int reg, int at, const Nativ
at++; at++;
} }
if (mTrueJump && mTrueJump->PatchSingleUseGlobalLoad(reg, 0, ains)) if (mTrueJump && mTrueJump->PatchSingleUseGlobalLoad(block, reg, 0, ains))
changed = true; changed = true;
if (mFalseJump && mFalseJump->PatchSingleUseGlobalLoad(reg, 0, ains)) if (mFalseJump && mFalseJump->PatchSingleUseGlobalLoad(block, reg, 0, ains))
changed = true; changed = true;
} }
return changed; 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) if (!mPatched)
{ {
@ -10724,8 +10993,13 @@ bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int index,
return true; return true;
if (mNumEntries > 1) if (mNumEntries > 1)
{
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->IsDominatedBy(block))
return false;
yval = -1; yval = -1;
} }
}
while (at < mIns.Size()) while (at < mIns.Size())
{ {
@ -10761,16 +11035,16 @@ bool NativeCodeBasicBlock::CheckForwardSumYPointer(int reg, int base, int index,
at++; at++;
} }
if (mTrueJump && !mTrueJump->CheckForwardSumYPointer(reg, base, index, 0, yval)) if (mTrueJump && !mTrueJump->CheckForwardSumYPointer(block, reg, base, index, 0, yval))
return false; return false;
if (mFalseJump && !mFalseJump->CheckForwardSumYPointer(reg, base, index, 0, yval)) if (mFalseJump && !mFalseJump->CheckForwardSumYPointer(block, reg, base, index, 0, yval))
return false; return false;
} }
return true; 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; bool changed = false;
@ -10821,16 +11095,36 @@ bool NativeCodeBasicBlock::PatchForwardSumYPointer(int reg, int base, int index,
at++; at++;
} }
if (mTrueJump && mTrueJump->PatchForwardSumYPointer(reg, base, index, 0, yval)) if (mTrueJump && mTrueJump->PatchForwardSumYPointer(block, reg, base, index, 0, yval))
changed = true; changed = true;
if (mFalseJump && mFalseJump->PatchForwardSumYPointer(reg, base, index, 0, yval)) if (mFalseJump && mFalseJump->PatchForwardSumYPointer(block, reg, base, index, 0, yval))
changed = true; changed = true;
} }
return changed; 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) if (!mPatched)
{ {
@ -10842,8 +11136,13 @@ bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yv
return true; return true;
if (mNumEntries > 1) if (mNumEntries > 1)
{
for (int i = 0; i < mEntryBlocks.Size(); i++)
if (!mEntryBlocks[i]->IsDominatedBy(block))
return false;
yval = -1; yval = -1;
} }
}
while (at < mIns.Size()) while (at < mIns.Size())
{ {
@ -10877,16 +11176,16 @@ bool NativeCodeBasicBlock::CheckGlobalAddressSumYPointer(int reg, int at, int yv
at++; at++;
} }
if (mTrueJump && !mTrueJump->CheckGlobalAddressSumYPointer(reg, 0, yval)) if (mTrueJump && !mTrueJump->CheckGlobalAddressSumYPointer(block, reg, 0, yval))
return false; return false;
if (mFalseJump && !mFalseJump->CheckGlobalAddressSumYPointer(reg, 0, yval)) if (mFalseJump && !mFalseJump->CheckGlobalAddressSumYPointer(block, reg, 0, yval))
return false; return false;
} }
return true; 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; bool changed = false;
@ -10933,9 +11232,9 @@ bool NativeCodeBasicBlock::PatchGlobalAddressSumYPointer(int reg, int at, int yv
at++; at++;
} }
if (mTrueJump && mTrueJump->PatchGlobalAddressSumYPointer(reg, 0, yval, lobj, address)) if (mTrueJump && mTrueJump->PatchGlobalAddressSumYPointer(block, reg, 0, yval, lobj, address))
changed = true; changed = true;
if (mFalseJump && mFalseJump->PatchGlobalAddressSumYPointer(reg, 0, yval, lobj, address)) if (mFalseJump && mFalseJump->PatchGlobalAddressSumYPointer(block, reg, 0, yval, lobj, address))
changed = true; 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))) 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(); 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(); 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; 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) mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ABSOLUTE)
{ {
proc->ResetPatched(); 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(); 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; progress = true;
} }
} }
@ -18259,7 +18558,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 5].mLive & LIVE_CPU_REG_A)) !(mIns[i + 5].mLive & LIVE_CPU_REG_A))
{ {
proc->ResetPatched(); 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); 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; mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED;
proc->ResetPatched(); 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; progress = true;
} }
} }
@ -18286,14 +18585,14 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 5].mLive & LIVE_CPU_REG_A)) !(mIns[i + 5].mLive & LIVE_CPU_REG_A))
{ {
proc->ResetPatched(); 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 + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;
mIns[i + 4].mType = ASMIT_NOP; mIns[i + 4].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; mIns[i + 5].mType = ASMIT_NOP; mIns[i + 5].mMode = ASMIM_IMPLIED;
proc->ResetPatched(); 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; progress = true;
} }
} }
@ -18329,7 +18628,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 6].mLive & LIVE_CPU_REG_A)) !(mIns[i + 6].mLive & LIVE_CPU_REG_A))
{ {
proc->ResetPatched(); 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 + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].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; mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED;
proc->ResetPatched(); 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; progress = true;
} }
} }
@ -18357,7 +18656,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 6].mLive & LIVE_CPU_REG_A)) !(mIns[i + 6].mLive & LIVE_CPU_REG_A))
{ {
proc->ResetPatched(); 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 + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].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; mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED;
proc->ResetPatched(); 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; progress = true;
} }
} }
@ -18385,7 +18684,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
!(mIns[i + 6].mLive & LIVE_CPU_REG_A)) !(mIns[i + 6].mLive & LIVE_CPU_REG_A))
{ {
proc->ResetPatched(); 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 + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].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; mIns[i + 6].mType = ASMIT_NOP; mIns[i + 6].mMode = ASMIM_IMPLIED;
proc->ResetPatched(); 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; progress = true;
} }
} }
@ -19069,6 +19368,7 @@ NativeCodeBasicBlock::NativeCodeBasicBlock(void)
mBypassed = false; mBypassed = false;
mAssembled = false; mAssembled = false;
mLocked = false; mLocked = false;
mDominator = nullptr;
mLoopHeadBlock = nullptr; mLoopHeadBlock = nullptr;
} }
@ -19603,9 +19903,10 @@ void NativeCodeProcedure::Optimize(void)
mBlocks[i]->mVisiting = false; mBlocks[i]->mVisiting = false;
mBlocks[i]->mLoopHead = false; mBlocks[i]->mLoopHead = false;
mBlocks[i]->mFromJump = nullptr; mBlocks[i]->mFromJump = nullptr;
mBlocks[i]->mDominator = nullptr;
} }
mEntryBlock->CountEntries(nullptr); mEntryBlock->CountEntries(nullptr);
mEntryBlock->BuildDominatorTree(nullptr);
#if 1 #if 1
do do
{ {
@ -19785,6 +20086,13 @@ void NativeCodeProcedure::Optimize(void)
#endif #endif
#endif #endif
if (step == 5)
{
ResetVisited();
if (mEntryBlock->AlternateXYUsage())
changed = true;
}
#if 1 #if 1
ResetVisited(); ResetVisited();
if (mEntryBlock->ForwardZpYIndex(step >= 4)) if (mEntryBlock->ForwardZpYIndex(step >= 4))

View File

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