Size optimizations
This commit is contained in:
parent
bf6fc7fd0b
commit
a81f810a63
202
include/stdlib.c
202
include/stdlib.c
|
@ -224,6 +224,11 @@ int atoi(const char * s)
|
||||||
const float tpow10[7] = {1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0};
|
const float tpow10[7] = {1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0, 1000000.0};
|
||||||
|
|
||||||
float atof(const char * s)
|
float atof(const char * s)
|
||||||
|
{
|
||||||
|
return strtof(s, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
float strtof(const char *s, const char **endp)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
while ((c = *s++) <= ' ')
|
while ((c = *s++) <= ' ')
|
||||||
|
@ -302,9 +307,206 @@ float atof(const char * s)
|
||||||
if (neg)
|
if (neg)
|
||||||
v = -v;
|
v = -v;
|
||||||
|
|
||||||
|
if (endp)
|
||||||
|
*endp = (char *)s;
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int strtoi(const char *s, const char **endp, char base)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
while ((c = *s++) <= ' ')
|
||||||
|
if (!c) return 0;
|
||||||
|
|
||||||
|
bool neg = false;
|
||||||
|
if (c == '-')
|
||||||
|
{
|
||||||
|
neg = true;
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
else if (c == '+')
|
||||||
|
c = *s++;
|
||||||
|
|
||||||
|
if (c == '0')
|
||||||
|
{
|
||||||
|
c = *s++;
|
||||||
|
if (c == 'x' || c == 'X')
|
||||||
|
{
|
||||||
|
base = 16;
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
else if (base == 0)
|
||||||
|
base = 8;
|
||||||
|
} else if (base == 0)
|
||||||
|
base = 10;
|
||||||
|
|
||||||
|
int v = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
v = v * base + (c - '0');
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
v = v * base + (c - 'a' + 10);
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
v = v * base + (c - 'A' + 10);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (neg)
|
||||||
|
v = -v;
|
||||||
|
|
||||||
|
if (endp)
|
||||||
|
*endp = (char *)s;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned strtou(const char *s, const char **endp, char base)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
while ((c = *s++) <= ' ')
|
||||||
|
if (!c) return 0;
|
||||||
|
|
||||||
|
if (c == '0')
|
||||||
|
{
|
||||||
|
c = *s++;
|
||||||
|
if (c == 'x' || c == 'X')
|
||||||
|
{
|
||||||
|
base = 16;
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
else if (base == 0)
|
||||||
|
base = 8;
|
||||||
|
} else if (base == 0)
|
||||||
|
base = 10;
|
||||||
|
|
||||||
|
unsigned v = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
v = v * base + (c - '0');
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
v = v * base + (c - 'a' + 10);
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
v = v * base + (c - 'A' + 10);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endp)
|
||||||
|
*endp = (char *)s;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
long strtol(const char *s, const char **endp, char base)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
while ((c = *s++) <= ' ')
|
||||||
|
if (!c) return 0;
|
||||||
|
|
||||||
|
bool neg = false;
|
||||||
|
if (c == '-')
|
||||||
|
{
|
||||||
|
neg = true;
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
else if (c == '+')
|
||||||
|
c = *s++;
|
||||||
|
|
||||||
|
if (c == '0')
|
||||||
|
{
|
||||||
|
c = *s++;
|
||||||
|
if (c == 'x' || c == 'X')
|
||||||
|
{
|
||||||
|
base = 16;
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
else if (base == 0)
|
||||||
|
base = 8;
|
||||||
|
} else if (base == 0)
|
||||||
|
base = 10;
|
||||||
|
|
||||||
|
long v = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
v = v * base + (c - '0');
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
v = v * base + (c - 'a' + 10);
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
v = v * base + (c - 'A' + 10);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (neg)
|
||||||
|
v = -v;
|
||||||
|
|
||||||
|
if (endp)
|
||||||
|
*endp = (char *)s;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long strtoul(const char *s, const char **endp, char base)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
while ((c = *s++) <= ' ')
|
||||||
|
if (!c) return 0;
|
||||||
|
|
||||||
|
if (c == '0')
|
||||||
|
{
|
||||||
|
c = *s++;
|
||||||
|
if (c == 'x' || c == 'X')
|
||||||
|
{
|
||||||
|
base = 16;
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
else if (base == 0)
|
||||||
|
base = 8;
|
||||||
|
} else if (base == 0)
|
||||||
|
base = 10;
|
||||||
|
|
||||||
|
unsigned long v = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
v = v * base + (c - '0');
|
||||||
|
else if (c >= 'a' && c <= 'f')
|
||||||
|
v = v * base + (c - 'a' + 10);
|
||||||
|
else if (c >= 'A' && c <= 'F')
|
||||||
|
v = v * base + (c - 'A' + 10);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
c = *s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endp)
|
||||||
|
*endp = (char *)s;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int abs(int n)
|
||||||
|
{
|
||||||
|
return n < 0 ? - n : n;
|
||||||
|
}
|
||||||
|
|
||||||
|
long labs(long n)
|
||||||
|
{
|
||||||
|
return n < 0 ? - n : n;
|
||||||
|
}
|
||||||
|
|
||||||
void exit(int status)
|
void exit(int status)
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
|
|
|
@ -16,8 +16,24 @@ void ultoa(unsigned long n, char * s, unsigned radix);
|
||||||
|
|
||||||
int atoi(const char * s);
|
int atoi(const char * s);
|
||||||
|
|
||||||
|
long atol(const char * s);
|
||||||
|
|
||||||
float atof(const char * s);
|
float atof(const char * s);
|
||||||
|
|
||||||
|
float strtof(const char *s, const char **endp);
|
||||||
|
|
||||||
|
int strtoi(const char *s, const char **endp, char base);
|
||||||
|
|
||||||
|
unsigned strtou(const char *s, const char **endp, char base);
|
||||||
|
|
||||||
|
long strtol(const char *s, const char **endp, char base);
|
||||||
|
|
||||||
|
unsigned long strtoul(const char *s, const char **endp, char base);
|
||||||
|
|
||||||
|
int abs(int n);
|
||||||
|
|
||||||
|
long labs(long n);
|
||||||
|
|
||||||
|
|
||||||
void exit(int status);
|
void exit(int status);
|
||||||
|
|
||||||
|
|
|
@ -263,6 +263,16 @@ public:
|
||||||
Grow(at, false);
|
Grow(at, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Remove(int at, int n)
|
||||||
|
{
|
||||||
|
while (at + n < size)
|
||||||
|
{
|
||||||
|
array[at] = array[at + n];
|
||||||
|
at++;
|
||||||
|
}
|
||||||
|
Grow(at, false);
|
||||||
|
}
|
||||||
|
|
||||||
T Top(void) const
|
T Top(void) const
|
||||||
{
|
{
|
||||||
return array[size - 1];
|
return array[size - 1];
|
||||||
|
|
|
@ -14,6 +14,11 @@ int InterTypeSize[] = {
|
||||||
2
|
2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool IsCommutative(InterOperator op)
|
||||||
|
{
|
||||||
|
return op == IA_ADD || op == IA_MUL || op == IA_AND || op == IA_OR || op == IA_XOR;
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsIntegerType(InterType type)
|
static bool IsIntegerType(InterType type)
|
||||||
{
|
{
|
||||||
return type >= IT_INT8 && type <= IT_INT32;
|
return type >= IT_INT8 && type <= IT_INT32;
|
||||||
|
@ -509,12 +514,21 @@ static bool SameMem(const InterOperand& op, const InterInstruction* ins)
|
||||||
static bool SameInstruction(const InterInstruction* ins1, const InterInstruction* ins2)
|
static bool SameInstruction(const InterInstruction* ins1, const InterInstruction* ins2)
|
||||||
{
|
{
|
||||||
if (ins1->mCode == ins2->mCode && ins1->mNumOperands == ins2->mNumOperands && ins1->mOperator == ins2->mOperator)
|
if (ins1->mCode == ins2->mCode && ins1->mNumOperands == ins2->mNumOperands && ins1->mOperator == ins2->mOperator)
|
||||||
|
{
|
||||||
|
if (ins1->mCode == IC_BINARY_OPERATOR && IsCommutative(ins1->mOperator))
|
||||||
|
{
|
||||||
|
return
|
||||||
|
ins1->mSrc[0].IsEqual(ins2->mSrc[0]) && ins1->mSrc[1].IsEqual(ins2->mSrc[1]) ||
|
||||||
|
ins1->mSrc[0].IsEqual(ins2->mSrc[1]) && ins1->mSrc[1].IsEqual(ins2->mSrc[0]);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ins1->mNumOperands; i++)
|
for (int i = 0; i < ins1->mNumOperands; i++)
|
||||||
if (!ins1->mSrc[i].IsEqual(ins2->mSrc[i]))
|
if (!ins1->mSrc[i].IsEqual(ins2->mSrc[i]))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1246,6 +1260,9 @@ void TempForwardingTable::Build(int from, int to)
|
||||||
|
|
||||||
bool InterInstruction::ReferencesTemp(int temp) const
|
bool InterInstruction::ReferencesTemp(int temp) const
|
||||||
{
|
{
|
||||||
|
if (temp < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (temp == mDst.mTemp)
|
if (temp == mDst.mTemp)
|
||||||
return true;
|
return true;
|
||||||
for (int i = 0; i < mNumOperands; i++)
|
for (int i = 0; i < mNumOperands; i++)
|
||||||
|
@ -5611,6 +5628,21 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
|
||||||
ins->mSrc[0].mRange.LimitMax(vr.mMaxValue - ins->mSrc[1].mIntConst);
|
ins->mSrc[0].mRange.LimitMax(vr.mMaxValue - ins->mSrc[1].mIntConst);
|
||||||
mReverseValueRange[ins->mSrc[0].mTemp].Limit(ins->mSrc[0].mRange);
|
mReverseValueRange[ins->mSrc[0].mTemp].Limit(ins->mSrc[0].mRange);
|
||||||
}
|
}
|
||||||
|
else if (ins->mSrc[0].mTemp >= 0 && ins->mSrc[1].mTemp >= 0)
|
||||||
|
{
|
||||||
|
if (vr.mMinState == IntegerValueRange::S_BOUND && ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND)
|
||||||
|
ins->mSrc[1].mRange.LimitMin(vr.mMinValue - ins->mSrc[0].mRange.mMaxValue);
|
||||||
|
if (vr.mMaxState == IntegerValueRange::S_BOUND && ins->mSrc[0].mRange.mMinState == IntegerValueRange::S_BOUND)
|
||||||
|
ins->mSrc[1].mRange.LimitMax(vr.mMaxValue - ins->mSrc[0].mRange.mMinValue);
|
||||||
|
|
||||||
|
if (vr.mMinState == IntegerValueRange::S_BOUND && ins->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND)
|
||||||
|
ins->mSrc[0].mRange.LimitMin(vr.mMinValue - ins->mSrc[1].mRange.mMaxValue);
|
||||||
|
if (vr.mMaxState == IntegerValueRange::S_BOUND && ins->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND)
|
||||||
|
ins->mSrc[0].mRange.LimitMax(vr.mMaxValue - ins->mSrc[1].mRange.mMinValue);
|
||||||
|
|
||||||
|
mReverseValueRange[ins->mSrc[0].mTemp].Limit(ins->mSrc[0].mRange);
|
||||||
|
mReverseValueRange[ins->mSrc[1].mTemp].Limit(ins->mSrc[1].mRange);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case IA_MUL:
|
case IA_MUL:
|
||||||
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0 && ins->mSrc[0].mIntConst > 0)
|
if (ins->mSrc[0].mTemp < 0 && ins->mSrc[1].mTemp >= 0 && ins->mSrc[0].mIntConst > 0)
|
||||||
|
@ -7817,13 +7849,13 @@ void InterCodeBasicBlock::MarkRelevantStatics(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InterCodeBasicBlock::CanMoveInstructionBehindBlock(int ii) const
|
bool InterCodeBasicBlock::CanMoveInstructionDown(int si, int ti) const
|
||||||
{
|
{
|
||||||
InterInstruction* ins = mInstructions[ii];
|
InterInstruction* ins = mInstructions[si];
|
||||||
|
|
||||||
if (ins->mCode == IC_LOAD)
|
if (ins->mCode == IC_LOAD)
|
||||||
{
|
{
|
||||||
for (int i = ii + 1; i < mInstructions.Size(); i++)
|
for (int i = si + 1; i < ti; i++)
|
||||||
if (!CanBypassLoad(ins, mInstructions[i]))
|
if (!CanBypassLoad(ins, mInstructions[i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -7836,7 +7868,7 @@ bool InterCodeBasicBlock::CanMoveInstructionBehindBlock(int ii) const
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = ii + 1; i < mInstructions.Size(); i++)
|
for (int i = si + 1; i < ti; i++)
|
||||||
if (!CanBypass(ins, mInstructions[i]))
|
if (!CanBypass(ins, mInstructions[i]))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -7844,6 +7876,12 @@ bool InterCodeBasicBlock::CanMoveInstructionBehindBlock(int ii) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterCodeBasicBlock::CanMoveInstructionBehindBlock(int ii) const
|
||||||
|
{
|
||||||
|
return CanMoveInstructionDown(ii, mInstructions.Size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii) const
|
bool InterCodeBasicBlock::CanMoveInstructionBeforeBlock(int ii) const
|
||||||
{
|
{
|
||||||
|
@ -9676,10 +9714,6 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsCommutative(InterOperator op)
|
|
||||||
{
|
|
||||||
return op == IA_ADD || op == IA_MUL || op == IA_AND || op == IA_OR || op == IA_XOR;
|
|
||||||
}
|
|
||||||
void InterCodeBasicBlock::CompactInstructions(void)
|
void InterCodeBasicBlock::CompactInstructions(void)
|
||||||
{
|
{
|
||||||
if (!mVisited)
|
if (!mVisited)
|
||||||
|
@ -10271,7 +10305,28 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
|
||||||
mInstructions[i + 1]->mSrc[0] = mInstructions[i + 0]->mDst;
|
mInstructions[i + 1]->mSrc[0] = mInstructions[i + 0]->mDst;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
#if 1
|
||||||
|
else if (
|
||||||
|
mInstructions[i + 0]->mCode == IC_LEA && mInstructions[i + 0]->mSrc[1].mMemory == IM_GLOBAL &&
|
||||||
|
mInstructions[i + 1]->mCode == IC_LEA && mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal &&
|
||||||
|
mInstructions[i + 1]->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND && !mInstructions[i + 1]->mSrc[0].IsUByte() &&
|
||||||
|
mInstructions[i + 0]->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND && !mInstructions[i + 0]->mSrc[0].IsUByte())
|
||||||
|
{
|
||||||
|
mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1];
|
||||||
|
|
||||||
|
mInstructions[i + 0]->mCode = IC_BINARY_OPERATOR;
|
||||||
|
mInstructions[i + 0]->mOperator = IA_ADD;
|
||||||
|
mInstructions[i + 0]->mSrc[1] = mInstructions[i + 1]->mSrc[0];
|
||||||
|
mInstructions[i + 0]->mDst.mType = IT_INT16;
|
||||||
|
mInstructions[i + 0]->mDst.mRange.mMaxState = IntegerValueRange::S_BOUND;
|
||||||
|
mInstructions[i + 0]->mDst.mRange.mMaxValue = mInstructions[i + 0]->mSrc[1].mRange.mMaxValue + mInstructions[i + 0]->mSrc[0].mRange.mMaxValue;
|
||||||
|
mInstructions[i + 0]->mDst.mRange.mMinState = IntegerValueRange::S_BOUND;
|
||||||
|
mInstructions[i + 0]->mDst.mRange.mMinValue = 0;
|
||||||
|
|
||||||
|
mInstructions[i + 1]->mSrc[0] = mInstructions[i + 0]->mDst;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if 1
|
#if 1
|
||||||
// Postincrement artifact
|
// Postincrement artifact
|
||||||
if (mInstructions[i + 0]->mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
|
if (mInstructions[i + 0]->mCode == IC_LOAD_TEMPORARY && mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR &&
|
||||||
|
@ -10302,6 +10357,25 @@ void InterCodeBasicBlock::PeepholeOptimization(const GrowingVariableArray& stati
|
||||||
|
|
||||||
} while (changed);
|
} while (changed);
|
||||||
|
|
||||||
|
// build trains
|
||||||
|
|
||||||
|
for(int i = mInstructions.Size() - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
InterInstruction* tins = mInstructions[i];
|
||||||
|
|
||||||
|
j = i - 1;
|
||||||
|
while (j >= 0 && !tins->ReferencesTemp(mInstructions[j]->mDst.mTemp))
|
||||||
|
j--;
|
||||||
|
if (j >= 0 && j < i - 1)
|
||||||
|
{
|
||||||
|
if (CanMoveInstructionDown(j, i))
|
||||||
|
{
|
||||||
|
mInstructions.Insert(i, mInstructions[j]);
|
||||||
|
mInstructions.Remove(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// sort stores up
|
// sort stores up
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -11414,6 +11488,21 @@ void InterCodeProcedure::Close(void)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
do {
|
||||||
|
GrowingInstructionPtrArray gipa(nullptr);
|
||||||
|
ResetVisited();
|
||||||
|
changed = mEntryBlock->LoadStoreForwarding(gipa);
|
||||||
|
|
||||||
|
RemoveUnusedStoreInstructions(paramMemory);
|
||||||
|
|
||||||
|
TempForwarding();
|
||||||
|
RemoveUnusedInstructions();
|
||||||
|
|
||||||
|
DisassembleDebug("Load/Store forwarding2");
|
||||||
|
} while (changed);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
BuildLoopPrefix();
|
BuildLoopPrefix();
|
||||||
DisassembleDebug("added dominators");
|
DisassembleDebug("added dominators");
|
||||||
|
@ -11638,6 +11727,39 @@ bool InterCodeBasicBlock::SameExitCode(const InterCodeBasicBlock* block) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PartitionSameExitCode(GrowingArray<InterCodeBasicBlock* > & eblocks, GrowingArray<InterCodeBasicBlock* > & mblocks)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
mblocks.SetSize(0, true);
|
||||||
|
|
||||||
|
while (i + 1 < eblocks.Size())
|
||||||
|
{
|
||||||
|
int j = i + 1;
|
||||||
|
while (j < eblocks.Size())
|
||||||
|
{
|
||||||
|
if (eblocks[i]->SameExitCode(eblocks[j]))
|
||||||
|
{
|
||||||
|
mblocks.Push(eblocks[j]);
|
||||||
|
eblocks.Remove(j);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mblocks.Size())
|
||||||
|
{
|
||||||
|
mblocks.Push(eblocks[i]);
|
||||||
|
eblocks.Remove(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void InterCodeProcedure::MergeBasicBlocks(void)
|
void InterCodeProcedure::MergeBasicBlocks(void)
|
||||||
{
|
{
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
|
@ -11646,6 +11768,8 @@ void InterCodeProcedure::MergeBasicBlocks(void)
|
||||||
ResetVisited();
|
ResetVisited();
|
||||||
mEntryBlock->SplitBranches(this);
|
mEntryBlock->SplitBranches(this);
|
||||||
|
|
||||||
|
DisassembleDebug("PostSplit");
|
||||||
|
|
||||||
bool changed;
|
bool changed;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -11735,29 +11859,49 @@ void InterCodeProcedure::MergeBasicBlocks(void)
|
||||||
|
|
||||||
if (eblocks.Size() == block->mNumEntries)
|
if (eblocks.Size() == block->mNumEntries)
|
||||||
{
|
{
|
||||||
bool ok;
|
GrowingArray<InterCodeBasicBlock* > mblocks(nullptr);
|
||||||
do {
|
|
||||||
ok = false;
|
|
||||||
|
|
||||||
if (eblocks[0]->mInstructions.Size() > 1)
|
while (PartitionSameExitCode(eblocks, mblocks))
|
||||||
{
|
{
|
||||||
InterInstruction* ins = eblocks[0]->mInstructions[eblocks[0]->mInstructions.Size() - 2];
|
InterCodeBasicBlock* nblock;
|
||||||
|
|
||||||
int j = 1;
|
if (eblocks.Size() || mblocks.IndexOf(block) != -1)
|
||||||
while (j < eblocks.Size() && eblocks[0]->SameExitCode(eblocks[j]))
|
|
||||||
j++;
|
|
||||||
if (j == eblocks.Size())
|
|
||||||
{
|
{
|
||||||
block->mInstructions.Insert(0, ins);
|
// break;
|
||||||
for (int j = 0; j < eblocks.Size(); j++)
|
|
||||||
eblocks[j]->mInstructions.Remove(eblocks[j]->mInstructions.Size() - 2);
|
nblock = new InterCodeBasicBlock();
|
||||||
ok = true;
|
this->Append(nblock);
|
||||||
|
|
||||||
|
for (int i = 0; i < mblocks.Size(); i++)
|
||||||
|
mblocks[i]->mTrueJump = nblock;
|
||||||
|
block->mNumEntries -= mblocks.Size();
|
||||||
|
|
||||||
|
InterInstruction* jins = new InterInstruction();
|
||||||
|
jins->mCode = IC_JUMP;
|
||||||
|
nblock->mInstructions.Push(jins);
|
||||||
|
nblock->Close(block, nullptr);
|
||||||
|
|
||||||
|
nblock->mNumEntries = mblocks.Size();
|
||||||
|
block->mNumEntries++;
|
||||||
|
|
||||||
|
eblocks.Push(nblock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
nblock = block;
|
||||||
|
|
||||||
|
InterInstruction* ins = mblocks[0]->mInstructions[mblocks[0]->mInstructions.Size() - 2];
|
||||||
|
|
||||||
|
nblock->mInstructions.Insert(0, ins);
|
||||||
|
for (int j = 0; j < mblocks.Size(); j++)
|
||||||
|
{
|
||||||
|
assert(mblocks[j]->mInstructions[mblocks[j]->mInstructions.Size() - 1]->mCode == IC_JUMP);
|
||||||
|
assert(mblocks[j]->mInstructions[mblocks[j]->mInstructions.Size() - 2]->IsEqual(ins));
|
||||||
|
|
||||||
|
mblocks[j]->mInstructions.Remove(mblocks[j]->mInstructions.Size() - 2);
|
||||||
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (ok);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -460,6 +460,7 @@ public:
|
||||||
bool PushSinglePathResultInstructions(void);
|
bool PushSinglePathResultInstructions(void);
|
||||||
bool CanMoveInstructionBeforeBlock(int ii) const;
|
bool CanMoveInstructionBeforeBlock(int ii) const;
|
||||||
bool CanMoveInstructionBehindBlock(int ii) const;
|
bool CanMoveInstructionBehindBlock(int ii) const;
|
||||||
|
bool CanMoveInstructionDown(int si, int ti) const;
|
||||||
bool MergeCommonPathInstructions(void);
|
bool MergeCommonPathInstructions(void);
|
||||||
|
|
||||||
void PeepholeOptimization(const GrowingVariableArray& staticVars);
|
void PeepholeOptimization(const GrowingVariableArray& staticVars);
|
||||||
|
|
|
@ -13075,6 +13075,69 @@ bool NativeCodeBasicBlock::PropagateSinglePath(void)
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::Is16BitAddSubImmediate(int at, int& sreg, int& dreg, int& offset) const
|
||||||
|
{
|
||||||
|
if (mIns[at + 0].mType == ASMIT_CLC &&
|
||||||
|
mIns[at + 1].mType == ASMIT_LDA && mIns[at + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[at + 2].mType == ASMIT_ADC && mIns[at + 2].mMode == ASMIM_IMMEDIATE &&
|
||||||
|
mIns[at + 3].mType == ASMIT_STA && mIns[at + 3].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[at + 4].mType == ASMIT_LDA && mIns[at + 4].mMode == ASMIM_ZERO_PAGE && mIns[at + 4].mAddress == mIns[at + 1].mAddress + 1 &&
|
||||||
|
mIns[at + 5].mType == ASMIT_ADC && mIns[at + 5].mMode == ASMIM_IMMEDIATE &&
|
||||||
|
mIns[at + 6].mType == ASMIT_STA && mIns[at + 6].mMode == ASMIM_ZERO_PAGE && mIns[at + 6].mAddress == mIns[at + 3].mAddress + 1 &&
|
||||||
|
!(mIns[at + 6].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z)))
|
||||||
|
{
|
||||||
|
sreg = mIns[at + 1].mAddress;
|
||||||
|
dreg = mIns[at + 3].mAddress;
|
||||||
|
offset = mIns[at + 2].mAddress + 256 * mIns[at + 5].mAddress;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::CanForward16BitAddSubImmediate(int sreg, int dreg, int offset, int& index) const
|
||||||
|
{
|
||||||
|
int i = mIns.Size() - 1;
|
||||||
|
while (i >= 6)
|
||||||
|
{
|
||||||
|
int asreg, adreg, aoffset;
|
||||||
|
if (Is16BitAddSubImmediate(i - 6, asreg, adreg, aoffset) && asreg == sreg && adreg == dreg && aoffset == offset)
|
||||||
|
{
|
||||||
|
index = i - 6;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIns[i].ReferencesZeroPage(dreg) || mIns[i].ReferencesZeroPage(dreg + 1) || mIns[i].ChangesZeroPage(sreg) || mIns[i].ChangesZeroPage(sreg + 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::CanForwardZPMove(int saddr, int daddr, int & index) const
|
||||||
|
{
|
||||||
|
int i = mIns.Size() - 1;
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
if (mIns[i].ChangesZeroPage(saddr))
|
||||||
|
return false;
|
||||||
|
if (mIns[i].ChangesZeroPage(daddr))
|
||||||
|
{
|
||||||
|
index = i - 1;
|
||||||
|
return
|
||||||
|
(mIns[i].mType == ASMIT_STA && mIns[i - 1].mType == ASMIT_LDA && mIns[i - 1].mMode == ASMIM_ZERO_PAGE && mIns[i - 1].mAddress == saddr && !(mIns[i].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z))) ||
|
||||||
|
(mIns[i].mType == ASMIT_STX && mIns[i - 1].mType == ASMIT_LDX && mIns[i - 1].mMode == ASMIM_ZERO_PAGE && mIns[i - 1].mAddress == saddr && !(mIns[i].mLive & (LIVE_CPU_REG_X | LIVE_CPU_REG_Z)));
|
||||||
|
}
|
||||||
|
if (mIns[i].ReferencesZeroPage(daddr))
|
||||||
|
return false;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool loops)
|
bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool loops)
|
||||||
{
|
{
|
||||||
|
@ -13096,6 +13159,37 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
||||||
{
|
{
|
||||||
NativeCodeBasicBlock* eb = mEntryBlocks[0];
|
NativeCodeBasicBlock* eb = mEntryBlocks[0];
|
||||||
|
|
||||||
|
if (mEntryRequiredRegs.Size() && !mEntryRequiredRegs[CPU_REG_Z] && (!mEntryRequiredRegs[CPU_REG_A] || !mEntryRequiredRegs[CPU_REG_X]) && !mEntryRequiredRegs[CPU_REG_C])
|
||||||
|
{
|
||||||
|
for (int i = eb->mIns.Size() - 7; i >= 0; i--)
|
||||||
|
{
|
||||||
|
int sreg, dreg, offset;
|
||||||
|
if (eb->Is16BitAddSubImmediate(i, sreg, dreg, offset))
|
||||||
|
{
|
||||||
|
int j = 0;
|
||||||
|
while (j < mEntryBlocks.Size() && mEntryBlocks[j]->CanForward16BitAddSubImmediate(sreg, dreg, offset, mEntryBlocks[j]->mTemp))
|
||||||
|
j++;
|
||||||
|
|
||||||
|
if (j == mEntryBlocks.Size())
|
||||||
|
{
|
||||||
|
for (int k = 0; k < 7; k++)
|
||||||
|
mIns.Insert(k, eb->mIns[i + k]);
|
||||||
|
|
||||||
|
for (int j = 0; j < mEntryBlocks.Size(); j++)
|
||||||
|
mEntryBlocks[j]->mIns.Remove(mEntryBlocks[j]->mTemp, 7);
|
||||||
|
|
||||||
|
if (mEntryRequiredRegs[CPU_REG_A])
|
||||||
|
{
|
||||||
|
mIns.Insert(0, NativeCodeInstruction(ASMIT_TAX));
|
||||||
|
mIns.Insert(8, NativeCodeInstruction(ASMIT_TXA));
|
||||||
|
}
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (eb->mIns.Size() > 0)
|
while (eb->mIns.Size() > 0)
|
||||||
{
|
{
|
||||||
NativeCodeInstruction& ins(eb->mIns[eb->mIns.Size() - 1]);
|
NativeCodeInstruction& ins(eb->mIns[eb->mIns.Size() - 1]);
|
||||||
|
@ -13139,6 +13233,37 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!changed && !mEntryRequiredRegs[CPU_REG_Z] && (!mEntryRequiredRegs[CPU_REG_A] || !mEntryRequiredRegs[CPU_REG_X]))
|
||||||
|
{
|
||||||
|
for (int i = eb->mIns.Size() - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
if (eb->mIns[i - 1].mType == ASMIT_LDA && eb->mIns[i - 1].mMode == ASMIM_ZERO_PAGE && eb->mIns[i - 0].mType == ASMIT_STA && eb->mIns[i - 0].mMode == ASMIM_ZERO_PAGE ||
|
||||||
|
eb->mIns[i - 1].mType == ASMIT_LDX && eb->mIns[i - 1].mMode == ASMIM_ZERO_PAGE && eb->mIns[i - 0].mType == ASMIT_STX && eb->mIns[i - 0].mMode == ASMIM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
int saddr = eb->mIns[i - 1].mAddress, daddr = eb->mIns[i - 0].mAddress;
|
||||||
|
int j = 0;
|
||||||
|
while (j < mEntryBlocks.Size() && mEntryBlocks[j]->CanForwardZPMove(saddr, daddr, mEntryBlocks[j]->mTemp))
|
||||||
|
j++;
|
||||||
|
|
||||||
|
if (j == mEntryBlocks.Size())
|
||||||
|
{
|
||||||
|
if (!mEntryRequiredRegs[CPU_REG_A])
|
||||||
|
{
|
||||||
|
mIns.Insert(0, NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, saddr));
|
||||||
|
mIns.Insert(1, NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, daddr));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (!mEntryRequiredRegs[CPU_REG_X])
|
||||||
|
{
|
||||||
|
mIns.Insert(0, NativeCodeInstruction(ASMIT_LDX, ASMIM_ZERO_PAGE, saddr));
|
||||||
|
mIns.Insert(1, NativeCodeInstruction(ASMIT_STX, ASMIM_ZERO_PAGE, daddr));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mEntryBlocks.Size() > 2)
|
if (mEntryBlocks.Size() > 2)
|
||||||
|
@ -13150,6 +13275,7 @@ bool NativeCodeBasicBlock::JoinTailCodeSequences(NativeCodeProcedure* proc, bool
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (mEntryBlocks.Size() == 1)
|
if (mEntryBlocks.Size() == 1)
|
||||||
|
@ -15216,6 +15342,47 @@ bool NativeCodeBasicBlock::MoveLoadIndirectTempStoreUp(int at)
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (mIns[j].mType == ASMIT_STX && mIns[j].mMode == ASMIM_ZERO_PAGE && (mIns[j].mAddress == mIns[at + 1].mAddress || mIns[j].mAddress == mIns[at + 1].mAddress + 1))
|
||||||
|
{
|
||||||
|
if (mIns[j - 3].mType == ASMIT_LDX && mIns[j - 3].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[j - 2].mType == ASMIT_STX && mIns[j - 2].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[j - 1].mType == ASMIT_LDX && mIns[j - 1].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[j - 0].mType == ASMIT_STX && mIns[j - 0].mMode == ASMIM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
if (mIns[j - 2].mAddress == mIns[at + 1].mAddress &&
|
||||||
|
mIns[j - 0].mAddress == mIns[at + 1].mAddress + 1 &&
|
||||||
|
mIns[j - 1].mAddress == mIns[j - 3].mAddress + 1)
|
||||||
|
{
|
||||||
|
int addr = mIns[j - 3].mAddress;
|
||||||
|
|
||||||
|
while (mIns[j].mLive & LIVE_CPU_REG_A)
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
if (mIns[j].ReferencesZeroPage(addr) || mIns[j].ReferencesZeroPage(addr + 1))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIns[at + 1].mLive |= mIns[j].mLive;
|
||||||
|
mIns[at + 2].mLive |= mIns[j].mLive;
|
||||||
|
mIns[at + 3].mLive |= mIns[j].mLive;
|
||||||
|
|
||||||
|
mIns[at + 1].mAddress = addr;
|
||||||
|
mIns[at + 1].mLive |= LIVE_MEM;
|
||||||
|
|
||||||
|
mIns.Insert(j + 1, mIns[at + 2]);
|
||||||
|
mIns.Insert(j + 1, mIns[at + 2]);
|
||||||
|
mIns.Insert(j + 1, mIns[at + 2]);
|
||||||
|
|
||||||
|
mIns.Remove(at + 3);
|
||||||
|
mIns.Remove(at + 3);
|
||||||
|
mIns.Remove(at + 3);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (mIns[j].ReferencesYReg())
|
if (mIns[j].ReferencesYReg())
|
||||||
return false;
|
return false;
|
||||||
|
@ -15232,6 +15399,107 @@ bool NativeCodeBasicBlock::MoveLoadIndirectTempStoreUp(int at)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeCodeBasicBlock::MoveLoadIndirectBypassYUp(int at)
|
||||||
|
{
|
||||||
|
// ldy #imm
|
||||||
|
// lda (t0), y
|
||||||
|
|
||||||
|
// move up, and keep A in Y for the intervall
|
||||||
|
|
||||||
|
int j = at - 1;
|
||||||
|
while (j >= 3)
|
||||||
|
{
|
||||||
|
if (mIns[j].mType == ASMIT_STA && mIns[j].mMode == ASMIM_ZERO_PAGE && (mIns[j].mAddress == mIns[at + 1].mAddress || mIns[j].mAddress == mIns[at + 1].mAddress + 1))
|
||||||
|
{
|
||||||
|
if (mIns[j - 3].mType == ASMIT_LDA && mIns[j - 3].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[j - 2].mType == ASMIT_STA && mIns[j - 2].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[j - 1].mType == ASMIT_LDA && mIns[j - 1].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[j - 0].mType == ASMIT_STA && mIns[j - 0].mMode == ASMIM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
if (mIns[j - 2].mAddress == mIns[at + 1].mAddress &&
|
||||||
|
mIns[j - 0].mAddress == mIns[at + 1].mAddress + 1 &&
|
||||||
|
mIns[j - 1].mAddress == mIns[j - 3].mAddress + 1)
|
||||||
|
{
|
||||||
|
mIns[at + 0].mLive |= mIns[j].mLive;
|
||||||
|
mIns[at + 1].mLive |= mIns[j].mLive;
|
||||||
|
|
||||||
|
mIns[at + 1].mAddress = mIns[j - 3].mAddress;
|
||||||
|
mIns[at + 1].mLive |= LIVE_MEM;
|
||||||
|
|
||||||
|
mIns.Insert(j + 1, mIns[at + 0]);
|
||||||
|
mIns.Remove(at + 1);
|
||||||
|
mIns.Insert(j + 2, mIns[at + 1]);
|
||||||
|
mIns.Remove(at + 2);
|
||||||
|
|
||||||
|
mIns.Insert(at + 2, NativeCodeInstruction(ASMIT_TYA));
|
||||||
|
mIns.Insert(j + 3, NativeCodeInstruction(ASMIT_TAY));
|
||||||
|
|
||||||
|
for (int k = j + 3; k < at + 3; k++)
|
||||||
|
mIns[k].mLive |= LIVE_CPU_REG_Y;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mIns[j].mType == ASMIT_STX && mIns[j].mMode == ASMIM_ZERO_PAGE && (mIns[j].mAddress == mIns[at + 1].mAddress || mIns[j].mAddress == mIns[at + 1].mAddress + 1))
|
||||||
|
{
|
||||||
|
if (mIns[j - 3].mType == ASMIT_LDX && mIns[j - 3].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[j - 2].mType == ASMIT_STX && mIns[j - 2].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[j - 1].mType == ASMIT_LDX && mIns[j - 1].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
mIns[j - 0].mType == ASMIT_STX && mIns[j - 0].mMode == ASMIM_ZERO_PAGE)
|
||||||
|
{
|
||||||
|
if (mIns[j - 2].mAddress == mIns[at + 1].mAddress &&
|
||||||
|
mIns[j - 0].mAddress == mIns[at + 1].mAddress + 1 &&
|
||||||
|
mIns[j - 1].mAddress == mIns[j - 3].mAddress + 1)
|
||||||
|
{
|
||||||
|
int addr = mIns[j - 3].mAddress;
|
||||||
|
|
||||||
|
while (mIns[j].mLive & LIVE_CPU_REG_A)
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
if (mIns[j].ReferencesZeroPage(addr) || mIns[j].ReferencesZeroPage(addr + 1))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mIns[at + 0].mLive |= mIns[j].mLive;
|
||||||
|
mIns[at + 1].mLive |= mIns[j].mLive;
|
||||||
|
|
||||||
|
mIns[at + 1].mAddress = addr;
|
||||||
|
mIns[at + 1].mLive |= LIVE_MEM;
|
||||||
|
|
||||||
|
mIns.Insert(j + 1, mIns[at + 0]);
|
||||||
|
mIns.Remove(at + 1);
|
||||||
|
mIns.Insert(j + 2, mIns[at + 1]);
|
||||||
|
mIns.Remove(at + 2);
|
||||||
|
|
||||||
|
mIns.Insert(at + 2, NativeCodeInstruction(ASMIT_TYA));
|
||||||
|
mIns.Insert(j + 3, NativeCodeInstruction(ASMIT_TAY));
|
||||||
|
|
||||||
|
for (int k = j + 3; k < at + 3; k++)
|
||||||
|
mIns[k].mLive |= LIVE_CPU_REG_Y;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIns[j].ReferencesYReg())
|
||||||
|
return false;
|
||||||
|
if (mIns[j].ChangesZeroPage(mIns[at + 1].mAddress))
|
||||||
|
return false;
|
||||||
|
if (mIns[j].ChangesZeroPage(mIns[at + 1].mAddress + 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at)
|
bool NativeCodeBasicBlock::MoveIndirectLoadStoreUp(int at)
|
||||||
{
|
{
|
||||||
int j = at - 1;
|
int j = at - 1;
|
||||||
|
@ -19309,11 +19577,13 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// move load (),y store zp down to potential user
|
// move load (),y store zp down to potential user
|
||||||
for (int i = 2; i + 1 < mIns.Size(); i++)
|
for (int i = 0; i + 1 < mIns.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_INDIRECT_Y && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
|
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_INDIRECT_Y && mIns[i + 1].mType == ASMIT_STA && mIns[i + 1].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 1].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z)))
|
||||||
{
|
{
|
||||||
if (MoveIndirectLoadStoreDown(i))
|
if (MoveLoadIndirectTempStoreUp(i))
|
||||||
|
changed = true;
|
||||||
|
else if (MoveIndirectLoadStoreDown(i))
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19324,13 +19594,12 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// move load (),y store zp up to potential user
|
// move load (),y store zp up to potential user
|
||||||
for (int i = 4; i + 2 < mIns.Size(); i++)
|
for (int i = 4; i + 1 < mIns.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE &&
|
if (mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE &&
|
||||||
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 1].mLive & LIVE_MEM) &&
|
mIns[i + 1].mType == ASMIT_LDA && mIns[i + 1].mMode == ASMIM_INDIRECT_Y && !(mIns[i + 1].mLive & (LIVE_MEM | LIVE_CPU_REG_Y)))
|
||||||
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 2].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Z | LIVE_CPU_REG_Y)))
|
|
||||||
{
|
{
|
||||||
if (MoveLoadIndirectTempStoreUp(i))
|
if (MoveLoadIndirectBypassYUp(i))
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21594,6 +21863,21 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
mIns[i + 1].mType = ASMIT_STA; mIns[i + 1].mLive |= mIns[i + 2].mLive;
|
mIns[i + 1].mType = ASMIT_STA; mIns[i + 1].mLive |= mIns[i + 2].mLive;
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
else if (
|
||||||
|
mIns[i + 0].mType == ASMIT_LDX &&
|
||||||
|
mIns[i + 1].mType == ASMIT_STX && !(mIns[i + 1].mLive & LIVE_CPU_REG_X) &&
|
||||||
|
mIns[i + 2].mType == ASMIT_STA && !(mIns[i + 2].mLive & LIVE_CPU_REG_A) &&
|
||||||
|
!mIns[i + 0].MayBeChangedOnAddress(mIns[i + 2]) &&
|
||||||
|
!mIns[i + 1].MayBeChangedOnAddress(mIns[i + 2]))
|
||||||
|
{
|
||||||
|
NativeCodeInstruction ins = mIns[i + 2];
|
||||||
|
mIns[i + 2] = mIns[i + 1];
|
||||||
|
mIns[i + 1] = mIns[i + 0];
|
||||||
|
mIns[i + 0] = ins;
|
||||||
|
mIns[i + 1].mType = ASMIT_LDA; mIns[i + 1].mLive |= LIVE_CPU_REG_A | mIns[i + 0].mLive;
|
||||||
|
mIns[i + 2].mType = ASMIT_STA; mIns[i + 2].mLive |= mIns[i + 0].mLive;
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 0].mType == ASMIT_LDX &&
|
mIns[i + 0].mType == ASMIT_LDX &&
|
||||||
mIns[i + 1].mType == ASMIT_STX &&
|
mIns[i + 1].mType == ASMIT_STX &&
|
||||||
|
|
|
@ -148,7 +148,7 @@ public:
|
||||||
|
|
||||||
GrowingArray<NativeCodeBasicBlock*> mEntryBlocks;
|
GrowingArray<NativeCodeBasicBlock*> mEntryBlocks;
|
||||||
|
|
||||||
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset;
|
int mOffset, mSize, mPlace, mNumEntries, mNumEntered, mFrameOffset, mTemp;
|
||||||
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched, mPatchFail;
|
bool mPlaced, mCopied, mKnownShortBranch, mBypassed, mAssembled, mNoFrame, mVisited, mLoopHead, mVisiting, mLocked, mPatched, mPatchFail;
|
||||||
NativeCodeBasicBlock * mDominator, * mSameBlock;
|
NativeCodeBasicBlock * mDominator, * mSameBlock;
|
||||||
|
|
||||||
|
@ -258,6 +258,7 @@ public:
|
||||||
bool MoveAbsoluteLoadStoreUp(int at);
|
bool MoveAbsoluteLoadStoreUp(int at);
|
||||||
bool MoveLoadStoreOutOfXYRangeUp(int at);
|
bool MoveLoadStoreOutOfXYRangeUp(int at);
|
||||||
bool MoveLoadIndirectTempStoreUp(int at);
|
bool MoveLoadIndirectTempStoreUp(int at);
|
||||||
|
bool MoveLoadIndirectBypassYUp(int at);
|
||||||
|
|
||||||
bool MoveLoadAddImmStoreAbsXUp(int at);
|
bool MoveLoadAddImmStoreAbsXUp(int at);
|
||||||
bool MoveStaTaxLdaStaDown(int at);
|
bool MoveStaTaxLdaStaDown(int at);
|
||||||
|
@ -344,6 +345,9 @@ public:
|
||||||
bool AlternateXYUsage(void);
|
bool AlternateXYUsage(void);
|
||||||
bool OptimizeXYPairUsage(void);
|
bool OptimizeXYPairUsage(void);
|
||||||
bool ForwardAbsoluteLoadStores(void);
|
bool ForwardAbsoluteLoadStores(void);
|
||||||
|
bool CanForwardZPMove(int saddr, int daddr, int & index) const;
|
||||||
|
bool Is16BitAddSubImmediate(int at, int& sreg, int &dreg, int& offset) const;
|
||||||
|
bool CanForward16BitAddSubImmediate(int sreg, int dreg, int offset, int & index) const;
|
||||||
|
|
||||||
bool CheckPatchFail(const NativeCodeBasicBlock* block, int reg);
|
bool CheckPatchFail(const NativeCodeBasicBlock* block, int reg);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue