Make loop head extraction explicit

This commit is contained in:
drmortalwombat 2025-06-10 17:41:16 +02:00
parent 5b4e0c2b55
commit d6802f3cb9
5 changed files with 542 additions and 99 deletions

View File

@ -99,6 +99,61 @@ void IntegerValueRange::Restart(void)
} }
bool IntegerValueRange::Weaker(const IntegerValueRange& range) const
{
bool minWeak = false, maxWeak = false;
if (range.mMinState == S_UNKNOWN)
minWeak = false;
else if (mMinState == S_UNKNOWN)
minWeak = true;
else if (mMinState == S_BOUND)
{
if (range.mMinState >= S_WEAK && mMinValue < range.mMinValue)
minWeak = true;
}
else if (mMinState == S_WEAK)
{
if (range.mMinState == S_BOUND)
minWeak = true;
if (range.mMinState == S_WEAK && mMinValue != range.mMinValue)
minWeak = true;
}
else if (mMinState == S_UNBOUND)
{
if (mMinExpanded >= 32 && range.mMinState == S_WEAK)
;
else if (range.mMinState != S_UNBOUND)
minWeak = true;
}
if (range.mMaxState == S_UNKNOWN)
maxWeak = false;
else if (mMaxState == S_UNKNOWN)
maxWeak = true;
else if (mMaxState == S_BOUND)
{
if (range.mMaxState >= S_WEAK && mMaxValue > range.mMaxValue)
maxWeak = true;
}
else if (mMaxState == S_WEAK)
{
if (range.mMaxState == S_BOUND)
maxWeak = true;
if (range.mMaxState == S_WEAK && mMaxValue != range.mMaxValue)
maxWeak = true;
}
else if (mMaxState == S_UNBOUND)
{
if (mMaxExpanded >= 32 && range.mMaxState == S_WEAK)
;
else if (range.mMaxState != S_UNBOUND)
maxWeak = true;
}
return minWeak || maxWeak;
}
bool IntegerValueRange::Same(const IntegerValueRange& range) const bool IntegerValueRange::Same(const IntegerValueRange& range) const
{ {
if (mMinState == range.mMinState && mMaxState == range.mMaxState) if (mMinState == range.mMinState && mMaxState == range.mMaxState)
@ -266,6 +321,91 @@ void IntegerValueRange::SetBounds(State minState, int64 minValue, State maxState
void IntegerValueRange::Expand(const IntegerValueRange& range) void IntegerValueRange::Expand(const IntegerValueRange& range)
{ {
if (mMinState == S_BOUND)
{
if (range.mMinState == S_BOUND)
{
if (range.mMinValue > mMinValue)
mMinValue = range.mMinValue;
}
else if (range.mMinState == S_WEAK)
{
if (range.mMinValue > mMinValue)
{
mMinValue = range.mMinValue;
mMinState = S_WEAK;
}
}
}
else if (mMinState == S_WEAK)
{
if (range.mMinState == S_BOUND)
{
mMinState = range.mMinState;
mMinValue = range.mMinValue;
}
else if (range.mMinState == S_WEAK)
{
if (range.mMinValue != mMinValue)
{
mMinExpanded++;
mMinValue = range.mMinValue;
if (mMinExpanded >= 32)
mMinState = S_UNBOUND;
}
}
else if (range.mMinState == S_UNBOUND)
mMinState = S_UNBOUND;
}
else if (mMinState == S_UNKNOWN || range.mMinState != S_UNKNOWN)
{
mMinState = range.mMinState;
mMinValue = range.mMinValue;
}
if (mMaxState == S_BOUND)
{
if (range.mMaxState == S_BOUND)
{
if (range.mMaxValue < mMaxValue)
mMaxValue = range.mMaxValue;
}
else if (range.mMaxState == S_WEAK)
{
if (range.mMaxValue < mMaxValue)
{
mMaxValue = range.mMaxValue;
mMaxState = S_WEAK;
}
}
}
else if (mMaxState == S_WEAK)
{
if (range.mMaxState == S_BOUND)
{
mMaxValue = range.mMaxValue;
mMaxState = S_BOUND;
}
else if (range.mMaxState == S_WEAK)
{
if (range.mMaxValue != mMaxValue)
{
mMaxExpanded++;
mMaxValue = range.mMaxValue;
if (mMaxExpanded >= 32)
mMaxState = S_UNBOUND;
}
}
else if (range.mMaxState == S_UNBOUND)
mMaxState = S_UNBOUND;
}
else if (mMaxState == S_UNKNOWN || range.mMaxState != S_UNKNOWN)
{
mMaxState = range.mMaxState;
mMaxValue = range.mMaxValue;
}
#if 0
if (range.mMinState == S_BOUND && mMinState == S_BOUND && range.mMinValue < mMinValue) if (range.mMinState == S_BOUND && mMinState == S_BOUND && range.mMinValue < mMinValue)
{ {
mMinValue = range.mMinValue; mMinValue = range.mMinValue;
@ -292,6 +432,7 @@ void IntegerValueRange::Expand(const IntegerValueRange& range)
mMaxState = range.mMaxState; mMaxState = range.mMaxState;
mMaxValue = range.mMaxValue; mMaxValue = range.mMaxValue;
} }
#endif
} }
void IntegerValueRange::Union(const IntegerValueRange& range) void IntegerValueRange::Union(const IntegerValueRange& range)
@ -6103,13 +6244,20 @@ bool InterCodeBasicBlock::IsDominator(InterCodeBasicBlock* block)
void InterCodeBasicBlock::CollectEntries(void) void InterCodeBasicBlock::CollectEntries(void)
{ {
if (mInPath)
{
mLoopDebug = true;
mLoopHead = true;
}
mNumEntries++; mNumEntries++;
if (!mVisited) if (!mVisited)
{ {
mVisited = true; mVisited = true;
mInPath = true;
if (mTrueJump) mTrueJump->CollectEntries(); if (mTrueJump) mTrueJump->CollectEntries();
if (mFalseJump) mFalseJump->CollectEntries(); if (mFalseJump) mFalseJump->CollectEntries();
mInPath = false;
} }
} }
@ -6133,6 +6281,61 @@ static bool IsInfiniteLoop(InterCodeBasicBlock* head, InterCodeBasicBlock* block
return false; return false;
} }
bool InterCodeBasicBlock::StripLoopHead(void)
{
bool changed = false;
if (!mVisited)
{
if (mLoopHead && mFalseJump && mTrueJump != this && mFalseJump != this && mLoopPrefix && mInstructions.Size() < 10)
{
// printf("StripA %s %d\n", mProc->mIdent->mString, mIndex);
ExpandingArray<InterCodeBasicBlock*> lblocks;
if (CollectSingleEntryGenericLoop(lblocks))
{
// printf("StripB %s %d\n", mProc->mIdent->mString, mIndex);
mLoopPrefix->mInstructions.SetSize(0);
for (int i = 0; i < mInstructions.Size(); i++)
mLoopPrefix->mInstructions.Push(mInstructions[i]->Clone());
mLoopPrefix->mFalseJump = mFalseJump;
mLoopPrefix->mTrueJump = mTrueJump;
mEntryBlocks.RemoveAll(mLoopPrefix);
mNumEntries--;
mLoopHead = false;
mTrueJump->mEntryBlocks.Push(mLoopPrefix);
mTrueJump->mNumEntries++;
mFalseJump->mEntryBlocks.Push(mLoopPrefix);
mFalseJump->mNumEntries++;
if (!lblocks.Contains(mTrueJump))
{
mFalseJump->mLoopHead = true;
}
else if (!lblocks.Contains(mFalseJump))
{
mTrueJump->mLoopHead = true;
}
changed = true;
}
}
mVisited = true;
if (mTrueJump && mTrueJump->StripLoopHead())
changed = true;
if (mFalseJump && mFalseJump->StripLoopHead())
changed = true;
}
return changed;
}
void InterCodeBasicBlock::GenerateTraces(int expand, bool compact) void InterCodeBasicBlock::GenerateTraces(int expand, bool compact)
{ {
if (mInPath) if (mInPath)
@ -6237,6 +6440,9 @@ void InterCodeBasicBlock::GenerateTraces(int expand, bool compact)
} }
else if (mTrueJump && !mFalseJump && ((mTrueJump->mInstructions.Size() < expand && mTrueJump->mInstructions.Size() > 1 && !mLoopHead) || mTrueJump->mNumEntries == 1) && !mTrueJump->mLoopHead && !IsInfiniteLoop(mTrueJump, mTrueJump)) else if (mTrueJump && !mFalseJump && ((mTrueJump->mInstructions.Size() < expand && mTrueJump->mInstructions.Size() > 1 && !mLoopHead) || mTrueJump->mNumEntries == 1) && !mTrueJump->mLoopHead && !IsInfiniteLoop(mTrueJump, mTrueJump))
{ {
// if (mLoopDebug)
// printf("StripC %s %d %d\n", mProc->mIdent->mString, mTrueJump->mIndex, mTrueJump->mInstructions.Size());
mTrueJump->mNumEntries--; mTrueJump->mNumEntries--;
int n = mTrueJump->mNumEntries; int n = mTrueJump->mNumEntries;
@ -8189,11 +8395,11 @@ bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(bool initial, const Growin
assert(mLocalParamValueRange.Size() == paramVars.Size()); assert(mLocalParamValueRange.Size() == paramVars.Size());
for (int i = 0; i < mProc->mLocalValueRange.Size(); i++) for (int i = 0; i < mProc->mLocalValueRange.Size(); i++)
if (!mProc->mLocalValueRange[i].Same(mEntryValueRange[i])) if (mEntryValueRange[i].Weaker(mProc->mLocalValueRange[i]))
changed = true; changed = true;
for (int i = 0; i < mLocalParamValueRange.Size(); i++) for (int i = 0; i < mLocalParamValueRange.Size(); i++)
if (!mLocalParamValueRange[i].Same(mEntryParamValueRange[i])) if (mEntryParamValueRange[i].Weaker(mLocalParamValueRange[i]))
changed = true; changed = true;
if (mVisited && mNumEntered >= 2 * mEntryBlocks.Size()) if (mVisited && mNumEntered >= 2 * mEntryBlocks.Size())
@ -9551,6 +9757,15 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
mTrueValueRange[s].mMaxState = IntegerValueRange::S_BOUND; mTrueValueRange[s].mMaxState = IntegerValueRange::S_BOUND;
mTrueValueRange[s].mMaxValue = 1; mTrueValueRange[s].mMaxValue = 1;
mFalseValueRange[s].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[s].mMinValue = 0;
mFalseValueRange[s].mMaxState = IntegerValueRange::S_BOUND;
mFalseValueRange[s].mMaxValue = 0;
}
else if (mInstructions[sz - 1]->mCode == IC_BRANCH && mInstructions[sz - 1]->mSrc[0].mTemp >= 0 && IsIntegerType(mInstructions[sz - 1]->mSrc[0].mType))
{
int s = mInstructions[sz - 1]->mSrc[0].mTemp;
mFalseValueRange[s].mMinState = IntegerValueRange::S_BOUND; mFalseValueRange[s].mMinState = IntegerValueRange::S_BOUND;
mFalseValueRange[s].mMinValue = 0; mFalseValueRange[s].mMinValue = 0;
mFalseValueRange[s].mMaxState = IntegerValueRange::S_BOUND; mFalseValueRange[s].mMaxState = IntegerValueRange::S_BOUND;
@ -15520,8 +15735,76 @@ bool InterCodeBasicBlock::InvalidatedBy(const InterInstruction* ins, const Inter
return CollidingMem(by, ins); return CollidingMem(by, ins);
} }
void InterCodeBasicBlock::CollectReachable(ExpandingArray<InterCodeBasicBlock*>& lblock)
{
if (!mVisited && !mPatched)
{
lblock.Push(this);
mPatched = true;
bool InterCodeBasicBlock::CollectSingleHeadLoopBody(InterCodeBasicBlock* head, InterCodeBasicBlock* tail, GrowingArray<InterCodeBasicBlock*>& body) if (mTrueJump) mTrueJump->CollectReachable(lblock);
if (mFalseJump) mFalseJump->CollectReachable(lblock);
}
}
bool InterCodeBasicBlock::CollectGenericLoop(ExpandingArray<InterCodeBasicBlock*>& lblocks)
{
ExpandingArray<InterCodeBasicBlock*> rblocks;
mProc->ResetPatched();
CollectReachable(rblocks);
mProc->ResetPatched();
bool changed;
do
{
changed = false;
for (int i = 0; i < rblocks.Size(); i++)
{
InterCodeBasicBlock* block(rblocks[i]);
if (!block->mPatched &&
(block->mTrueJump && (block->mTrueJump->mPatched || block->mTrueJump == this) ||
block->mFalseJump && (block->mFalseJump->mPatched || block->mFalseJump == this)))
{
lblocks.Push(block);
block->mPatched = true;
changed = true;
}
}
} while (changed);
return lblocks.Size() > 0;
}
bool InterCodeBasicBlock::CollectSingleEntryGenericLoop(ExpandingArray<InterCodeBasicBlock*>& lblocks)
{
if (CollectGenericLoop(lblocks))
{
for (int i = 0; i < lblocks.Size(); i++)
{
InterCodeBasicBlock* block = lblocks[i];
if (block != this)
{
for (int j = 0; j < block->mEntryBlocks.Size(); j++)
if (!lblocks.Contains(block->mEntryBlocks[j]))
return false;
}
}
return true;
}
else
return false;
}
bool InterCodeBasicBlock::CollectSingleHeadLoopBody(InterCodeBasicBlock* head, InterCodeBasicBlock* tail, ExpandingArray<InterCodeBasicBlock*>& body)
{ {
int i = 0; int i = 0;
body.Push(head); body.Push(head);
@ -16063,7 +16346,7 @@ bool InterCodeBasicBlock::MergeLoopTails(void)
return modified; return modified;
} }
bool IsSingleLoopAssign(int at, InterCodeBasicBlock* block, const GrowingArray<InterCodeBasicBlock*>& body) bool IsSingleLoopAssign(int at, InterCodeBasicBlock* block, const ExpandingArray<InterCodeBasicBlock*>& body)
{ {
InterInstruction* ai = block->mInstructions[at]; InterInstruction* ai = block->mInstructions[at];
if (ai->mDst.mTemp < 0) if (ai->mDst.mTemp < 0)
@ -16078,7 +16361,7 @@ bool IsSingleLoopAssign(int at, InterCodeBasicBlock* block, const GrowingArray<I
return true; return true;
} }
bool IsLoopInvariantTemp(int tmp, const GrowingArray<InterCodeBasicBlock*>& body) bool IsLoopInvariantTemp(int tmp, const ExpandingArray<InterCodeBasicBlock*>& body)
{ {
if (tmp < 0) if (tmp < 0)
return true; return true;
@ -16118,7 +16401,7 @@ bool InterCodeBasicBlock::SingleTailLoopOptimization(const NumberSet& aliasedPar
if (post && post->mNumEntries == 1) if (post && post->mNumEntries == 1)
{ {
GrowingArray<InterCodeBasicBlock*> body(nullptr); ExpandingArray<InterCodeBasicBlock*> body;
if (tail->CollectSingleHeadLoopBody(this, tail, body)) if (tail->CollectSingleHeadLoopBody(this, tail, body))
{ {
@ -17927,6 +18210,44 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt
} }
} }
} }
#if 1
else if (loops)
{
ExpandingArray<InterCodeBasicBlock*> lblocks;
if (CollectSingleEntryGenericLoop(lblocks))
{
for (int i = 0; i < ltvalue.Size(); i++)
{
if (ltvalue[i])
{
bool fail = false;
for (int k = 0; k < lblocks.Size() && !fail; k++)
{
InterCodeBasicBlock* b = lblocks[k];
for (int j = 0; j < b->mInstructions.Size() && !fail; j++)
{
InterInstruction* ins = b->mInstructions[j];
if (ins->mDst.mTemp == i)
{
if (ins->mCode == IC_LEA && ins->mSrc[1].mTemp == i)
;
else
fail = true;
}
}
}
if (fail)
ltvalue[i] = nullptr;
}
}
}
else
ltvalue.Clear();
}
#else
else if (loops && mNumEntries == 2) else if (loops && mNumEntries == 2)
{ {
InterCodeBasicBlock* tail, * post; InterCodeBasicBlock* tail, * post;
@ -17943,7 +18264,7 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt
if (post && post->mNumEntries == 1) if (post && post->mNumEntries == 1)
{ {
GrowingArray<InterCodeBasicBlock*> body(nullptr); ExpandingArray<InterCodeBasicBlock*> body;
if (tail->CollectSingleHeadLoopBody(this, tail, body)) if (tail->CollectSingleHeadLoopBody(this, tail, body))
{ {
@ -17978,6 +18299,7 @@ void InterCodeBasicBlock::PropagateMemoryAliasingInfo(const GrowingInstructionPt
} }
} }
} }
#endif
else else
ltvalue.Clear(); ltvalue.Clear();
} }
@ -18387,7 +18709,7 @@ bool InterCodeBasicBlock::MoveConditionOutOfLoop(void)
if (post && post->mNumEntries == 1) if (post && post->mNumEntries == 1)
{ {
GrowingArray<InterCodeBasicBlock*> lbody(nullptr); ExpandingArray<InterCodeBasicBlock*> lbody;
if (tail->CollectSingleHeadLoopBody(this, tail, lbody)) if (tail->CollectSingleHeadLoopBody(this, tail, lbody))
{ {
@ -21255,6 +21577,7 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
{ {
mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1]; mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1];
mInstructions[i + 2]->mSrc[1].mIntConst += mInstructions[i + 0]->mSrc[0].mIntConst << mInstructions[i + 1]->mSrc[0].mIntConst; mInstructions[i + 2]->mSrc[1].mIntConst += mInstructions[i + 0]->mSrc[0].mIntConst << mInstructions[i + 1]->mSrc[0].mIntConst;
mInstructions[i + 2]->mSrc[0].mRange.AddConstValue(IT_INT16, - (mInstructions[i + 0]->mSrc[0].mIntConst << mInstructions[i + 1]->mSrc[0].mIntConst));
mInstructions[i + 0]->mCode = IC_NONE; mInstructions[i + 0]->mNumOperands = 0; mInstructions[i + 0]->mCode = IC_NONE; mInstructions[i + 0]->mNumOperands = 0;
changed = true; changed = true;
@ -23081,6 +23404,12 @@ void InterCodeProcedure::ResetEntryBlocks(void)
mBlocks[i]->mEntryBlocks.SetSize(0); mBlocks[i]->mEntryBlocks.SetSize(0);
} }
void InterCodeProcedure::ResetPatched(void)
{
for (int i = 0; i < mBlocks.Size(); i++)
mBlocks[i]->mPatched = false;
}
void InterCodeProcedure::ResetVisited(void) void InterCodeProcedure::ResetVisited(void)
{ {
int i; int i;
@ -23216,6 +23545,7 @@ void InterCodeProcedure::BuildTraces(int expand, bool dominators, bool compact)
{ {
mBlocks[i]->mNumEntries = 0; mBlocks[i]->mNumEntries = 0;
mBlocks[i]->mLoopHead = false; mBlocks[i]->mLoopHead = false;
mBlocks[i]->mLoopDebug = false;
mBlocks[i]->mTraceIndex = -1; mBlocks[i]->mTraceIndex = -1;
} }
mEntryBlock->CollectEntries(); mEntryBlock->CollectEntries();
@ -24238,7 +24568,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "trench_init"); CheckFunc = !strcmp(mIdent->mString, "main");
CheckCase = false; CheckCase = false;
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];
@ -24246,12 +24576,28 @@ void InterCodeProcedure::Close(void)
DisassembleDebug("start"); DisassembleDebug("start");
BuildTraces(10); BuildTraces(10);
DisassembleDebug("traces"); DisassembleDebug("traces");
EarlyBranchElimination(); EarlyBranchElimination();
BuildTraces(0);
do {
BuildLoopPrefix();
ResetVisited();
} while (mEntryBlock->StripLoopHead());
DisassembleDebug("Loop Head");
BuildTraces(0);
DisassembleDebug("branch elimination"); DisassembleDebug("branch elimination");
#if 0
do {
BuildLoopPrefix();
ResetVisited();
} while (mEntryBlock->StripLoopHead());
DisassembleDebug("Loop Head");
BuildTraces(0);
#endif
ResetVisited(); ResetVisited();
mLeafProcedure = mEntryBlock->IsLeafProcedure(); mLeafProcedure = mEntryBlock->IsLeafProcedure();

View File

@ -169,6 +169,7 @@ public:
} mMinState, mMaxState; } mMinState, mMaxState;
bool Same(const IntegerValueRange& range) const; bool Same(const IntegerValueRange& range) const;
bool Weaker(const IntegerValueRange& range) const;
bool Merge(const IntegerValueRange& range, bool head, bool initial); bool Merge(const IntegerValueRange& range, bool head, bool initial);
void Expand(const IntegerValueRange& range); void Expand(const IntegerValueRange& range);
void Union(const IntegerValueRange& range); void Union(const IntegerValueRange& range);
@ -380,7 +381,7 @@ public:
InterCodeBasicBlock * mTrueJump, * mFalseJump, * mLoopPrefix, * mDominator; InterCodeBasicBlock * mTrueJump, * mFalseJump, * mLoopPrefix, * mDominator;
GrowingInstructionArray mInstructions; GrowingInstructionArray mInstructions;
bool mVisited, mInPath, mLoopHead, mChecked, mConditionBlockTrue, mUnreachable, mLoopPath, mValueRangeValid; bool mVisited, mInPath, mLoopHead, mChecked, mConditionBlockTrue, mUnreachable, mLoopPath, mValueRangeValid, mPatched, mLoopDebug;
mutable int mMark; mutable int mMark;
NumberSet mLocalUsedTemps, mLocalModifiedTemps; NumberSet mLocalUsedTemps, mLocalModifiedTemps;
@ -431,6 +432,7 @@ public:
void CollectEntryBlocks(InterCodeBasicBlock* from); void CollectEntryBlocks(InterCodeBasicBlock* from);
void GenerateTraces(int expand, bool compact); void GenerateTraces(int expand, bool compact);
void BuildDominatorTree(InterCodeBasicBlock * from); void BuildDominatorTree(InterCodeBasicBlock * from);
bool StripLoopHead(void);
bool MergeSameConditionTraces(void); bool MergeSameConditionTraces(void);
@ -648,7 +650,11 @@ public:
bool PullStoreUpToConstAddress(void); bool PullStoreUpToConstAddress(void);
bool CollectSingleHeadLoopBody(InterCodeBasicBlock* head, InterCodeBasicBlock* tail, GrowingArray<InterCodeBasicBlock*>& body); bool CollectSingleHeadLoopBody(InterCodeBasicBlock* head, InterCodeBasicBlock* tail, ExpandingArray<InterCodeBasicBlock*>& body);
bool CollectGenericLoop(ExpandingArray<InterCodeBasicBlock*>& lblocks);
bool CollectSingleEntryGenericLoop(ExpandingArray<InterCodeBasicBlock*>& lblocks);
void CollectReachable(ExpandingArray<InterCodeBasicBlock*>& lblock);
bool SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars); bool SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
bool MergeLoopTails(void); bool MergeLoopTails(void);
@ -707,6 +713,7 @@ protected:
GrowingIntegerValueRangeArray mLocalValueRange, mReverseValueRange; GrowingIntegerValueRangeArray mLocalValueRange, mReverseValueRange;
void ResetVisited(void); void ResetVisited(void);
void ResetPatched(void);
void ResetEntryBlocks(void); void ResetEntryBlocks(void);
public: public:
InterCodeBasicBlock * mEntryBlock; InterCodeBasicBlock * mEntryBlock;

View File

@ -26516,7 +26516,7 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
mTrueJump->mIns.Remove(0); mTrueJump->mIns.Remove(0);
mTrueJump->mEntryRequiredRegs += CPU_REG_A; mTrueJump->mEntryRequiredRegs += CPU_REG_A;
if (mTrueJump->mIns.Size() > 0 && (mTrueJump->mIns[0].mLive & LIVE_CPU_REG_Z)) if (zlive)
mTrueJump->mEntryRequiredRegs += CPU_REG_Z; mTrueJump->mEntryRequiredRegs += CPU_REG_Z;
changed = true; changed = true;
@ -37084,13 +37084,10 @@ bool NativeCodeBasicBlock::CheckLoopIndexXRegisters(NativeCodeBasicBlock* head,
{ {
for (int i = mIns.Size() - 1; i >= 0; i--) for (int i = mIns.Size() - 1; i >= 0; i--)
{ {
if (mIns[i].ChangesXReg()) if ((mIns[i].mType == ASMIT_LDX || mIns[i].mType == ASMIT_STX) && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == xreg)
{ return true;
if ((mIns[i].mType == ASMIT_LDX || mIns[i].mType == ASMIT_STX) && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == xreg) else if (mIns[i].ChangesXReg() || mIns[i].ChangesZeroPage(xreg))
return true; return false;
else if (mIns[i].ChangesXReg() || mIns[i].ChangesZeroPage(xreg))
return false;
}
} }
if (this == head) if (this == head)
@ -37112,13 +37109,10 @@ bool NativeCodeBasicBlock::CheckLoopIndexYRegisters(NativeCodeBasicBlock* head,
{ {
for (int i = mIns.Size() - 1; i >= 0; i--) for (int i = mIns.Size() - 1; i >= 0; i--)
{ {
if (mIns[i].ChangesYReg()) if ((mIns[i].mType == ASMIT_LDY || mIns[i].mType == ASMIT_STY) && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == yreg)
{ return true;
if ((mIns[i].mType == ASMIT_LDY || mIns[i].mType == ASMIT_STY) && mIns[i].mMode == ASMIM_ZERO_PAGE && mIns[i].mAddress == yreg) else if (mIns[i].ChangesYReg() || mIns[i].ChangesZeroPage(yreg))
return true; return false;
else if (mIns[i].ChangesYReg() || mIns[i].ChangesZeroPage(yreg))
return false;
}
} }
if (this == head) if (this == head)
@ -38922,8 +38916,17 @@ bool NativeCodeBasicBlock::OptimizeLoopRegisterWrapAround(void)
mIns[j].mLive |= LIVE_CPU_REG_X; mIns[j].mLive |= LIVE_CPU_REG_X;
for (int j = 0; j < i; j++) for (int j = 0; j < i; j++)
hblock->mIns[j].mLive |= LIVE_CPU_REG_X; hblock->mIns[j].mLive |= LIVE_CPU_REG_X;
ins.mType = ASMIT_NOP; if (ins.mLive & LIVE_CPU_REG_Z)
ins.mMode = ASMIM_IMPLIED; {
ins.mType = ASMIT_CPX;
ins.mMode = ASMIM_IMMEDIATE;
ins.mAddress = 0;
}
else
{
ins.mType = ASMIT_NOP;
ins.mMode = ASMIM_IMPLIED;
}
mExitRequiredRegs += CPU_REG_X; mExitRequiredRegs += CPU_REG_X;
pblock->mExitRequiredRegs += CPU_REG_X; pblock->mExitRequiredRegs += CPU_REG_X;
@ -43110,6 +43113,44 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BuildSingleExit(NativeCodeProcedure*
return block; return block;
} }
int NativeCodeBasicBlock::CorrectXOffset(const InterInstruction * ins, int xoffset, int at)
{
while (xoffset > 0)
{
mIns.Insert(at, NativeCodeInstruction(ins, ASMIT_DEX));
at++;
xoffset--;
}
while (xoffset < 0)
{
mIns.Insert(at, NativeCodeInstruction(ins, ASMIT_INX));
at++;
xoffset++;
}
return at;
}
int NativeCodeBasicBlock::CorrectYOffset(const InterInstruction * ins, int yoffset, int at)
{
while (yoffset > 0)
{
mIns.Insert(at, NativeCodeInstruction(ins, ASMIT_DEY));
at++;
yoffset--;
}
while (yoffset < 0)
{
mIns.Insert(at, NativeCodeInstruction(ins, ASMIT_INY));
at++;
yoffset++;
}
return at;
}
bool NativeCodeBasicBlock::OptimizeGenericLoop(void) bool NativeCodeBasicBlock::OptimizeGenericLoop(void)
{ {
@ -43642,47 +43683,39 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(void)
if (yoffset && yreg >= 0 && !(ins.mLive & LIVE_CPU_REG_Y)) if (yoffset && yreg >= 0 && !(ins.mLive & LIVE_CPU_REG_Y))
{ {
while (yoffset > 0) if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.mType == ASMIT_CMP)
{ {
j++; printf("oopsie Y\n");
block->mIns.Insert(j, NativeCodeInstruction(ins.mIns, ASMIT_DEY));
yoffset--;
} }
else
while (yoffset < 0)
{ {
j++; j = block->CorrectYOffset(ins.mIns, yoffset, j + 1) - 1;
block->mIns.Insert(j, NativeCodeInstruction(ins.mIns, ASMIT_INY)); yoffset = 0;
yoffset++;
}
if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.ChangesAccuAndFlag()) if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.ChangesAccuAndFlag())
{ {
ins.mLive |= LIVE_CPU_REG_A; ins.mLive |= LIVE_CPU_REG_A;
block->mIns.Push(NativeCodeInstruction(ins.mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0)); block->mIns.Push(NativeCodeInstruction(ins.mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0));
}
} }
} }
if (xoffset && xreg >= 0 && !(ins.mLive & LIVE_CPU_REG_X)) if (xoffset && xreg >= 0 && !(ins.mLive & LIVE_CPU_REG_X))
{ {
while (xoffset > 0) if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.mType == ASMIT_CMP)
{ {
j++; printf("oopsie X\n");
block->mIns.Insert(j, NativeCodeInstruction(ins.mIns, ASMIT_DEX));
xoffset--;
} }
else
while (xoffset < 0)
{ {
j++; j = block->CorrectXOffset(ins.mIns, xoffset, j + 1) - 1;
block->mIns.Insert(j, NativeCodeInstruction(ins.mIns, ASMIT_INX)); xoffset = 0;
xoffset++;
}
if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.ChangesAccuAndFlag()) if (j + 1 == block->mIns.Size() && (ins.mLive & LIVE_CPU_REG_Z) && ins.ChangesAccuAndFlag())
{ {
ins.mLive |= LIVE_CPU_REG_A; ins.mLive |= LIVE_CPU_REG_A;
block->mIns.Push(NativeCodeInstruction(ins.mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0)); block->mIns.Push(NativeCodeInstruction(ins.mIns, ASMIT_ORA, ASMIM_IMMEDIATE, 0));
}
} }
} }
@ -43695,50 +43728,76 @@ bool NativeCodeBasicBlock::OptimizeGenericLoop(void)
} }
if (block->mTrueJump && !lblocks.Contains(block->mTrueJump)) if (block->mTrueJump)
{ {
block->mTrueJump = block->BuildSingleEntry(mProc, block->mTrueJump); if (!lblocks.Contains(block->mTrueJump))
if (areg >= 0 && block->mTrueJump->mEntryRequiredRegs[areg])
{ {
if (areg < 256) block->mTrueJump = block->BuildSingleEntry(mProc, block->mTrueJump);
block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STA, ASMIM_ZERO_PAGE, areg)); if (areg >= 0 && block->mTrueJump->mEntryRequiredRegs[areg])
block->mExitRequiredRegs += CPU_REG_A; {
block->mTrueJump->mEntryRequiredRegs += CPU_REG_A; if (areg < 256)
block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STA, ASMIM_ZERO_PAGE, areg));
block->mExitRequiredRegs += CPU_REG_A;
block->mTrueJump->mEntryRequiredRegs += CPU_REG_A;
}
if (yreg >= 0 && block->mTrueJump->mEntryRequiredRegs[yreg])
{
int j = block->mTrueJump->CorrectYOffset(block->mBranchIns, yoffset, 0);
block->mTrueJump->mIns.Insert(j, NativeCodeInstruction(block->mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, yreg));
block->mExitRequiredRegs += CPU_REG_Y;
block->mTrueJump->mEntryRequiredRegs += CPU_REG_Y;
}
if (xreg >= 0 && block->mTrueJump->mEntryRequiredRegs[xreg])
{
int j = block->mTrueJump->CorrectXOffset(block->mBranchIns, xoffset, 0);
block->mTrueJump->mIns.Insert(j, NativeCodeInstruction(block->mBranchIns, ASMIT_STX, ASMIM_ZERO_PAGE, xreg));
block->mExitRequiredRegs += CPU_REG_X;
block->mTrueJump->mEntryRequiredRegs += CPU_REG_X;
}
} }
if (yreg >= 0 && block->mTrueJump->mEntryRequiredRegs[yreg]) else
{ {
block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, yreg)); if (yreg >= 0 && yoffset != 0 && block->mFalseJump->mEntryRequiredRegs[yreg])
block->mExitRequiredRegs += CPU_REG_Y; block->mTrueJump->CorrectYOffset(block->mBranchIns, yoffset, 0);
block->mTrueJump->mEntryRequiredRegs += CPU_REG_Y; if (xreg >= 0 && xoffset != 0 && block->mFalseJump->mEntryRequiredRegs[xreg])
} block->mTrueJump->CorrectXOffset(block->mBranchIns, xoffset, 0);
if (xreg >= 0 && block->mTrueJump->mEntryRequiredRegs[xreg])
{
block->mTrueJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STX, ASMIM_ZERO_PAGE, xreg));
block->mExitRequiredRegs += CPU_REG_X;
block->mTrueJump->mEntryRequiredRegs += CPU_REG_X;
} }
} }
if (block->mFalseJump && !lblocks.Contains(block->mFalseJump)) if (block->mFalseJump)
{ {
block->mFalseJump = block->BuildSingleEntry(mProc, block->mFalseJump); if (!lblocks.Contains(block->mFalseJump))
if (areg >= 0 && block->mFalseJump->mEntryRequiredRegs[areg])
{ {
if (areg < 256) block->mFalseJump = block->BuildSingleEntry(mProc, block->mFalseJump);
block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STA, ASMIM_ZERO_PAGE, areg)); if (areg >= 0 && block->mFalseJump->mEntryRequiredRegs[areg])
block->mExitRequiredRegs += CPU_REG_A; {
block->mFalseJump->mEntryRequiredRegs += CPU_REG_A; if (areg < 256)
block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STA, ASMIM_ZERO_PAGE, areg));
block->mExitRequiredRegs += CPU_REG_A;
block->mFalseJump->mEntryRequiredRegs += CPU_REG_A;
}
if (yreg >= 0 && block->mFalseJump->mEntryRequiredRegs[yreg])
{
int j = block->mTrueJump->CorrectYOffset(block->mBranchIns, yoffset, 0);
block->mFalseJump->mIns.Insert(j, NativeCodeInstruction(block->mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, yreg));
block->mExitRequiredRegs += CPU_REG_Y;
block->mFalseJump->mEntryRequiredRegs += CPU_REG_Y;
}
if (xreg >= 0 && block->mFalseJump->mEntryRequiredRegs[xreg])
{
int j = block->mTrueJump->CorrectXOffset(block->mBranchIns, xoffset, 0);
block->mFalseJump->mIns.Insert(j, NativeCodeInstruction(block->mBranchIns, ASMIT_STX, ASMIM_ZERO_PAGE, xreg));
block->mExitRequiredRegs += CPU_REG_X;
block->mFalseJump->mEntryRequiredRegs += CPU_REG_X;
}
} }
if (yreg >= 0 && block->mFalseJump->mEntryRequiredRegs[yreg]) else
{ {
block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STY, ASMIM_ZERO_PAGE, yreg)); if (yreg >= 0 && yoffset != 0 && block->mFalseJump->mEntryRequiredRegs[yreg])
block->mExitRequiredRegs += CPU_REG_Y; block->mFalseJump->CorrectYOffset(block->mBranchIns, yoffset, 0);
block->mFalseJump->mEntryRequiredRegs += CPU_REG_Y; if (xreg >= 0 && xoffset != 0 && block->mFalseJump->mEntryRequiredRegs[xreg])
} block->mFalseJump->CorrectXOffset(block->mBranchIns, xoffset, 0);
if (xreg >= 0 && block->mFalseJump->mEntryRequiredRegs[xreg])
{
block->mFalseJump->mIns.Insert(0, NativeCodeInstruction(block->mBranchIns, ASMIT_STX, ASMIM_ZERO_PAGE, xreg));
block->mExitRequiredRegs += CPU_REG_X;
block->mFalseJump->mEntryRequiredRegs += CPU_REG_X;
} }
} }
@ -44275,7 +44334,8 @@ bool NativeCodeBasicBlock::BlockSizeCopyReduction(NativeCodeProcedure* proc, int
#if 1 #if 1
if (si + 5 < mIns.Size() && if (si + 5 < mIns.Size() &&
mIns[si + 0].mType == ASMIT_LDY && mIns[si + 0].mMode == ASMIM_IMMEDIATE && mIns[si + 0].mType == ASMIT_LDY && mIns[si + 0].mMode == ASMIM_IMMEDIATE &&
mIns[si + 1].mType == ASMIT_STA && mIns[si + 1].mMode == ASMIM_INDIRECT_Y) mIns[si + 1].mType == ASMIT_STA && mIns[si + 1].mMode == ASMIM_INDIRECT_Y &&
!(mIns[si + 1].mLive & LIVE_CPU_REG_C))
{ {
int i = 1; int i = 1;
while (si + 2 * i + 1 < mIns.Size() && while (si + 2 * i + 1 < mIns.Size() &&
@ -48956,6 +49016,28 @@ bool NativeCodeBasicBlock::PeepHoleOptimizerIterate3(int i, int pass)
return true; return true;
} }
if (
mIns[i + 0].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDX, mIns[i + 0].mMode) &&
mIns[i + 1].mType == ASMIT_TAX &&
mIns[i + 2].mType == ASMIT_CMP && HasAsmInstructionMode(ASMIT_CPX, mIns[i + 2].mMode) && !(mIns[i + 2].mLive & LIVE_CPU_REG_A))
{
mIns[i + 0].mType = ASMIT_LDX; mIns[i + 0].mLive |= LIVE_CPU_REG_X;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_CPX;
return true;
}
if (
mIns[i + 0].mType == ASMIT_LDA && HasAsmInstructionMode(ASMIT_LDY, mIns[i + 0].mMode) &&
mIns[i + 1].mType == ASMIT_TAY &&
mIns[i + 2].mType == ASMIT_CMP && HasAsmInstructionMode(ASMIT_CPY, mIns[i + 2].mMode) && !(mIns[i + 2].mLive & LIVE_CPU_REG_A))
{
mIns[i + 0].mType = ASMIT_LDY; mIns[i + 0].mLive |= LIVE_CPU_REG_Y;
mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED;
mIns[i + 2].mType = ASMIT_CPY;
return true;
}
if ( if (
mIns[i + 0].mType == ASMIT_LDA && !mIns[i + 0].RequiresXReg() && mIns[i + 0].mType == ASMIT_LDA && !mIns[i + 0].RequiresXReg() &&
mIns[i + 1].mType == ASMIT_LDX && mIns[i + 1].mType == ASMIT_LDX &&
@ -55848,7 +55930,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
mInterProc->mLinkerObject->mNativeProc = this; mInterProc->mLinkerObject->mNativeProc = this;
CheckFunc = !strcmp(mIdent->mString, "sidfx_loop"); CheckFunc = !strcmp(mIdent->mString, "main");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];
@ -57750,14 +57832,14 @@ void NativeCodeProcedure::Optimize(void)
} }
#if _DEBUG #if _DEBUG
ResetVisited(); ResetVisited();
mEntryBlock->CheckAsmCode(); mEntryBlock->CheckAsmCode();
#endif #endif
#if DISASSEMBLE_OPT #if DISASSEMBLE_OPT
char fname[100]; char fname[100];
sprintf_s(fname, "Optimize %d, %d", step, cnt); sprintf_s(fname, "Optimize %d, %d", step, cnt);
DisassembleDebug(fname); DisassembleDebug(fname);
#endif #endif
#if 1 #if 1
@ -57915,8 +57997,8 @@ void NativeCodeProcedure::Optimize(void)
if (mEntryBlock->ApplyEntryDataSet()) if (mEntryBlock->ApplyEntryDataSet())
changed = true; changed = true;
#endif #endif
#if 1 #if 1
ResetVisited(); ResetVisited();
mEntryBlock->BlockSizeReduction(this, -1, -1, -1); mEntryBlock->BlockSizeReduction(this, -1, -1, -1);

View File

@ -373,6 +373,8 @@ public:
bool OptimizeInnerLoops(NativeCodeProcedure* proc); bool OptimizeInnerLoops(NativeCodeProcedure* proc);
NativeCodeBasicBlock* CollectInnerLoop(NativeCodeBasicBlock* head, ExpandingArray<NativeCodeBasicBlock*>& lblocks); NativeCodeBasicBlock* CollectInnerLoop(NativeCodeBasicBlock* head, ExpandingArray<NativeCodeBasicBlock*>& lblocks);
int CorrectXOffset(const InterInstruction * ins, int yoffset, int at);
int CorrectYOffset(const InterInstruction * ins, int yoffset, int at);
bool OptimizeGenericLoop(void); bool OptimizeGenericLoop(void);
bool CollectGenericLoop(ExpandingArray<NativeCodeBasicBlock*>& lblocks); bool CollectGenericLoop(ExpandingArray<NativeCodeBasicBlock*>& lblocks);
bool CollectSingleEntryGenericLoop(ExpandingArray<NativeCodeBasicBlock*>& lblocks); bool CollectSingleEntryGenericLoop(ExpandingArray<NativeCodeBasicBlock*>& lblocks);

View File

@ -515,6 +515,12 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio
} }
} }
if (mdec->mBits == 24 && mdec->mOffset > 0 && mdec->mShift == 0)
{
mdec->mOffset--;
mdec->mShift = 8;
}
if (mdec->mShift == 0 && mdec->mBits == 8 * mdec->mSize) if (mdec->mShift == 0 && mdec->mBits == 8 * mdec->mSize)
mdec->mBits = 0; mdec->mBits = 0;
} }