diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index f13b166b..3dc886ae 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -5413,20 +5413,30 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(bool initial, const Growin assert(mLocalValueRange.Size() == mExitRequiredTemps.Size()); + bool firstEntry = true; + for (int j = 0; j < mEntryBlocks.Size(); j++) { InterCodeBasicBlock* from = mEntryBlocks[j]; GrowingIntegerValueRangeArray& range(this == from->mTrueJump ? from->mTrueValueRange : from->mFalseValueRange); - if (j == 0) - mLocalValueRange = range; - else + + if (range.Size()) { - for (int i = 0; i < mLocalValueRange.Size(); i++) - mLocalValueRange[i].Merge(range[i], mLoopHead, initial); + if (firstEntry) + { + firstEntry = false; + mLocalValueRange = range; + } + else + { + for (int i = 0; i < mLocalValueRange.Size(); i++) + mLocalValueRange[i].Merge(range[i], mLoopHead, initial); + } } - assert(mLocalValueRange.Size() == mExitRequiredTemps.Size()); } + assert(mLocalValueRange.Size() == mExitRequiredTemps.Size()); + for (int i = 0; i < mLocalValueRange.Size(); i++) if (!mLocalValueRange[i].Same(mEntryValueRange[i])) changed = true; @@ -5715,15 +5725,14 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray vr.mMinState = IntegerValueRange::S_UNBOUND; } -#if 0 +#if 1 if (ins->mDst.mType == IT_INT8) { - if (vr.mMinValue < 0) - vr.mMaxValue = 255; - if (vr.mMaxValue > 127) - vr.mMinValue = -128; - vr.LimitMax(255); - vr.LimitMin(-128); + if (vr.mMinState == IntegerValueRange::S_BOUND && vr.mMinValue < -255 || vr.mMaxState == IntegerValueRange::S_BOUND && vr.mMaxValue > 255) + { + vr.LimitMax(255); + vr.LimitMin(-128); + } } #endif break; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index f8fba155..43bb1ded 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -1018,6 +1018,11 @@ bool NativeCodeInstruction::ChangesXReg(void) const return mType == ASMIT_TAX || mType == ASMIT_LDX || mType == ASMIT_INX || mType == ASMIT_DEX || mType == ASMIT_JSR; } +bool NativeCodeInstruction::ReferencesCarry(void) const +{ + return ChangesCarry() || RequiresCarry(); +} + bool NativeCodeInstruction::ReferencesAccu(void) const { return ChangesAccu() || RequiresAccu(); @@ -3292,38 +3297,47 @@ bool NativeCodeInstruction::ValueForwarding(NativeRegisterDataSet& data, AsmInsT break; case ASMIT_STA: - data.ResetZeroPage(mAddress); - if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE || data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE_ADDRESS) + if (data.mRegs[mAddress].SameData(data.mRegs[CPU_REG_A]) || data.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE && data.mRegs[CPU_REG_A].mValue == mAddress) { - data.mRegs[mAddress] = data.mRegs[CPU_REG_A]; + mType = ASMIT_NOP; + mMode = ASMIM_IMPLIED; + changed = true; } - else if (data.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE) + else { + data.ResetZeroPage(mAddress); + if (data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE || data.mRegs[CPU_REG_A].mMode == NRDM_IMMEDIATE_ADDRESS) + { + data.mRegs[mAddress] = data.mRegs[CPU_REG_A]; + } + else if (data.mRegs[CPU_REG_A].mMode == NRDM_ZERO_PAGE) + { #if 1 - if (data.mRegs[data.mRegs[CPU_REG_A].mValue].mMode == NRDM_UNKNOWN && - (mAddress >= BC_REG_FPARAMS && mAddress < BC_REG_FPARAMS_END) && - !(data.mRegs[CPU_REG_A].mValue >= BC_REG_FPARAMS && data.mRegs[CPU_REG_A].mValue < BC_REG_FPARAMS_END)) + if (data.mRegs[data.mRegs[CPU_REG_A].mValue].mMode == NRDM_UNKNOWN && + (mAddress >= BC_REG_FPARAMS && mAddress < BC_REG_FPARAMS_END) && + !(data.mRegs[CPU_REG_A].mValue >= BC_REG_FPARAMS && data.mRegs[CPU_REG_A].mValue < BC_REG_FPARAMS_END)) + { + data.mRegs[data.mRegs[CPU_REG_A].mValue].mMode = NRDM_ZERO_PAGE; + data.mRegs[data.mRegs[CPU_REG_A].mValue].mValue = mAddress; + data.mRegs[mAddress].Reset(); + } + else +#endif + { + data.mRegs[mAddress].mMode = NRDM_ZERO_PAGE; + data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_A].mValue; + } + + } + else if (data.mRegs[CPU_REG_A].mMode == NRDM_ABSOLUTE) { - data.mRegs[data.mRegs[CPU_REG_A].mValue].mMode = NRDM_ZERO_PAGE; - data.mRegs[data.mRegs[CPU_REG_A].mValue].mValue = mAddress; - data.mRegs[mAddress].Reset(); + data.mRegs[mAddress] = data.mRegs[CPU_REG_A]; } else -#endif { - data.mRegs[mAddress].mMode = NRDM_ZERO_PAGE; - data.mRegs[mAddress].mValue = data.mRegs[CPU_REG_A].mValue; + data.mRegs[CPU_REG_A].mMode = NRDM_ZERO_PAGE; + data.mRegs[CPU_REG_A].mValue = mAddress; } - - } - else if (data.mRegs[CPU_REG_A].mMode == NRDM_ABSOLUTE) - { - data.mRegs[mAddress] = data.mRegs[CPU_REG_A]; - } - else - { - data.mRegs[CPU_REG_A].mMode = NRDM_ZERO_PAGE; - data.mRegs[CPU_REG_A].mValue = mAddress; } break; case ASMIT_STX: @@ -13496,7 +13510,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) mIns[i + 4].mType == ASMIT_AND && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 5].mType == ASMIT_EOR && mIns[i + 5].mMode == ASMIM_IMMEDIATE) { - char veq = mIns[i + 4].mAddress ^ mIns[i + 5].mAddress, vne = mIns[i + 5].mAddress; + uint8 veq = mIns[i + 4].mAddress ^ mIns[i + 5].mAddress, vne = mIns[i + 5].mAddress; changed = true; @@ -13600,7 +13614,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) mIns[i + 3].mType == ASMIT_AND && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mType == ASMIT_EOR && mIns[i + 4].mMode == ASMIM_IMMEDIATE) { - char veq = mIns[i + 3].mAddress ^ mIns[i + 4].mAddress, vne = mIns[i + 4].mAddress; + uint8 veq = mIns[i + 3].mAddress ^ mIns[i + 4].mAddress, vne = mIns[i + 4].mAddress; changed = true; @@ -13643,7 +13657,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress == 0xff && mIns[i + 4].mType == ASMIT_AND && mIns[i + 4].mMode == ASMIM_IMMEDIATE) { - char veq = mIns[i + 4].mAddress, vne = 0; + uint8 veq = mIns[i + 4].mAddress, vne = 0; changed = true; @@ -14293,6 +14307,147 @@ bool NativeCodeBasicBlock::ReduceLocalXPressure(void) return changed; } +bool NativeCodeBasicBlock::CombineZPPair(int at, int r0, int r1, bool use0, bool use1) +{ + bool changed = false; + + int i = at; + while (i < mIns.Size() && !use0 && !use1) + { + NativeCodeInstruction& ins(mIns[i]); + + if (ins.mMode == ASMIM_ZERO_PAGE) + { + if (ins.ChangesAddress()) + { + if (ins.mAddress == r0) + use1 = true; + else if (ins.mAddress == r1) + use0 = true; + } + else if (!(ins.mLive & LIVE_MEM)) + { + if (ins.mAddress == r0) + use1 = true; + else if (ins.mAddress == r1) + use0 = true; + } + } + else + { + if (ins.ReferencesZeroPage(r0)) + use0 = true; + if (ins.ReferencesZeroPage(r1)) + use1 = true; + } + + i++; + } + + if (use0 && use1) + return false; + + if (!use0 && !use1) + { + if (!mExitRequiredRegs[r0]) + use1 = true; + else if (!mExitRequiredRegs[r1]) + use0 = true; + else + return false; + } + + bool valid0 = true, valid1 = true; + + i = at; + while (i < mIns.Size() && valid0 && valid1) + { + NativeCodeInstruction& ins(mIns[i]); + + if (ins.mMode == ASMIM_ZERO_PAGE) + { + if (ins.ChangesAddress()) + { + if (ins.mAddress == r0) + valid0 = false; + else if (ins.mAddress == r1) + valid1 = false; + } + else + { + if (use1) + { + if (ins.mAddress == r0) + { + ins.mAddress = r1; + changed = true; + } + else if (ins.mAddress == r1) + ins.mLive |= LIVE_MEM; + } + else if (use0) + { + if (ins.mAddress == r1) + { + ins.mAddress = r0; + changed = true; + } + else if (ins.mAddress == r0) + ins.mLive |= LIVE_MEM; + } + } + } + else if (ins.ChangesZeroPage(r0)) + valid0 = false; + else if (ins.ChangesZeroPage(r1)) + valid1 = false; + + i++; + } + + return changed; +} + +bool NativeCodeBasicBlock::RemoveDoubleZPStore(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + for (int i = 0; i + 1 < mIns.Size(); i++) + { + if (mIns[i + 0].mType == ASMIT_STX && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_STX && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress != mIns[i + 1].mAddress) + { + if (CombineZPPair(i + 2, mIns[i + 0].mAddress, mIns[i + 1].mAddress, false, false)) + changed = true; + } + else if (mIns[i + 0].mType == ASMIT_STA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress != mIns[i + 1].mAddress) + { + if (CombineZPPair(i + 2, mIns[i + 0].mAddress, mIns[i + 1].mAddress, false, false)) + changed = true; + } + else if (mIns[i + 0].mType == ASMIT_STY && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_STY && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 0].mAddress != mIns[i + 1].mAddress) + { + if (CombineZPPair(i + 2, mIns[i + 0].mAddress, mIns[i + 1].mAddress, false, false)) + changed = true; + } + } + + if (mTrueJump && mTrueJump->RemoveDoubleZPStore()) + changed = true; + + if (mFalseJump && mFalseJump->RemoveDoubleZPStore()) + changed = true; + } + + return changed; +} + bool NativeCodeBasicBlock::LocalRegisterXYMap(void) { bool changed = false; @@ -17791,6 +17946,30 @@ bool NativeCodeBasicBlock::JoinTAXARange(int from, int to) CheckLive(); + return true; + } + else if (ins.mMode == ASMIM_INDIRECT_Y) + { + for (int i = from + 1; i < to; i++) + { + if (mIns[i].MayBeSameAddress(ins)) + return false; + else if (mIns[i].ChangesZeroPage(ins.mAddress) || mIns[i].ChangesZeroPage(ins.mAddress + 1)) + return false; + else if (mIns[i].ChangesYReg()) + return false; + } + + ins.mLive |= mIns[from].mLive; + + mIns.Remove(to); + mIns.Remove(to); + mIns.Remove(from); + + mIns.Insert(from, ins); + + CheckLive(); + return true; } } @@ -20256,10 +20435,20 @@ bool NativeCodeBasicBlock::MoveASLMemUp(int at) { int j = at; while (j > 0 && !mIns[j - 1].SameEffectiveAddress(mIns[at])) + { + if ((mIns[at].mLive & LIVE_CPU_REG_C) && mIns[j - 1].ReferencesCarry()) + return false; j--; + } if (j > 0 && mIns[j - 1].mType == ASMIT_STA && !(mIns[j - 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) { + if (mIns[at].mLive & LIVE_CPU_REG_C) + { + for (int i = j - 1; i < at; i++) + mIns[i].mLive |= LIVE_CPU_REG_C; + } + mIns.Insert(j - 1, NativeCodeInstruction(mIns[at].mType)); mIns.Remove(at + 1); return true; @@ -23924,7 +24113,7 @@ bool NativeCodeBasicBlock::OptimizeSelect(NativeCodeProcedure* proc) { if (mBranch == ASMIT_BNE || mBranch == ASMIT_BEQ) { - char vt = mTrueJump->mIns[0].mAddress, vf = mFalseJump->mIns[0].mAddress; + uint8 vt = mTrueJump->mIns[0].mAddress, vf = mFalseJump->mIns[0].mAddress; mTrueJump = mTrueJump->mTrueJump; mFalseJump = nullptr; @@ -25883,7 +26072,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #if 1 for (int i = 2; i < mIns.Size(); i++) { - if ((mIns[i].mType == ASMIT_ASL || mIns[i].mType == ASMIT_LSR) && mIns[i].mMode == ASMIM_ZERO_PAGE && !(mIns[i].mLive & (LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + if ((mIns[i].mType == ASMIT_ASL || mIns[i].mType == ASMIT_LSR) && mIns[i].mMode == ASMIM_ZERO_PAGE && !(mIns[i].mLive & LIVE_CPU_REG_Z)) { if (MoveASLMemUp(i)) changed = true; @@ -28944,6 +29133,17 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; progress = true; } + else if ( + mIns[i + 0].mType == ASMIT_STX && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && mIns[i + 1].mAddress != mIns[i + 0].mAddress && + mIns[i + 2].mType == ASMIT_TXA && + mIns[i + 3].IsCommutative() && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress) + { + mIns[i + 2].mType = ASMIT_NOP; + mIns[i + 1].mLive |= LIVE_CPU_REG_A; + mIns[i + 3].mAddress = mIns[i + 0].mAddress; + progress = true; + } if ( mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && @@ -31626,7 +31826,7 @@ void NativeCodeProcedure::RebuildEntry(void) void NativeCodeProcedure::Optimize(void) { - CheckFunc = !strcmp(mInterProc->mIdent->mString, "chains_draw"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "chain_prepend"); #if 1 int step = 0; int cnt = 0; @@ -31789,6 +31989,12 @@ void NativeCodeProcedure::Optimize(void) } #endif + if (step == 4) + { + ResetVisited(); + if (mEntryBlock->RemoveDoubleZPStore()) + changed = true; + } #if 1 if (step > 0) { @@ -32142,6 +32348,45 @@ void NativeCodeProcedure::Optimize(void) CompressTemporaries(); #endif +#if 1 + do + { + RebuildEntry(); + + BuildDataFlowSets(); + ResetVisited(); + changed = mEntryBlock->RemoveUnusedResultInstructions(); + + if (!changed) + { + ResetVisited(); + NativeRegisterDataSet data; + if (mEntryBlock->ValueForwarding(data, true, true)) + { + changed = true; + } + else + { +#if 1 + ResetPatched(); + mEntryBlock->CheckVisited(); + + ResetVisited(); + if (mEntryBlock->GlobalValueForwarding()) + changed = true; +#endif + } + } + + if (!changed) + { + ResetVisited(); + changed = mEntryBlock->PeepHoleOptimizer(this, 10); + } + + } while (changed); +#endif + #if 1 ResetVisited(); mEntryBlock->BlockSizeReduction(this, -1, -1); diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 5731d665..97687038 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -122,6 +122,7 @@ class NativeCodeInstruction bool ChangesYReg(void) const; bool ChangesXReg(void) const; + bool ReferencesCarry(void) const; bool ReferencesAccu(void) const; bool ReferencesYReg(void) const; bool ReferencesXReg(void) const; @@ -422,6 +423,9 @@ class NativeCodeBasicBlock bool ReduceLocalYPressure(void); bool ReduceLocalXPressure(void); + bool CombineZPPair(int at, int r0, int r1, bool use0, bool use1); + bool RemoveDoubleZPStore(void); + bool ExpandADCToBranch(NativeCodeProcedure* proc); bool Split16BitLoopCount(NativeCodeProcedure* proc); bool SimplifyDiamond(NativeCodeProcedure* proc); diff --git a/oscar64/oscar64.cpp b/oscar64/oscar64.cpp index adb6f216..bc1f1358 100644 --- a/oscar64/oscar64.cpp +++ b/oscar64/oscar64.cpp @@ -74,7 +74,7 @@ int main2(int argc, const char** argv) #else strcpy(strProductName, "oscar64"); - strcpy(strProductVersion, "1.12.175"); + strcpy(strProductVersion, "1.12.176"); #ifdef __APPLE__ uint32_t length = sizeof(basePath); diff --git a/oscar64/oscar64.rc b/oscar64/oscar64.rc index a2c6d080..053fd21f 100644 --- a/oscar64/oscar64.rc +++ b/oscar64/oscar64.rc @@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,12,175,0 - PRODUCTVERSION 1,12,175,0 + FILEVERSION 1,12,176,0 + PRODUCTVERSION 1,12,176,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -43,12 +43,12 @@ BEGIN BEGIN VALUE "CompanyName", "oscar64" VALUE "FileDescription", "oscar64 compiler" - VALUE "FileVersion", "1.12.175.0" + VALUE "FileVersion", "1.12.176.0" VALUE "InternalName", "oscar64.exe" VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "OriginalFilename", "oscar64.exe" VALUE "ProductName", "oscar64" - VALUE "ProductVersion", "1.12.175.0" + VALUE "ProductVersion", "1.12.176.0" END END BLOCK "VarFileInfo" diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index 8e3658c8..e70333fd 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -4450,15 +4450,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:oscar64" - "ProductCode" = "8:{2D54553F-8D43-43A2-9E21-D8825A9DA799}" - "PackageCode" = "8:{32868128-65EE-44DF-B846-310909366FA6}" + "ProductCode" = "8:{E0F08F69-BB99-4D80-9DBA-6C7898ED4DDB}" + "PackageCode" = "8:{8623BC03-009C-4E14-9DC8-16C927655E48}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "AspNetVersion" = "8:2.0.50727.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:FALSE" - "ProductVersion" = "8:1.12.175" + "ProductVersion" = "8:1.12.176" "Manufacturer" = "8:oscar64" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:"