Bug 1113445 - SpiderMonkey: Handle -0 properly in SIMD.float32x4.signMask r=bbouvier,waldo

This commit is contained in:
Dan Gohman 2014-12-23 13:52:49 -08:00
parent e6a7e193e7
commit d25afeab4b
4 changed files with 51 additions and 7 deletions

View File

@ -13,6 +13,7 @@
#include "builtin/SIMD.h"
#include "mozilla/IntegerTypeTraits.h"
#include "jsapi.h"
#include "jsfriendapi.h"
@ -147,12 +148,17 @@ static bool SignMask(JSContext *cx, unsigned argc, Value *vp)
return false;
}
Elem *data = reinterpret_cast<Elem *>(typedObj.typedMem());
int32_t mx = data[0] < 0.0 ? 1 : 0;
int32_t my = data[1] < 0.0 ? 1 : 0;
int32_t mz = data[2] < 0.0 ? 1 : 0;
int32_t mw = data[3] < 0.0 ? 1 : 0;
int32_t result = mx | my << 1 | mz << 2 | mw << 3;
// Load the data as integer so that we treat the sign bit consistently,
// since -0.0 is not less than zero, but it still has the sign bit set.
typedef typename mozilla::SignedStdintTypeForSize<sizeof(Elem)>::Type Int;
static_assert(SimdType::lanes * sizeof(Int) <= jit::Simd128DataSize,
"signMask access should respect the bounds of the type");
const Elem *elems = reinterpret_cast<const Elem *>(typedObj.typedMem());
int32_t result = 0;
for (unsigned i = 0; i < SimdType::lanes; ++i) {
Int x = mozilla::BitwiseCast<Int>(elems[i]);
result |= (x < 0) << i;
}
args.rval().setInt32(result);
return true;
}

View File

@ -188,7 +188,7 @@ assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f() { var x=i4(0,-
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(f32(1), f32(-13.37), f32(42), f32(-Infinity)); return x.signMask | 0 } return f'), this)(), 0b1010);
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var Infinity = glob.Infinity; function f() { var x=f4(0,0,0,0); x=f4(f32(-1), f32(0), f32(-0.000001), f32(Infinity)); return x.signMask | 0 } return f'), this)(), 0b0101);
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var NaN = glob.NaN; function f() { var x=f4(0,0,0,0); x=f4(f32(-1), f32(NaN), f32(3.), f32(4.)); return x.signMask | 0 } return f'), this)(), 0b0001);
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + 'var NaN = glob.NaN; function f() { var x=f4(0,0,0,0); x=f4(f32(-1), f32(NaN), f32(-0), f32(0)); return x.signMask | 0 } return f'), this)(), 0b0101);
// 1.3.3. Variable assignments
assertAsmTypeFail('glob', USE_ASM + I32 + I32A + "function f() {var x=i4(1,2,3,4); x=i4();} return f");

View File

@ -0,0 +1,33 @@
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
var float32x4 = SIMD.float32x4;
var int32x4 = SIMD.int32x4;
function test_float32x4() {
var v, w;
for ([v, w] of [[float32x4(-1, 20, 30, 4), 0b0001],
[float32x4(9.999, 2.1234, 30.4443, -4), 0b1000],
[float32x4(0, -Infinity, +Infinity, -0), 0b1010]])
{
assertEq(v.signMask, w);
}
if (typeof reportCompare === "function")
reportCompare(true, true);
}
function test_int32x4() {
var v, w;
for ([v, w] of [[int32x4(-1, 20, 30, 4), 0b0001],
[int32x4(10, 2, 30.2, -4), 0b1000],
[int32x4(0, 0x80000000, 0x7fffffff, -0), 0b0010]])
{
assertEq(v.signMask, w);
}
if (typeof reportCompare === "function")
reportCompare(true, true);
}
test_float32x4();
test_int32x4();

View File

@ -79,6 +79,11 @@ struct UnsignedStdintTypeForSize
: detail::StdintTypeForSizeAndSignedness<Size, false>
{};
template<size_t Size>
struct SignedStdintTypeForSize
: detail::StdintTypeForSizeAndSignedness<Size, true>
{};
template<typename IntegerType>
struct PositionOfSignBit
{