From d160b2ae65ebfb762e26ee59b631c4be0d937130 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 14 Oct 2023 16:51:33 +0200 Subject: [PATCH] Optimize bitfields --- autotest/bitfields.cpp | 107 +++++++++++++++++++++++++++++++++++++++ oscar64/InterCode.cpp | 111 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 209 insertions(+), 9 deletions(-) diff --git a/autotest/bitfields.cpp b/autotest/bitfields.cpp index 3e7cd44..9a4d4e9 100644 --- a/autotest/bitfields.cpp +++ b/autotest/bitfields.cpp @@ -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) { +#if 0 test_char_fit(); test_char_cross(); test_word_fit(); @@ -244,5 +344,12 @@ int main(void) test_char_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; } diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 1b1b5f0..a5204d7 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -7150,16 +7150,21 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray else if (ins->mSrc[1].mTemp < 0) { 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; - 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.mMaxState == IntegerValueRange::S_WEAK) + vr.mMinState = 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.mMinValue = ins->mSrc[1].mIntConst - maxv; @@ -9381,7 +9386,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra { 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()) return true; @@ -9404,7 +9409,7 @@ bool InterCodeBasicBlock::SimplifyIntegerNumeric(const GrowingInstructionPtrArra nins->mDst.mRange = ins->mDst.mRange; mInstructions.Insert(i + 1, nins); - ins->mOperator = IA_ADD; + ins->mOperator = ains->mOperator; ins->mSrc[0] = ains->mSrc[0]; ins->mSrc[0].mIntConst <<= nins->mSrc[0].mIntConst; ins->mSrc[1] = nins->mDst; @@ -15892,7 +15897,94 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 2]->mSrc[0].mIntConst = 0; 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 (i + 2 < mInstructions.Size() && mInstructions[i + 0]->mCode == IC_BINARY_OPERATOR && @@ -17925,7 +18017,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "ftoa"); + CheckFunc = !strcmp(mIdent->mString, "test_add_char_cross"); CheckCase = false; mEntryBlock = mBlocks[0]; @@ -18281,6 +18373,7 @@ void InterCodeProcedure::Close(void) BuildDataFlowSets(); DisassembleDebug("Followed Jumps 2"); + CheckCase = true; RebuildIntegerRangeSet();