From 3a94be4a35ad9caf6378ea1ba3e36b059aa0dc65 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 12 Sep 2021 17:28:02 +0200 Subject: [PATCH] Use caller saved registers for temps not overlapping calls --- oscar64/InterCode.cpp | 62 ++++++++++++++++++++++++++++++++++--------- oscar64/InterCode.h | 2 ++ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index c77aa64..bd7fcdf 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -1143,6 +1143,19 @@ bool InterInstruction::RemoveUnusedResultInstructions(InterInstruction* pre, Num return changed; } +void InterInstruction::BuildCallerSaveTempSet(NumberSet& requiredTemps, NumberSet& callerSaveTemps) +{ + if (mTTemp >= 0) + requiredTemps -= mTTemp; + + if (mCode == IC_CALL || mCode == IC_JSR) + callerSaveTemps |= requiredTemps; + + if (mSTemp[0] >= 0) requiredTemps += mSTemp[0]; + if (mSTemp[1] >= 0) requiredTemps += mSTemp[1]; + if (mSTemp[2] >= 0) requiredTemps += mSTemp[2]; +} + bool InterInstruction::RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, InterInstruction* pre, NumberSet& requiredTemps) { bool changed = false; @@ -2234,6 +2247,25 @@ bool InterCodeBasicBlock::RemoveUnusedResultInstructions(int numStaticTemps) return changed; } +void InterCodeBasicBlock::BuildCallerSaveTempSet(NumberSet& callerSaveTemps) +{ + if (!mVisited) + { + mVisited = true; + + NumberSet requiredTemps(mExitRequiredTemps); + int i; + + for (i = mInstructions.Size() - 1; i >= 0; i--) + mInstructions[i].BuildCallerSaveTempSet(requiredTemps, callerSaveTemps); + + if (mTrueJump) + mTrueJump->BuildCallerSaveTempSet(callerSaveTemps); + if (mFalseJump) + mFalseJump->BuildCallerSaveTempSet(callerSaveTemps); + } +} + void InterCodeBasicBlock::BuildLocalVariableSets(const GrowingVariableArray& localVars) { @@ -3564,25 +3596,31 @@ void InterCodeProcedure::ReduceTemporaries(void) ResetVisited(); } while (mBlocks[0]->BuildGlobalRequiredTempSet(totalRequired3)); + + NumberSet callerSaved(numRenamedTemps); + ResetVisited(); + mBlocks[0]->BuildCallerSaveTempSet(callerSaved); + + int callerSavedTemps = 0, calleeSavedTemps = 16; + mTempOffset.SetSize(0); - int offset = 0; - if (!mLeafProcedure) - offset += 16; for (int i = 0; i < mTemporaries.Size(); i++) { - mTempOffset.Push(offset); - switch (mTemporaries[i]) + int size = mTemporaries[i] == IT_FLOAT ? 4 : 2; + + if (callerSavedTemps + size <= 16 && !callerSaved[i]) { - case IT_FLOAT: - offset += 4; - break; - default: - offset += 2; - break; + mTempOffset.Push(callerSavedTemps); + callerSavedTemps += size; + } + else + { + mTempOffset.Push(calleeSavedTemps); + calleeSavedTemps += size; } } - mTempSize = offset; + mTempSize = calleeSavedTemps; } void InterCodeProcedure::Disassemble(const char* name, bool dumpSets) diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 96f7b64..ef9c21f 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -284,6 +284,7 @@ public: bool RemoveUnusedResultInstructions(InterInstruction* pre, NumberSet& requiredTemps, int numStaticTemps); bool RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, InterInstruction* pre, NumberSet& requiredTemps); void PerformValueForwarding(GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid); + void BuildCallerSaveTempSet(NumberSet& requiredTemps, NumberSet& callerSaveTemps); void LocalRenameRegister(GrowingIntArray& renameTable, int& num, int fixed); void GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries); @@ -382,6 +383,7 @@ public: void BuildGlobalProvidedTempSet(NumberSet fromProvidedTemps); bool BuildGlobalRequiredTempSet(NumberSet& fromRequiredTemps); bool RemoveUnusedResultInstructions(int numStaticTemps); + void BuildCallerSaveTempSet(NumberSet& callerSaveTemps); void BuildLocalVariableSets(const GrowingVariableArray& localVars); void BuildGlobalProvidedVariableSet(const GrowingVariableArray& localVars, NumberSet fromProvidedVars);