diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 28e834e..5f741d8 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -1118,6 +1118,49 @@ static void PerformTempDefineForwarding(int temp, TempForwardingTable& forwardin } } +bool InterInstruction::PropagateConstTemps(const GrowingInstructionPtrArray& ctemps) +{ + switch (mCode) + { + case IC_LOAD: + if (mSTemp[0] >= 0 && ctemps[mSTemp[0]]) + { + InterInstruction* ains = ctemps[mSTemp[0]]; + mSIntConst[0] = ains->mIntValue; + mVarIndex = ains->mVarIndex; + mMemory = ains->mMemory; + mSTemp[0] = -1; + return true; + } + break; + case IC_STORE: + if (mSTemp[1] >= 0 && ctemps[mSTemp[1]]) + { + InterInstruction* ains = ctemps[mSTemp[1]]; + mSIntConst[1] = ains->mIntValue; + mVarIndex = ains->mVarIndex; + mMemory = ains->mMemory; + mSTemp[1] = -1; + return true; + } + break; + case IC_LOAD_TEMPORARY: + if (mSTemp[0] >= 0 && ctemps[mSTemp[0]]) + { + InterInstruction* ains = ctemps[mSTemp[0]]; + mCode = IC_CONSTANT; + mIntValue = ains->mIntValue; + mFloatValue = ains->mFloatValue; + mVarIndex = ains->mVarIndex; + mMemory = ains->mMemory; + mSTemp[0] = -1; + return true; + } + } + + return false; +} + void InterInstruction::PerformTempForwarding(TempForwardingTable& forwardingTable) { PerformTempUseForwarding(mSTemp[0], forwardingTable); @@ -2187,6 +2230,60 @@ void InterCodeBasicBlock::MarkAliasedLocalTemps(const GrowingIntArray& localTabl } } +void InterCodeBasicBlock::CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps) +{ + int i; + + if (!mVisited) + { + mVisited = true; + + for (i = 0; i < mInstructions.Size(); i++) + { + int ttemp = mInstructions[i].mTTemp; + if (ttemp >= 0) + { + if (assignedTemps[ttemp]) + ctemps[ttemp] = nullptr; + else + { + assignedTemps += ttemp; + if (mInstructions[i].mCode == IC_CONSTANT) + ctemps[ttemp] = &(mInstructions[i]); + } + } + } + + if (mTrueJump) mTrueJump->CollectConstTemps(ctemps, assignedTemps); + if (mFalseJump) mFalseJump->CollectConstTemps(ctemps, assignedTemps); + } +} + +bool InterCodeBasicBlock::PropagateConstTemps(const GrowingInstructionPtrArray& ctemps) +{ + bool changed = false; + + int i; + + if (!mVisited) + { + mVisited = true; + + for (i = 0; i < mInstructions.Size(); i++) + { + if (mInstructions[i].PropagateConstTemps(ctemps)) + changed = true; + } + + if (mTrueJump && mTrueJump->PropagateConstTemps(ctemps)) + changed = true; + if (mFalseJump && mFalseJump->PropagateConstTemps(ctemps)) + changed = true; + } + + return changed; +} + void InterCodeBasicBlock::BuildLocalTempSets(int num, int numFixed) { int i; @@ -3472,6 +3569,8 @@ void InterCodeProcedure::Close(void) ResetVisited(); mBlocks[0]->PerformMachineSpecificValueUsageCheck(mValueForwardingTable, tvalidSet); + GlobalConstantPropagation(); + DisassembleDebug("machine value forwarding"); // @@ -3575,7 +3674,9 @@ void InterCodeProcedure::Close(void) RenameTemporaries(); - TempForwarding(); + do { + TempForwarding(); + } while (GlobalConstantPropagation()); // // Now remove unused instructions @@ -3635,6 +3736,20 @@ void InterCodeProcedure::MapVariables(void) } } +bool InterCodeProcedure::GlobalConstantPropagation(void) +{ + + NumberSet assignedTemps(mTemporaries.Size()); + GrowingInstructionPtrArray ctemps(nullptr); + + + ResetVisited(); + mBlocks[0]->CollectConstTemps(ctemps, assignedTemps); + + ResetVisited(); + return mBlocks[0]->PropagateConstTemps(ctemps); +} + void InterCodeProcedure::ReduceTemporaries(void) { NumberSet* collisionSet; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index b727581..eb7d2ed 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -293,6 +293,7 @@ public: void GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries); void PerformTempForwarding(TempForwardingTable& forwardingTable); + bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps); void BuildCollisionTable(NumberSet& liveTemps, NumberSet* collisionSets); void ReduceTemporaries(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries); @@ -385,6 +386,9 @@ public: void CollectLocalAddressTemps(GrowingIntArray& localTable, GrowingIntArray& paramTable); void MarkAliasedLocalTemps(const GrowingIntArray& localTable, NumberSet& aliasedLocals, const GrowingIntArray& paramTable, NumberSet& aliasedParams); + void CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps); + bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps); + void BuildLocalTempSets(int num, int numFixed); void BuildGlobalProvidedTempSet(NumberSet fromProvidedTemps); bool BuildGlobalRequiredTempSet(NumberSet& fromRequiredTemps); @@ -478,6 +482,7 @@ protected: void RenameTemporaries(void); void TempForwarding(void); void RemoveUnusedInstructions(void); + bool GlobalConstantPropagation(void); void DisassembleDebug(const char* name); }; diff --git a/oscar64/NumberSet.h b/oscar64/NumberSet.h index bea31e6..54a07a7 100644 --- a/oscar64/NumberSet.h +++ b/oscar64/NumberSet.h @@ -1,5 +1,7 @@ #pragma once +#include + typedef unsigned __int32 uint32; class NumberSet @@ -35,6 +37,7 @@ public: __forceinline NumberSet& NumberSet::operator+=(int elem) { + assert(elem >= 0 && elem < size); bits[elem >> 5] |= (1UL << (elem & 31)); return *this; @@ -42,6 +45,7 @@ __forceinline NumberSet& NumberSet::operator+=(int elem) __forceinline NumberSet& NumberSet::operator-=(int elem) { + assert(elem >= 0 && elem < size); bits[elem >> 5] &= ~(1UL << (elem & 31)); return *this; @@ -49,6 +53,7 @@ __forceinline NumberSet& NumberSet::operator-=(int elem) __forceinline bool NumberSet::operator[](int elem) const { + assert(elem >= 0 && elem < size); return (bits[elem >> 5] & (1UL << (elem & 31))) != 0; }