Value range annotation for intermediate code
This commit is contained in:
parent
b9c477976a
commit
05a6c71698
|
@ -77,16 +77,17 @@ int main(void)
|
|||
a[i] = i % 10;
|
||||
al[i] = i % 10;
|
||||
}
|
||||
|
||||
#if 0
|
||||
assert(sum(a, 100) == 450);
|
||||
copy(b, a, 100);
|
||||
assert(sum(b, 100) == 450);
|
||||
reverse(c, a, 100);
|
||||
assert(sum(c, 100) == 450);
|
||||
|
||||
assert(sumb(a, 100) == 450);
|
||||
#endif
|
||||
copyb(b, a, 100);
|
||||
assert(sumb(b, 100) == 450);
|
||||
#if 0
|
||||
reverseb(c, a, 100);
|
||||
assert(sumb(c, 100) == 450);
|
||||
|
||||
|
@ -97,6 +98,6 @@ int main(void)
|
|||
|
||||
reversel(cl, al, 100);
|
||||
assert(suml(cl, 100) == 450);
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,90 @@ static bool IsIntegerType(InterType type)
|
|||
return type >= IT_INT8 && type <= IT_INT32;
|
||||
}
|
||||
|
||||
IntegerValueRange::IntegerValueRange(void)
|
||||
: mMinState(S_UNKNOWN), mMaxState(S_UNKNOWN)
|
||||
{}
|
||||
|
||||
IntegerValueRange::~IntegerValueRange(void)
|
||||
{}
|
||||
|
||||
bool IntegerValueRange::Same(const IntegerValueRange& range) const
|
||||
{
|
||||
if (mMinState == range.mMinState && mMaxState == range.mMaxState)
|
||||
{
|
||||
if ((mMinState == S_BOUND || mMinState == S_WEAK) && mMinValue != range.mMinValue)
|
||||
return false;
|
||||
if ((mMaxState == S_BOUND || mMaxState == S_WEAK) && mMaxValue != range.mMaxValue)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IntegerValueRange::Merge(const IntegerValueRange& range)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (mMinState != S_UNBOUND)
|
||||
{
|
||||
if (range.mMinState == S_UNKNOWN)
|
||||
{
|
||||
if (mMinState == S_BOUND)
|
||||
mMinState = S_WEAK;
|
||||
}
|
||||
else if (range.mMinState == S_UNBOUND)
|
||||
{
|
||||
mMinState = S_UNBOUND;
|
||||
changed = true;
|
||||
}
|
||||
else if (mMinState == S_UNKNOWN)
|
||||
{
|
||||
mMinState = S_WEAK;
|
||||
mMinValue = range.mMinValue;
|
||||
changed = true;
|
||||
}
|
||||
else if (range.mMinValue < mMinValue)
|
||||
{
|
||||
if (range.mMinState == S_WEAK)
|
||||
mMinState = S_WEAK;
|
||||
mMinValue = range.mMinValue;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mMaxState != S_UNBOUND)
|
||||
{
|
||||
if (range.mMaxState == S_UNKNOWN)
|
||||
{
|
||||
if (mMaxState == S_BOUND)
|
||||
mMaxState = S_WEAK;
|
||||
}
|
||||
else if (range.mMaxState == S_UNBOUND)
|
||||
{
|
||||
mMaxState = S_UNBOUND;
|
||||
changed = true;
|
||||
}
|
||||
else if (mMaxState == S_UNKNOWN)
|
||||
{
|
||||
mMaxState = S_WEAK;
|
||||
mMaxValue = range.mMaxValue;
|
||||
changed = true;
|
||||
}
|
||||
else if (range.mMaxValue > mMaxValue)
|
||||
{
|
||||
if (range.mMaxState == S_WEAK)
|
||||
mMaxState = S_WEAK;
|
||||
mMaxValue = range.mMaxValue;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
ValueSet::ValueSet(void)
|
||||
{
|
||||
mSize = 32;
|
||||
|
@ -1485,6 +1569,13 @@ InterOperand::InterOperand(void)
|
|||
: mTemp(INVALID_TEMPORARY), mType(IT_NONE), mFinal(false), mIntConst(0), mFloatConst(0), mVarIndex(-1), mOperandSize(0), mLinkerObject(nullptr), mMemory(IM_NONE)
|
||||
{}
|
||||
|
||||
bool InterOperand::IsUByte(void) const
|
||||
{
|
||||
return
|
||||
mRange.mMinState == IntegerValueRange::S_BOUND && mRange.mMinValue >= 0 &&
|
||||
mRange.mMaxState == IntegerValueRange::S_BOUND && mRange.mMaxValue < 256;
|
||||
}
|
||||
|
||||
bool InterOperand::IsEqual(const InterOperand& op) const
|
||||
{
|
||||
if (mType != op.mType || mTemp != op.mTemp)
|
||||
|
@ -2202,6 +2293,46 @@ void InterInstruction::SimpleLocalToTemp(int vindex, int temp)
|
|||
}
|
||||
}
|
||||
|
||||
void InterOperand::Disassemble(FILE* file)
|
||||
{
|
||||
static char typechars[] = "NBCILFP";
|
||||
|
||||
if (mTemp >= 0)
|
||||
{
|
||||
fprintf(file, "R%d(%c)", mTemp, typechars[mType]);
|
||||
if (mRange.mMinState >= IntegerValueRange::S_WEAK || mRange.mMaxState >= IntegerValueRange::S_WEAK)
|
||||
{
|
||||
fprintf(file, "[");
|
||||
if (mRange.mMinState == IntegerValueRange::S_WEAK)
|
||||
fprintf(file, "~%d", int(mRange.mMinValue));
|
||||
else if (mRange.mMinState == IntegerValueRange::S_BOUND)
|
||||
fprintf(file, "%d", int(mRange.mMinValue));
|
||||
else if (mRange.mMinState == IntegerValueRange::S_UNKNOWN)
|
||||
fprintf(file, "?");
|
||||
fprintf(file, "..");
|
||||
if (mRange.mMaxState == IntegerValueRange::S_WEAK)
|
||||
fprintf(file, "~%d", int(mRange.mMaxValue));
|
||||
else if (mRange.mMaxState == IntegerValueRange::S_BOUND)
|
||||
fprintf(file, "%d", int(mRange.mMaxValue));
|
||||
else if (mRange.mMaxState == IntegerValueRange::S_UNKNOWN)
|
||||
fprintf(file, "?");
|
||||
fprintf(file, "]");
|
||||
}
|
||||
}
|
||||
else if (mType == IT_POINTER)
|
||||
{
|
||||
fprintf(file, "V%d+%d", mVarIndex, int(mIntConst));
|
||||
}
|
||||
else if (IsIntegerType(mType) || mType == IT_BOOL)
|
||||
{
|
||||
fprintf(file, "C%c:%d", typechars[mType], int(mIntConst));
|
||||
}
|
||||
else if (mType == IT_FLOAT)
|
||||
{
|
||||
fprintf(file, "C%c:%f", typechars[mType], mFloatConst);
|
||||
}
|
||||
}
|
||||
|
||||
void InterInstruction::Disassemble(FILE* file)
|
||||
{
|
||||
if (this->mCode != IC_NONE)
|
||||
|
@ -2285,18 +2416,11 @@ void InterInstruction::Disassemble(FILE* file)
|
|||
static char typechars[] = "NBCILFP";
|
||||
|
||||
fprintf(file, "\t");
|
||||
if (mDst.mTemp >= 0) fprintf(file, "R%d(%c)", mDst.mTemp, typechars[mDst.mType]);
|
||||
if (mDst.mTemp >= 0)
|
||||
mDst.Disassemble(file);
|
||||
fprintf(file, "\t<-\t");
|
||||
|
||||
if (mSrc[2].mTemp >= 0) fprintf(file, "R%d(%c%c), ", mSrc[2].mTemp, typechars[mSrc[2].mType], mSrc[2].mFinal ? 'F' : '-');
|
||||
if (mSrc[1].mTemp >= 0)
|
||||
fprintf(file, "R%d(%c%c), ", mSrc[1].mTemp, typechars[mSrc[1].mType], mSrc[1].mFinal ? 'F' : '-');
|
||||
else if (this->mCode == IC_STORE)
|
||||
fprintf(file, "V%d+%d, ", mSrc[1].mVarIndex, int(mSrc[1].mIntConst));
|
||||
if (mSrc[0].mTemp >= 0)
|
||||
fprintf(file, "R%d(%c%c)", mSrc[0].mTemp, typechars[mSrc[0].mType], mSrc[0].mFinal ? 'F' : '-');
|
||||
else if (this->mCode == IC_LOAD)
|
||||
fprintf(file, "V%d+%d", mSrc[0].mVarIndex, int(mSrc[0].mIntConst));
|
||||
|
||||
if (this->mCode == IC_CONSTANT)
|
||||
{
|
||||
if (mDst.mType == IT_POINTER)
|
||||
|
@ -2304,23 +2428,39 @@ void InterInstruction::Disassemble(FILE* file)
|
|||
fprintf(file, "C%c%d(%d:%d)", memchars[mConst.mMemory], mConst.mOperandSize, mConst.mVarIndex, int(mConst.mIntConst));
|
||||
}
|
||||
else if (mDst.mType == IT_FLOAT)
|
||||
fprintf(file, "C%f", mConst.mFloatConst);
|
||||
fprintf(file, "CF:%f", mConst.mFloatConst);
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
fprintf(file, "C%I64d", mConst.mIntConst);
|
||||
fprintf(file, "CI:%I64d", mConst.mIntConst);
|
||||
#else
|
||||
fprintf(file, "C%lld", mConst.mIntConst);
|
||||
fprintf(file, "CI:%lld", mConst.mIntConst);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool first = true;
|
||||
for (int i = 0; i < mNumOperands; i++)
|
||||
{
|
||||
int j = mNumOperands - i - 1;
|
||||
if (!first)
|
||||
fprintf(file, ", ");
|
||||
if (mSrc[j].mType != IT_NONE)
|
||||
{
|
||||
mSrc[j].Disassemble(file);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
InterCodeBasicBlock::InterCodeBasicBlock(void)
|
||||
: mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mDominator(nullptr)
|
||||
: mInstructions(nullptr), mEntryRenameTable(-1), mExitRenameTable(-1), mMergeTValues(nullptr), mTrueJump(nullptr), mFalseJump(nullptr), mDominator(nullptr),
|
||||
mEntryValueRange(IntegerValueRange()), mTrueValueRange(IntegerValueRange()), mFalseValueRange(IntegerValueRange()), mLocalValueRange(IntegerValueRange()), mEntryBlocks(nullptr)
|
||||
{
|
||||
mInPath = false;
|
||||
mLoopHead = false;
|
||||
|
@ -2353,6 +2493,26 @@ void InterCodeBasicBlock::Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlo
|
|||
}
|
||||
|
||||
|
||||
void InterCodeBasicBlock::CollectEntryBlocks(InterCodeBasicBlock* from)
|
||||
{
|
||||
if (from)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < mEntryBlocks.Size() && mEntryBlocks[i] != from)
|
||||
i++;
|
||||
if (i == mEntryBlocks.Size())
|
||||
mEntryBlocks.Push(from);
|
||||
}
|
||||
|
||||
if (!mVisited)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
if (mTrueJump) mTrueJump->CollectEntryBlocks(this);
|
||||
if (mFalseJump) mFalseJump->CollectEntryBlocks(this);
|
||||
}
|
||||
}
|
||||
|
||||
void InterCodeBasicBlock::CollectEntries(void)
|
||||
{
|
||||
mNumEntries++;
|
||||
|
@ -3130,6 +3290,392 @@ bool InterCodeBasicBlock::PropagateConstTemps(const GrowingInstructionPtrArray&
|
|||
return changed;
|
||||
}
|
||||
|
||||
bool InterCodeBasicBlock::BuildGlobalIntegerRangeSets(void)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
mNumEntered++;
|
||||
if (!mLoopHead && mNumEntered < mEntryBlocks.Size())
|
||||
return false;
|
||||
|
||||
mLocalValueRange.Clear();
|
||||
|
||||
for (int j = 0; j < mEntryBlocks.Size(); j++)
|
||||
{
|
||||
InterCodeBasicBlock* from = mEntryBlocks[j];
|
||||
GrowingIntegerValueRangeArray& range(this == from->mTrueJump ? from->mTrueValueRange : from->mFalseValueRange);
|
||||
if (j == 0)
|
||||
mLocalValueRange = range;
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < mLocalValueRange.Size(); i++)
|
||||
mLocalValueRange[i].Merge(range[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mLocalValueRange.Size(); i++)
|
||||
if (!mLocalValueRange[i].Same(mEntryValueRange[i]))
|
||||
changed = true;
|
||||
|
||||
if (mVisited && mNumEntered >= 2 * mEntryBlocks.Size())
|
||||
return changed;
|
||||
|
||||
if (!mVisited || changed)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
if (changed)
|
||||
{
|
||||
mEntryValueRange = mLocalValueRange;
|
||||
|
||||
UpdateLocalIntegerRangeSets();
|
||||
}
|
||||
|
||||
if (mTrueJump && mTrueJump->BuildGlobalIntegerRangeSets())
|
||||
changed = true;
|
||||
if (mFalseJump && mFalseJump->BuildGlobalIntegerRangeSets())
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
|
||||
{
|
||||
mLocalValueRange = mEntryValueRange;
|
||||
|
||||
int sz = mInstructions.Size();
|
||||
|
||||
for (int i = 0; i < sz; i++)
|
||||
{
|
||||
InterInstruction* ins(mInstructions[i]);
|
||||
|
||||
for (int i = 0; i < ins->mNumOperands; i++)
|
||||
{
|
||||
if (ins->mSrc[i].mTemp >= 0)
|
||||
ins->mSrc[i].mRange = mLocalValueRange[ins->mSrc[i].mTemp];
|
||||
}
|
||||
|
||||
if (ins->mDst.mTemp >= 0 && IsIntegerType(ins->mDst.mType))
|
||||
{
|
||||
IntegerValueRange& vr(mLocalValueRange[ins->mDst.mTemp]);
|
||||
|
||||
switch (ins->mCode)
|
||||
{
|
||||
case IC_CONSTANT:
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND;
|
||||
vr.mMinValue = vr.mMaxValue = ins->mConst.mIntConst;
|
||||
break;
|
||||
case IC_UNARY_OPERATOR:
|
||||
{
|
||||
switch (ins->mOperator)
|
||||
{
|
||||
case IA_NEG:
|
||||
{
|
||||
IntegerValueRange tr;
|
||||
IntegerValueRange& sr(mLocalValueRange[ins->mSrc[0].mTemp]);
|
||||
|
||||
tr.mMinState = vr.mMaxState;
|
||||
tr.mMinValue = -vr.mMaxValue;
|
||||
tr.mMaxState = vr.mMinState;
|
||||
tr.mMaxValue = -vr.mMinValue;
|
||||
vr = tr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IC_CONVERSION_OPERATOR:
|
||||
switch (ins->mOperator)
|
||||
{
|
||||
case IA_EXT8TO16S:
|
||||
vr = mLocalValueRange[ins->mSrc[0].mTemp];
|
||||
if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < -128 || vr.mMaxValue > 127)
|
||||
{
|
||||
vr.mMaxState = IntegerValueRange::S_BOUND;
|
||||
vr.mMaxValue = 127;
|
||||
}
|
||||
if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < -128 || vr.mMinValue > 127)
|
||||
{
|
||||
vr.mMinState = IntegerValueRange::S_BOUND;
|
||||
vr.mMinValue = -128;
|
||||
}
|
||||
break;
|
||||
|
||||
case IA_EXT8TO16U:
|
||||
vr = mLocalValueRange[ins->mSrc[0].mTemp];
|
||||
if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < 0 || vr.mMaxValue > 255)
|
||||
{
|
||||
vr.mMaxState = IntegerValueRange::S_BOUND;
|
||||
vr.mMaxValue = 255;
|
||||
}
|
||||
if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < 0 || vr.mMinValue > 255)
|
||||
{
|
||||
vr.mMinState = IntegerValueRange::S_BOUND;
|
||||
vr.mMinValue = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
}
|
||||
break;
|
||||
|
||||
case IC_BINARY_OPERATOR:
|
||||
switch (ins->mOperator)
|
||||
{
|
||||
case IA_ADD:
|
||||
if (ins->mSrc[0].mTemp < 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
vr = mLocalValueRange[ins->mSrc[0].mTemp];
|
||||
if (ins->mSrc[1].mIntConst > 0 && vr.mMaxState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
else if (ins->mSrc[1].mIntConst < 0 && vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
vr.mMaxValue += ins->mSrc[1].mIntConst;
|
||||
vr.mMinValue += ins->mSrc[1].mIntConst;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND && ins->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND)
|
||||
{
|
||||
vr.mMaxState = IntegerValueRange::S_BOUND;
|
||||
vr.mMaxValue = ins->mSrc[0].mRange.mMaxValue + ins->mSrc[1].mRange.mMaxValue;
|
||||
}
|
||||
else
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
|
||||
if (ins->mSrc[0].mRange.mMinState == IntegerValueRange::S_BOUND && ins->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND)
|
||||
{
|
||||
vr.mMinState = IntegerValueRange::S_BOUND;
|
||||
vr.mMinValue = ins->mSrc[0].mRange.mMinValue + ins->mSrc[1].mRange.mMinValue;
|
||||
}
|
||||
else
|
||||
vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
}
|
||||
|
||||
break;
|
||||
case IA_SUB:
|
||||
if (ins->mSrc[0].mTemp < 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
vr = mLocalValueRange[ins->mSrc[0].mTemp];
|
||||
int maxv = vr.mMaxValue, minv = vr.mMinValue;
|
||||
|
||||
if (vr.mMaxState == IntegerValueRange::S_WEAK)
|
||||
{
|
||||
if (vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
}
|
||||
if (vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
|
||||
vr.mMaxValue = ins->mSrc[1].mIntConst - minv;
|
||||
vr.mMinValue = ins->mSrc[1].mIntConst - maxv;
|
||||
}
|
||||
else
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
|
||||
break;
|
||||
case IA_MUL:
|
||||
if (ins->mSrc[0].mTemp < 0)
|
||||
{
|
||||
vr = mLocalValueRange[ins->mSrc[1].mTemp];
|
||||
if (ins->mSrc[0].mIntConst > 0)
|
||||
{
|
||||
if (vr.mMaxState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
else if (vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
|
||||
vr.mMaxValue *= ins->mSrc[0].mIntConst;
|
||||
vr.mMinValue *= ins->mSrc[0].mIntConst;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vr.mMaxState == IntegerValueRange::S_WEAK)
|
||||
{
|
||||
if (vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
}
|
||||
if (vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
|
||||
int maxv = vr.mMaxValue, minv = vr.mMinValue;
|
||||
vr.mMaxValue = ins->mSrc[0].mIntConst * minv;
|
||||
vr.mMinValue = ins->mSrc[0].mIntConst * maxv;
|
||||
}
|
||||
}
|
||||
else if (ins->mSrc[1].mTemp < 0)
|
||||
{
|
||||
vr = mLocalValueRange[ins->mSrc[0].mTemp];
|
||||
if (ins->mSrc[1].mIntConst > 0)
|
||||
{
|
||||
if (vr.mMaxState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
else if (vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
|
||||
vr.mMaxValue *= ins->mSrc[1].mIntConst;
|
||||
vr.mMinValue *= ins->mSrc[1].mIntConst;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vr.mMaxState == IntegerValueRange::S_WEAK)
|
||||
{
|
||||
if (vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
}
|
||||
if (vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
|
||||
int maxv = vr.mMaxValue, minv = vr.mMinValue;
|
||||
vr.mMaxValue = ins->mSrc[1].mIntConst * minv;
|
||||
vr.mMinValue = ins->mSrc[1].mIntConst * maxv;
|
||||
}
|
||||
}
|
||||
else
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
|
||||
break;
|
||||
case IA_SHL:
|
||||
if (ins->mSrc[0].mTemp < 0)
|
||||
{
|
||||
vr = mLocalValueRange[ins->mSrc[1].mTemp];
|
||||
if (vr.mMaxState == IntegerValueRange::S_WEAK)
|
||||
vr.mMaxState = IntegerValueRange::S_UNBOUND;
|
||||
else if (vr.mMinState == IntegerValueRange::S_WEAK)
|
||||
vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
|
||||
vr.mMaxValue <<= ins->mSrc[0].mIntConst;
|
||||
vr.mMinValue <<= ins->mSrc[0].mIntConst;
|
||||
}
|
||||
else
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
break;
|
||||
case IA_AND:
|
||||
if (ins->mSrc[0].mTemp < 0)
|
||||
{
|
||||
vr = mLocalValueRange[ins->mSrc[1].mTemp];
|
||||
if (ins->mSrc[0].mIntConst >= 0)
|
||||
{
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND;
|
||||
vr.mMaxValue = ins->mSrc[0].mIntConst;
|
||||
vr.mMinValue = 0;
|
||||
}
|
||||
}
|
||||
else if (ins->mSrc[1].mTemp < 0)
|
||||
{
|
||||
vr = mLocalValueRange[ins->mSrc[0].mTemp];
|
||||
if (ins->mSrc[1].mIntConst >= 0)
|
||||
{
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_BOUND;
|
||||
vr.mMaxValue = ins->mSrc[1].mIntConst;
|
||||
vr.mMinValue = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
break;
|
||||
|
||||
default:
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
|
||||
}
|
||||
|
||||
ins->mDst.mRange = vr;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < mLocalValueRange.Size(); i++)
|
||||
if (!mExitRequiredTemps[i])
|
||||
mLocalValueRange[i].mMinState = mLocalValueRange[i].mMaxState = IntegerValueRange::S_UNKNOWN;
|
||||
|
||||
mTrueValueRange = mLocalValueRange;
|
||||
mFalseValueRange = mLocalValueRange;
|
||||
|
||||
if (sz >= 2)
|
||||
{
|
||||
if (mInstructions[sz - 1]->mCode == IC_BRANCH && mInstructions[sz - 2]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[sz - 1]->mSrc[0].mTemp == mInstructions[sz - 2]->mDst.mTemp)
|
||||
{
|
||||
if (mInstructions[sz - 2]->mOperator == IA_CMPLS)
|
||||
{
|
||||
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
|
||||
{
|
||||
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
|
||||
mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
|
||||
mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1;
|
||||
|
||||
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
|
||||
mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
|
||||
}
|
||||
}
|
||||
else if (mInstructions[sz - 2]->mOperator == IA_CMPLU)
|
||||
{
|
||||
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
|
||||
{
|
||||
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
|
||||
mTrueValueRange[t].mMaxState = IntegerValueRange::S_BOUND;
|
||||
mTrueValueRange[t].mMaxValue = mInstructions[sz - 2]->mSrc[0].mIntConst - 1;
|
||||
mTrueValueRange[t].mMinState = IntegerValueRange::S_BOUND;
|
||||
mTrueValueRange[t].mMinValue = 0;
|
||||
|
||||
mFalseValueRange[t].mMinState = IntegerValueRange::S_BOUND;
|
||||
mFalseValueRange[t].mMinValue = mInstructions[sz - 2]->mSrc[0].mIntConst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InterCodeBasicBlock::BuildLocalIntegerRangeSets(int num)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mVisited)
|
||||
{
|
||||
mVisited = true;
|
||||
|
||||
mEntryValueRange.SetSize(num, true);
|
||||
mTrueValueRange.SetSize(num, true);
|
||||
mFalseValueRange.SetSize(num, true);
|
||||
mLocalValueRange.SetSize(num, true);
|
||||
|
||||
UpdateLocalIntegerRangeSets();
|
||||
|
||||
if (mTrueJump) mTrueJump->BuildLocalIntegerRangeSets(num);
|
||||
if (mFalseJump) mFalseJump->BuildLocalIntegerRangeSets(num);
|
||||
}
|
||||
}
|
||||
|
||||
void InterCodeBasicBlock::BuildLocalTempSets(int num)
|
||||
{
|
||||
int i;
|
||||
|
@ -5926,13 +6472,27 @@ void InterCodeProcedure::Close(void)
|
|||
ResetVisited();
|
||||
mEntryBlock->CollectActiveTemporaries(activeSet);
|
||||
|
||||
|
||||
mTemporaries.SetSize(activeSet.Num(), true);
|
||||
|
||||
|
||||
ResetVisited();
|
||||
mEntryBlock->ShrinkActiveTemporaries(activeSet, mTemporaries);
|
||||
|
||||
ResetVisited();
|
||||
mEntryBlock->CollectEntryBlocks(nullptr);
|
||||
|
||||
BuildDataFlowSets();
|
||||
|
||||
ResetVisited();
|
||||
mEntryBlock->BuildLocalIntegerRangeSets(mTemporaries.Size());
|
||||
|
||||
do {
|
||||
DisassembleDebug("tt");
|
||||
|
||||
ResetVisited();
|
||||
} while (mEntryBlock->BuildGlobalIntegerRangeSets());
|
||||
|
||||
DisassembleDebug("Estimated value range");
|
||||
|
||||
MapVariables();
|
||||
|
||||
DisassembleDebug("mapped variabled");
|
||||
|
|
|
@ -128,6 +128,30 @@ typedef GrowingArray<InterVariable * > GrowingVariableArray;
|
|||
|
||||
#define INVALID_TEMPORARY (-1)
|
||||
|
||||
class IntegerValueRange
|
||||
{
|
||||
public:
|
||||
IntegerValueRange(void);
|
||||
~IntegerValueRange(void);
|
||||
|
||||
int64 mMinValue, mMaxValue;
|
||||
|
||||
enum State
|
||||
{
|
||||
S_UNKNOWN,
|
||||
S_UNBOUND,
|
||||
S_WEAK,
|
||||
S_BOUND
|
||||
} mMinState, mMaxState;
|
||||
|
||||
bool Same(const IntegerValueRange& range) const;
|
||||
bool Merge(const IntegerValueRange& range);
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef GrowingArray<IntegerValueRange> GrowingIntegerValueRangeArray;
|
||||
|
||||
class ValueSet
|
||||
{
|
||||
protected:
|
||||
|
@ -300,10 +324,15 @@ public:
|
|||
int mVarIndex, mOperandSize;
|
||||
LinkerObject * mLinkerObject;
|
||||
InterMemory mMemory;
|
||||
IntegerValueRange mRange;
|
||||
|
||||
InterOperand(void);
|
||||
|
||||
bool IsEqual(const InterOperand & op) const;
|
||||
|
||||
bool IsUByte(void) const;
|
||||
|
||||
void Disassemble(FILE* file);
|
||||
};
|
||||
|
||||
class InterInstruction
|
||||
|
@ -430,6 +459,10 @@ public:
|
|||
NumberSet mEntryRequiredParams, mEntryProvidedParams;
|
||||
NumberSet mExitRequiredParams, mExitProvidedParams;
|
||||
|
||||
GrowingIntegerValueRangeArray mEntryValueRange, mTrueValueRange, mFalseValueRange, mLocalValueRange;
|
||||
|
||||
GrowingArray<InterCodeBasicBlock*> mEntryBlocks;
|
||||
|
||||
GrowingInstructionPtrArray mMergeTValues;
|
||||
ValueSet mMergeValues;
|
||||
TempForwardingTable mMergeForwardingTable;
|
||||
|
@ -441,6 +474,7 @@ public:
|
|||
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
|
||||
|
||||
void CollectEntries(void);
|
||||
void CollectEntryBlocks(InterCodeBasicBlock* from);
|
||||
void GenerateTraces(bool expand);
|
||||
|
||||
void LocalToTemp(int vindex, int temp);
|
||||
|
@ -467,6 +501,10 @@ public:
|
|||
bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars);
|
||||
bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars);
|
||||
|
||||
void BuildLocalIntegerRangeSets(int num);
|
||||
void UpdateLocalIntegerRangeSets(void);
|
||||
bool BuildGlobalIntegerRangeSets(void);
|
||||
|
||||
GrowingIntArray mEntryRenameTable;
|
||||
GrowingIntArray mExitRenameTable;
|
||||
|
||||
|
|
|
@ -5624,9 +5624,17 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
|||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
if (InterTypeSize[ins->mDst.mType] > 1)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
||||
mIns.Push(insh);
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
if (ins->mDst.IsUByte())
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp] + 1));
|
||||
mIns.Push(insh);
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5645,9 +5653,17 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
|||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
if (InterTypeSize[ins->mDst.mType] > 1)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
||||
mIns.Push(insh);
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
if (ins->mDst.IsUByte())
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
||||
mIns.Push(insh);
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5929,77 +5945,131 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
|
|||
|
||||
if (ins->mSrc[0].mTemp < 0)
|
||||
{
|
||||
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||
|
||||
int shift = ins->mSrc[0].mIntConst & 15;
|
||||
if (shift == 0)
|
||||
if (ins->mDst.IsUByte())
|
||||
{
|
||||
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
||||
if (shift == 0)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
if (sreg != treg)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (shift == 1)
|
||||
{
|
||||
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
||||
else if (shift == 1)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
}
|
||||
else
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
||||
}
|
||||
}
|
||||
else if (shift >= 8)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
||||
}
|
||||
else if (shift > 5)
|
||||
{
|
||||
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
||||
for(int i=shift; i<8; i++)
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_AND, ASMIM_IMMEDIATE, 0xff << shift));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg ));
|
||||
}
|
||||
else
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
|
||||
for (int i = 0; i < shift; i++)
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
}
|
||||
}
|
||||
else if (shift == 7)
|
||||
{
|
||||
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 0));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
||||
}
|
||||
else if (shift >= 8)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||
for (int i = 8; i < shift; i++)
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
||||
if (shift == 0)
|
||||
{
|
||||
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
}
|
||||
}
|
||||
else if (shift == 1)
|
||||
{
|
||||
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_ZERO_PAGE, treg + 1));
|
||||
}
|
||||
}
|
||||
else if (shift == 7)
|
||||
{
|
||||
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LSR, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, sreg + 0));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROR, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
||||
}
|
||||
else if (shift >= 8)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
||||
for (int i = 8; i < shift; i++)
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
||||
}
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
||||
for (int i = 1; i < shift; i++)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
||||
if (ins->mSrc[1].mTemp != ins->mDst.mTemp)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_IMPLIED));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp] + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
||||
}
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
||||
for (int i = 1; i < shift; i++)
|
||||
{
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ASL, ASMIM_ZERO_PAGE, treg));
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_ROL, ASMIM_IMPLIED));
|
||||
}
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
}
|
||||
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
|
||||
}
|
||||
}
|
||||
else if (ins->mSrc[1].mTemp < 0 && IsPowerOf2(ins->mSrc[1].mIntConst & 0xffff))
|
||||
|
@ -8699,6 +8769,109 @@ bool NativeCodeBasicBlock::FindGlobalAddressSumY(int at, int reg, bool direct, i
|
|||
return false;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::PatchDirectAddressSumY(int at, int reg, int apos, int breg)
|
||||
{
|
||||
int yindex = 0;
|
||||
int last = at;
|
||||
|
||||
while (last < mIns.Size())
|
||||
{
|
||||
if (mIns[last].mType == ASMIT_LDY && mIns[last].mMode == ASMIM_IMMEDIATE && (mIns[last].mAddress == yindex || mIns[last].mAddress == yindex + 1))
|
||||
yindex = mIns[last].mAddress;
|
||||
else if (mIns[last].ChangesYReg())
|
||||
return false;
|
||||
else if (mIns[last].mMode == ASMIM_ZERO_PAGE && (mIns[last].mAddress == breg || mIns[last].mAddress == breg + 1 || mIns[last].mAddress == reg || mIns[last].mAddress == reg + 1) && mIns[last].ChangesAddress())
|
||||
return false;
|
||||
else if (mIns[last].mMode == ASMIM_INDIRECT_Y && mIns[last].mAddress == reg)
|
||||
{
|
||||
if (!(mIns[last].mLive & LIVE_MEM))
|
||||
break;
|
||||
}
|
||||
else if (mIns[last].RequiresYReg())
|
||||
return false;
|
||||
last++;
|
||||
}
|
||||
|
||||
if (last == mIns.Size())
|
||||
return false;
|
||||
|
||||
mIns[apos].mType = ASMIT_TAY;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
mIns[apos + i + 1].mType = ASMIT_NOP;
|
||||
mIns[apos + i + 1].mMode = ASMIM_IMPLIED;
|
||||
}
|
||||
yindex = 0;
|
||||
|
||||
for (int i = apos; i <= last; i++)
|
||||
{
|
||||
mIns[i].mLive | LIVE_CPU_REG_Y;
|
||||
|
||||
if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_IMMEDIATE)
|
||||
{
|
||||
if (mIns[i].mAddress == yindex)
|
||||
{
|
||||
mIns[i].mType = ASMIT_NOP;
|
||||
mIns[i].mMode = ASMIM_IMPLIED;
|
||||
}
|
||||
else
|
||||
{
|
||||
mIns[i].mType = ASMIT_INY;
|
||||
mIns[i].mMode = ASMIM_IMPLIED;
|
||||
yindex++;
|
||||
}
|
||||
}
|
||||
else if (mIns[i].mMode == ASMIM_INDIRECT_Y && mIns[i].mAddress == reg)
|
||||
{
|
||||
mIns[i].mAddress = breg;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NativeCodeBasicBlock::FindDirectAddressSumY(int at, int reg, int& apos, int& breg)
|
||||
{
|
||||
int j = at - 6;
|
||||
while (j >= 0)
|
||||
{
|
||||
if (
|
||||
mIns[j + 0].mType == ASMIT_CLC &&
|
||||
mIns[j + 1].mType == ASMIT_ADC && mIns[j + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[j + 2].mType == ASMIT_STA && mIns[j + 2].mMode == ASMIM_ZERO_PAGE && mIns[j + 2].mAddress == reg &&
|
||||
mIns[j + 3].mType == ASMIT_LDA && mIns[j + 3].mMode == ASMIM_ZERO_PAGE && mIns[j + 3].mAddress == mIns[j + 1].mAddress + 1 &&
|
||||
mIns[j + 4].mType == ASMIT_ADC && mIns[j + 4].mMode == ASMIM_IMMEDIATE && mIns[j + 4].mAddress == 0 &&
|
||||
mIns[j + 5].mType == ASMIT_STA && mIns[j + 5].mMode == ASMIM_ZERO_PAGE && mIns[j + 5].mAddress == reg + 1)
|
||||
{
|
||||
breg = mIns[j + 1].mAddress;
|
||||
int k = j + 6;
|
||||
while (k < at)
|
||||
{
|
||||
if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1) && mIns[k].ChangesAddress())
|
||||
return false;
|
||||
|
||||
if (mIns[k].mMode == ASMIM_ZERO_PAGE && (mIns[k].mAddress == breg || mIns[k].mAddress == breg + 1))
|
||||
return false;
|
||||
if (mIns[k].mMode == ASMIM_INDIRECT_Y && mIns[k].mAddress == breg)
|
||||
return false;
|
||||
|
||||
k++;
|
||||
}
|
||||
|
||||
apos = j;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mIns[j + 5].mMode == ASMIM_ZERO_PAGE && (mIns[j + 5].mAddress == reg || mIns[j + 5].mAddress == reg + 1) && mIns[j + 5].ChangesAddress() || mIns[j + 5].ChangesYReg() || mIns[j + 5].RequiresYReg())
|
||||
return false;
|
||||
|
||||
j--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool NativeCodeBasicBlock::FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg)
|
||||
{
|
||||
|
@ -12011,6 +12184,18 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
|||
}
|
||||
|
||||
#if 1
|
||||
if (i + 1 < mIns.Size() && mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_IMMEDIATE && mIns[i + 0].mAddress == 0 && mIns[i + 1].mMode == ASMIM_INDIRECT_Y)
|
||||
{
|
||||
int apos, breg;
|
||||
if (FindDirectAddressSumY(i, mIns[i + 1].mAddress, apos, breg))
|
||||
{
|
||||
if (PatchDirectAddressSumY(i, mIns[i + 1].mAddress, apos, breg))
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#if 0
|
||||
if (i + 7 < mIns.Size())
|
||||
{
|
||||
if (
|
||||
|
@ -12042,7 +12227,79 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#if 1
|
||||
#if 0
|
||||
if (i + 8 < mIns.Size())
|
||||
{
|
||||
if (
|
||||
mIns[i + 0].mType == ASMIT_CLC &&
|
||||
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 &&
|
||||
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 &&
|
||||
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
|
||||
!mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 6].RequiresYReg() &&
|
||||
mIns[i + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE && mIns[i + 7].mAddress == 0 &&
|
||||
mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 2].mAddress && !(mIns[i + 8].mLive & LIVE_MEM))
|
||||
{
|
||||
for (int j = 0; j < 6; j++)
|
||||
{
|
||||
mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED;
|
||||
}
|
||||
|
||||
if (mIns[i + 8].mLive & LIVE_CPU_REG_Y)
|
||||
{
|
||||
mIns.Insert(i + 9, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
|
||||
mIns[i + 9].mLive |= LIVE_CPU_REG_Y;
|
||||
}
|
||||
|
||||
mIns[i + 0].mType = ASMIT_TAY;
|
||||
mIns[i + 0].mMode = ASMIM_IMPLIED;
|
||||
mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED;
|
||||
mIns[i + 8].mAddress = mIns[i + 1].mAddress;
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if (i + 11 < mIns.Size())
|
||||
{
|
||||
if (
|
||||
mIns[i + 0].mType == ASMIT_CLC &&
|
||||
mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 2].mType == ASMIT_STA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
|
||||
mIns[i + 3].mType == ASMIT_LDA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && mIns[i + 3].mAddress == mIns[i + 1].mAddress + 1 &&
|
||||
mIns[i + 4].mType == ASMIT_ADC && mIns[i + 4].mMode == ASMIM_IMMEDIATE && mIns[i + 4].mAddress == 0 &&
|
||||
mIns[i + 5].mType == ASMIT_STA && mIns[i + 5].mMode == ASMIM_ZERO_PAGE && mIns[i + 5].mAddress == mIns[i + 2].mAddress + 1 &&
|
||||
!mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 6].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 6].RequiresYReg() &&
|
||||
mIns[i + 7].mType == ASMIT_LDY && mIns[i + 7].mMode == ASMIM_IMMEDIATE && mIns[i + 7].mAddress == 0 &&
|
||||
mIns[i + 8].mMode == ASMIM_INDIRECT_Y && mIns[i + 8].mAddress == mIns[i + 2].mAddress &&
|
||||
!mIns[i + 9].ChangesZeroPage(mIns[i + 1].mAddress) && !mIns[i + 9].ChangesZeroPage(mIns[i + 1].mAddress + 1) && !mIns[i + 9].RequiresYReg() &&
|
||||
mIns[i + 10].mType == ASMIT_LDY && mIns[i + 10].mMode == ASMIM_IMMEDIATE && mIns[i + 10].mAddress == 1 &&
|
||||
mIns[i + 11].mMode == ASMIM_INDIRECT_Y && mIns[i + 11].mAddress == mIns[i + 2].mAddress &&
|
||||
!(mIns[i + 11].mLive & LIVE_MEM))
|
||||
{
|
||||
for (int j = 0; j < 6; j++)
|
||||
{
|
||||
mIns[i + j].mType = ASMIT_NOP; mIns[i + j].mMode = ASMIM_IMPLIED;
|
||||
}
|
||||
|
||||
if (mIns[i + 11].mLive & LIVE_CPU_REG_Y)
|
||||
{
|
||||
mIns.Insert(i + 12, NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 1));
|
||||
mIns[i + 12].mLive |= LIVE_CPU_REG_Y;
|
||||
}
|
||||
|
||||
mIns[i + 0].mType = ASMIT_TAY;
|
||||
mIns[i + 0].mMode = ASMIM_IMPLIED;
|
||||
mIns[i + 7].mType = ASMIT_NOP; mIns[i + 7].mMode = ASMIM_IMPLIED;
|
||||
mIns[i + 8].mAddress = mIns[i + 1].mAddress;
|
||||
mIns[i + 10].mType = ASMIT_INY; mIns[i + 10].mMode = ASMIM_IMPLIED;
|
||||
mIns[i + 11].mAddress = mIns[i + 1].mAddress;
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if (i + 9 < mIns.Size())
|
||||
{
|
||||
if (
|
||||
|
|
|
@ -197,6 +197,8 @@ public:
|
|||
bool MoveLoadAddImmStoreUp(int at);
|
||||
bool MoveCLCLoadAddZPStoreUp(int at);
|
||||
bool MoveLoadAddZPStoreUp(int at);
|
||||
bool FindDirectAddressSumY(int at, int reg, int& apos, int& breg);
|
||||
bool PatchDirectAddressSumY(int at, int reg, int apos, int breg);
|
||||
bool FindAddressSumY(int at, int reg, int & apos, int& breg, int& ireg);
|
||||
bool FindGlobalAddress(int at, int reg, int& apos);
|
||||
bool FindGlobalAddressSumY(int at, int reg, bool direct, int& apos, const NativeCodeInstruction * & ains, const NativeCodeInstruction*& iins, uint32 & flags);
|
||||
|
|
Loading…
Reference in New Issue