Optimize static and global variable usage

This commit is contained in:
drmortalwombat 2021-10-31 16:22:11 +01:00
parent b9cbf525e9
commit 7e340cc816
7 changed files with 267 additions and 22 deletions

View File

@ -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

16
autotest/randsumtest.c Normal file
View File

@ -0,0 +1,16 @@
// randsumtest
#include <stdlib.h>
#include <assert.h>
int main(void)
{
long lsum = 0;
for(unsigned i=0; i<1000; i++)
lsum += rand();
assert(lsum == 32157742L);
return 0
}

View File

@ -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
//

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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; }
};