Optimize bitfields

This commit is contained in:
drmortalwombat 2023-10-14 16:51:33 +02:00
parent 4f76ffa311
commit d160b2ae65
2 changed files with 209 additions and 9 deletions

View File

@ -232,9 +232,109 @@ void test_word_signed(void)
} }
} }
void test_inc_char_fit(void)
{
A ai;
ai.x = 7;
ai.y = 1;
ai.z = 2;
for(int i=0; i<16; i++)
{
assert(ai.x == ((7 + i) & 15));
assert(ai.y == ((1 + i) & 1));
assert(ai.z == ((2 + i) & 7));
ai.x++;
ai.y++;
ai.z++;
}
}
void test_inc_char_cross(void)
{
B bi;
bi.x = 11;
bi.y = 22;
bi.z = 33;
bi.w = 44;
for(int i=0; i<64; i++)
{
assert(bi.x == ((11 + i) & 0x3f));
assert(bi.y == ((22 + i) & 0x3f));
assert(bi.z == ((33 + i) & 0x3f));
assert(bi.w == ((44 + i) & 0x3f));
bi.x++;
bi.y++;
bi.z++;
bi.w++;
}
}
void test_add_char_cross(void)
{
B bi= {0};
bi.x = 11;
bi.y = 22;
bi.z = 33;
bi.w = 44;
for(int i=0; i<64; i++)
{
assert(bi.x == ((11 + 5 * i) & 0x3f));
assert(bi.y == ((22 + 21 * i) & 0x3f));
assert(bi.z == ((33 - 4 * i) & 0x3f));
assert(bi.w == ((44 - 11 * i) & 0x3f));
bi.x += 5;
bi.y += 21;
bi.z -= 4;
bi.w -= 11;
}
}
void test_add_word_fit(void)
{
C ci = {0};
ci.x = 7;
ci.y = 1;
ci.z = 2;
for(int i=0; i<16; i++)
{
assert(ci.x == ((7 + 5 * i) & 15));
assert(ci.y == ((1 + 21 * i) & 1));
assert(ci.z == ((2 - 4 * i) & 7));
ci.x += 5;
ci.y += 21;
ci.z -= 4;
}
}
void test_add_word_cross(void)
{
D di = {0};
di.x = 111;
di.y = 222;
di.z = 333;
di.w = 444;
for(int i=0; i<1024; i++)
{
assert(di.x == ((111 + 5 * i) & 0x3ff));
assert(di.y == ((222 + 21 * i) & 0x3ff));
assert(di.z == ((333 - 4 * i) & 0x3ff));
assert(di.w == ((444 - 11 * i) & 0x3ff));
di.x += 5;
di.y += 21;
di.z -= 4;
di.w -= 11;
}
}
int main(void) int main(void)
{ {
#if 0
test_char_fit(); test_char_fit();
test_char_cross(); test_char_cross();
test_word_fit(); test_word_fit();
@ -244,5 +344,12 @@ int main(void)
test_char_signed(); test_char_signed();
test_word_signed(); test_word_signed();
test_inc_char_fit();
test_inc_char_cross();
test_add_char_cross();
#endif
test_add_word_fit();
test_add_word_cross();
return 0; return 0;
} }

View File

@ -7150,16 +7150,21 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
else if (ins->mSrc[1].mTemp < 0) else if (ins->mSrc[1].mTemp < 0)
{ {
vr = mLocalValueRange[ins->mSrc[0].mTemp]; vr = mLocalValueRange[ins->mSrc[0].mTemp];
IntegerValueRange::State s = vr.mMinState;
vr.mMinState = vr.mMaxState;
vr.mMaxState = s;
int64 maxv = vr.mMaxValue, minv = vr.mMinValue; int64 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) if (vr.mMinState == IntegerValueRange::S_WEAK)
{
if (vr.mMaxState == IntegerValueRange::S_WEAK)
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxState = IntegerValueRange::S_UNBOUND; vr.mMaxState = IntegerValueRange::S_UNBOUND;
}
if (vr.mMaxState == IntegerValueRange::S_WEAK)
vr.mMinState = IntegerValueRange::S_UNBOUND;
vr.mMaxValue = ins->mSrc[1].mIntConst - minv; vr.mMaxValue = ins->mSrc[1].mIntConst - minv;
vr.mMinValue = ins->mSrc[1].mIntConst - maxv; vr.mMinValue = ins->mSrc[1].mIntConst - maxv;
@ -9381,7 +9386,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra
{ {
InterInstruction* ains = ltvalue[pins->mSrc[0].mTemp]; InterInstruction* ains = ltvalue[pins->mSrc[0].mTemp];
if (ains->mCode == IC_BINARY_OPERATOR && ains->mOperator == IA_ADD && ains->mSrc[0].mTemp < 0) if (ains->mCode == IC_BINARY_OPERATOR && (ains->mOperator == IA_ADD || ains->mOperator == IA_SUB) && ains->mSrc[0].mTemp < 0)
{ {
if (spareTemps + 2 >= ltvalue.Size()) if (spareTemps + 2 >= ltvalue.Size())
return true; return true;
@ -9404,7 +9409,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra
nins->mDst.mRange = ins->mDst.mRange; nins->mDst.mRange = ins->mDst.mRange;
mInstructions.Insert(i + 1, nins); mInstructions.Insert(i + 1, nins);
ins->mOperator = IA_ADD; ins->mOperator = ains->mOperator;
ins->mSrc[0] = ains->mSrc[0]; ins->mSrc[0] = ains->mSrc[0];
ins->mSrc[0].mIntConst <<= nins->mSrc[0].mIntConst; ins->mSrc[0].mIntConst <<= nins->mSrc[0].mIntConst;
ins->mSrc[1] = nins->mDst; ins->mSrc[1] = nins->mDst;
@ -15892,7 +15897,94 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
mInstructions[i + 2]->mSrc[0].mIntConst = 0; mInstructions[i + 2]->mSrc[0].mIntConst = 0;
changed = true; changed = true;
} }
#if 1
if (i + 2 < mInstructions.Size() &&
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_AND &&
mInstructions[i + 0]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 1]->mOperator == IA_SHR &&
mInstructions[i + 1]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal &&
mInstructions[i + 2]->mCode == IC_RELATIONAL_OPERATOR &&
mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 1]->mDst.mTemp && mInstructions[i + 2]->mSrc[0].mFinal &&
mInstructions[i + 2]->mSrc[0].mTemp < 0)
{
mInstructions[i + 0]->mSrc[0].mIntConst &= ~((1 << mInstructions[i + 1]->mSrc[0].mIntConst) - 1);
mInstructions[i + 2]->mSrc[0].mIntConst <<= mInstructions[i + 1]->mSrc[0].mIntConst;
mInstructions[i + 2]->mSrc[1] = mInstructions[i + 0]->mDst;
mInstructions[i + 1]->mCode = IC_NONE;
mInstructions[i + 1]->mNumOperands = 0;
changed = true;
}
if (i + 2 < mInstructions.Size() &&
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_SHR &&
mInstructions[i + 0]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mCode == IC_RELATIONAL_OPERATOR &&
mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[0].mFinal &&
mInstructions[i + 1]->mSrc[0].mTemp < 0)
{
mInstructions[i + 1]->mSrc[0].mIntConst <<= mInstructions[i + 0]->mSrc[0].mIntConst;
mInstructions[i + 0]->mOperator = IA_AND;
mInstructions[i + 0]->mSrc[0].mIntConst = ~((1 << mInstructions[i + 0]->mSrc[0].mIntConst) - 1);
mInstructions[i + 0]->mDst.mRange.Reset();
mInstructions[i + 1]->mSrc[1].mRange.Reset();
changed = true;
}
if (i + 3 < mInstructions.Size() &&
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_SHR &&
mInstructions[i + 0]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && (mInstructions[i + 1]->mOperator == IA_ADD || mInstructions[i + 1]->mOperator == IA_SUB) &&
mInstructions[i + 1]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal &&
mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 2]->mOperator == IA_SHL &&
mInstructions[i + 2]->mSrc[0].mTemp < 0 &&
mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 1]->mDst.mTemp && mInstructions[i + 2]->mSrc[1].mFinal &&
mInstructions[i + 3]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 3]->mOperator == IA_AND &&
mInstructions[i + 3]->mSrc[0].mTemp < 0 &&
mInstructions[i + 3]->mSrc[1].mTemp == mInstructions[i + 2]->mDst.mTemp && mInstructions[i + 3]->mSrc[1].mFinal &&
mInstructions[i + 0]->mSrc[0].mIntConst == mInstructions[i + 2]->mSrc[0].mIntConst)
{
mInstructions[i + 3]->mSrc[0].mIntConst &= ~((1 << mInstructions[i + 0]->mSrc[0].mIntConst) - 1);
mInstructions[i + 1]->mSrc[0].mIntConst <<= mInstructions[i + 0]->mSrc[0].mIntConst;
mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1];
mInstructions[i + 1]->mDst = mInstructions[i + 2]->mDst;
mInstructions[i + 0]->mCode = IC_NONE;
mInstructions[i + 0]->mNumOperands = 0;
mInstructions[i + 2]->mCode = IC_NONE;
mInstructions[i + 2]->mNumOperands = 0;
changed = true;
}
if (i + 2 < mInstructions.Size() &&
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mOperator == IA_AND &&
mInstructions[i + 0]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && (mInstructions[i + 1]->mOperator == IA_ADD || mInstructions[i + 1]->mOperator == IA_SUB) &&
mInstructions[i + 1]->mSrc[0].mTemp < 0 &&
mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal &&
mInstructions[i + 2]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 2]->mOperator == IA_AND &&
mInstructions[i + 2]->mSrc[0].mTemp < 0 &&
mInstructions[i + 2]->mSrc[1].mTemp == mInstructions[i + 1]->mDst.mTemp && mInstructions[i + 2]->mSrc[1].mFinal &&
(mInstructions[i + 0]->mSrc[0].mIntConst & (mInstructions[i + 0]->mSrc[0].mIntConst + 1)) == 0 && // Is power of two - 1
(~mInstructions[i + 0]->mSrc[0].mIntConst & mInstructions[i + 1]->mSrc[0].mIntConst) == 0 && // add is part of initial mask
(~mInstructions[i + 0]->mSrc[0].mIntConst & mInstructions[i + 2]->mSrc[0].mIntConst) == 0) // final mask is part of initial mask
{
mInstructions[i + 1]->mSrc[1] = mInstructions[i + 0]->mSrc[1];
mInstructions[i + 0]->mCode = IC_NONE;
mInstructions[i + 0]->mNumOperands = 0;
changed = true;
}
#endif
#if 1 #if 1
if (i + 2 < mInstructions.Size() && if (i + 2 < mInstructions.Size() &&
mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR &&
@ -17925,7 +18017,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "ftoa"); CheckFunc = !strcmp(mIdent->mString, "test_add_char_cross");
CheckCase = false; CheckCase = false;
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];
@ -18281,6 +18373,7 @@ void InterCodeProcedure::Close(void)
BuildDataFlowSets(); BuildDataFlowSets();
DisassembleDebug("Followed Jumps 2"); DisassembleDebug("Followed Jumps 2");
CheckCase = true;
RebuildIntegerRangeSet(); RebuildIntegerRangeSet();