From d2503aaf1f62de5c434339d8b61e590d67c19962 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 27 Mar 2022 17:18:44 +0200 Subject: [PATCH] Constant folding address of global and static variables --- include/c64/rasterirq.h | 8 + oscar64/Declaration.cpp | 11 + oscar64/InterCode.cpp | 66 +++++- oscar64/InterCode.h | 6 +- oscar64/InterCodeGenerator.cpp | 5 + oscar64/NativeCodeGenerator.cpp | 392 ++++++++++++++++++++++++++++---- oscar64/NativeCodeGenerator.h | 31 ++- 7 files changed, 454 insertions(+), 65 deletions(-) diff --git a/include/c64/rasterirq.h b/include/c64/rasterirq.h index ca54c52..f47cc5d 100644 --- a/include/c64/rasterirq.h +++ b/include/c64/rasterirq.h @@ -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); diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 4a610b5..8a978d4 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -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) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 9ca1c44..ba65777 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -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()) { diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index bf86625..45c7e30 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -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; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index f03bb37..be0a728 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -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 { diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 5fc5a93..e4f8920 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -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)) diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index f44139f..91befb0 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -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 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