Prepare per function optimization config using pragmas

This commit is contained in:
drmortalwombat 2023-04-02 19:04:10 +02:00
parent 14ab294a47
commit 32ea493c17
13 changed files with 538 additions and 30 deletions

View File

@ -596,7 +596,8 @@ Expression* Expression::ConstantFold(Errors * errors)
Declaration::Declaration(const Location& loc, DecType type) Declaration::Declaration(const Location& loc, DecType type)
: mLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), : mLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0),
mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1),
mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1) mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1),
mCompilerOptions(0)
{} {}
Declaration::~Declaration(void) Declaration::~Declaration(void)

View File

@ -189,7 +189,7 @@ public:
int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe; int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe;
int64 mInteger, mMinValue, mMaxValue; int64 mInteger, mMinValue, mMaxValue;
double mNumber; double mNumber;
uint64 mFlags; uint64 mFlags, mCompilerOptions;
const Ident * mIdent; const Ident * mIdent;
LinkerSection * mSection; LinkerSection * mSection;
const uint8 * mData; const uint8 * mData;

View File

@ -769,6 +769,22 @@ const char* NativeCodeDisassembler::AddrName(int addr, char* buffer, InterCodePr
if (linker) if (linker)
{ {
LinkerObject* obj; LinkerObject* obj;
if (proc && proc->mLinkerObject && addr < 256)
{
obj = proc->mLinkerObject;
int i = 0;
while (i < obj->mZeroPageRanges.Size() && !(addr >= obj->mZeroPageRanges[i].mOffset && addr < obj->mZeroPageRanges[i].mOffset + obj->mZeroPageRanges[i].mSize))
i++;
if (i < obj->mZeroPageRanges.Size())
{
sprintf_s(buffer, 160, "; (%s + %d)", obj->mZeroPageRanges[i].mIdent->mString, addr - obj->mZeroPageRanges[i].mOffset);
return buffer;
}
}
if (proc && proc->mLinkerObject && addr >= proc->mLinkerObject->mAddress && addr < proc->mLinkerObject->mAddress + proc->mLinkerObject->mSize) if (proc && proc->mLinkerObject && addr >= proc->mLinkerObject->mAddress && addr < proc->mLinkerObject->mAddress + proc->mLinkerObject->mSize)
obj = proc->mLinkerObject; obj = proc->mLinkerObject;

View File

@ -68,6 +68,9 @@ enum ErrorID
ERRR_USE_OF_UNINITIALIZED_VARIABLE, ERRR_USE_OF_UNINITIALIZED_VARIABLE,
ERRR_STRIPE_REQUIRES_FIXED_SIZE_ARRAY, ERRR_STRIPE_REQUIRES_FIXED_SIZE_ARRAY,
ERRR_STACK_OVERFLOW,
ERRR_INVALID_NUMBER,
EERR_INVALID_PREPROCESSOR, EERR_INVALID_PREPROCESSOR,
}; };

View File

@ -82,11 +82,11 @@ void GlobalAnalyzer::AutoInline(void)
int cost = (f->mComplexity - 20 * nparams); int cost = (f->mComplexity - 20 * nparams);
bool doinline = false; bool doinline = false;
if ((mCompilerOptions & COPT_OPTIMIZE_INLINE) && (f->mFlags & DTF_REQUEST_INLINE)) if ((f->mCompilerOptions & COPT_OPTIMIZE_INLINE) && (f->mFlags & DTF_REQUEST_INLINE))
doinline = true; doinline = true;
if ((mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE) && (cost * (f->mCallers.Size() - 1) <= 0)) if ((f->mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE) && (cost * (f->mCallers.Size() - 1) <= 0))
doinline = true; doinline = true;
if ((mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE_ALL) && (cost * (f->mCallers.Size() - 1) <= 10000)) if ((f->mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE_ALL) && (cost * (f->mCallers.Size() - 1) <= 10000))
doinline = true; doinline = true;
if (doinline) if (doinline)

View File

@ -5851,6 +5851,38 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
assert(mLocalValueRange.Size() == mExitRequiredTemps.Size()); assert(mLocalValueRange.Size() == mExitRequiredTemps.Size());
InterCodeBasicBlock * pblock;
int nloop;
bool singleLoop = CheckSingleBlockLimitedLoop(pblock, nloop);
FastNumberSet dependTemps(mExitRequiredTemps.Size());
if (singleLoop)
{
FastNumberSet changedTemps(mExitRequiredTemps.Size());
for (int i = 0; i < sz; i++)
{
InterInstruction* ins(mInstructions[i]);
if (ins->mCode == IC_BINARY_OPERATOR && ins->mOperator == IA_ADD && ins->mDst.mTemp == ins->mSrc[1].mTemp && ins->mSrc[0].mTemp < 0 && ins->mSrc[0].mIntConst > 0)
{
if (dependTemps[ins->mDst.mTemp])
changedTemps += ins->mDst.mTemp;
else if (pblock->mTrueValueRange[ins->mDst.mTemp].IsConstant())
dependTemps += ins->mDst.mTemp;
else
changedTemps += ins->mDst.mTemp;
}
else if (ins->mDst.mTemp >= 0)
{
changedTemps += ins->mDst.mTemp;
dependTemps -= ins->mDst.mTemp;
}
}
}
for (int i = 0; i < sz; i++) for (int i = 0; i < sz; i++)
{ {
InterInstruction* ins(mInstructions[i]); InterInstruction* ins(mInstructions[i]);
@ -6033,13 +6065,21 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
case IA_ADD: case IA_ADD:
if (ins->mSrc[0].mTemp < 0) if (ins->mSrc[0].mTemp < 0)
{ {
vr = mLocalValueRange[ins->mSrc[1].mTemp]; if (ins->mSrc[1].mTemp == ins->mDst.mTemp && dependTemps[ins->mDst.mTemp] && i + 3 != sz)
if (ins->mSrc[0].mIntConst > 0 && vr.mMaxState == IntegerValueRange::S_WEAK) {
vr.mMaxState = IntegerValueRange::S_UNBOUND; int start = pblock->mTrueValueRange[ins->mDst.mTemp].mMinValue;
else if (ins->mSrc[0].mIntConst < 0 && vr.mMinState == IntegerValueRange::S_WEAK) vr.SetLimit(start + ins->mSrc[0].mIntConst, start + nloop * ins->mSrc[0].mIntConst);
vr.mMinState = IntegerValueRange::S_UNBOUND; }
vr.mMaxValue += ins->mSrc[0].mIntConst; else
vr.mMinValue += ins->mSrc[0].mIntConst; {
vr = mLocalValueRange[ins->mSrc[1].mTemp];
if (ins->mSrc[0].mIntConst > 0 && vr.mMaxState == IntegerValueRange::S_WEAK)
vr.mMaxState = IntegerValueRange::S_UNBOUND;
else if (ins->mSrc[0].mIntConst < 0 && vr.mMinState == IntegerValueRange::S_WEAK)
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxValue += ins->mSrc[0].mIntConst;
vr.mMinValue += ins->mSrc[0].mIntConst;
}
} }
else if (ins->mSrc[1].mTemp < 0) else if (ins->mSrc[1].mTemp < 0)
{ {
@ -6604,11 +6644,13 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
{ {
if (ins->mSrc[0].mTemp < 0) if (ins->mSrc[0].mTemp < 0)
{ {
mMemoryValueSize[ins->mSrc[1].mTemp] = mMemoryValueSize[ins->mDst.mTemp] - ins->mSrc[0].mIntConst; if (ins->mSrc[0].mIntConst >= 0)
mMemoryValueSize[ins->mSrc[1].mTemp] = mMemoryValueSize[ins->mDst.mTemp] - ins->mSrc[0].mIntConst;
} }
else if (ins->mSrc[0].mRange.mMinState == IntegerValueRange::S_BOUND) else if (ins->mSrc[0].mRange.mMinState == IntegerValueRange::S_BOUND)
{ {
mMemoryValueSize[ins->mSrc[1].mTemp] = mMemoryValueSize[ins->mDst.mTemp] - ins->mSrc[0].mRange.mMinValue; if (ins->mSrc[0].mRange.mMinValue >= 0)
mMemoryValueSize[ins->mSrc[1].mTemp] = mMemoryValueSize[ins->mDst.mTemp] - ins->mSrc[0].mRange.mMinValue;
} }
} }
break; break;
@ -9486,6 +9528,16 @@ bool InterCodeBasicBlock::IsTempReferencedInRange(int from, int to, int temp)
return false; return false;
} }
InterInstruction* InterCodeBasicBlock::FindTempOrigin(int temp) const
{
for (int i = mInstructions.Size() - 1; i >= 0; i--)
{
if (mInstructions[i]->mDst.mTemp == temp)
return mInstructions[i];
}
return nullptr;
}
bool InterCodeBasicBlock::CanMoveInstructionDown(int si, int ti) const bool InterCodeBasicBlock::CanMoveInstructionDown(int si, int ti) const
{ {
InterInstruction* ins = mInstructions[si]; InterInstruction* ins = mInstructions[si];
@ -11607,6 +11659,236 @@ void InterCodeBasicBlock::PushMoveOutOfLoop(void)
} }
} }
bool InterCodeBasicBlock::CheckSingleBlockLimitedLoop(InterCodeBasicBlock*& pblock, int& nloop)
{
if (mLoopHead && mNumEntries == 2 && mFalseJump && (mTrueJump == this || mFalseJump == this) && mInstructions.Size() > 3)
{
int nins = mInstructions.Size();
pblock = mEntryBlocks[0];
if (pblock == this)
pblock = mEntryBlocks[1];
if (mInstructions[nins - 1]->mCode == IC_BRANCH &&
mInstructions[nins - 2]->mCode == IC_RELATIONAL_OPERATOR &&
mInstructions[nins - 3]->mCode == IC_BINARY_OPERATOR && mInstructions[nins - 3]->mOperator == IA_ADD)
{
InterInstruction* ains = mInstructions[nins - 3];
InterInstruction* cins = mInstructions[nins - 2];
InterInstruction* bins = mInstructions[nins - 1];
if (bins->mSrc[0].mTemp == cins->mDst.mTemp &&
cins->mSrc[1].mTemp == ains->mDst.mTemp &&
cins->mSrc[0].mTemp < 0 &&
ains->mSrc[1].mTemp == ains->mDst.mTemp &&
ains->mSrc[0].mTemp < 0 &&
(cins->mOperator == IA_CMPLU || cins->mOperator == IA_CMPLEU) &&
cins->mSrc[0].mIntConst < 255 &&
ains->mSrc[0].mIntConst > 0)
{
int pi = pblock->mInstructions.Size() - 1;
while (pi >= 0 && pblock->mInstructions[pi]->mDst.mTemp != ains->mDst.mTemp)
pi--;
int i = 0;
while (i < nins - 3 && mInstructions[i]->mDst.mTemp != ains->mDst.mTemp)
i++;
if (i == nins - 3)
{
nloop = cins->mSrc[0].mIntConst;
if (cins->mOperator == IA_CMPLEU)
nloop++;
nloop = (nloop + ains->mSrc[0].mIntConst - 1) / ains->mSrc[0].mIntConst;
return true;
}
}
}
}
return false;
}
bool InterCodeBasicBlock::SingleBlockLoopPointerToByte(int& spareTemps)
{
bool changed = false;
if (!mVisited)
{
mVisited = true;
if (mLoopHead && mNumEntries == 2 && mFalseJump && (mTrueJump == this || mFalseJump == this) && mInstructions.Size() > 3)
{
int nins = mInstructions.Size();
InterCodeBasicBlock* pblock = mEntryBlocks[0], * eblock = mFalseJump;
if (pblock == this)
pblock = mEntryBlocks[1];
if (eblock == this)
eblock = mTrueJump;
if (mInstructions[nins - 1]->mCode == IC_BRANCH &&
mInstructions[nins - 2]->mCode == IC_RELATIONAL_OPERATOR &&
mInstructions[nins - 3]->mCode == IC_BINARY_OPERATOR && mInstructions[nins - 3]->mOperator == IA_ADD)
{
InterInstruction* ains = mInstructions[nins - 3];
InterInstruction* cins = mInstructions[nins - 2];
InterInstruction* bins = mInstructions[nins - 1];
if (bins->mSrc[0].mTemp == cins->mDst.mTemp &&
cins->mSrc[1].mTemp == ains->mDst.mTemp &&
cins->mSrc[0].mTemp < 0 &&
ains->mSrc[1].mTemp == ains->mDst.mTemp &&
ains->mSrc[0].mTemp < 0 &&
(cins->mOperator == IA_CMPLU || cins->mOperator == IA_CMPLEU) &&
cins->mSrc[0].mIntConst < 255 &&
ains->mSrc[0].mIntConst > 0)
{
GrowingArray<InterInstructionPtr> tvalues(nullptr);
tvalues.SetSize(mEntryRequiredTemps.Size() + 16);
GrowingArray<int> mtemps(-1);
int pi = pblock->mInstructions.Size() - 1;
while (pi >= 0 && pblock->mInstructions[pi]->mDst.mTemp != ains->mDst.mTemp)
pi--;
int i = 0;
while (i < nins - 3 && mInstructions[i]->mDst.mTemp != ains->mDst.mTemp)
i++;
if (i == nins - 3)
{
int nloop = cins->mSrc[0].mIntConst;
if (cins->mOperator == IA_CMPLEU)
nloop++;
nloop /= ains->mSrc[0].mIntConst;
for (int i = 0; i < mInstructions.Size() - 3; i++)
{
InterInstruction* lins = mInstructions[i];
if (lins->mCode == IC_LEA && lins->mDst.mTemp == lins->mSrc[1].mTemp && lins->mSrc[0].mTemp < 0 && lins->mSrc[0].mIntConst > 0 && lins->mSrc[0].mIntConst * nloop < 256 &&
!IsTempReferencedInRange(i + 1, mInstructions.Size(), lins->mDst.mTemp) && !IsTempModifiedInRange(0, i, lins->mDst.mTemp) &&
!eblock->mEntryRequiredTemps[lins->mDst.mTemp])
{
bool isglobal = false;
InterInstruction* slins = pblock->FindTempOrigin(lins->mSrc[1].mTemp);
if (slins)
{
if (slins->mCode == IC_CONSTANT)
{
if (slins->mConst.mMemory == IM_ABSOLUTE || slins->mConst.mMemory == IM_GLOBAL)
isglobal = true;
}
else if (slins->mCode == IC_LEA)
{
if (slins->mSrc[0].mTemp < 0)
{
if (slins->mSrc[1].mMemory == IM_ABSOLUTE || slins->mSrc[1].mMemory == IM_GLOBAL)
isglobal = true;
}
}
}
bool failed = false;
for (int j = 0; j < i; j++)
{
InterInstruction* jins = mInstructions[j];
if (jins->ReferencesTemp(lins->mDst.mTemp))
{
if (jins->mCode == IC_LOAD)
{
if (!isglobal && (jins->mSrc[0].mIntConst < 0 || jins->mSrc[0].mIntConst > 2))
failed = true;
}
else if (jins->mCode == IC_STORE)
{
if (!isglobal && (jins->mSrc[1].mIntConst < 0 || jins->mSrc[1].mIntConst > 2))
failed = true;
}
else
failed = true;
}
}
if (!failed)
{
if (spareTemps + 2 >= mEntryRequiredTemps.Size() + 16)
return true;
int inc = lins->mSrc[0].mIntConst;
int ireg = mtemps[inc];
if (ireg < 0)
{
ireg = spareTemps++;
InterInstruction* cins = new InterInstruction(lins->mLocation, IC_CONSTANT);
cins->mDst.mTemp = ireg;
cins->mDst.mType = IT_INT16;
cins->mConst.mType = IT_INT16;
cins->mConst.mIntConst = 0;
mtemps[inc] = cins->mDst.mTemp;
pblock->mInstructions.Insert(pblock->mInstructions.Size() - 1, cins);
InterInstruction* iins = new InterInstruction(lins->mLocation, IC_BINARY_OPERATOR);
iins->mNumOperands = 2;
iins->mOperator = IA_ADD;
iins->mDst = cins->mDst;
iins->mSrc[1] = cins->mDst;
iins->mSrc[0].mTemp = -1;
iins->mSrc[0].mType = IT_INT16;
iins->mSrc[0].mIntConst = lins->mSrc[0].mIntConst;
iins->mSrc[1].mRange.SetLimit(0, inc * (nloop - 1));
iins->mDst.mRange.SetLimit(lins->mSrc[0].mIntConst, inc * nloop);
mInstructions.Insert(i, iins);
}
InterInstruction* nins = new InterInstruction(lins->mLocation, IC_LEA);
nins->mNumOperands = 2;
nins->mDst.mTemp = spareTemps++;
nins->mDst.mType = IT_POINTER;
nins->mSrc[1] = lins->mSrc[1];
nins->mSrc[1].mFinal = false;
nins->mSrc[0].mType = IT_INT16;
nins->mSrc[0].mTemp = ireg;
nins->mSrc[0].mRange.SetLimit(0, inc * (nloop - 1));
for (int j = 0; j < i; j++)
{
InterInstruction* jins = mInstructions[j];
for (int k = 0; k < jins->mNumOperands; k++)
if (jins->mSrc[k].mTemp == lins->mDst.mTemp)
jins->mSrc[k].mTemp = nins->mDst.mTemp;
}
mInstructions.Insert(0, nins);
lins->mCode = IC_NONE;
lins->mNumOperands = 0;
lins->mDst.mTemp = -1;
changed = true;
}
}
}
}
}
}
}
if (mTrueJump && mTrueJump->SingleBlockLoopPointerToByte(spareTemps))
changed = true;
if (mFalseJump && mFalseJump->SingleBlockLoopPointerToByte(spareTemps))
changed = true;
}
return changed;
}
bool InterCodeBasicBlock::SingleBlockLoopPointerSplit(int& spareTemps) bool InterCodeBasicBlock::SingleBlockLoopPointerSplit(int& spareTemps)
{ {
@ -14757,6 +15039,53 @@ void InterCodeProcedure::MergeIndexedLoadStore(void)
DisassembleDebug("SimplifyPointerOffsets"); DisassembleDebug("SimplifyPointerOffsets");
} }
void InterCodeProcedure::SingleBlockLoopPointerToByte(FastNumberSet& activeSet)
{
int silvused = mTemporaries.Size();
do
{
mTemporaries.SetSize(silvused, true);
DisassembleDebug("SingleBlockLoopPointerToByteA");
BuildDataFlowSets();
DisassembleDebug("SingleBlockLoopPointerToByteB");
TempForwarding();
RemoveUnusedInstructions();
DisassembleDebug("SingleBlockLoopPointerToByteC");
activeSet.Clear();
ResetVisited();
mEntryBlock->CollectActiveTemporaries(activeSet);
silvused = activeSet.Num();
if (silvused != mTemporaries.Size())
{
mTemporaries.SetSize(activeSet.Num(), true);
ResetVisited();
mEntryBlock->ShrinkActiveTemporaries(activeSet, mTemporaries);
ResetVisited();
mEntryBlock->RemapActiveTemporaries(activeSet);
}
ResetVisited();
} while (mEntryBlock->SingleBlockLoopPointerToByte(silvused));
assert(silvused == mTemporaries.Size());
DisassembleDebug("SingleBlockLoopPointerToByte");
}
void InterCodeProcedure::SingleBlockLoopPointerSplit(FastNumberSet& activeSet) void InterCodeProcedure::SingleBlockLoopPointerSplit(FastNumberSet& activeSet)
{ {
int silvused = mTemporaries.Size(); int silvused = mTemporaries.Size();
@ -15082,7 +15411,13 @@ void InterCodeProcedure::Close(void)
InterMemory paramMemory = mFastCallProcedure ? IM_FPARAM : IM_PARAM; InterMemory paramMemory = mFastCallProcedure ? IM_FPARAM : IM_PARAM;
PromoteSimpleLocalsToTemp(paramMemory, nlocals, nparams); if (mCompilerOptions & COPT_OPTIMIZE_BASIC)
PromoteSimpleLocalsToTemp(paramMemory, nlocals, nparams);
else
{
ResetVisited();
mEntryBlock->CollectVariables(mModule->mGlobalVars, mLocalVars, mParamVars, paramMemory);
}
BuildDataFlowSets(); BuildDataFlowSets();
@ -15265,6 +15600,8 @@ void InterCodeProcedure::Close(void)
SingleBlockLoopPointerSplit(activeSet); SingleBlockLoopPointerSplit(activeSet);
MergeIndexedLoadStore(); MergeIndexedLoadStore();
SingleBlockLoopPointerToByte(activeSet);
#if 1 #if 1
DisassembleDebug("PreMoveTrainCrossBlockA"); DisassembleDebug("PreMoveTrainCrossBlockA");
@ -15384,7 +15721,7 @@ void InterCodeProcedure::Close(void)
#endif #endif
#if 1 #if 1
if (mModule->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL) if (mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
{ {
ResetVisited(); ResetVisited();
mEntryBlock->SingleBlockLoopUnrolling(); mEntryBlock->SingleBlockLoopUnrolling();
@ -15715,6 +16052,25 @@ void InterCodeProcedure::Close(void)
if (mSaveTempsLinkerObject && mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP) if (mSaveTempsLinkerObject && mTempSize > BC_REG_TMP_SAVED - BC_REG_TMP)
mSaveTempsLinkerObject->AddSpace(mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP)); mSaveTempsLinkerObject->AddSpace(mTempSize - (BC_REG_TMP_SAVED - BC_REG_TMP));
for (int i = 0; i < mParamVars.Size(); i++)
{
InterVariable* v(mParamVars[i]);
if (v && v->mIdent)
{
if (v->mLinkerObject)
{
}
else
{
LinkerObjectRange range;
range.mIdent = v->mIdent;
range.mOffset = i + BC_REG_FPARAMS;
range.mSize = v->mSize;
mLinkerObject->mZeroPageRanges.Push(range);
}
}
}
} }
void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc) void InterCodeProcedure::AddCalledFunction(InterCodeProcedure* proc)

View File

@ -425,6 +425,8 @@ public:
bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars); bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars);
bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars); bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars);
bool CheckSingleBlockLimitedLoop(InterCodeBasicBlock*& pblock, int& nloop);
void RestartLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars); void RestartLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
void BuildLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars); void BuildLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
void UpdateLocalIntegerRangeSets(const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars); void UpdateLocalIntegerRangeSets(const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
@ -498,6 +500,8 @@ public:
bool IsTempUsedInRange(int from, int to, int temp); bool IsTempUsedInRange(int from, int to, int temp);
bool IsTempReferencedInRange(int from, int to, int temp); bool IsTempReferencedInRange(int from, int to, int temp);
InterInstruction* FindTempOrigin(int temp) const;
void CheckFinalLocal(void); void CheckFinalLocal(void);
void CheckFinal(void); void CheckFinal(void);
void CheckBlocks(void); void CheckBlocks(void);
@ -508,6 +512,7 @@ public:
void SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars); void SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
void SingleBlockLoopUnrolling(void); void SingleBlockLoopUnrolling(void);
bool SingleBlockLoopPointerSplit(int& spareTemps); bool SingleBlockLoopPointerSplit(int& spareTemps);
bool SingleBlockLoopPointerToByte(int& spareTemps);
bool CollectLoopBody(InterCodeBasicBlock* head, GrowingArray<InterCodeBasicBlock*> & body); bool CollectLoopBody(InterCodeBasicBlock* head, GrowingArray<InterCodeBasicBlock*> & body);
void CollectLoopPath(const GrowingArray<InterCodeBasicBlock*>& body, GrowingArray<InterCodeBasicBlock*>& path); void CollectLoopPath(const GrowingArray<InterCodeBasicBlock*>& body, GrowingArray<InterCodeBasicBlock*>& path);
void InnerLoopOptimization(const NumberSet& aliasedParams); void InnerLoopOptimization(const NumberSet& aliasedParams);
@ -577,6 +582,8 @@ public:
LinkerObject * mLinkerObject, * mSaveTempsLinkerObject; LinkerObject * mLinkerObject, * mSaveTempsLinkerObject;
Declaration * mDeclaration; Declaration * mDeclaration;
uint64 mCompilerOptions;
InterCodeProcedure(InterCodeModule * module, const Location & location, const Ident * ident, LinkerObject* linkerObject); InterCodeProcedure(InterCodeModule * module, const Location & location, const Ident * ident, LinkerObject* linkerObject);
~InterCodeProcedure(void); ~InterCodeProcedure(void);
@ -615,6 +622,7 @@ protected:
void PromoteSimpleLocalsToTemp(InterMemory paramMemory, int nlocals, int nparams); void PromoteSimpleLocalsToTemp(InterMemory paramMemory, int nlocals, int nparams);
void SimplifyIntegerNumeric(FastNumberSet& activeSet); void SimplifyIntegerNumeric(FastNumberSet& activeSet);
void SingleBlockLoopPointerSplit(FastNumberSet& activeSet); void SingleBlockLoopPointerSplit(FastNumberSet& activeSet);
void SingleBlockLoopPointerToByte(FastNumberSet& activeSet);
void MergeIndexedLoadStore(void); void MergeIndexedLoadStore(void);
void EliminateAliasValues(); void EliminateAliasValues();
void LoadStoreForwarding(InterMemory paramMemory); void LoadStoreForwarding(InterMemory paramMemory);

View File

@ -230,6 +230,15 @@ static inline InterType InterTypeOfArithmetic(InterType t1, InterType t2)
return IT_INT16; return IT_INT16;
} }
void InterCodeGenerator::InitParameter(InterCodeProcedure* proc, Declaration* dec, int index)
{
if (!proc->mParamVars[index])
{
proc->mParamVars[index] = new InterVariable();
proc->mParamVars[index]->mIdent = dec->mIdent;
}
}
void InterCodeGenerator::InitLocalVariable(InterCodeProcedure* proc, Declaration* dec, int index) void InterCodeGenerator::InitLocalVariable(InterCodeProcedure* proc, Declaration* dec, int index)
{ {
if (!proc->mLocalVars[index]) if (!proc->mLocalVars[index])
@ -1204,14 +1213,20 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
{ {
ins->mConst.mMemory = IM_LOCAL; ins->mConst.mMemory = IM_LOCAL;
ins->mConst.mVarIndex = inlineMapper->mParams[dec->mVarIndex]; ins->mConst.mVarIndex = inlineMapper->mParams[dec->mVarIndex];
InitLocalVariable(proc, dec, ins->mConst.mVarIndex);
} }
else if (procType->mFlags & DTF_FASTCALL) else if (procType->mFlags & DTF_FASTCALL)
{ {
ins->mConst.mMemory = IM_FPARAM; ins->mConst.mMemory = IM_FPARAM;
ins->mConst.mVarIndex += procType->mFastCallBase; ins->mConst.mVarIndex += procType->mFastCallBase;
InitParameter(proc, dec, ins->mConst.mVarIndex);
} }
else else
{
ins->mConst.mMemory = IM_PARAM; ins->mConst.mMemory = IM_PARAM;
InitParameter(proc, dec, ins->mConst.mVarIndex);
}
if (dec->mBase->mType == DT_TYPE_ARRAY) if (dec->mBase->mType == DT_TYPE_ARRAY)
{ {
ref = 2; ref = 2;
@ -2275,7 +2290,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
} }
} }
bool canInline = exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION && !(inlineMapper && inlineMapper->mDepth > 10); bool canInline = exp->mLeft->mType == EX_CONSTANT &&
exp->mLeft->mDecValue->mType == DT_CONST_FUNCTION &&
(mCompilerOptions & COPT_OPTIMIZE_INLINE) &&
!(inlineMapper && inlineMapper->mDepth > 10);
bool doInline = false, inlineConstexpr = false; bool doInline = false, inlineConstexpr = false;
if (canInline) if (canInline)
@ -2309,8 +2327,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
doInline = true; doInline = true;
else if (exp->mLeft->mDecValue->mFlags & DTF_INLINE) else if (exp->mLeft->mDecValue->mFlags & DTF_INLINE)
{ {
if (proc->mNativeProcedure || !(exp->mLeft->mDecValue->mFlags & DTF_NATIVE)) if ((exp->mLeft->mDecValue->mFlags & DTF_REQUEST_INLINE) || (mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE))
doInline = true; {
if (proc->mNativeProcedure || !(exp->mLeft->mDecValue->mFlags & DTF_NATIVE))
doInline = true;
}
} }
} }
@ -3665,6 +3686,11 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
{ {
InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mIdent, mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_BYTE_CODE)); InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mIdent, mLinker->AddObject(dec->mLocation, dec->mIdent, dec->mSection, LOT_BYTE_CODE));
uint64 outerCompilerOptions = mCompilerOptions;
mCompilerOptions = dec->mCompilerOptions;
proc->mCompilerOptions = mCompilerOptions;
dec->mVarIndex = proc->mID; dec->mVarIndex = proc->mID;
dec->mLinkerObject = proc->mLinkerObject; dec->mLinkerObject = proc->mLinkerObject;
proc->mNumLocals = dec->mNumVars; proc->mNumLocals = dec->mNumVars;
@ -3733,5 +3759,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
proc->Close(); proc->Close();
} }
mCompilerOptions = outerCompilerOptions;
return proc; return proc;
} }

View File

@ -27,6 +27,7 @@ public:
void TranslateAssembler(InterCodeModule* mod, Expression * exp, GrowingArray<Declaration *> * refvars); void TranslateAssembler(InterCodeModule* mod, Expression * exp, GrowingArray<Declaration *> * refvars);
void InitGlobalVariable(InterCodeModule* mod, Declaration* dec); void InitGlobalVariable(InterCodeModule* mod, Declaration* dec);
void InitLocalVariable(InterCodeProcedure* proc, Declaration* dec, int index); void InitLocalVariable(InterCodeProcedure* proc, Declaration* dec, int index);
void InitParameter(InterCodeProcedure* proc, Declaration* dec, int index);
protected: protected:
Errors* mErrors; Errors* mErrors;

View File

@ -187,6 +187,7 @@ public:
ExpandingArray<LinkerObjectRange> mRanges; ExpandingArray<LinkerObjectRange> mRanges;
ExpandingArray<CodeLocation> mCodeLocations; ExpandingArray<CodeLocation> mCodeLocations;
ExpandingArray<LinkerObjectRange> mZeroPageRanges;
LinkerObject(void); LinkerObject(void);
~LinkerObject(void); ~LinkerObject(void);

View File

@ -6857,9 +6857,9 @@ NativeCodeBasicBlock * NativeCodeBasicBlock::CopyValue(InterCodeProcedure* proc,
if (sstride > 1 || dstride > 1) if (sstride > 1 || dstride > 1)
msize = 32; msize = 32;
else if (nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL) else if (nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL)
msize = 8; msize = 8;
else if (nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) else if (nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE)
msize = 2; msize = 2;
#if 1 #if 1
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp < 0) if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp < 0)
@ -8771,8 +8771,8 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
int lcost = 8 + 2 * (nbytes - 1); int lcost = 8 + 2 * (nbytes - 1);
int ucost = shift * (1 + 2 * nbytes); int ucost = shift * (1 + 2 * nbytes);
if ((nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && lcost < ucost || if ((nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE) && lcost < ucost ||
!(nproc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL) && 2 * lcost < ucost) !(nproc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_AUTO_UNROLL) && 2 * lcost < ucost)
{ {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_IMMEDIATE, shift)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_IMMEDIATE, shift));
this->Close(ins, lblock, nullptr, ASMIT_JMP); this->Close(ins, lblock, nullptr, ASMIT_JMP);
@ -11768,7 +11768,7 @@ void NativeCodeBasicBlock::CallAssembler(InterCodeProcedure* proc, NativeCodePro
assert(ins->mSrc[0].mLinkerObject); assert(ins->mSrc[0].mLinkerObject);
if (ins->mCode == IC_ASSEMBLER && (proc->mModule->mCompilerOptions & COPT_OPTIMIZE_ASSEMBLER)) if (ins->mCode == IC_ASSEMBLER && (proc->mCompilerOptions & COPT_OPTIMIZE_ASSEMBLER))
{ {
ExpandingArray<NativeCodeInstruction> tains; ExpandingArray<NativeCodeInstruction> tains;
@ -12372,20 +12372,24 @@ bool NativeCodeBasicBlock::MergeBasicBlocks(void)
changed = true; changed = true;
} }
while (mTrueJump && mTrueJump->mIns.Size() == 0 && !mTrueJump->mFalseJump && !mTrueJump->mLocked && mTrueJump != this && mTrueJump->mTrueJump != mTrueJump) int steps = 100;
while (mTrueJump && mTrueJump->mIns.Size() == 0 && !mTrueJump->mFalseJump && !mTrueJump->mLocked && mTrueJump != this && mTrueJump->mTrueJump != mTrueJump && steps > 0)
{ {
mTrueJump->mNumEntries--; mTrueJump->mNumEntries--;
mTrueJump = mTrueJump->mTrueJump; mTrueJump = mTrueJump->mTrueJump;
mTrueJump->mNumEntries++; mTrueJump->mNumEntries++;
changed = true; changed = true;
steps--;
} }
while (mFalseJump && mFalseJump->mTrueJump && mFalseJump->mIns.Size() == 0 && !mFalseJump->mFalseJump && !mFalseJump->mLocked && mFalseJump != this && mFalseJump->mTrueJump != mFalseJump) steps = 100;
while (mFalseJump && mFalseJump->mTrueJump && mFalseJump->mIns.Size() == 0 && !mFalseJump->mFalseJump && !mFalseJump->mLocked && mFalseJump != this && mFalseJump->mTrueJump != mFalseJump && steps > 0)
{ {
mFalseJump->mNumEntries--; mFalseJump->mNumEntries--;
mFalseJump = mFalseJump->mTrueJump; mFalseJump = mFalseJump->mTrueJump;
mFalseJump->mNumEntries++; mFalseJump->mNumEntries++;
changed = true; changed = true;
steps--;
} }
if (mTrueJump && mTrueJump == mFalseJump) if (mTrueJump && mTrueJump == mFalseJump)
@ -25777,6 +25781,8 @@ bool NativeCodeBasicBlock::MoveLoadShiftStoreUp(int at)
return false; return false;
} }
mIns[j].mLive |= LIVE_CPU_REG_A;
mIns[at + 1].mLive |= mIns[j].mLive; mIns[at + 1].mLive |= mIns[j].mLive;
mIns[at + 2].mLive |= mIns[j].mLive; mIns[at + 2].mLive |= mIns[j].mLive;
@ -26437,6 +26443,9 @@ bool NativeCodeBasicBlock::ValueForwarding(NativeCodeProcedure* proc, const Nati
if (ins.mMode == ASMIM_ZERO_PAGE && ins.ChangesAddress()) if (ins.mMode == ASMIM_ZERO_PAGE && ins.ChangesAddress())
mNDataSet.ResetZeroPage(ins.mAddress); mNDataSet.ResetZeroPage(ins.mAddress);
else if (ins.mMode == ASMIM_ABSOLUTE && ins.ChangesAddress())
mNDataSet.ResetAbsolute(ins.mLinkerObject, ins.mAddress);
if (ins.mType == ASMIT_JSR) if (ins.mType == ASMIT_JSR)
{ {
mNDataSet.ResetWorkRegs(); mNDataSet.ResetWorkRegs();
@ -30165,7 +30174,7 @@ static bool CheckBlockCopySequence(const ExpandingArray<NativeCodeInstruction>&
bool NativeCodeBasicBlock::BlockSizeCopyReduction(NativeCodeProcedure* proc, int& si, int& di) bool NativeCodeBasicBlock::BlockSizeCopyReduction(NativeCodeProcedure* proc, int& si, int& di)
{ {
if ((proc->mGenerator->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE)) if ((proc->mInterProc->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE))
{ {
if (si + 1 < mIns.Size() && if (si + 1 < mIns.Size() &&
mIns[si + 0].mType == ASMIT_LDA && (mIns[si + 0].mMode == ASMIM_ZERO_PAGE || mIns[si + 0].mMode == ASMIM_ABSOLUTE) && mIns[si + 0].mType == ASMIT_LDA && (mIns[si + 0].mMode == ASMIM_ZERO_PAGE || mIns[si + 0].mMode == ASMIM_ABSOLUTE) &&
@ -38656,7 +38665,7 @@ void NativeCodeProcedure::RebuildEntry(void)
void NativeCodeProcedure::Optimize(void) void NativeCodeProcedure::Optimize(void)
{ {
CheckFunc = !strcmp(mInterProc->mIdent->mString, "test"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "main");
#if 1 #if 1
int step = 0; int step = 0;
@ -39968,6 +39977,8 @@ void NativeCodeGenerator::CompleteRuntime(void)
LinkerObject* NativeCodeGenerator::AllocateShortMulTable(InterOperator op, int factor, int size, bool msb) LinkerObject* NativeCodeGenerator::AllocateShortMulTable(InterOperator op, int factor, int size, bool msb)
{ {
assert(size > 0);
int i = 0; int i = 0;
while (i < mMulTables.Size() && (mMulTables[i].mFactor != factor || mMulTables[i].mOperator != op)) while (i < mMulTables.Size() && (mMulTables[i].mFactor != factor || mMulTables[i].mOperator != op))
i++; i++;

View File

@ -16,6 +16,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn
mUnrollLoop = 0; mUnrollLoop = 0;
mUnrollLoopPage = false; mUnrollLoopPage = false;
mInlineCall = false; mInlineCall = false;
mCompilerOptionSP = 0;
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
mCharMap[i] = i; mCharMap[i] = i;
@ -1284,6 +1285,9 @@ Declaration* Parser::ParseDeclaration(bool variable, bool expression)
if (ndec->mFlags & DTF_DEFINED) if (ndec->mFlags & DTF_DEFINED)
mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition"); mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition");
ndec->mCompilerOptions = mCompilerOptions;
ndec->mBase->mCompilerOptions = mCompilerOptions;
ndec->mVarIndex = -1; ndec->mVarIndex = -1;
ndec->mValue = ParseFunction(ndec->mBase); ndec->mValue = ParseFunction(ndec->mBase);
ndec->mFlags |= DTF_DEFINED; ndec->mFlags |= DTF_DEFINED;
@ -3234,9 +3238,20 @@ bool Parser::ConsumeTokenIf(Token token)
} }
else else
return false; return false;
} }
bool Parser::ConsumeIdentIf(const char* ident)
{
if (mScanner->mToken == TK_IDENT && !strcmp(ident, mScanner->mTokenIdent->mString))
{
mScanner->NextToken();
return true;
}
else
return false;
}
void Parser::ParsePragma(void) void Parser::ParsePragma(void)
{ {
if (mScanner->mToken == TK_IDENT) if (mScanner->mToken == TK_IDENT)
@ -3947,6 +3962,71 @@ void Parser::ParsePragma(void)
ConsumeToken(TK_CLOSE_PARENTHESIS); ConsumeToken(TK_CLOSE_PARENTHESIS);
mInlineCall = true; mInlineCall = true;
} }
else if (ConsumeIdentIf("optimize"))
{
mScanner->NextToken();
ConsumeToken(TK_OPEN_PARENTHESIS);
if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS))
{
do {
if (ConsumeIdentIf("push"))
{
if (mCompilerOptionSP < 32)
mCompilerOptionStack[mCompilerOptionSP++] = mCompilerOptions;
else
mErrors->Error(mScanner->mLocation, ERRR_STACK_OVERFLOW, "Stack overflow");
}
else if (ConsumeIdentIf("pop"))
{
if (mCompilerOptionSP > 0)
mCompilerOptions = mCompilerOptionStack[--mCompilerOptionSP] = mCompilerOptions;
else
mErrors->Error(mScanner->mLocation, ERRR_STACK_OVERFLOW, "Stack underflow");
}
else if (mScanner->mToken == TK_INTEGER)
{
mCompilerOptions &= ~(COPT_OPTIMIZE_ALL);
switch (mScanner->mTokenInteger)
{
case 0:
break;
case 1:
mCompilerOptions |= COPT_OPTIMIZE_DEFAULT;
break;
case 2:
mCompilerOptions |= COPT_OPTIMIZE_SPEED;
break;
case 3:
mCompilerOptions |= COPT_OPTIMIZE_ALL;
break;
default:
mErrors->Error(mScanner->mLocation, ERRR_INVALID_NUMBER, "Invalid number");
}
}
else if (ConsumeIdentIf("asm"))
mCompilerOptions |= COPT_OPTIMIZE_ASSEMBLER;
else if (ConsumeIdentIf("noasm"))
mCompilerOptions &= ~COPT_OPTIMIZE_ASSEMBLER;
else if (ConsumeIdentIf("size"))
mCompilerOptions |= COPT_OPTIMIZE_SIZE;
else if (ConsumeIdentIf("speed"))
mCompilerOptions &= ~COPT_OPTIMIZE_SIZE;
else if (ConsumeIdentIf("noinline"))
mCompilerOptions &= ~(COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL);
else if (ConsumeIdentIf("inline"))
mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE;
else if (ConsumeIdentIf("autoinline"))
mCompilerOptions |= COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE;
else if (ConsumeIdentIf("maxinline"))
mCompilerOptions |= COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_INLINE_ALL;
else
mErrors->Error(mScanner->mLocation, EERR_INVALID_IDENTIFIER, "Invalid option");
} while (ConsumeTokenIf(TK_COMMA));
ConsumeToken(TK_CLOSE_PARENTHESIS);
}
}
else else
{ {
mScanner->NextToken(); mScanner->NextToken();

View File

@ -16,12 +16,15 @@ public:
LinkerSection * mCodeSection, * mDataSection, * mBSSection; LinkerSection * mCodeSection, * mDataSection, * mBSSection;
uint64 mCompilerOptions; uint64 mCompilerOptions;
uint64 mCompilerOptionStack[32];
int mCompilerOptionSP;
void Parse(void); void Parse(void);
protected: protected:
bool ConsumeToken(Token token); bool ConsumeToken(Token token);
bool ConsumeTokenIf(Token token); bool ConsumeTokenIf(Token token);
bool ConsumeIdentIf(const char* ident);
char mCharMap[256]; char mCharMap[256];
int mUnrollLoop; int mUnrollLoop;