Improve function placement in linker

This commit is contained in:
drmortalwombat 2023-12-23 10:40:45 +01:00
parent 59b1d971d0
commit a305dbb1cd
10 changed files with 907 additions and 270 deletions

View File

@ -298,6 +298,9 @@ exit /b %errorlevel%
..\release\oscar64 -e -O3 -n %~1
@if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -xz -Oz -n %~1
@if %errorlevel% neq 0 goto :error
@exit /b 0
:testb
@ -334,4 +337,7 @@ exit /b %errorlevel%
..\release\oscar64 -e -O3 -n %~1
@if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -xz -Oz -n %~1
@if %errorlevel% neq 0 goto :error
@exit /b 0

View File

@ -1087,7 +1087,10 @@ bool Compiler::GenerateCode(void)
mLinker->ReferenceObject(mCompilationUnits->mReferenced[i]->mLinkerObject);
if (mCompilerOptions & COPT_OPTIMIZE_BASIC)
{
mLinker->CombineSameConst();
mLinker->CheckDirectJumps();
}
if (mCompilerOptions & COPT_VERBOSE)
printf("Link executable\n");
@ -1286,6 +1289,9 @@ int Compiler::ExecuteCode(bool profile, int trace)
printf("Running emulation...\n");
Emulator* emu = new Emulator(mLinker);
if (mCompilerOptions & COPT_EXTENDED_ZERO_PAGE)
emu->mJiffies = false;
int ecode = 20;
if (mCompilerOptions & COPT_TARGET_PRG)
{

View File

@ -919,7 +919,7 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
Declaration* dec = new Declaration(mLocation, DT_VARIABLE_REF);
dec->mFlags = mLeft->mDecValue->mFlags;
dec->mBase = mLeft->mDecValue;
dec->mOffset = mDecType->mSize * mRight->mDecValue->mInteger;
dec->mOffset = int(mDecType->mSize * mRight->mDecValue->mInteger);
dec->mSize = mDecType->mSize;
ex->mDecValue = dec;
ex->mDecType = mDecType;
@ -1770,6 +1770,7 @@ Declaration* Declaration::ToStriped(Errors * errors)
else
{
ndec->mStride = 1;
if (mBase->mSize > 0)
ndec->mBase = mBase->ToStriped(mSize / mBase->mSize);
}
}

View File

@ -7,6 +7,7 @@ Emulator::Emulator(Linker* linker)
{
for (int i = 0; i < 0x10000; i++)
mMemory[i] = 0;
mJiffies = true;
}
@ -513,6 +514,8 @@ int Emulator::Emulate(int startIP, int trace)
int ticks = 0;
while (mIP != 0)
{
if (mJiffies)
{
ticks++;
if (ticks > 4500)
@ -528,6 +531,7 @@ int Emulator::Emulate(int startIP, int trace)
}
ticks = 0;
}
}
if (mIP == 0xffd2)
{

View File

@ -16,6 +16,7 @@ public:
int mIP;
uint8 mRegA, mRegX, mRegY, mRegS, mRegP;
bool mJiffies;
Linker* mLinker;

View File

@ -698,7 +698,7 @@ static bool SameMemRegion(const InterOperand& op1, const InterOperand& op2)
// returns true if op2 is part of op1
static bool SameMemSegment(const InterOperand& op1, const InterOperand& op2)
{
if (op1.mMemory != op2.mMemory || op1.mIntConst > op2.mIntConst || op1.mIntConst + op1.mOperandSize < op2.mIntConst + op2.mOperandSize)
if (op1.mMemory != op2.mMemory || op1.mIntConst > op2.mIntConst || op1.mIntConst + op1.mOperandSize < op2.mIntConst + op2.mOperandSize || op1.mStride != op2.mStride)
return false;
switch (op1.mMemory)
@ -4698,14 +4698,14 @@ void InterInstruction::Disassemble(FILE* file, InterCodeProcedure* proc)
if (mSrc[1].mStride != 1)
{
if (mSrc[0].mStride != 1)
fprintf(file, "COPY%c%d%c%d", memchars[mSrc[0].mMemory], mSrc[0].mStride, memchars[mSrc[1].mMemory], mSrc[1].mStride);
fprintf(file, "COPY%d:%c%d%c%d", mSrc[0].mOperandSize, memchars[mSrc[0].mMemory], mSrc[0].mStride, memchars[mSrc[1].mMemory], mSrc[1].mStride);
else
fprintf(file, "COPY%c%c%d", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory], mSrc[1].mStride);
fprintf(file, "COPY%d:%c%c%d", mSrc[0].mOperandSize, memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory], mSrc[1].mStride);
}
else if (mSrc[0].mStride != 1)
fprintf(file, "COPY%c%d%c", memchars[mSrc[0].mMemory], mSrc[0].mStride, memchars[mSrc[1].mMemory]);
fprintf(file, "COPY%d:%c%d%c", mSrc[0].mOperandSize, memchars[mSrc[0].mMemory], mSrc[0].mStride, memchars[mSrc[1].mMemory]);
else
fprintf(file, "COPY%c%c", memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]);
fprintf(file, "COPY%d:%c%c", mSrc[0].mOperandSize, memchars[mSrc[0].mMemory], memchars[mSrc[1].mMemory]);
break;
case IC_MALLOC:
@ -6279,7 +6279,10 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray
ins->mSrc[0].mMemory = ltemps[k]->mSrc[0].mMemory;
ins->mSrc[0].mTemp = ltemps[k]->mSrc[0].mTemp;
ins->mSrc[0].mVarIndex = ltemps[k]->mSrc[0].mVarIndex;
ins->mSrc[0].mIntConst = ins->mSrc[0].mIntConst * ltemps[k]->mSrc[0].mStride + ltemps[k]->mSrc[0].mIntConst;
if (ltemps[k]->mSrc[0].mStride != ltemps[k]->mSrc[1].mStride)
ins->mSrc[0].mIntConst = (ins->mSrc[0].mIntConst - ltemps[k]->mSrc[1].mIntConst) / ltemps[k]->mSrc[1].mStride * ltemps[k]->mSrc[0].mStride + ltemps[k]->mSrc[0].mIntConst;
else
ins->mSrc[0].mIntConst = ins->mSrc[0].mIntConst - ltemps[k]->mSrc[1].mIntConst + ltemps[k]->mSrc[0].mIntConst;
ins->mSrc[0].mLinkerObject = ltemps[k]->mSrc[0].mLinkerObject;
ins->mSrc[0].mStride = ltemps[k]->mSrc[0].mStride;
changed = true;
@ -6330,15 +6333,15 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray
j = 0;
for (int k = 0; k < ltemps.Size(); k++)
{
if (ltemps[k]->mSrc[0].mTemp < 0 && ltemps[k]->mSrc[0].mMemory == IM_LOCAL && aliasedLocals[ltemps[k]->mSrc[0].mVarIndex] ||
ltemps[k]->mSrc[1].mTemp < 0 && ltemps[k]->mSrc[1].mMemory == IM_LOCAL && aliasedLocals[ltemps[k]->mSrc[1].mVarIndex] ||
ltemps[k]->mSrc[0].mTemp < 0 && (ltemps[k]->mSrc[0].mMemory == IM_PARAM || ltemps[k]->mSrc[0].mMemory == IM_FPARAM) && aliasedParams[ltemps[k]->mSrc[0].mVarIndex] ||
ltemps[k]->mSrc[1].mTemp < 0 && (ltemps[k]->mSrc[1].mMemory == IM_PARAM || ltemps[k]->mSrc[1].mMemory == IM_FPARAM) && aliasedParams[ltemps[k]->mSrc[1].mVarIndex])
if (ltemps[k]->mSrc[0].mTemp < 0 && ltemps[k]->mSrc[1].mTemp < 0 &&
(ltemps[k]->mSrc[0].mMemory == IM_LOCAL && !aliasedLocals[ltemps[k]->mSrc[0].mVarIndex] ||
(ltemps[k]->mSrc[0].mMemory == IM_PARAM || ltemps[k]->mSrc[0].mMemory == IM_FPARAM) && !aliasedParams[ltemps[k]->mSrc[0].mVarIndex]) &&
(ltemps[k]->mSrc[1].mMemory == IM_LOCAL && !aliasedLocals[ltemps[k]->mSrc[1].mVarIndex] ||
(ltemps[k]->mSrc[1].mMemory == IM_PARAM || ltemps[k]->mSrc[1].mMemory == IM_FPARAM) && !aliasedParams[ltemps[k]->mSrc[1].mVarIndex]))
{
}
else
ltemps[j++] = ltemps[k];
}
}
ltemps.SetSize(j);
}
break;

View File

@ -46,6 +46,7 @@ bool LinkerReference::operator!=(const LinkerReference& ref)
LinkerObject::LinkerObject(void)
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr), mIdent(nullptr), mFullIdent(nullptr), mStartUsed(0x10000), mEndUsed(0x00000), mMemory(nullptr)
, mPrefix(nullptr), mSuffix(nullptr)
{}
LinkerObject::~LinkerObject(void)
@ -307,6 +308,44 @@ bool LinkerObject::IsSameConst(const LinkerObject* obj) const
return false;
}
int LinkerObject::FirstBank(void) const
{
if (mRegion->mCartridgeBanks)
{
uint64 m = mRegion->mCartridgeBanks;
int i = 1;
while (!(m & 1))
{
i++;
m >>= 1;
}
return i;
}
else
return 0;
}
bool LinkerObject::IsBefore(const LinkerObject* obj) const
{
if (mFlags & LOBJF_PLACED)
{
if (obj->mFlags & LOBJF_PLACED)
{
int b0 = FirstBank(), b1 = obj->FirstBank();
if (b0 < b1)
return true;
else if (b0 == b1)
return mAddress < obj->mAddress;
else
return false;
}
else
return true;
}
else
return false;
}
LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, LinkerSection * section, LinkerObjectType type, int alignment)
{
LinkerObject* obj = new LinkerObject;
@ -327,6 +366,47 @@ LinkerObject * Linker::AddObject(const Location& location, const Ident* ident, L
return obj;
}
static bool Forwards(LinkerObject* pobj, LinkerObject* lobj)
{
if (lobj->mAlignment == 1 && pobj && lobj->mType == LOT_NATIVE_CODE && pobj->mType == LOT_NATIVE_CODE && lobj->mSection == pobj->mSection)
{
if (pobj->mSize >= 3 && pobj->mData[pobj->mSize - 3] == 0x4c && pobj->mReferences.Size() > 0)
{
int i = 0;
while (i < pobj->mReferences.Size() && pobj->mReferences[i]->mOffset != pobj->mSize - 2)
i++;
if (i < pobj->mReferences.Size() && pobj->mReferences[i]->mRefObject == lobj && pobj->mReferences[i]->mRefOffset == 0)
{
printf("Direct %s -> %s\n", pobj->mIdent->mString, lobj->mIdent->mString);
pobj->mSuffixReference = i;
return true;
}
}
}
return false;
}
void Linker::CheckDirectJumps(void)
{
for (int i = 0; i < mObjects.Size(); i++)
{
for (int j = 0; j < mObjects.Size(); j++)
{
if (i != j && !mObjects[j]->mPrefix && Forwards(mObjects[i], mObjects[j]))
{
mObjects[i]->mSuffix = mObjects[j];
mObjects[j]->mPrefix = mObjects[i];
break;
}
}
}
}
void Linker::CombineSameConst(void)
{
bool changed = true;
@ -415,32 +495,17 @@ void Linker::ReferenceObject(LinkerObject* obj)
}
}
static bool Forwards(LinkerObject* pobj, LinkerObject* lobj)
{
if (lobj->mAlignment == 1 && pobj && lobj->mType == LOT_NATIVE_CODE && pobj->mType == LOT_NATIVE_CODE)
{
if (pobj->mSize >= 3 && pobj->mData[pobj->mSize - 3] == 0x4c && pobj->mReferences.Size() > 0)
{
int i = 0;
while (i < pobj->mReferences.Size() && pobj->mReferences[i]->mOffset != pobj->mSize - 2)
i++;
if (i < pobj->mReferences.Size() && pobj->mReferences[i]->mRefObject == lobj && pobj->mReferences[i]->mRefOffset == 0)
{
printf("Direct %s -> %s\n", pobj->mIdent->mString, lobj->mIdent->mString);
pobj->mReferences[i]->mFlags = 0;
pobj->mSize -= 3;
return true;
}
}
}
return false;
}
bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge)
{
if (merge && lobj->mPrefix && !(lobj->mPrefix->mFlags & LOBJF_PLACED))
{
if (!Allocate(linker, lobj->mPrefix, true))
return false;
if (lobj->mFlags & LOBJF_PLACED)
return true;
}
int i = 0;
while (i < mFreeChunks.Size())
{
@ -451,9 +516,11 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge)
;
else if (end <= mFreeChunks[i].mEnd)
{
// Check if directly follows an object that jumps to this new object
if (merge && Forwards(mFreeChunks[i].mLastObject, lobj))
if (merge && lobj->mPrefix && lobj->mPrefix == mFreeChunks[i].mLastObject)
{
lobj->mPrefix->mReferences[lobj->mPrefix->mSuffixReference]->mFlags = 0;
lobj->mPrefix->mSize -= 3;
start -= 3;
end -= 3;
}
@ -483,6 +550,12 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge)
mFreeChunks[i].mEnd = start;
}
if (merge && lobj->mSuffix && !(lobj->mSuffix->mFlags & LOBJF_PLACED))
{
if (!Allocate(linker, lobj->mSuffix, true))
return false;
}
return true;
}
i++;
@ -500,8 +573,11 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge)
if (end <= mEnd)
{
// Check if directly follows an object that jumps to this new object
if (merge && Forwards(mLastObject, lobj))
if (merge && lobj->mPrefix && lobj->mPrefix == mLastObject)
{
lobj->mPrefix->mReferences[lobj->mPrefix->mSuffixReference]->mFlags = 0;
lobj->mPrefix->mSize -= 3;
start -= 3;
end -= 3;
mLastObject = nullptr;
@ -520,6 +596,12 @@ bool LinkerRegion::Allocate(Linker * linker, LinkerObject* lobj, bool merge)
mLastObject = lobj;
if (merge && lobj->mSuffix && !(lobj->mSuffix->mFlags & LOBJF_PLACED))
{
if (!Allocate(linker, lobj->mSuffix, true))
return false;
}
return true;
}
@ -735,6 +817,36 @@ void Linker::PlaceObjects(void)
}
}
void Linker::SortObjectsPartition(int l, int r)
{
while (l < r)
{
int pi = (l + r) >> 1;
LinkerObject* po = mObjects[pi];
mObjects[pi] = mObjects[l];
pi = l;
for (int i = l + 1; i < r; i++)
{
if (mObjects[i]->IsBefore(po))
{
mObjects[pi++] = mObjects[i];
mObjects[i] = mObjects[pi];
}
}
mObjects[pi] = po;
SortObjectsPartition(l, pi);
l = pi + 1;
}
}
void Linker::SortObjects(void)
{
SortObjectsPartition(0, mObjects.Size());
}
void Linker::Link(void)
{
if (mErrors->mErrorCount == 0)
@ -885,8 +997,9 @@ void Linker::Link(void)
}
}
}
}
SortObjects();
}
static const char * LinkerObjectTypeNames[] =

View File

@ -195,6 +195,8 @@ public:
int mNumTemporaries;
ZeroPageSet mZeroPageSet;
LinkerSection * mStackSection;
LinkerObject * mPrefix, * mSuffix;
int mSuffixReference;
ExpandingArray<LinkerObjectRange> mRanges;
ExpandingArray<CodeLocation> mCodeLocations;
@ -219,6 +221,9 @@ public:
void MarkRelevant(void);
bool IsSameConst(const LinkerObject* obj) const;
bool IsBefore(const LinkerObject* obj) const;
int FirstBank(void) const;
};
class LinkerOverlay
@ -256,6 +261,8 @@ public:
LinkerOverlay* AddOverlay(const Location& location, const Ident* ident, int bank);
void SortObjects(void);
// void AddReference(const LinkerReference& ref);
bool WritePrgFile(DiskImage * image, const char* filename);
@ -291,6 +298,7 @@ public:
void ReferenceObject(LinkerObject* obj);
void CheckDirectJumps(void);
void CollectReferences(void);
void CombineSameConst(void);
void PatchReferences(bool inlays);
@ -301,5 +309,7 @@ protected:
NativeCodeDisassembler mNativeDisassembler;
ByteCodeDisassembler mByteCodeDisassembler;
void SortObjectsPartition(int l, int r);
Errors* mErrors;
};

File diff suppressed because it is too large Load Diff

View File

@ -615,6 +615,7 @@ public:
bool SinglePathRegisterForwardY(NativeCodeBasicBlock* path, int yreg);
bool SinglePathRegisterForward(void);
bool SinglePathStoreForward(void);
bool CanBytepassLoad(const NativeCodeInstruction& ains, int from = 0) const;
bool CanHoistStore(const NativeCodeInstruction& ains) const;
@ -717,7 +718,7 @@ public:
bool PatchCrossBlockY2XFlood(const NativeCodeBasicBlock* block, int at);
bool PatchCrossBlockY2XFloodExit(const NativeCodeBasicBlock* block);
void PropagateZPAbsolute(void);
void PropagateZPAbsolute(const NativeRegisterDataSet& data);
void RegisterFunctionCalls(void);
bool MergeFunctionCalls(void);
@ -770,6 +771,7 @@ class NativeCodeProcedure
void ResetVisited(void);
void ResetPatched(void);
void RebuildEntry(void);
void ResetIndexFlipped(void);
void SaveTempsToStack(int tempSave);
void LoadTempsFromStack(int tempSave);
@ -801,6 +803,7 @@ public:
};
LinkerObject* AllocateShortMulTable(InterOperator op, int factor, int size, bool msb);
void PopulateShortMulTables(void);
Runtime& ResolveRuntime(const Ident* ident);
@ -820,6 +823,7 @@ public:
bool IsSame(const FunctionCall* fc) const;
int Matches(const FunctionCall* fc) const;
int PotentialMatches(const FunctionCall* fc) const;
};
FunctionCall* mFunctionCalls;