More integer range optimizations
This commit is contained in:
parent
6eedb931a7
commit
9161b088ee
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
{
|
|
||||||
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 + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst);
|
void InterCodeBasicBlock::RestartLocalIntegerRangeSets(void)
|
||||||
mFalseValueRange[t].LimitMin(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mInstructions[sz - 2]->mOperator == IA_CMPGEU)
|
|
||||||
{
|
{
|
||||||
if (mInstructions[sz - 2]->mSrc[0].mTemp < 0)
|
int i;
|
||||||
|
|
||||||
|
if (!mVisited)
|
||||||
{
|
{
|
||||||
int t = mInstructions[sz - 2]->mSrc[1].mTemp;
|
mVisited = true;
|
||||||
// if (mTrueValueRange[t].mMinState == IntegerValueRange::S_BOUND && mTrueValueRange[t].mMinValue >= 0)
|
|
||||||
|
for (int i = 0; i < mEntryValueRange.Size(); i++)
|
||||||
{
|
{
|
||||||
mTrueValueRange[t].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst);
|
IntegerValueRange& vr(mEntryValueRange[i]);
|
||||||
|
if (vr.mMinState == IntegerValueRange::S_UNBOUND)
|
||||||
|
vr.mMinState = IntegerValueRange::S_UNKNOWN;
|
||||||
|
if (vr.mMaxState == IntegerValueRange::S_UNBOUND)
|
||||||
|
vr.mMaxState = IntegerValueRange::S_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
mFalseValueRange[t].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst - 1);
|
UpdateLocalIntegerRangeSets();
|
||||||
mFalseValueRange[t].LimitMin(0);
|
|
||||||
}
|
if (mTrueJump) mTrueJump->RestartLocalIntegerRangeSets();
|
||||||
}
|
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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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:"
|
||||||
|
|
Loading…
Reference in New Issue