Skip to content

Simd.js: Removing Float32x4 MinNum and MaxNum builtins. #1030

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 0 additions & 126 deletions lib/Backend/LowerMDSharedSimd128.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,10 +346,6 @@ IR::Instr* LowererMD::Simd128LowerUnMappedInstruction(IR::Instr *instr)
case Js::OpCode::Simd128_Max_F4:
return Simd128LowerMinMax_F4(instr);

case Js::OpCode::Simd128_MinNum_F4:
case Js::OpCode::Simd128_MaxNum_F4:
return Simd128LowerMinMaxNum(instr);

case Js::OpCode::Simd128_AnyTrue_B4:
case Js::OpCode::Simd128_AnyTrue_B8:
case Js::OpCode::Simd128_AnyTrue_B16:
Expand Down Expand Up @@ -2241,128 +2237,6 @@ IR::Instr* LowererMD::Simd128LowerMinMax_F4(IR::Instr* instr)

}


IR::Instr* LowererMD::Simd128LowerMinMaxNum(IR::Instr* instr)
{
IR::Instr *pInstr;
IR::Opnd* dst = instr->GetDst();
IR::Opnd* src1 = instr->GetSrc1();
IR::Opnd* src2 = instr->GetSrc2();
Assert(dst->IsRegOpnd() && dst->IsSimd128());
Assert(src1->IsRegOpnd() && src1->IsSimd128());
Assert(src2->IsRegOpnd() && src2->IsSimd128());
IR::RegOpnd* tmp1 = IR::RegOpnd::New(src1->GetType(), m_func);
IR::RegOpnd* tmp2 = IR::RegOpnd::New(src1->GetType(), m_func);
IR::RegOpnd* mask = IR::RegOpnd::New(src1->GetType(), m_func);
IR::RegOpnd* mask2 = IR::RegOpnd::New(src1->GetType(), m_func);

if (instr->m_opcode == Js::OpCode::Simd128_MinNum_F4)
{
// dst = MINPS src1, src2
// This is the correct result or b if either is NaN or both are +/-0.0
pInstr = IR::Instr::New(Js::OpCode::MINPS, dst, src1, src2, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// mask = CMPUNORD src2, src2
// Find NaNs in b
pInstr = IR::Instr::New(Js::OpCode::CMPUNORDPS, mask, src2, src2, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// mask2 = PCMPEQD src1, [X86_TWO_31_I4]
// Find -0.0 in a
pInstr = IR::Instr::New(Js::OpCode::PCMPEQD, mask2, src1, IR::MemRefOpnd::New((void*)&X86_TWO_31_I4, TySimd128I4, m_func), m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// mask2 = ANDPS mask2, [X86_TWO_31_I4]
// mask2 is -0.0 where a is -0.0
pInstr = IR::Instr::New(Js::OpCode::ANDPS, mask2, mask2, IR::MemRefOpnd::New((void*)&X86_TWO_31_I4, TySimd128I4, m_func), m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// dst = ORPS dst, mask2
// For lanes where a is -0.0, the result is either correct (negative), or b which is possibly +0.0
// Safe to force sign to negative for those lanes, +0.0 becomes -0.0.
pInstr = IR::Instr::New(Js::OpCode::ORPS, dst, dst, mask2, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// tmp1 = ANDPS src1, mask
// tmp2 = ANDNPS mask, dst
// dst = ORPS tmp1, tmp2
// For NaNs in b, choose a, else keep result.
pInstr = IR::Instr::New(Js::OpCode::ANDPS, tmp1, src1, mask, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

pInstr = IR::Instr::New(Js::OpCode::ANDNPS, tmp2, mask, dst, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

pInstr = IR::Instr::New(Js::OpCode::ORPS, dst, tmp1, tmp2, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);
}
else if (instr->m_opcode == Js::OpCode::Simd128_MaxNum_F4)
{
// dst = MAXPS src1, src2
// This is the correct result or b if either is NaN or both are +/-0.0
pInstr = IR::Instr::New(Js::OpCode::MAXPS, dst, src1, src2, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// Find NaNs in b
// mask = CMPUNORPS src2, src2
pInstr = IR::Instr::New(Js::OpCode::CMPUNORDPS, mask, src2, src2, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// mask2 = PCMPEQD src1, [X86_ALL_ZEROS]
// Find +0.0 in a
pInstr = IR::Instr::New(Js::OpCode::PCMPEQD, mask2, src1, IR::MemRefOpnd::New((void*)&X86_ALL_ZEROS, TySimd128I4, m_func), m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// mask2 = ANDPS mask2, [X86_TWO_31_I4]
// mask2 is -0.0 (sign mask) where a is +0.0
pInstr = IR::Instr::New(Js::OpCode::ANDPS, mask2, mask2, IR::MemRefOpnd::New((void*)&X86_TWO_31_I4, TySimd128I4, m_func), m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// dst = ANDNPS mask2, dst
// For lanes where a is +0.0, the result is either correct (positive), or b which is possibly -0.0
// Safe to force sign to positive for those lanes, +0.0 becomes -0.0.
pInstr = IR::Instr::New(Js::OpCode::ANDNPS, dst, mask2, dst, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

// tmp1 = ANDPS src1, mask
// tmp2 = ANDNPS mask, dst
// dst = ORPS tmp1, tmp2
// For NaNs in b, choose a, else keep result.
pInstr = IR::Instr::New(Js::OpCode::ANDPS, tmp1, src1, mask, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

pInstr = IR::Instr::New(Js::OpCode::ANDNPS, tmp2, mask, dst, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);

pInstr = IR::Instr::New(Js::OpCode::ORPS, dst, tmp1, tmp2, m_func);
instr->InsertBefore(pInstr);
Legalize(pInstr);
}
else
{
Assert(UNREACHED);
}
pInstr = instr->m_prev;
instr->Remove();
return pInstr;
}

IR::Instr* LowererMD::Simd128LowerAnyTrue(IR::Instr* instr)
{
Assert(instr->m_opcode == Js::OpCode::Simd128_AnyTrue_B4 || instr->m_opcode == Js::OpCode::Simd128_AnyTrue_B8 ||
Expand Down
2 changes: 0 additions & 2 deletions lib/Runtime/Base/JnDirectFields.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ ENTRY(equal)
ENTRY(notEqual)
ENTRY(greaterThanOrEqual)
ENTRY(greaterThan)
ENTRY(minNum)
ENTRY(maxNum)
ENTRY(shiftLeft)
ENTRY(shiftLeftByScalar)
ENTRY(shiftRightByScalar)
Expand Down
3 changes: 0 additions & 3 deletions lib/Runtime/ByteCode/OpCodesSimd.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,6 @@ MACRO_SIMD_EXTEND_WMS ( Simd128_FromUint16x8Bits_F4 , Float32x4_1Uin
MACRO_SIMD_EXTEND_WMS ( Simd128_FromInt8x16Bits_F4 , Float32x4_1Int8x16_1 , None , OpCanCSE , 0)
MACRO_SIMD_EXTEND_WMS ( Simd128_FromUint8x16Bits_F4 , Float32x4_1Uint8x16_1 , None , OpCanCSE , 0)

MACRO_SIMD_EXTEND_WMS ( Simd128_MinNum_F4 , Float32x4_3 , None , OpCanCSE , 0)
MACRO_SIMD_EXTEND_WMS ( Simd128_MaxNum_F4 , Float32x4_3 , None , OpCanCSE , 0)

MACRO_SIMD_EXTEND_WMS ( Simd128_LtEq_I4 , Bool32x4_1Int32x4_2 , None , None , 0)
MACRO_SIMD_EXTEND_WMS ( Simd128_GtEq_I4 , Bool32x4_1Int32x4_2 , None , None , 0)
MACRO_SIMD_EXTEND_WMS ( Simd128_Neq_I4 , Bool32x4_1Int32x4_2 , None , None , 0)
Expand Down
2 changes: 0 additions & 2 deletions lib/Runtime/Language/AsmJsBuiltInNames.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,6 @@ ASMJS_SIMD_O_NAMES(float32x4_mul, mul,
ASMJS_SIMD_O_NAMES(float32x4_div, div, Float32x4, Div )
ASMJS_SIMD_O_NAMES(float32x4_min, min, Float32x4, Min )
ASMJS_SIMD_O_NAMES(float32x4_max, max, Float32x4, Max )
ASMJS_SIMD_O_NAMES(float32x4_minNum, minNum, Float32x4, MinNum )
ASMJS_SIMD_O_NAMES(float32x4_maxNum, maxNum, Float32x4, MaxNum )
ASMJS_SIMD_O_NAMES(float32x4_reciprocal, reciprocalApproximation, Float32x4, Reciprocal )
ASMJS_SIMD_O_NAMES(float32x4_reciprocalSqrt, reciprocalSqrtApproximation, Float32x4, ReciprocalSqrt )
ASMJS_SIMD_O_NAMES(float32x4_sqrt, sqrt, Float32x4, Sqrt )
Expand Down
2 changes: 0 additions & 2 deletions lib/Runtime/Language/AsmJsModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1537,8 +1537,6 @@ namespace Js
simdFunctions[AsmJsSIMDBuiltin_float32x4_div] = SIMDFunc(PropertyIds::div, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_div, OpCodeAsmJs::Simd128_Div_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
simdFunctions[AsmJsSIMDBuiltin_float32x4_min] = SIMDFunc(PropertyIds::min, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_min, OpCodeAsmJs::Simd128_Min_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
simdFunctions[AsmJsSIMDBuiltin_float32x4_max] = SIMDFunc(PropertyIds::max, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_max, OpCodeAsmJs::Simd128_Max_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
simdFunctions[AsmJsSIMDBuiltin_float32x4_minNum] = SIMDFunc(PropertyIds::minNum, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_minNum, OpCodeAsmJs::Simd128_MinNum_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
simdFunctions[AsmJsSIMDBuiltin_float32x4_maxNum] = SIMDFunc(PropertyIds::maxNum, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 2, AsmJsSIMDBuiltin_float32x4_maxNum, OpCodeAsmJs::Simd128_MaxNum_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4, AsmJsType::Float32x4));
simdFunctions[AsmJsSIMDBuiltin_float32x4_reciprocal] = SIMDFunc(PropertyIds::reciprocalApproximation, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_reciprocal, OpCodeAsmJs::Simd128_Rcp_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
simdFunctions[AsmJsSIMDBuiltin_float32x4_reciprocalSqrt] = SIMDFunc(PropertyIds::reciprocalSqrtApproximation, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_reciprocalSqrt, OpCodeAsmJs::Simd128_RcpSqrt_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
simdFunctions[AsmJsSIMDBuiltin_float32x4_sqrt] = SIMDFunc(PropertyIds::sqrt, Anew(&mAllocator, AsmJsSIMDFunction, nullptr, &mAllocator, 1, AsmJsSIMDBuiltin_float32x4_sqrt, OpCodeAsmJs::Simd128_Sqrt_F4, AsmJsRetType::Float32x4, AsmJsType::Float32x4));
Expand Down
3 changes: 0 additions & 3 deletions lib/Runtime/Language/InterpreterHandlerAsmJs.inl
Original file line number Diff line number Diff line change
Expand Up @@ -377,9 +377,6 @@ EXDEF2 (NOPASMJS , NopEx , Empty
EXDEF3_WMS ( CUSTOM_ASMJS , Simd128_StArrConst_F4 , OP_SimdStArrConstIndex , AsmSimdTypedArr )
EXDEF3_WMS ( CUSTOM_ASMJS , Simd128_StArrConst_I4 , OP_SimdStArrConstIndex , AsmSimdTypedArr )

EXDEF2_WMS ( SIMD_F4_2toF4_1 , Simd128_MinNum_F4 , Js::SIMDFloat32x4Operation::OpMinNum )
EXDEF2_WMS ( SIMD_F4_2toF4_1 , Simd128_MaxNum_F4 , Js::SIMDFloat32x4Operation::OpMaxNum )

EXDEF2_WMS ( SIMD_U4_1toF4_1 , Simd128_FromUint32x4_F4 , Js::SIMDFloat32x4Operation::OpFromUint32x4 )
EXDEF2_WMS ( SIMD_I8_1toF4_1 , Simd128_FromInt16x8Bits_F4 , Js::SIMDUtils::FromSimdBits )
EXDEF2_WMS ( SIMD_I16_1toF4_1 , Simd128_FromInt8x16Bits_F4 , Js::SIMDUtils::FromSimdBits )
Expand Down
43 changes: 0 additions & 43 deletions lib/Runtime/Language/SimdFloat32x4Operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,6 @@ namespace Js
Min/Max(a, b) spec semantics:
If any value is NaN, return NaN
a < b ? a : b; where +0.0 > -0.0 (vice versa for Max)

MinNum/MaxNum(a, b) spec semantics:
If 1st value is NaN, return 2nd
If 2nd value is NaN, return 1st
return Min/Max(a, b)
*/
SIMDValue SIMDFloat32x4Operation::OpMin(const SIMDValue& aValue, const SIMDValue& bValue)
{
Expand Down Expand Up @@ -283,44 +278,6 @@ namespace Js
return result;
}

SIMDValue SIMDFloat32x4Operation::OpMinNum(const SIMDValue& aValue, const SIMDValue& bValue)
{
SIMDValue result = OpMin(aValue, bValue);
for (uint i = 0; i < 4; i++)
{
float a = aValue.f32[i];
float b = bValue.f32[i];
if (Js::NumberUtilities::IsNan(a))
{
result.f32[i] = b;
}
else if (Js::NumberUtilities::IsNan(b))
{
result.f32[i] = a;
}
}
return result;
}

SIMDValue SIMDFloat32x4Operation::OpMaxNum(const SIMDValue& aValue, const SIMDValue& bValue)
{
SIMDValue result = OpMax(aValue, bValue);
for (uint i = 0; i < 4; i++)
{
float a = aValue.f32[i];
float b = bValue.f32[i];
if (Js::NumberUtilities::IsNan(a))
{
result.f32[i] = b;
}
else if (Js::NumberUtilities::IsNan(b))
{
result.f32[i] = a;
}
}
return result;
}

SIMDValue SIMDFloat32x4Operation::OpScale(const SIMDValue& Value, float scaleValue)
{
SIMDValue result;
Expand Down
4 changes: 0 additions & 4 deletions lib/Runtime/Language/SimdFloat32x4Operation.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ namespace Js {
static SIMDValue OpXor(const SIMDValue& aValue, const SIMDValue& bValue);
static SIMDValue OpMin(const SIMDValue& aValue, const SIMDValue& bValue);
static SIMDValue OpMax(const SIMDValue& aValue, const SIMDValue& bValue);
static SIMDValue OpMinNum(const SIMDValue& aValue, const SIMDValue& bValue);
static SIMDValue OpMaxNum(const SIMDValue& aValue, const SIMDValue& bValue);


static SIMDValue OpScale(const SIMDValue& Value, float scaleValue);

static SIMDValue OpLessThan(const SIMDValue& aValue, const SIMDValue& bValue);
Expand Down
58 changes: 0 additions & 58 deletions lib/Runtime/Language/SimdFloat32x4OperationX86X64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,6 @@ namespace Js
If any value is NaN, return NaN
a < b ? a : b; where +0.0 > -0.0 (vice versa for Max)

MinNum/MaxNum(a, b) spec semantics:
If 1st value is NaN, return 2nd
If 2nd value is NaN, return 1st
return Min/Max(a, b)

X86 MIN/MAXPS semantics:
If any value is NaN, return 2nd operand
If both values are +/-0.0, return 2nd operand
Expand Down Expand Up @@ -273,59 +268,6 @@ namespace Js
return X86SIMDValue::ToSIMDValue(x86Result);
}


SIMDValue SIMDFloat32x4Operation::OpMinNum(const SIMDValue& aValue, const SIMDValue& bValue)
{
X86SIMDValue x86Result;
X86SIMDValue tmpaValue = X86SIMDValue::ToX86SIMDValue(aValue);
X86SIMDValue tmpbValue = X86SIMDValue::ToX86SIMDValue(bValue);
X86SIMDValue mask, mask2, t1, t2;

// This is the correct result or b if either is NaN or both are +/-0.0
x86Result.m128_value = _mm_min_ps(tmpaValue.m128_value, tmpbValue.m128_value);
// Find NaNs in b
mask.m128_value = _mm_cmpunord_ps(tmpbValue.m128_value, tmpbValue.m128_value);
// Find -0.0 in a
mask2.m128i_value = _mm_cmpeq_epi32(tmpaValue.m128i_value, X86_TWO_31_I4.m128i_value);
// mask2 is -0.0 where a is -0.0
mask2.m128_value = _mm_and_ps(mask2.m128_value, X86_TWO_31_I4.m128_value);
// For lanes where a is -0.0, the result is either correct (negative), or b which is possibly +0.0
// Safe to force sign to negative for those lanes, +0.0 becomes -0.0.
x86Result.m128_value = _mm_or_ps(x86Result.m128_value, mask2.m128_value);
// For NaNs in b, choose a, else keep result.
t1.m128_value = _mm_and_ps(tmpaValue.m128_value, mask.m128_value);
t2.m128_value = _mm_andnot_ps(mask.m128_value, x86Result.m128_value);
x86Result.m128_value = _mm_or_ps(t1.m128_value, t2.m128_value);

return X86SIMDValue::ToSIMDValue(x86Result);
}

SIMDValue SIMDFloat32x4Operation::OpMaxNum(const SIMDValue& aValue, const SIMDValue& bValue)
{
X86SIMDValue x86Result;
X86SIMDValue tmpaValue = X86SIMDValue::ToX86SIMDValue(aValue);
X86SIMDValue tmpbValue = X86SIMDValue::ToX86SIMDValue(bValue);
X86SIMDValue mask, mask2, t1, t2;

// This is the correct result or b if either is NaN or both are +/-0.0
x86Result.m128_value = _mm_max_ps(tmpaValue.m128_value, tmpbValue.m128_value);
// Find NaNs in b
mask.m128_value = _mm_cmpunord_ps(tmpbValue.m128_value, tmpbValue.m128_value);
// Find +0.0 in a
mask2.m128i_value = _mm_cmpeq_epi32(tmpaValue.m128i_value, X86_ALL_ZEROS.m128i_value);
// mask2 is -0.0 where a is +0.0
mask2.m128_value = _mm_and_ps(mask2.m128_value, X86_TWO_31_I4.m128_value);
// For lanes where a is +0.0, the result is either correct (positive), or b which is possibly -0.0
// Safe to force sign to positive for those lanes, +0.0 becomes -0.0.
x86Result.m128_value = _mm_andnot_ps(mask2.m128_value, x86Result.m128_value);
// For NaNs in b, choose a, else keep result.
t1.m128_value = _mm_and_ps(tmpaValue.m128_value, mask.m128_value);
t2.m128_value = _mm_andnot_ps(mask.m128_value, x86Result.m128_value);
x86Result.m128_value = _mm_or_ps(t1.m128_value, t2.m128_value);

return X86SIMDValue::ToSIMDValue(x86Result);
}

SIMDValue SIMDFloat32x4Operation::OpScale(const SIMDValue& Value, float scaleValue)
{
X86SIMDValue x86Result;
Expand Down
Loading