diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 4f666e7..4eb3ce9 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -99,6 +99,9 @@ if %errorlevel% neq 0 goto :error call :test structmembertest.c if %errorlevel% neq 0 goto :error +call :test randsumtest.c +if %errorlevel% neq 0 goto :error + exit /b 0 :error diff --git a/autotest/randsumtest.c b/autotest/randsumtest.c new file mode 100644 index 0000000..cbb9aa0 --- /dev/null +++ b/autotest/randsumtest.c @@ -0,0 +1,16 @@ +// randsumtest + +#include +#include + +int main(void) +{ + long lsum = 0; + for(unsigned i=0; i<1000; i++) + lsum += rand(); + + assert(lsum == 32157742L); + + return 0 +} + diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index fb7cd67..3c77e53 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -1291,6 +1291,40 @@ void InterInstruction::FilterTempUsage(NumberSet& requiredTemps, NumberSet& prov FilterTempDefineUsage(requiredTemps, providedTemps, mDst.mTemp); } +void InterInstruction::FilterStaticVarsUsage(const GrowingVariableArray& staticVars, NumberSet& requiredVars, NumberSet& providedVars) +{ + if (mCode == IC_LOAD) + { + if (mSrc[0].mMemory == IM_INDIRECT) + { + requiredVars.OrNot(providedVars); + } + else if (mSrc[0].mMemory == IM_GLOBAL) + { + if (!providedVars[mSrc[0].mVarIndex]) + requiredVars += mSrc[0].mVarIndex; + } + } + else if (mCode == IC_STORE) + { + if (mSrc[1].mMemory == IM_INDIRECT) + { + requiredVars.OrNot(providedVars); + } + else if (mSrc[1].mMemory == IM_GLOBAL) + { + if (mSrc[1].mIntConst == 0 && mSrc[1].mOperandSize == staticVars[mSrc[1].mVarIndex]->mSize) + providedVars += mSrc[1].mVarIndex; + else if (!providedVars[mSrc[1].mVarIndex]) + requiredVars += mSrc[1].mVarIndex; + } + } + else if (mCode == IC_COPY || mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE) + { + requiredVars.OrNot(providedVars); + } +} + void InterInstruction::FilterVarsUsage(const GrowingVariableArray& localVars, NumberSet& requiredVars, NumberSet& providedVars, const GrowingVariableArray& params, NumberSet& requiredParams, NumberSet& providedParams, InterMemory paramMemory) { if (mCode == IC_LOAD) @@ -1522,6 +1556,49 @@ bool InterInstruction::RemoveUnusedStoreInstructions(const GrowingVariableArray& return changed; } +bool InterInstruction::RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars, NumberSet& requiredVars) +{ + bool changed = false; + + if (mCode == IC_LOAD) + { + if (mSrc[0].mMemory == IM_INDIRECT) + { + requiredVars.Fill(); + } + else if (mSrc[0].mMemory == IM_GLOBAL) + { + requiredVars += mSrc[0].mVarIndex; + } + } + else if (mCode == IC_STORE) + { + if (mSrc[1].mMemory == IM_GLOBAL) + { + if (requiredVars[mSrc[1].mVarIndex]) + { + if (mSrc[1].mIntConst == 0 && mSrc[1].mOperandSize == staticVars[mSrc[1].mVarIndex]->mSize) + requiredVars -= mSrc[1].mVarIndex; + } + else if (!mVolatile) + { + mCode = IC_NONE; + changed = true; + } + } + } + else if (mCode == IC_COPY) + { + requiredVars.Fill(); + } + else if (mCode == IC_CALL || mCode == IC_CALL_NATIVE || mCode == IC_RETURN || mCode == IC_RETURN_STRUCT || mCode == IC_RETURN_VALUE) + { + requiredVars.Fill(); + } + + return changed; +} + bool InterInstruction::UsesTemp(int temp) const { for (int i = 0; i < mNumOperands; i++) @@ -1789,13 +1866,13 @@ void InterInstruction::Disassemble(FILE* file) fprintf(file, "BINOP%d", mOperator); break; case IC_UNARY_OPERATOR: - fprintf(file, "UNOP"); + fprintf(file, "UNOP%d", mOperator); break; case IC_RELATIONAL_OPERATOR: - fprintf(file, "RELOP"); + fprintf(file, "RELOP%d", mOperator); break; case IC_CONVERSION_OPERATOR: - fprintf(file, "CONV"); + fprintf(file, "CONV%d", mOperator); break; case IC_STORE: fprintf(file, "STORE%c%d", memchars[mSrc[1].mMemory], mSrc[1].mOperandSize); @@ -2874,6 +2951,108 @@ void InterCodeBasicBlock::BuildCallerSaveTempSet(NumberSet& callerSaveTemps) } +void InterCodeBasicBlock::BuildStaticVariableSet(const GrowingVariableArray& staticVars) +{ + if (!mVisited) + { + mVisited = true; + + mLocalRequiredStatics = NumberSet(staticVars.Size()); + mLocalProvidedStatics = NumberSet(staticVars.Size()); + + mEntryRequiredStatics = NumberSet(staticVars.Size()); + mEntryProvidedStatics = NumberSet(staticVars.Size()); + mExitRequiredStatics = NumberSet(staticVars.Size()); + mExitProvidedStatics = NumberSet(staticVars.Size()); + + for (int i = 0; i < mInstructions.Size(); i++) + mInstructions[i]->FilterStaticVarsUsage(staticVars, mLocalRequiredStatics, mLocalProvidedStatics); + + mEntryRequiredStatics = mLocalRequiredStatics; + mExitProvidedStatics = mLocalProvidedStatics; + + if (mTrueJump) mTrueJump->BuildStaticVariableSet(staticVars); + if (mFalseJump) mFalseJump->BuildStaticVariableSet(staticVars); + } +} + +void InterCodeBasicBlock::BuildGlobalProvidedStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet fromProvidedVars) +{ + if (!mVisited || !(fromProvidedVars <= mEntryProvidedStatics)) + { + mEntryProvidedStatics |= fromProvidedVars; + fromProvidedVars |= mExitProvidedStatics; + + mVisited = true; + + if (mTrueJump) mTrueJump->BuildGlobalProvidedStaticVariableSet(staticVars, fromProvidedVars); + if (mFalseJump) mFalseJump->BuildGlobalProvidedStaticVariableSet(staticVars, fromProvidedVars); + } +} + +bool InterCodeBasicBlock::BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars) +{ + bool revisit = false; + int i; + + if (!mVisited) + { + mVisited = true; + + NumberSet newRequiredVars(mExitRequiredStatics); + + if (mTrueJump && mTrueJump->BuildGlobalRequiredStaticVariableSet(staticVars, newRequiredVars)) revisit = true; + if (mFalseJump && mFalseJump->BuildGlobalRequiredStaticVariableSet(staticVars, newRequiredVars)) revisit = true; + + if (!(newRequiredVars <= mExitRequiredStatics)) + { + revisit = true; + + mExitRequiredStatics = newRequiredVars; + newRequiredVars -= mLocalProvidedStatics; + mEntryRequiredStatics |= newRequiredVars; + } + + } + + fromRequiredVars |= mEntryRequiredStatics; + + return revisit; +} + +bool InterCodeBasicBlock::RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + + NumberSet requiredVars(mExitRequiredStatics); + + int i; + + for (i = mInstructions.Size() - 1; i >= 0; i--) + { + if (mInstructions[i]->RemoveUnusedStaticStoreInstructions(staticVars, requiredVars)) + changed = true; + } + + if (mTrueJump) + { + if (mTrueJump->RemoveUnusedStaticStoreInstructions(staticVars)) + changed = true; + } + if (mFalseJump) + { + if (mFalseJump->RemoveUnusedStaticStoreInstructions(staticVars)) + changed = true; + } + } + + return changed; +} + void InterCodeBasicBlock::BuildLocalVariableSets(const GrowingVariableArray& localVars, const GrowingVariableArray& params, InterMemory paramMemory) { int i; @@ -4809,6 +4988,30 @@ void InterCodeProcedure::Close(void) DisassembleDebug("removed unused local stores"); } + // Remove unused global stores + + if (mModule->mGlobalVars.Size()) + { + do { + ResetVisited(); + mEntryBlock->BuildStaticVariableSet(mModule->mGlobalVars); + + ResetVisited(); + mEntryBlock->BuildGlobalProvidedStaticVariableSet(mModule->mGlobalVars, NumberSet(mModule->mGlobalVars.Size())); + + NumberSet totalRequired2(mModule->mGlobalVars.Size()); + + do { + ResetVisited(); + } while (mEntryBlock->BuildGlobalRequiredStaticVariableSet(mModule->mGlobalVars, totalRequired2)); + + ResetVisited(); + } while (mEntryBlock->RemoveUnusedStaticStoreInstructions(mModule->mGlobalVars)); + + DisassembleDebug("removed unused static stores"); + } + + // // Promote local variables to temporaries // diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index af39322..b6cd1c4 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -332,9 +332,11 @@ public: void FilterTempUsage(NumberSet& requiredTemps, NumberSet& providedTemps); void FilterVarsUsage(const GrowingVariableArray& localVars, NumberSet& requiredVars, NumberSet& providedVars, const GrowingVariableArray& params, NumberSet& requiredParams, NumberSet& providedParams, InterMemory paramMemory); - + void FilterStaticVarsUsage(const GrowingVariableArray& staticVars, NumberSet& requiredVars, NumberSet& providedVars); + bool RemoveUnusedResultInstructions(InterInstruction* pre, NumberSet& requiredTemps); bool RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, NumberSet& requiredVars, const GrowingVariableArray& params, NumberSet& requiredParams, InterMemory paramMemory); + bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars, NumberSet& requiredVars); void PerformValueForwarding(GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid); void BuildCallerSaveTempSet(NumberSet& requiredTemps, NumberSet& callerSaveTemps); @@ -418,6 +420,10 @@ public: NumberSet mEntryRequiredVars, mEntryProvidedVars; NumberSet mExitRequiredVars, mExitProvidedVars; + NumberSet mLocalRequiredStatics, mLocalProvidedStatics; + NumberSet mEntryRequiredStatics, mEntryProvidedStatics; + NumberSet mExitRequiredStatics, mExitProvidedStatics; + NumberSet mLocalRequiredParams, mLocalProvidedParams; NumberSet mEntryRequiredParams, mEntryProvidedParams; NumberSet mExitRequiredParams, mExitProvidedParams; @@ -454,6 +460,11 @@ public: bool BuildGlobalRequiredVariableSet(const GrowingVariableArray& localVars, NumberSet& fromRequiredVars, const GrowingVariableArray& params, NumberSet& fromRequiredParams, InterMemory paramMemory); bool RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, const GrowingVariableArray& params, InterMemory paramMemory); + void BuildStaticVariableSet(const GrowingVariableArray& staticVars); + void BuildGlobalProvidedStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet fromProvidedVars); + bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars); + bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars); + GrowingIntArray mEntryRenameTable; GrowingIntArray mExitRenameTable; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 03077c7..65da3a7 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -564,6 +564,8 @@ bool NativeCodeInstruction::UsesZeroPage(int address) const { if (mMode == ASMIM_ZERO_PAGE && mAddress == address) return true; + else if (mMode == ASMIM_INDIRECT_Y && (mAddress == address || mAddress == address + 1)) + return true; else return false; } @@ -9168,28 +9170,28 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) } else if ( mIns[i + 0].mType == ASMIT_TXA && - mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE) + mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE)) { mIns[i + 1].mType = ASMIT_STX; progress = true; } else if ( mIns[i + 0].mType == ASMIT_TYA && - mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE) + mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE)) { mIns[i + 1].mType = ASMIT_STY; progress = true; } else if ( mIns[i + 0].mType == ASMIT_TAX && - mIns[i + 1].mType == ASMIT_STX && mIns[i + 1].mMode == ASMIM_ZERO_PAGE) + mIns[i + 1].mType == ASMIT_STX && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE)) { mIns[i + 1].mType = ASMIT_STA; progress = true; } else if ( mIns[i + 0].mType == ASMIT_TAY && - mIns[i + 1].mType == ASMIT_STY && mIns[i + 1].mMode == ASMIM_ZERO_PAGE) + mIns[i + 1].mType == ASMIT_STY && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE)) { mIns[i + 1].mType = ASMIT_STA; progress = true; @@ -9223,7 +9225,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) progress = true; } else if ( - mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) && mIns[i + 1].mType == ASMIT_TAY && !(mIns[i + 1].mLive & LIVE_CPU_REG_A)) { mIns[i + 0].mType = ASMIT_LDY; mIns[i + 0].mLive |= mIns[i + 1].mLive; @@ -9231,7 +9233,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(void) progress = true; } else if ( - mIns[i + 0].mType == ASMIT_LDA && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && + mIns[i + 0].mType == ASMIT_LDA && (mIns[i + 0].mMode == ASMIM_ZERO_PAGE || mIns[i + 0].mMode == ASMIM_ABSOLUTE) && mIns[i + 1].mType == ASMIT_TAX && !(mIns[i + 1].mLive & LIVE_CPU_REG_A)) { mIns[i + 0].mType = ASMIT_LDX; mIns[i + 0].mLive |= mIns[i + 1].mLive; @@ -10682,19 +10684,10 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode { if (ins->mSrc[0].mTemp != ins->mDst.mTemp) { - block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp])); - block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp])); - if (InterTypeSize[ins->mDst.mType] > 1) + for (int i = 0; i < InterTypeSize[ins->mDst.mType]; i++) { - block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 1)); - block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp] + 1)); - } - if (ins->mSrc[0].mType == IT_FLOAT) - { - block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 2)); - block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp] + 2)); - block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + 3)); - block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp] + 3)); + block->mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mSrc[0].mTemp] + i)); + block->mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + iproc->mTempOffset[ins->mDst.mTemp] + i)); } } } break; diff --git a/oscar64/NumberSet.cpp b/oscar64/NumberSet.cpp index cb7b222..6119c5f 100644 --- a/oscar64/NumberSet.cpp +++ b/oscar64/NumberSet.cpp @@ -68,6 +68,22 @@ void NumberSet::Reset(int size, bool set) } } +void NumberSet::Fill(void) +{ + int i; + + for (i = 0; i < dwsize; i++) + bits[i] = 0xffffffff; +} + +void NumberSet::OrNot(const NumberSet& set) +{ + int i; + + for (i = 0; i < dwsize; i++) + bits[i] |= ~set.bits[i]; +} + void NumberSet::Clear(void) { int i; diff --git a/oscar64/NumberSet.h b/oscar64/NumberSet.h index a66f411..7cf0640 100644 --- a/oscar64/NumberSet.h +++ b/oscar64/NumberSet.h @@ -30,7 +30,10 @@ public: bool operator<=(const NumberSet& set); + void OrNot(const NumberSet& set); + void Clear(void); + void Fill(void); int Size(void) { return size; } };