Static stack allocations for complex locals in non recursive calls

This commit is contained in:
drmortalwombat 2022-03-13 15:46:03 +01:00
parent 24a17c937b
commit ea09c2aa7b
13 changed files with 322 additions and 48 deletions

View File

@ -135,6 +135,9 @@ rem @echo off
@call :test ptrarraycmptest.c
@if %errorlevel% neq 0 goto :error
@call :test cplxstructtest.c
@if %errorlevel% neq 0 goto :error
@exit /b 0
:error

View File

@ -362,6 +362,7 @@ int main(void)
shr16b(0xfedc, 0xfedc);
shl16n(0x0000, 0x0000);
shl16n(0xffff, 0xffff);
shl16n(0x1234, 0x1234);
shl16n(0xfedc, 0xfedc);

97
autotest/cplxstructtest.c Normal file
View File

@ -0,0 +1,97 @@
#include <stdio.h>
#include <math.h>
#include <assert.h>
struct cplx
{
float r, i;
};
cplx cplx_add(cplx a, cplx b)
{
cplx c;
c.r = a.r + b.r;
c.i = a.i + b.i;
return c;
}
cplx cplx_sub(cplx a, cplx b)
{
cplx c;
c.r = a.r - b.r;
c.i = a.i - b.i;
return c;
}
cplx cplx_mul(cplx a, cplx b)
{
cplx c;
c.r = a.r * b.r - a.i * b.i;
c.i = a.i * b.r + a.r * b.i;
return c;
}
float cplx_abs(cplx a)
{
return sqrt(a.r * a.r + a.i * a.i);
}
cplx cplx_sum(cplx p, const cplx * a, int n)
{
cplx s = {0.0, 0.0};
cplx c = {1.0, 0.0};
for(int i=0; i<n; i++)
{
s = cplx_add(s, cplx_mul(a[i], c));
c = cplx_mul(c, p);
}
return s;
}
int main(void)
{
cplx sig[100];
for(int i=0; i<100; i++)
{
sig[i].r = cos(i * 1.3);
sig[i].i = sin(i * 1.3);
}
cplx c = {1.0, 0.0};
float phi = 0.1 * PI;
cplx t;
t.r = cos(phi); t.i = sin(phi);
float p[20], q[20];
for(int i=0; i<20; i++)
{
p[i] = cplx_abs(cplx_sum(c, sig, 100));
c = cplx_mul(c, t);
}
for(int i=0; i<20; i++)
{
float sumr = 0.0, sumi = 0.0;
for(int j=0; j<100; j++)
{
float co = cos(i * j * 0.1 * PI), si = sin(i * j * 0.1 * PI);
sumr += co * sig[j].r - si * sig[j].i;
sumi += si * sig[j].r + co * sig[j].i;
}
q[i] = sqrt(sumr * sumr + sumi * sumi);
}
#if 0
for(int i=0; i<20; i++)
{
printf("%d, %f - %f\n", i, p[i], q[i]);
}
#endif
for(int i=0; i<20; i++)
assert(fabs(p[i] - q[i]) < 1.0);
return 0;
}

View File

@ -27,7 +27,7 @@ Compiler::Compiler(void)
mByteCodeGenerator = new ByteCodeGenerator(mErrors, mLinker);
mInterCodeGenerator = new InterCodeGenerator(mErrors, mLinker);
mNativeCodeGenerator = new NativeCodeGenerator(mErrors, mLinker, mCompilationUnits->mSectionCode);
mInterCodeModule = new InterCodeModule();
mInterCodeModule = new InterCodeModule(mLinker);
mGlobalAnalyzer = new GlobalAnalyzer(mErrors, mLinker);
}
@ -311,6 +311,9 @@ bool Compiler::GenerateCode(void)
#endif
CompileProcedure(proc);
if (proc->mLinkerObject->mStackSection)
mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection);
}
LinkerObject* byteCodeObject = nullptr;

View File

@ -127,7 +127,7 @@ void GlobalAnalyzer::AutoInline(void)
void GlobalAnalyzer::CheckFastcall(Declaration* procDec)
{
if (!(procDec->mBase->mFlags & DTF_FASTCALL) && !(procDec->mBase->mFlags & DTF_STACKCALL))
if (!(procDec->mBase->mFlags & DTF_FASTCALL) && !(procDec->mBase->mFlags & DTF_STACKCALL) && (procDec->mType == DT_CONST_FUNCTION))
{
if (!(procDec->mBase->mFlags & DTF_VARIADIC) && !(procDec->mFlags & DTF_FUNC_VARIABLE) && !(procDec->mFlags & DTF_FUNC_RECURSIVE))
{
@ -150,6 +150,10 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec)
}
int nparams = 0;
if (procDec->mBase->mBase->mType == DT_TYPE_STRUCT)
nparams += 2;
Declaration* dec = procDec->mBase->mParams;
while (dec)
{

View File

@ -2702,6 +2702,13 @@ bool InterInstruction::ConstantFolding(void)
mNumOperands = 1;
return true;
}
else if ((mOperator == IA_AND || mOperator == IA_MUL || mOperator == IA_SHL || mOperator == IA_SHR || mOperator == IA_SAR) && mSrc[1].mIntConst == 0)
{
mCode = IC_CONSTANT;
mConst.mIntConst = 0;
mNumOperands = 0;
return true;
}
}
}
#endif
@ -6954,6 +6961,65 @@ bool InterCodeBasicBlock::IsEqual(const InterCodeBasicBlock* block) const
return false;
}
bool InterCodeBasicBlock::CheckStaticStack(void)
{
if (!mVisited)
{
mVisited = true;
for (int i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE)
{
if (mInstructions[i]->mSrc[0].mTemp >= 0 || !mInstructions[i]->mSrc[0].mLinkerObject)
return false;
else if (!(mInstructions[i]->mSrc[0].mLinkerObject->mFlags & LOBJF_STATIC_STACK))
return false;
}
}
if (mTrueJump && !mTrueJump->CheckStaticStack())
return false;
if (mFalseJump && !mFalseJump->CheckStaticStack())
return false;
}
return true;
}
void ApplyStaticStack(InterOperand & iop, const GrowingVariableArray& localVars)
{
if (iop.mMemory == IM_LOCAL)
{
iop.mMemory = IM_GLOBAL;
iop.mLinkerObject = localVars[iop.mVarIndex]->mLinkerObject;
}
}
void InterCodeBasicBlock::CollectStaticStack(LinkerObject* lobj, const GrowingVariableArray& localVars)
{
if (!mVisited)
{
mVisited = true;
for (int i = 0; i < mInstructions.Size(); i++)
{
if (mInstructions[i]->mCode == IC_CALL || mInstructions[i]->mCode == IC_CALL_NATIVE)
lobj->mStackSection->mSections.Push(mInstructions[i]->mSrc[0].mLinkerObject->mStackSection);
if (mInstructions[i]->mCode == IC_LOAD)
ApplyStaticStack(mInstructions[i]->mSrc[0], localVars);
else if (mInstructions[i]->mCode == IC_STORE || mInstructions[i]->mCode == IC_LEA)
ApplyStaticStack(mInstructions[i]->mSrc[1], localVars);
else if (mInstructions[i]->mCode == IC_CONSTANT && mInstructions[i]->mDst.mType == IT_POINTER)
ApplyStaticStack(mInstructions[i]->mConst, localVars);
}
if (mTrueJump) mTrueJump->CollectStaticStack(lobj, localVars);
if (mFalseJump) mFalseJump->CollectStaticStack(lobj, localVars);
}
}
bool InterCodeBasicBlock::DropUnreachable(void)
{
if (!mVisited)
@ -7243,7 +7309,7 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams)
for (int i = 0; i < path.Size(); i++)
printf("path %d\n", path[i]->mIndex);
#endif
bool hasCall = false;
bool hasCall = false, hasFrame = false;
for (int bi = 0; bi < body.Size(); bi++)
{
InterCodeBasicBlock* block = body[bi];
@ -7255,10 +7321,11 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams)
ins->mExpensive = false;
if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE)
hasCall = true;
else if (ins->mCode == IC_PUSH_FRAME)
hasFrame = true;
}
}
for (int bi = 0; bi < path.Size(); bi++)
{
InterCodeBasicBlock* block = path[bi];
@ -7270,6 +7337,10 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams)
if (!IsMoveable(ins->mCode))
ins->mInvariant = false;
else if (ins->mCode == IC_CONSTANT && ins->mDst.mType == IT_POINTER && ins->mConst.mMemory == IM_FRAME && hasFrame)
ins->mInvariant = false;
else if (ins->mCode == IC_LEA && ins->mSrc[1].mMemory == IM_FRAME && hasFrame)
ins->mInvariant = false;
else if (ins->mCode == IC_LOAD)
{
if (ins->mSrc[0].mTemp >= 0 || ins->mVolatile)
@ -7305,6 +7376,10 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams)
ins->mInvariant = false;
}
}
else if (sins->mCode == IC_COPY)
{
ins->mInvariant = false;
}
}
}
}
@ -7572,13 +7647,23 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
GrowingArray<InterInstructionPtr> tvalues(nullptr);
GrowingArray<int> nassigns(0);
int frameLevel = 0;
for (int i = 0; i < mInstructions.Size(); i++)
{
InterInstruction* ins = mInstructions[i];
ins->mInvariant = true;
if (ins->mCode == IC_PUSH_FRAME)
frameLevel++;
else if (ins->mCode == IC_POP_FRAME)
frameLevel--;
if (!IsMoveable(ins->mCode))
ins->mInvariant = false;
else if (ins->mCode == IC_CONSTANT && ins->mDst.mType == IT_POINTER && ins->mConst.mMemory == IM_FRAME && frameLevel != 0)
ins->mInvariant = false;
else if (ins->mCode == IC_LEA && ins->mSrc[1].mMemory == IM_FRAME && frameLevel != 0)
ins->mInvariant = false;
else if (ins->mCode == IC_LOAD)
{
if (ins->mSrc[0].mTemp >= 0 || ins->mVolatile)
@ -7627,6 +7712,10 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
ins->mInvariant = false;
}
}
else if (sins->mCode == IC_COPY)
{
ins->mInvariant = false;
}
}
}
}
@ -9094,6 +9183,7 @@ void InterCodeProcedure::Close(void)
int vi = simpleLocals.Element(i);
if (!complexLocals[vi])
{
mLocalVars[vi]->mTemp = true;
ResetVisited();
mEntryBlock->SimpleLocalToTemp(vi, AddTemporary(localTypes[vi]));
}
@ -9122,6 +9212,7 @@ void InterCodeProcedure::Close(void)
TempForwarding();
}
BuildLoopPrefix();
DisassembleDebug("added dominators");
@ -9366,6 +9457,28 @@ void InterCodeProcedure::Close(void)
#endif
#if 1
ResetVisited();
if (mEntryBlock->CheckStaticStack())
{
mLinkerObject->mFlags |= LOBJF_STATIC_STACK;
mLinkerObject->mStackSection = mModule->mLinker->AddSection(mIdent, LST_STATIC_STACK);
for (int i = 0; i < mLocalVars.Size(); i++)
{
InterVariable* var(mLocalVars[i]);
if (var && !var->mTemp && !var->mLinkerObject)
{
var->mLinkerObject = mModule->mLinker->AddObject(mLocation, var->mIdent, mLinkerObject->mStackSection, LOT_BSS);
var->mLinkerObject->AddSpace(var->mSize);
}
}
ResetVisited();
mEntryBlock->CollectStaticStack(mLinkerObject, mLocalVars);
}
#endif
MapVariables();
DisassembleDebug("mapped variabled");
@ -9379,6 +9492,7 @@ void InterCodeProcedure::Close(void)
MergeBasicBlocks();
BuildTraces(false);
DisassembleDebug("Merged basic blocks");
}
void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc)
@ -9412,7 +9526,7 @@ void InterCodeProcedure::MapVariables(void)
mLocalSize = 0;
for (int i = 0; i < mLocalVars.Size(); i++)
{
if (mLocalVars[i] && mLocalVars[i]->mUsed)
if (mLocalVars[i] && mLocalVars[i]->mUsed && !mLocalVars[i]->mLinkerObject)
{
mLocalVars[i]->mOffset = mLocalSize;
mLocalSize += mLocalVars[i]->mSize;
@ -9765,8 +9879,8 @@ void InterCodeProcedure::Disassemble(const char* name, bool dumpSets)
#endif
}
InterCodeModule::InterCodeModule(void)
: mGlobalVars(nullptr), mProcedures(nullptr), mCompilerOptions(0)
InterCodeModule::InterCodeModule(Linker * linker)
: mLinker(linker), mGlobalVars(nullptr), mProcedures(nullptr), mCompilerOptions(0)
{
}

View File

@ -223,14 +223,14 @@ class InterVariable
{
public:
Location mLocation;
bool mUsed, mAliased;
bool mUsed, mAliased, mTemp;
int mIndex, mSize, mOffset, mAddr;
int mNumReferences;
const Ident * mIdent;
LinkerObject * mLinkerObject;
InterVariable(void)
: mUsed(false), mAliased(false), mIndex(-1), mSize(0), mOffset(0), mIdent(nullptr), mLinkerObject(nullptr)
: mUsed(false), mAliased(false), mTemp(false), mIndex(-1), mSize(0), mOffset(0), mIdent(nullptr), mLinkerObject(nullptr)
{
}
};
@ -460,6 +460,9 @@ public:
bool OptimizeIntervalCompare(void);
bool DropUnreachable(void);
bool CheckStaticStack(void);
void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars);
};
class InterCodeModule;
@ -533,7 +536,7 @@ protected:
class InterCodeModule
{
public:
InterCodeModule(void);
InterCodeModule(Linker * linker);
~InterCodeModule(void);
bool Disassemble(const char* name);
@ -542,6 +545,8 @@ public:
GrowingVariableArray mGlobalVars;
Linker * mLinker;
uint64 mCompilerOptions;
};

View File

@ -8,11 +8,11 @@ LinkerRegion::LinkerRegion(void)
{}
LinkerSection::LinkerSection(void)
: mObjects(nullptr)
: mObjects(nullptr), mSections(nullptr)
{}
LinkerObject::LinkerObject(void)
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1)
: mReferences(nullptr), mNumTemporaries(0), mSize(0), mAlignment(1), mStackSection(nullptr)
{}
LinkerObject::~LinkerObject(void)
@ -235,6 +235,42 @@ bool LinkerRegion::Allocate(LinkerObject* lobj)
return false;
}
void LinkerRegion::PlaceStackSection(LinkerSection* stackSection, LinkerSection* section)
{
if (!section->mEnd)
{
int start = stackSection->mEnd;
for(int i=0; i<section->mSections.Size(); i++)
{
PlaceStackSection(stackSection, section->mSections[i]);
if (section->mSections[i]->mStart < start)
start = section->mSections[i]->mStart;
}
section->mStart = start;
section->mEnd = start;
for (int i = 0; i < section->mObjects.Size(); i++)
{
LinkerObject* lobj = section->mObjects[i];
if (lobj->mFlags & LOBJF_REFERENCED)
{
section->mStart -= lobj->mSize;
section->mSize += lobj->mSize;
lobj->mFlags |= LOBJF_PLACED;
lobj->mAddress = section->mStart;
lobj->mRefAddress = section->mStart + mReloc;
lobj->mRegion = this;
}
}
if (stackSection->mStart > section->mStart)
stackSection->mStart = section->mStart;
}
}
void Linker::Link(void)
{
if (mErrors->mErrorCount == 0)
@ -304,10 +340,15 @@ void Linker::Link(void)
LinkerSection* lsec = lrgn->mSections[j];
if (lsec->mType == LST_STACK)
{
lsec->mStart = lrgn->mEnd - lsec->mSize;
lsec->mEnd = lrgn->mEnd;
lrgn->mEnd = lsec->mStart;
{
lsec->mStart = lsec->mEnd = lrgn->mEnd;
lrgn->mEnd = lsec->mStart - lsec->mSize;
for(int i=0; i<lsec->mSections.Size(); i++)
lrgn->PlaceStackSection(lsec, lsec->mSections[i]);
lsec->mEnd = lsec->mStart;
lsec->mStart = lrgn->mEnd;
}
}
}
@ -440,7 +481,8 @@ static const char* LinkerSectionTypeNames[] = {
"DATA",
"BSS",
"HEAP",
"STACK"
"STACK",
"SSTACK"
};
bool Linker::WriteBinFile(const char* filename)

View File

@ -30,7 +30,9 @@ enum LinkerSectionType
LST_DATA,
LST_BSS,
LST_HEAP,
LST_STACK
LST_STACK,
LST_STATIC_STACK
};
struct ZeroPageSet
@ -90,6 +92,7 @@ public:
GrowingArray<FreeChunk> mFreeChunks;
bool Allocate(LinkerObject* obj);
void PlaceStackSection(LinkerSection* stackSection, LinkerSection* section);
};
static const uint32 LREF_LOWBYTE = 0x00000001;
@ -111,7 +114,7 @@ public:
const Ident* mIdent;
GrowingArray <LinkerObject*> mObjects;
GrowingArray <LinkerSection*> mSections;
int mStart, mEnd, mSize;
LinkerSectionType mType;
@ -119,31 +122,32 @@ public:
LinkerSection(void);
};
static const uint32 LOBJF_REFERENCED = 0x00000001;
static const uint32 LOBJF_PLACED = 0x00000002;
static const uint32 LOBJF_NO_FRAME = 0x00000004;
static const uint32 LOBJF_INLINE = 0x00000008;
static const uint32 LOBJF_CONST = 0x00000010;
static const uint32 LOBJF_RELEVANT = 0x00000020;
static const uint32 LOBJF_REFERENCED = 0x00000001;
static const uint32 LOBJF_PLACED = 0x00000002;
static const uint32 LOBJF_NO_FRAME = 0x00000004;
static const uint32 LOBJF_INLINE = 0x00000008;
static const uint32 LOBJF_CONST = 0x00000010;
static const uint32 LOBJF_RELEVANT = 0x00000020;
static const uint32 LOBJF_STATIC_STACK = 0x00000040;
class LinkerObject
{
public:
Location mLocation;
const Ident * mIdent;
LinkerObjectType mType;
int mID;
int mAddress, mRefAddress;
int mSize, mAlignment;
LinkerSection * mSection;
LinkerRegion * mRegion;
uint8 * mData;
InterCodeProcedure* mProc;
uint32 mFlags;
uint8 mTemporaries[16], mTempSizes[16];
int mNumTemporaries;
ZeroPageSet mZeroPageSet;
Location mLocation;
const Ident * mIdent;
LinkerObjectType mType;
int mID;
int mAddress, mRefAddress;
int mSize, mAlignment;
LinkerSection * mSection;
LinkerRegion * mRegion;
uint8 * mData;
InterCodeProcedure * mProc;
uint32 mFlags;
uint8 mTemporaries[16], mTempSizes[16];
int mNumTemporaries;
ZeroPageSet mZeroPageSet;
LinkerSection * mStackSection;
LinkerObject(void);
~LinkerObject(void);

View File

@ -12135,6 +12135,7 @@ bool NativeCodeBasicBlock::MoveLoadStoreUp(int at)
}
mIns[j - 1].mLive |= LIVE_CPU_REG_A;
mIns[j] = mIns[at + 1];
mIns[j].mLive |= LIVE_CPU_REG_A;
mIns[at + 1].mType = ASMIT_NOP; mIns[at + 1].mMode = ASMIM_IMPLIED;
return true;

View File

@ -73,7 +73,7 @@ int main2(int argc, const char** argv)
#else
strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.4.101");
strcpy(strProductVersion, "1.5.102");
#ifdef __APPLE__
uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,4,101,0
PRODUCTVERSION 1,4,101,0
FILEVERSION 1,5,102,0
PRODUCTVERSION 1,5,102,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.4.101.0"
VALUE "FileVersion", "1.5.102.0"
VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.4.101.0"
VALUE "ProductVersion", "1.5.102.0"
END
END
BLOCK "VarFileInfo"

View File

@ -3945,15 +3945,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64"
"ProductCode" = "8:{015F3702-7631-43CC-8735-41950474E793}"
"PackageCode" = "8:{7D690EF3-EE02-4845-BCF6-64CB0E42ED95}"
"ProductCode" = "8:{6DCF4711-61FA-455B-87CE-A5383B7EEB4E}"
"PackageCode" = "8:{20057AF4-DA5C-4190-B17D-094F83470BE1}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.4.101"
"ProductVersion" = "8:1.5.102"
"Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:"