Optimize simple const ref to value in functions

This commit is contained in:
drmortalwombat 2023-08-18 13:13:39 +02:00
parent 0440f0ef19
commit 3a9cd85072
12 changed files with 210 additions and 18 deletions

View File

@ -955,6 +955,9 @@ bool Compiler::GenerateCode(void)
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
mLinker->ReferenceObject(mCompilationUnits->mReferenced[i]->mLinkerObject);
if (mCompilerOptions & COPT_OPTIMIZE_BASIC)
mLinker->CombineSameConst();
if (mCompilerOptions & COPT_VERBOSE)
printf("Link executable\n");

View File

@ -842,7 +842,7 @@ Declaration::Declaration(const Location& loc, DecType type)
mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0),
mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr),
mConst(nullptr), mMutable(nullptr),
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr),
mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mMoveConstructor(nullptr), mMoveAssignment(nullptr),
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr),
mVTable(nullptr), mTemplate(nullptr),
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr),
@ -1311,6 +1311,7 @@ Declaration* Declaration::ToConstType(void)
ndec->mDefaultConstructor = mDefaultConstructor;
ndec->mCopyConstructor = mCopyConstructor;
ndec->mMoveConstructor = mMoveConstructor;
ndec->mVectorConstructor = mVectorConstructor;
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
ndec->mVTable = mVTable;
@ -1341,6 +1342,7 @@ Declaration* Declaration::ToMutableType(void)
ndec->mDefaultConstructor = mDefaultConstructor;
ndec->mCopyConstructor = mCopyConstructor;
ndec->mMoveConstructor = mMoveConstructor;
ndec->mVectorConstructor = mVectorConstructor;
ndec->mVectorCopyConstructor = mVectorCopyConstructor;
ndec->mVTable = mVTable;

View File

@ -106,8 +106,9 @@ static const uint64 DTF_FUNC_PURE = (1ULL << 39);
static const uint64 DTF_FPARAM_CONST = (1ULL << 40);
static const uint64 DTF_FPARAM_NOCONST = (1ULL << 41);
static const uint64 DTF_VAR_ADDRESS = (1ULL << 42);
static const uint64 DTF_FUNC_THIS = (1ULL << 42);
static const uint64 DTF_FUNC_THIS = (1ULL << 43);
static const uint64 DTF_VAR_ALIASING = (1ULL << 48);
@ -255,7 +256,7 @@ public:
DecType mType;
Token mToken;
Declaration * mBase, * mParams, * mNext, * mPrev, * mConst, * mMutable;
Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment;
Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment, * mMoveConstructor, * mMoveAssignment;
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment;
Declaration * mVTable, * mClass, * mTemplate;

View File

@ -497,6 +497,21 @@ bool GlobalAnalyzer::IsStackParam(const Declaration* pdec) const
return false;
}
void GlobalAnalyzer::UndoParamReference(Expression* exp, Declaration * param)
{
if (exp)
{
if (exp->mType == EX_VARIABLE)
{
if (exp->mDecValue == param)
exp->mDecType = param->mBase;
}
UndoParamReference(exp->mLeft, param);
UndoParamReference(exp->mRight, param);
}
}
void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec)
{
dec->mUseCount++;
@ -535,6 +550,22 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec)
dec->mFlags |= DTF_FUNC_CONSTEXPR;
dec->mFlags |= DTF_FUNC_PURE;
Analyze(exp, dec, false);
Declaration* pdec = dec->mBase->mParams;
int vi = 0;
while (pdec)
{
pdec->mVarIndex += vi;
if (pdec->mBase->mType == DT_TYPE_REFERENCE && pdec->mBase->mBase->IsSimpleType() && !(pdec->mBase->mFlags & DTF_VAR_ADDRESS) && (pdec->mBase->mBase->mFlags & DTF_CONST))
{
pdec->mBase = pdec->mBase->mBase;
pdec->mSize = pdec->mBase->mSize;
vi += pdec->mSize - 2;
UndoParamReference(exp, pdec);
}
pdec = pdec->mNext;
}
}
else
mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent);
@ -672,6 +703,9 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
}
else
{
if (lhs)
exp->mDecValue->mFlags |= DTF_VAR_ADDRESS;
if (!(exp->mDecValue->mFlags & DTF_ANALYZED))
{
procDec->mLocalSize += exp->mDecValue->mSize;
@ -819,6 +853,11 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
if (pdec && pdec->mBase->mType == DT_TYPE_STRUCT && pdec->mBase->mCopyConstructor)
{
if (pdec->mBase->mMoveConstructor)
{
AnalyzeProcedure(pdec->mBase->mMoveConstructor->mValue, pdec->mBase->mMoveConstructor);
RegisterCall(procDec, pdec->mBase->mMoveConstructor);
}
AnalyzeProcedure(pdec->mBase->mCopyConstructor->mValue, pdec->mBase->mCopyConstructor);
RegisterCall(procDec, pdec->mBase->mCopyConstructor);
}
@ -846,6 +885,11 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
RegisterProc(Analyze(exp->mLeft, procDec, false));
if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor)
{
if (procDec->mBase->mBase->mMoveConstructor)
{
AnalyzeProcedure(procDec->mBase->mBase->mMoveConstructor->mValue, procDec->mBase->mBase->mMoveConstructor);
RegisterCall(procDec, procDec->mBase->mBase->mMoveConstructor);
}
AnalyzeProcedure(procDec->mBase->mBase->mCopyConstructor->mValue, procDec->mBase->mBase->mCopyConstructor);
RegisterCall(procDec, procDec->mBase->mBase->mCopyConstructor);
}

View File

@ -40,5 +40,6 @@ protected:
uint64 GetProcFlags(Declaration* to) const;
void RegisterCall(Declaration* from, Declaration* to);
void RegisterProc(Declaration* to);
void UndoParamReference(Expression* ex, Declaration* param);
};

View File

@ -3422,6 +3422,22 @@ bool InterInstruction::PropagateConstTemps(const GrowingInstructionPtrArray& cte
}
} break;
case IC_FREE:
{
if (mSrc[0].mTemp >= 0 && ctemps[mSrc[0].mTemp])
{
InterInstruction* ains = ctemps[mSrc[0].mTemp];
if (ains->mConst.mMemory == IM_ABSOLUTE && ains->mConst.mIntConst == 0)
{
mCode = IC_NONE;
mNumOperands = 0;
return true;
}
}
} break;
case IC_CONVERSION_OPERATOR:
case IC_UNARY_OPERATOR:
{
@ -15990,6 +16006,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l
mID = mModule->mProcedures.Size();
mModule->mProcedures.Push(this);
mLinkerObject->mProc = this;
mLinkerObject->mFlags |= LOBJF_CONST;
mCallerSavedTemps = BC_REG_TMP_SAVED - BC_REG_TMP;
}

View File

@ -1172,14 +1172,17 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
return ExValue(TheVoidTypeDeclaration);
}
void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper)
void InterCodeGenerator::CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving)
{
if (vr.mTemp == vl.mTemp)
return;
if (vl.mType->mCopyConstructor)
if (vl.mType->mCopyConstructor || moving && vl.mType->mMoveConstructor)
{
Declaration* ccdec = vl.mType->mCopyConstructor;
if (moving && vl.mType->mMoveConstructor)
ccdec = vl.mType->mMoveConstructor;
if (!ccdec->mLinkerObject)
this->TranslateProcedure(proc->mModule, ccdec->mValue, ccdec);
@ -3250,7 +3253,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
if (vp.mTemp != vr.mTemp)
{
CopyStruct(proc, exp, block, vp, vr, inlineMapper);
CopyStruct(proc, exp, block, vp, vr, inlineMapper, false);
#if 0
InterInstruction* cins = new InterInstruction(texp->mLocation, IC_COPY);
cins->mSrc[0].mType = IT_POINTER;
@ -3627,7 +3630,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
else if (vr.mReference != 1)
mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Non addressable object");
CopyStruct(proc, exp, block, rvr, vr, inlineMapper);
bool moving = exp->mLeft->IsRValue() || exp->mLeft->mType == EX_VARIABLE && !(exp->mLeft->mDecValue->mFlags & (DTF_STATIC | DTF_GLOBAL)) && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE;
CopyStruct(proc, exp, block, rvr, vr, inlineMapper, moving);
#if 0
if (procType->mBase->mCopyConstructor)
{
@ -4718,7 +4723,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
{
InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mQualIdent, mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_BYTE_CODE, dec->mAlignment));
#if 1
#if 0
if (proc->mIdent && !strcmp(proc->mIdent->mString, "dividers"))
exp->Dump(0);
#endif

View File

@ -85,7 +85,7 @@ protected:
ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr);
void TranslateLogic(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock* block, InterCodeBasicBlock* tblock, InterCodeBasicBlock* fblock, Expression* exp, DestructStack*& destack, InlineMapper* inlineMapper);
ExValue TranslateInline(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, Expression* exp, const BranchTarget& breakBlock, const BranchTarget& continueBlock, InlineMapper* inlineMapper, bool inlineConstexpr, ExValue* lrexp);
void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper);
void CopyStruct(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue vl, ExValue vr, InlineMapper* inlineMapper, bool moving);
void UnwindDestructStack(Declaration* procType, InterCodeProcedure* proc, InterCodeBasicBlock*& block, DestructStack* stack, DestructStack * bottom, InlineMapper* inlineMapper);
void BuildInitializer(InterCodeModule* mod, uint8 * dp, int offset, Declaration* data, InterVariable * variable);

View File

@ -28,6 +28,21 @@ void LinkerSection::AddObject(LinkerObject* obj)
obj->mSection = this;
}
bool LinkerReference::operator==(const LinkerReference& ref)
{
return
mFlags == ref.mFlags &&
mOffset == ref.mOffset &&
mRefOffset == ref.mRefOffset &&
mObject->mMapID == ref.mObject->mMapID &&
mRefObject->mMapID == ref.mRefObject->mMapID;
}
bool LinkerReference::operator!=(const LinkerReference& ref)
{
return !(*this == ref);
}
LinkerObject::LinkerObject(void)
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr)
{}
@ -263,7 +278,7 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, L
{
LinkerObject* obj = new LinkerObject;
obj->mLocation = location;
obj->mID = mObjects.Size();
obj->mID = obj->mMapID = mObjects.Size();
obj->mType = type;
obj->mData = nullptr;
obj->mSize = 0;
@ -278,6 +293,70 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, L
return obj;
}
void Linker::CombineSameConst(void)
{
bool changed = true;
while (changed)
{
changed = false;
for (int i = 0; i < mObjects.Size(); i++)
{
LinkerObject* dobj(mObjects[i]);
while (dobj->mMapID != mObjects[dobj->mMapID]->mMapID)
dobj->mMapID = mObjects[dobj->mMapID]->mMapID;
if ((dobj->mFlags & LOBJF_REFERENCED) && (dobj->mFlags & LOBJF_CONST) && dobj->mMapID == dobj->mID)
{
for (int j = i + 1; j < mObjects.Size(); j++)
{
LinkerObject* sobj(mObjects[j]);
if ((sobj->mFlags & LOBJF_REFERENCED) && (sobj->mFlags & LOBJF_CONST) && sobj->mMapID == sobj->mID)
{
if (dobj->mSize == sobj->mSize && dobj->mSection == sobj->mSection && dobj->mReferences.Size() == sobj->mReferences.Size())
{
int i = 0;
while (i < sobj->mSize && sobj->mData[i] == dobj->mData[i])
i++;
if (i == sobj->mSize)
{
i = 0;
while (i < sobj->mReferences.Size() && sobj->mReferences[i] == dobj->mReferences[i])
i++;
if (i == sobj->mReferences.Size())
{
sobj->mMapID = dobj->mMapID;
changed = true;
if (dobj->mIdent && sobj->mIdent)
{
printf("Match %s : %s\n", dobj->mIdent->mString, sobj->mIdent->mString);
}
}
}
}
}
}
}
}
}
for (int i = 0; i < mObjects.Size(); i++)
{
LinkerObject* lobj(mObjects[i]);
if (lobj->mFlags & LOBJF_REFERENCED)
{
if (lobj->mMapID != lobj->mID)
lobj->mFlags &= ~LOBJF_REFERENCED;
else
{
for (int j = 0; j < lobj->mReferences.Size(); j++)
lobj->mReferences[j]->mRefObject = mObjects[lobj->mReferences[j]->mRefObject->mMapID];
}
}
}
}
void Linker::CollectReferences(void)
{
for (int i = 0; i < mObjects.Size(); i++)

View File

@ -110,6 +110,10 @@ public:
LinkerObject* mObject, * mRefObject;
int mOffset, mRefOffset;
uint32 mFlags;
bool operator==(const LinkerReference& ref);
bool operator!=(const LinkerReference& ref);
};
static const uint32 LSECF_PACKED = 0x00000001;
@ -175,7 +179,7 @@ public:
Location mLocation;
const Ident * mIdent;
LinkerObjectType mType;
int mID;
int mID, mMapID;
int mAddress, mRefAddress;
int mSize, mAlignment;
LinkerSection * mSection;
@ -281,6 +285,7 @@ public:
void ReferenceObject(LinkerObject* obj);
void CollectReferences(void);
void CombineSameConst(void);
void Link(void);
protected:
NativeCodeDisassembler mNativeDisassembler;

View File

@ -14050,6 +14050,10 @@ bool NativeCodeBasicBlock::CombineSameXtoY(int xpos, int ypos, int end)
{
ReplaceXRegWithYReg(xpos, ypos);
ReplaceXRegWithYReg(ypos + 1, end);
for (int i = xpos; i < ypos; i++)
mIns[i].mLive |= LIVE_CPU_REG_Y;
if (!(mIns[ypos].mLive & LIVE_CPU_REG_Z))
{
mIns[ypos].mType = ASMIT_NOP;
@ -14063,6 +14067,9 @@ bool NativeCodeBasicBlock::CombineSameXtoY(int xpos, int ypos, int end)
if (CanCombineSameXtoY(xpos, end))
{
ReplaceXRegWithYReg(xpos, end);
for (int i = ypos; i < xpos; i++)
mIns[i].mLive |= LIVE_CPU_REG_Y;
if (!(mIns[xpos].mLive & LIVE_CPU_REG_Z))
{
mIns[xpos].mType = ASMIT_NOP;
@ -14085,6 +14092,10 @@ bool NativeCodeBasicBlock::CombineSameYtoX(int xpos, int ypos, int end)
{
ReplaceYRegWithXReg(ypos, xpos);
ReplaceYRegWithXReg(xpos + 1, end);
for (int i = ypos; i < xpos; i++)
mIns[i].mLive |= LIVE_CPU_REG_X;
if (!(mIns[xpos].mLive & LIVE_CPU_REG_Z))
{
mIns[xpos].mType = ASMIT_NOP;
@ -14098,6 +14109,9 @@ bool NativeCodeBasicBlock::CombineSameYtoX(int xpos, int ypos, int end)
if (CanCombineSameYtoX(ypos, end))
{
ReplaceYRegWithXReg(ypos, end);
for (int i = xpos; i < ypos; i++)
mIns[i].mLive |= LIVE_CPU_REG_X;
if (!(mIns[ypos].mLive & LIVE_CPU_REG_Z))
{
mIns[ypos].mType = ASMIT_NOP;
@ -14139,6 +14153,7 @@ bool NativeCodeBasicBlock::CombineSameXY(void)
changed = true;
yreg = -1;
}
CheckLive();
}
xreg = -1;
@ -14155,6 +14170,7 @@ bool NativeCodeBasicBlock::CombineSameXY(void)
changed = true;
xreg = -1;
}
CheckLive();
}
yreg = -1;
@ -25067,6 +25083,9 @@ bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at)
{
if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && mIns[j].mAddress == mIns[at].mAddress)
{
if (mIns[j].mLive & LIVE_CPU_REG_Y)
return false;
mIns[at + 1].mLive |= mIns[j].mLive;
mIns[at + 2].mLive |= mIns[j].mLive;
@ -25079,8 +25098,18 @@ bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at)
return true;
}
if (mIns[j].ReferencesYReg())
if (mIns[j].mMode == ASMIM_INDIRECT_Y && mIns[j].mAddress == mIns[at + 2].mAddress)
{
if (j > 0 && mIns[j - 1].mType == ASMIT_LDY && mIns[j - 1].mMode == ASMIM_IMMEDIATE && mIns[j - 1].mAddress != mIns[at + 1].mAddress)
;
else
return false;
}
else if (mIns[at + 2].MayBeSameAddress(mIns[j]))
return false;
else if (mIns[j].mType == ASMIT_JSR)
return false;
if (mIns[j].ChangesZeroPage(mIns[at].mAddress))
return false;
if (mIns[j].ChangesZeroPage(mIns[at + 2].mAddress))
@ -33644,6 +33673,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
bool changed = RemoveNops();
mIns.Reserve(mIns.Size() * 2 + 32);
mVisited = true;
CheckLive();
@ -33768,7 +33799,6 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
}
}
CheckLive();
#endif
#if 1
@ -35822,6 +35852,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
{
mIns[i + 0].mType = ASMIT_LDY;
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
if (mIns[i + 1].ChangesYReg())
{
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
}
mIns[i + 0].mLive |= LIVE_CPU_REG_Y;
mIns[i + 1].mLive |= LIVE_CPU_REG_Y;
progress = true;
@ -37951,8 +37985,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
// Flip arguments of ADC if second parameter in accu at entry
mIns[i + 3].CopyMode(mIns[i + 2]);
mIns[i + 2].mMode = ASMIM_ZERO_PAGE;
mIns[i + 2].mAddress = mIns[i + 0].mAddress;
mIns[i + 2].CopyMode(mIns[i + 0]);
progress = true;
}
@ -40784,7 +40817,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
{
mInterProc = proc;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "dump<struct opp::list<i16>>");
CheckFunc = !strcmp(mInterProc->mIdent->mString, "test_pab50");
int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks];
@ -42120,7 +42153,6 @@ void NativeCodeProcedure::Optimize(void)
} while (changed);
#if 1
ResetVisited();
mEntryBlock->ReduceLocalYPressure();

View File

@ -1858,10 +1858,11 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc)
void Parser::AddDefaultConstructors(Declaration* pthis)
{
bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true;
bool simpleDestructor = true, simpleAssignment = true, simpleConstructor = true, simpleCopy = true, simpleMove = true;
bool inlineDestructor = true;
bool inlineConstructor = true;
bool inlineCopy = true;
bool inlineMove = true;
const Ident* dtorident = pthis->mBase->mIdent->PreMangle("~");;
@ -1879,6 +1880,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
pthis->mBase->mDefaultConstructor = cdec;
else if (!tparam->mNext && tparam->mBase->mType == DT_TYPE_REFERENCE && pthis->mBase->IsConstSame(tparam->mBase->mBase))
pthis->mBase->mCopyConstructor = cdec;
else if (!tparam->mNext && tparam->mBase->mType == DT_TYPE_RVALUEREF && pthis->mBase->IsConstSame(tparam->mBase->mBase))
pthis->mBase->mMoveConstructor = cdec;
cdec = cdec->mNext;
}