More integer range optimizations

This commit is contained in:
drmortalwombat 2022-01-16 18:30:38 +01:00
parent 6eedb931a7
commit 9161b088ee
8 changed files with 568 additions and 102 deletions

View File

@ -23,7 +23,7 @@ The goal is to implement the actual C standard and not some subset for performan
## Limits and Errors ## Limits and Errors
There are still several open areas, but most targets have been reached. The current Dhrystone performance is 61 iterations per second with byte code (11504) and 278 iterations with native code (12184 Bytes). There are still several open areas, but most targets have been reached. The current Dhrystone performance is 68 iterations per second with byte code (11266) and 295 iterations with native code (11784 Bytes).
### Language ### Language
@ -119,7 +119,6 @@ A section of the file can be selected by providing a limit and or an offset into
The compiler can be provided with additional information using the built in function __assume(cond). This can be useful to mark unreachable code using __assume(false) for e.g. the default of a switch statement. Another good option is to limit the value range of arguments to allow the compiler using byte operations without the need for integer promotion. The compiler can be provided with additional information using the built in function __assume(cond). This can be useful to mark unreachable code using __assume(false) for e.g. the default of a switch statement. Another good option is to limit the value range of arguments to allow the compiler using byte operations without the need for integer promotion.
## Inline Assembler ## Inline Assembler
Inline assembler can be embedded inside of any functions, regardles of their compilation target of byte code or native. Inline assembler can be embedded inside of any functions, regardles of their compilation target of byte code or native.

View File

@ -60,6 +60,9 @@ rem @echo off
@call :test testinterval.c @call :test testinterval.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test cmprangeshortcuttest.c
@if %errorlevel% neq 0 goto :error
@call :test floatstringtest.c @call :test floatstringtest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error

View File

@ -0,0 +1,298 @@
#include <assert.h>
void check_s_lt(void)
{
int a5 = 0, a10 = 0, a15 = 0;
for(int i=5; i<15; i++)
{
if (i < 5)
a5++;
if (i < 10)
a10++;
if (i < 15)
a15++;
}
assert(a5 == 0);
assert(a10 == 5);
assert(a15 == 10);
}
void check_s_le(void)
{
int a4 = 0, a5 = 0, a10 = 0, a14 = 0, a15 = 0;
for(int i=5; i<15; i++)
{
if (i <= 4)
a4++;
if (i <= 5)
a5++;
if (i <= 10)
a10++;
if (i <= 14)
a14++;
if (i <= 15)
a15++;
}
assert(a4 == 0);
assert(a5 == 1);
assert(a10 == 6);
assert(a14 == 10);
assert(a15 == 10);
}
void check_s_ge(void)
{
int a5 = 0, a10 = 0, a15 = 0;
for(int i=5; i<15; i++)
{
if (i >= 5)
a5++;
if (i >= 10)
a10++;
if (i >= 15)
a15++;
}
assert(a5 == 10);
assert(a10 == 5);
assert(a15 == 0);
}
void check_s_gt(void)
{
int a4 = 0, a5 = 0, a10 = 0, a14 = 0, a15 = 0;
for(int i=5; i<15; i++)
{
if (i > 4)
a4++;
if (i > 5)
a5++;
if (i > 10)
a10++;
if (i > 14)
a14++;
if (i > 15)
a15++;
}
assert(a4 == 10);
assert(a5 == 9);
assert(a10 == 4);
assert(a14 == 0);
assert(a15 == 0);
}
void check_s_eq(void)
{
int a4 = 0, a5 = 0, a10 = 0, a14 = 0, a15 = 0;
for(int i=5; i<15; i++)
{
if (i == 4)
a4++;
if (i == 5)
a5++;
if (i == 10)
a10++;
if (i == 14)
a14++;
if (i == 15)
a15++;
}
assert(a4 == 0);
assert(a5 == 1);
assert(a10 == 1);
assert(a14 == 1);
assert(a15 == 0);
}
void check_s_ne(void)
{
int a4 = 0, a5 = 0, a10 = 0, a14 = 0, a15 = 0;
for(int i=5; i<15; i++)
{
if (i != 4)
a4++;
if (i != 5)
a5++;
if (i != 10)
a10++;
if (i != 14)
a14++;
if (i != 15)
a15++;
}
assert(a4 == 10);
assert(a5 == 9);
assert(a10 == 9);
assert(a14 == 9);
assert(a15 == 10);
}
void check_u_lt(void)
{
int a5 = 0, a10 = 0, a15 = 0;
for(unsigned i=5; i<15; i++)
{
if (i < 5)
a5++;
if (i < 10)
a10++;
if (i < 15)
a15++;
}
assert(a5 == 0);
assert(a10 == 5);
assert(a15 == 10);
}
void check_u_le(void)
{
int a4 = 0, a5 = 0, a10 = 0, a14 = 0, a15 = 0;
for(unsigned i=5; i<15; i++)
{
if (i <= 4)
a4++;
if (i <= 5)
a5++;
if (i <= 10)
a10++;
if (i <= 14)
a14++;
if (i <= 15)
a15++;
}
assert(a4 == 0);
assert(a5 == 1);
assert(a10 == 6);
assert(a14 == 10);
assert(a15 == 10);
}
void check_u_ge(void)
{
int a5 = 0, a10 = 0, a15 = 0;
for(unsigned i=5; i<15; i++)
{
if (i >= 5)
a5++;
if (i >= 10)
a10++;
if (i >= 15)
a15++;
}
assert(a5 == 10);
assert(a10 == 5);
assert(a15 == 0);
}
void check_u_gt(void)
{
int a4 = 0, a5 = 0, a10 = 0, a14 = 0, a15 = 0;
for(unsigned i=5; i<15; i++)
{
if (i > 4)
a4++;
if (i > 5)
a5++;
if (i > 10)
a10++;
if (i > 14)
a14++;
if (i > 15)
a15++;
}
assert(a4 == 10);
assert(a5 == 9);
assert(a10 == 4);
assert(a14 == 0);
assert(a15 == 0);
}
void check_u_eq(void)
{
int a4 = 0, a5 = 0, a10 = 0, a14 = 0, a15 = 0;
for(unsigned i=5; i<15; i++)
{
if (i == 4)
a4++;
if (i == 5)
a5++;
if (i == 10)
a10++;
if (i == 14)
a14++;
if (i == 15)
a15++;
}
assert(a4 == 0);
assert(a5 == 1);
assert(a10 == 1);
assert(a14 == 1);
assert(a15 == 0);
}
void check_u_ne(void)
{
int a4 = 0, a5 = 0, a10 = 0, a14 = 0, a15 = 0;
for(unsigned i=5; i<15; i++)
{
if (i != 4)
a4++;
if (i != 5)
a5++;
if (i != 10)
a10++;
if (i != 14)
a14++;
if (i != 15)
a15++;
}
assert(a4 == 10);
assert(a5 == 9);
assert(a10 == 9);
assert(a14 == 9);
assert(a15 == 10);
}
int main(void)
{
check_s_ne();
check_s_eq();
check_s_lt();
check_s_le();
check_s_gt();
check_s_ge();
check_u_ne();
check_u_eq();
check_u_lt();
check_u_le();
check_u_gt();
check_u_ge();
return 0;
}

View File

@ -2409,6 +2409,44 @@ bool InterInstruction::ConstantFolding(void)
mNumOperands = 0; mNumOperands = 0;
return true; return true;
} }
#if 1
else if (mSrc[0].mTemp < 0)
{
if (mDst.mType == IT_FLOAT)
{
}
else if (IsIntegerType(mDst.mType))
{
if ((mOperator == IA_ADD || mOperator == IA_SUB || mOperator == IA_OR || mOperator == IA_XOR || mOperator == IA_SHL || mOperator == IA_SHR || mOperator == IA_SAR) && mSrc[0].mIntConst == 0 ||
(mOperator == IA_MUL || mOperator == IA_DIVS || mOperator == IA_DIVU) && mSrc[0].mIntConst == 1)
{
mCode = IC_LOAD_TEMPORARY;
mSrc[0] = mSrc[1];
mSrc[1].mTemp = -1;
mNumOperands = 1;
return true;
}
}
}
else if (mSrc[1].mTemp < 0)
{
if (mDst.mType == IT_FLOAT)
{
}
else if (IsIntegerType(mDst.mType))
{
if ((mOperator == IA_ADD || mOperator == IA_OR || mOperator == IA_XOR) && mSrc[1].mIntConst == 0 || (mOperator == IA_MUL) && mSrc[1].mIntConst == 1)
{
mCode = IC_LOAD_TEMPORARY;
mSrc[1].mTemp = -1;
mNumOperands = 1;
return true;
}
}
}
#endif
break; break;
case IC_UNARY_OPERATOR: case IC_UNARY_OPERATOR:
if (mSrc[0].mTemp < 0) if (mSrc[0].mTemp < 0)
@ -3472,32 +3510,134 @@ void InterCodeBasicBlock::SimplifyIntegerRangeRelops(void)
int sz = mInstructions.Size(); int sz = mInstructions.Size();
if (sz >= 2 && mInstructions[sz - 1]->mCode == IC_BRANCH && mInstructions[sz - 2]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[sz - 2]->mDst.mTemp == mInstructions[sz - 1]->mSrc[0].mTemp) if (sz >= 2 && mInstructions[sz - 1]->mCode == IC_BRANCH && mInstructions[sz - 2]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[sz - 2]->mDst.mTemp == mInstructions[sz - 1]->mSrc[0].mTemp)
{ {
if (mInstructions[sz - 2]->mOperator == IA_CMPLS) InterInstruction* cins = mInstructions[sz - 2];
bool constFalse = false, constTrue = false;
if (cins->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND && cins->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND &&
cins->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND && cins->mSrc[0].mRange.mMinState == IntegerValueRange::S_BOUND)
{ {
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) switch (cins->mOperator)
{ {
if (mInstructions[sz - 2]->mSrc[1].IsUnsigned()) case IA_CMPEQ:
mInstructions[sz - 2]->mOperator = IA_CMPLU; if (cins->mSrc[1].mRange.mMaxValue < cins->mSrc[0].mRange.mMinValue || cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue)
constFalse = true;
break;
case IA_CMPNE:
if (cins->mSrc[1].mRange.mMaxValue < cins->mSrc[0].mRange.mMinValue || cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue)
constTrue = true;
break;
case IA_CMPLS:
if (cins->mSrc[1].mRange.mMaxValue < cins->mSrc[0].mRange.mMinValue)
constTrue = true;
else if (cins->mSrc[1].mRange.mMinValue >= cins->mSrc[0].mRange.mMaxValue)
constFalse = true;
break;
case IA_CMPLU:
if (cins->mSrc[1].IsUnsigned() && cins->mSrc[0].IsUnsigned())
{
if (cins->mSrc[1].mRange.mMaxValue < cins->mSrc[0].mRange.mMinValue)
constTrue = true;
else if (cins->mSrc[1].mRange.mMinValue >= cins->mSrc[0].mRange.mMaxValue)
constFalse = true;
} }
else if (mInstructions[sz - 2]->mSrc[0].IsUnsigned() && mInstructions[sz - 2]->mSrc[1].IsUnsigned()) break;
case IA_CMPLES:
if (cins->mSrc[1].mRange.mMaxValue <= cins->mSrc[0].mRange.mMinValue)
constTrue = true;
else if (cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue)
constFalse = true;
break;
case IA_CMPLEU:
if (cins->mSrc[1].IsUnsigned() && cins->mSrc[0].IsUnsigned())
{ {
mInstructions[sz - 2]->mOperator = IA_CMPLU; if (cins->mSrc[1].mRange.mMaxValue <= cins->mSrc[0].mRange.mMinValue)
constTrue = true;
else if (cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue)
constFalse = true;
}
break;
case IA_CMPGS:
if (cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue)
constTrue = true;
else if (cins->mSrc[1].mRange.mMaxValue <= cins->mSrc[0].mRange.mMinValue)
constFalse = true;
break;
case IA_CMPGU:
if (cins->mSrc[1].IsUnsigned() && cins->mSrc[0].IsUnsigned())
{
if (cins->mSrc[1].mRange.mMinValue > cins->mSrc[0].mRange.mMaxValue)
constTrue = true;
else if (cins->mSrc[1].mRange.mMaxValue <= cins->mSrc[0].mRange.mMinValue)
constFalse = true;
}
break;
case IA_CMPGES:
if (cins->mSrc[1].mRange.mMinValue >= cins->mSrc[0].mRange.mMaxValue)
constTrue = true;
else if (cins->mSrc[1].mRange.mMaxValue < cins->mSrc[0].mRange.mMinValue)
constFalse = true;
break;
case IA_CMPGEU:
if (cins->mSrc[1].IsUnsigned() && cins->mSrc[0].IsUnsigned())
{
if (cins->mSrc[1].mRange.mMinValue >= cins->mSrc[0].mRange.mMaxValue)
constTrue = true;
else if (cins->mSrc[1].mRange.mMaxValue < cins->mSrc[0].mRange.mMinValue)
constFalse = true;
}
break;
} }
} }
else if (mInstructions[sz - 2]->mOperator == IA_CMPLES)
if (constTrue || constFalse)
{ {
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) cins->mCode = IC_CONSTANT;
{ cins->mConst.mType = IT_BOOL;
if (mInstructions[sz - 2]->mSrc[1].IsUnsigned()) cins->mConst.mIntConst = constTrue ? 1 : 0;
mInstructions[sz - 2]->mOperator = IA_CMPLEU; cins->mNumOperands = 0;
} }
else if (mInstructions[sz - 2]->mSrc[0].IsUnsigned() && mInstructions[sz - 2]->mSrc[1].IsUnsigned()) else
{ {
mInstructions[sz - 2]->mOperator = IA_CMPLEU; switch (cins->mOperator)
{
case IA_CMPLS:
if (cins->mSrc[0].IsUnsigned() && cins->mSrc[1].IsUnsigned())
cins->mOperator = IA_CMPLU;
break;
case IA_CMPLES:
if (cins->mSrc[0].IsUnsigned() && cins->mSrc[1].IsUnsigned())
cins->mOperator = IA_CMPLEU;
break;
} }
} }
} }
#endif #endif
if (sz >= 2 && mInstructions[sz - 1]->mCode == IC_BRANCH && mInstructions[sz - 2]->mCode == IC_CONSTANT && mInstructions[sz - 2]->mDst.mTemp == mInstructions[sz - 1]->mSrc[0].mTemp)
{
InterInstruction* bins = mInstructions[sz - 1];
if (mInstructions[sz - 2]->mConst.mIntConst)
{
mFalseJump->mNumEntries--;
mFalseJump = nullptr;
bins->mCode = IC_JUMP;
bins->mSrc[0].mTemp = -1;
bins->mNumOperands = 0;
}
else
{
mTrueJump->mNumEntries--;
mTrueJump = mFalseJump;
mFalseJump = nullptr;
bins->mCode = IC_JUMP;
bins->mSrc[0].mTemp = -1;
bins->mNumOperands = 0;
}
}
#if 1 #if 1
for (int i = 0; i < sz; i++) for (int i = 0; i < sz; i++)
{ {
@ -4099,11 +4239,12 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
if (sz >= 2) 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 - 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)
{ {
int s1 = mInstructions[sz - 2]->mSrc[1].mTemp, s0 = mInstructions[sz - 2]->mSrc[0].mTemp; int s1 = mInstructions[sz - 2]->mSrc[1].mTemp, s0 = mInstructions[sz - 2]->mSrc[0].mTemp;
switch (mInstructions[sz - 2]->mOperator)
{
case IA_CMPLS:
if (s0 < 0) if (s0 < 0)
{ {
mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
@ -4125,104 +4266,108 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(void)
if (mLocalValueRange[s0].mMinState == IntegerValueRange::S_BOUND) if (mLocalValueRange[s0].mMinState == IntegerValueRange::S_BOUND)
mFalseValueRange[s1].LimitMin(mLocalValueRange[s0].mMinValue); mFalseValueRange[s1].LimitMin(mLocalValueRange[s0].mMinValue);
} }
break;
case IA_CMPLES:
if (s0 < 0)
{
mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
} }
else if (mInstructions[sz - 2]->mOperator == IA_CMPLES) break;
case IA_CMPGS:
if (s0 < 0)
{ {
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) mTrueValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
{ mFalseValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
} }
break;
case IA_CMPGES:
if (s0 < 0)
{
mTrueValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
} }
else if (mInstructions[sz - 2]->mOperator == IA_CMPGS) break;
{
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
}
}
else if (mInstructions[sz - 2]->mOperator == IA_CMPGES)
{
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
}
}
else if (mInstructions[sz - 2]->mOperator == IA_CMPLU)
{
if (mInstructions[sz - 2]->mSrc[1].mTemp >= 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
mTrueValueRange[t].LimitMin(0);
if (mFalseValueRange[t].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[t].mMinValue >= 0) case IA_CMPLU:
if (s1 >= 0)
{ {
mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst); if (s0 < 0)
{
mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
mTrueValueRange[s1].LimitMin(0);
if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0)
{
mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
} }
} }
else if (mInstructions[sz - 2]->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND) else if (mInstructions[sz - 2]->mSrc[0].mRange.mMaxState == IntegerValueRange::S_BOUND)
{ {
mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue - 1); mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue - 1);
mTrueValueRange[t].LimitMin(0); mTrueValueRange[s1].LimitMin(0);
if (mFalseValueRange[t].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[t].mMinValue >= 0) if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0)
{ {
mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue); mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mRange.mMaxValue);
} }
} }
} }
} break;
else if (mInstructions[sz - 2]->mOperator == IA_CMPLEU) case IA_CMPLEU:
if (s0 < 0)
{ {
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
{ mTrueValueRange[s1].LimitMin(0);
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
mTrueValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
mTrueValueRange[t].LimitMin(0);
if (mFalseValueRange[t].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[t].mMinValue >= 0) if (mFalseValueRange[s1].mMinState == IntegerValueRange::S_BOUND && mFalseValueRange[s1].mMinValue >= 0)
{ {
mFalseValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1); mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
}
}
break;
case IA_CMPGU:
if (s0 < 0)
{
mTrueValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1);
mFalseValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[s1].LimitMin(0);
}
break;
case IA_CMPGEU:
if (s0 < 0)
{
mTrueValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
mFalseValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
mFalseValueRange[s1].LimitMin(0);
}
break;
} }
} }
} }
else if (mInstructions[sz - 2]->mOperator == IA_CMPGU) }
void InterCodeBasicBlock::RestartLocalIntegerRangeSets(void)
{
int i;
if (!mVisited)
{ {
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0) mVisited = true;
for (int i = 0; i < mEntryValueRange.Size(); i++)
{ {
int t = mInstructions[sz - 2]->mSrc[1].mTemp; IntegerValueRange& vr(mEntryValueRange[i]);
// if (mTrueValueRange[t].mMinState == IntegerValueRange::S_BOUND && mTrueValueRange[t].mMinValue >= 0) if (vr.mMinState == IntegerValueRange::S_UNBOUND)
{ vr.mMinState = IntegerValueRange::S_UNKNOWN;
mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1); if (vr.mMaxState == IntegerValueRange::S_UNBOUND)
vr.mMaxState = IntegerValueRange::S_UNKNOWN;
} }
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst); UpdateLocalIntegerRangeSets();
mFalseValueRange[t].LimitMin(0);
}
}
else if (mInstructions[sz - 2]->mOperator == IA_CMPGEU)
{
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
{
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
// if (mTrueValueRange[t].mMinState == IntegerValueRange::S_BOUND && mTrueValueRange[t].mMinValue >= 0)
{
mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
}
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1); if (mTrueJump) mTrueJump->RestartLocalIntegerRangeSets();
mFalseValueRange[t].LimitMin(0); if (mFalseJump) mFalseJump->RestartLocalIntegerRangeSets();
}
}
}
} }
} }
@ -6127,6 +6272,9 @@ InterCodeBasicBlock* InterCodeBasicBlock::PropagateDominator(InterCodeProcedure*
{ {
mDominator = new InterCodeBasicBlock(); mDominator = new InterCodeBasicBlock();
proc->Append(mDominator); proc->Append(mDominator);
InterInstruction * jins = new InterInstruction();
jins->mCode = IC_JUMP;
mDominator->Append(jins);
mDominator->Close(this, nullptr); mDominator->Close(this, nullptr);
} }
} }
@ -6425,7 +6573,7 @@ void InterCodeBasicBlock::InnerLoopOptimization(const NumberSet& aliasedParams)
InterInstruction* ins = block->mInstructions[i]; InterInstruction* ins = block->mInstructions[i];
if (ins->mInvariant && ins->mExpensive) if (ins->mInvariant && ins->mExpensive)
{ {
mDominator->mInstructions.Push(ins); mDominator->mInstructions.Insert(mDominator->mInstructions.Size() - 1, ins);
} }
else else
{ {
@ -6583,7 +6731,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
InterInstruction* ins = mInstructions[i]; InterInstruction* ins = mInstructions[i];
if (ins->mInvariant) if (ins->mInvariant)
{ {
mDominator->mInstructions.Push(ins); mDominator->mInstructions.Insert(mDominator->mInstructions.Size() - 1, ins);
} }
else else
{ {
@ -7733,12 +7881,25 @@ void InterCodeProcedure::Close(void)
} while (mEntryBlock->BuildGlobalIntegerRangeSets()); } while (mEntryBlock->BuildGlobalIntegerRangeSets());
DisassembleDebug("Estimated value range"); DisassembleDebug("Estimated value range");
#if 1
ResetVisited();
mEntryBlock->RestartLocalIntegerRangeSets();
do {
DisassembleDebug("tr");
ResetVisited();
} while (mEntryBlock->BuildGlobalIntegerRangeSets());
DisassembleDebug("Estimated value range 2");
#endif
ResetVisited(); ResetVisited();
mEntryBlock->SimplifyIntegerRangeRelops(); mEntryBlock->SimplifyIntegerRangeRelops();
DisassembleDebug("Simplified range limited relational ops"); DisassembleDebug("Simplified range limited relational ops");
#endif #endif
#if 1 #if 1
ResetVisited(); ResetVisited();
mEntryBlock->DropUnreachable(); mEntryBlock->DropUnreachable();
@ -7752,6 +7913,9 @@ void InterCodeProcedure::Close(void)
RemoveUnusedInstructions(); RemoveUnusedInstructions();
DisassembleDebug("Removed unreachable branches"); DisassembleDebug("Removed unreachable branches");
BuildTraces(false);
#endif #endif
MapVariables(); MapVariables();

View File

@ -395,6 +395,7 @@ public:
void SimpleLocalToTemp(int vindex, int temp); void SimpleLocalToTemp(int vindex, int temp);
bool ConstantFolding(void); bool ConstantFolding(void);
bool ConstantFoldingRelationRange(void);
void Disassemble(FILE* file); void Disassemble(FILE* file);
}; };
@ -511,6 +512,7 @@ public:
bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars); bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars);
bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars); bool RemoveUnusedStaticStoreInstructions(const GrowingVariableArray& staticVars);
void RestartLocalIntegerRangeSets(void);
void BuildLocalIntegerRangeSets(int num); void BuildLocalIntegerRangeSets(int num);
void UpdateLocalIntegerRangeSets(void); void UpdateLocalIntegerRangeSets(void);
bool BuildGlobalIntegerRangeSets(void); bool BuildGlobalIntegerRangeSets(void);

View File

@ -73,7 +73,7 @@ int main(int argc, const char** argv)
#else #else
strcpy(strProductName, "oscar64"); strcpy(strProductName, "oscar64");
strcpy(strProductVersion, "1.2.61"); strcpy(strProductVersion, "1.2.62");
#ifdef __APPLE__ #ifdef __APPLE__
uint32_t length = sizeof(basePath); uint32_t length = sizeof(basePath);

View File

@ -25,8 +25,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,61,0 FILEVERSION 1,2,62,0
PRODUCTVERSION 1,2,61,0 PRODUCTVERSION 1,2,62,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -43,12 +43,12 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "oscar64" VALUE "CompanyName", "oscar64"
VALUE "FileDescription", "oscar64 compiler" VALUE "FileDescription", "oscar64 compiler"
VALUE "FileVersion", "1.2.61.0" VALUE "FileVersion", "1.2.62.0"
VALUE "InternalName", "oscar64.exe" VALUE "InternalName", "oscar64.exe"
VALUE "LegalCopyright", "Copyright (C) 2021" VALUE "LegalCopyright", "Copyright (C) 2021"
VALUE "OriginalFilename", "oscar64.exe" VALUE "OriginalFilename", "oscar64.exe"
VALUE "ProductName", "oscar64" VALUE "ProductName", "oscar64"
VALUE "ProductVersion", "1.2.61.0" VALUE "ProductVersion", "1.2.62.0"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -2987,15 +2987,15 @@
{ {
"Name" = "8:Microsoft Visual Studio" "Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:oscar64" "ProductName" = "8:oscar64"
"ProductCode" = "8:{FDB14C01-E512-47D7-AB10-6431DB1DC40B}" "ProductCode" = "8:{B0D25385-A6F7-4134-8C6B-8CEFA1F244B1}"
"PackageCode" = "8:{8C16AAEE-9A02-4BA9-9DD9-BD5606D870F6}" "PackageCode" = "8:{00172C8A-7F93-49AC-B3A4-A451DD1544E4}"
"UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}" "UpgradeCode" = "8:{9AB61EFF-ACAC-4079-9950-8D96615CD4EF}"
"AspNetVersion" = "8:2.0.50727.0" "AspNetVersion" = "8:2.0.50727.0"
"RestartWWWService" = "11:FALSE" "RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE" "RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE" "DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE" "InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:1.2.61" "ProductVersion" = "8:1.2.62"
"Manufacturer" = "8:oscar64" "Manufacturer" = "8:oscar64"
"ARPHELPTELEPHONE" = "8:" "ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:" "ARPHELPLINK" = "8:"