diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /js/src/jit-test/tests/SIMD | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'js/src/jit-test/tests/SIMD')
34 files changed, 1769 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/SIMD/binary-arith.js b/js/src/jit-test/tests/SIMD/binary-arith.js new file mode 100644 index 000000000..74211d46d --- /dev/null +++ b/js/src/jit-test/tests/SIMD/binary-arith.js @@ -0,0 +1,30 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var i1 = SIMD.Int32x4(1, 2, 3, 4); + var i2 = SIMD.Int32x4(4, 3, 2, 1); + + var f1 = SIMD.Float32x4(1, 2, 3, 4); + var f2 = SIMD.Float32x4(4, 3, 2, 1); + + var i8_1 = SIMD.Int8x16(1, 2, 3, 4, 20, 30, 40, 50, 100, 115, 120, 125); + var i8_2 = SIMD.Int8x16(4, 3, 2, 1, 8, 7, 6, 5, 12, 11, 10, 9); + + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Float32x4.add(f1, f2), binaryX((x, y) => x + y, f1, f2)); + assertEqX4(SIMD.Float32x4.sub(f1, f2), binaryX((x, y) => x - y, f1, f2)); + assertEqX4(SIMD.Float32x4.mul(f1, f2), binaryX((x, y) => x * y, f1, f2)); + + assertEqX4(SIMD.Int32x4.add(i1, i2), binaryX((x, y) => x + y, i1, i2)); + assertEqX4(SIMD.Int32x4.sub(i1, i2), binaryX((x, y) => x - y, i1, i2)); + assertEqX4(SIMD.Int32x4.mul(i1, i2), binaryX((x, y) => x * y, i1, i2)); + + assertEqX4(SIMD.Int8x16.add(i8_1, i8_2), binaryX((x, y) => (x + y) << 24 >> 24, i8_1, i8_2)); + assertEqX4(SIMD.Int8x16.sub(i8_1, i8_2), binaryX((x, y) => (x - y) << 24 >> 24, i8_1, i8_2)); + assertEqX4(SIMD.Int8x16.mul(i8_1, i8_2), binaryX((x, y) => (x * y) << 24 >> 24, i8_1, i8_2)); + } +} + +f(); diff --git a/js/src/jit-test/tests/SIMD/bool32x4-arith.js b/js/src/jit-test/tests/SIMD/bool32x4-arith.js new file mode 100644 index 000000000..bafceefa9 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bool32x4-arith.js @@ -0,0 +1,15 @@ +load(libdir + "simd.js"); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var b1 = SIMD.Bool32x4(true, false, true, false); + var b2 = SIMD.Bool32x4(true, true, true, true); + do { + assertEqX4(SIMD.Bool32x4.and(b1, b2), booleanBinaryX4((x, y) => x && y, b1, b2)); + assertEqX4(SIMD.Bool32x4.or(b1, b2), booleanBinaryX4((x, y) => x || y, b1, b2)); + assertEqX4(SIMD.Bool32x4.xor(b1, b2), booleanBinaryX4((x, y) => x != y, b1, b2)); + } while (!inIon()); +} + +f(); diff --git a/js/src/jit-test/tests/SIMD/bool32x4-const.js b/js/src/jit-test/tests/SIMD/bool32x4-const.js new file mode 100644 index 000000000..54bada215 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bool32x4-const.js @@ -0,0 +1,65 @@ +load(libdir + "simd.js"); + +setJitCompilerOption("ion.warmup.trigger", 50); + +// Test constant folding into the Bool32x4 constructor. +// Verify that we get the truthiness right, c.f. the ECMA ToBoolean() function. +function f1() { + var B = SIMD.Bool32x4; + var S = SIMD.Bool32x4.splat; + return [ + B(false, false, false, true), + B(true), + B(undefined, null, "", "x"), + B({}, 0, 1, -0.0), + B(NaN, -NaN, Symbol(), objectEmulatingUndefined()), + + S(false), + S(true), + S(undefined), + S(null), + + S(""), + S("x"), + S(0), + S(1), + + S({}), + S(-0.0), + S(NaN), + S(Symbol()), + + S(objectEmulatingUndefined()) + ]; +} + +function f() { + for (var i = 0; i < 100; i++) { + var a = f1() + assertEqX4(a[0], [false, false, false, true]); + assertEqX4(a[1], [true, false, false, false]); + assertEqX4(a[2], [false, false, false, true]); + assertEqX4(a[3], [true, false, true, false]); + assertEqX4(a[4], [false, false, true, false]); + + // Splats. + assertEqX4(a[5], [false, false, false, false]); + assertEqX4(a[6], [true, true, true, true]); + assertEqX4(a[7], [false, false, false, false]); + assertEqX4(a[8], [false, false, false, false]); + + assertEqX4(a[9], [false, false, false, false]); + assertEqX4(a[10], [true, true, true, true]); + assertEqX4(a[11], [false, false, false, false]); + assertEqX4(a[12], [true, true, true, true]); + + assertEqX4(a[13], [true, true, true, true]); + assertEqX4(a[14], [false, false, false, false]); + assertEqX4(a[15], [false, false, false, false]); + assertEqX4(a[16], [true, true, true, true]); + + assertEqX4(a[17], [false, false, false, false]); + } +} + +f(); diff --git a/js/src/jit-test/tests/SIMD/bug1109911.js b/js/src/jit-test/tests/SIMD/bug1109911.js new file mode 100644 index 000000000..23a5c5721 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug1109911.js @@ -0,0 +1,11 @@ +if (typeof TypedObject === "undefined" || typeof SIMD === 'undefined') + quit(); + +var Int32x4 = SIMD.Int32x4; +var a = Int32x4((4294967295), 200, 300, 400); +addCase( new Array(Math.pow(2,12)) ); +for ( var arg = "", i = 0; i < Math.pow(2,12); i++ ) {} +addCase( a ); +function addCase(object) { + object.length +} diff --git a/js/src/jit-test/tests/SIMD/bug1121299.js b/js/src/jit-test/tests/SIMD/bug1121299.js new file mode 100644 index 000000000..17ca46e2e --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug1121299.js @@ -0,0 +1,31 @@ +if (!this.hasOwnProperty("SIMD")) + quit(); + +setJitCompilerOption("baseline.warmup.trigger", 10); +setJitCompilerOption("ion.warmup.trigger", 30); + +function test_1(i) { + if (i >= 40) + return; + var a = SIMD.Float32x4(1.1, 2.2, 3.3, 4.6); + SIMD.Int32x4.fromFloat32x4(a); + test_1(i + 1); +} +test_1(0); + + +var Float32x4 = SIMD.Float32x4; +function test_2() { + var Array = Float32x4.array(3); + var array = new Array([ + Float32x4(1, 2, 3, 4), + Float32x4(5, 6, 7, 8), + Float32x4(9, 10, 11, 12) + ]); + if (typeof reportCompare === "function") + reportCompare(true, true); +} +test_2(); +evaluate("test_2(); test_2();", { + isRunOnce: true, +}); diff --git a/js/src/jit-test/tests/SIMD/bug1123631.js b/js/src/jit-test/tests/SIMD/bug1123631.js new file mode 100644 index 000000000..28c0e0aa1 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug1123631.js @@ -0,0 +1,9 @@ +if (!this.hasOwnProperty("SIMD")) + quit(); + +var Float64x2 = SIMD.Float64x2; +function test() { + var a = Float64x2(1, 2); +} +test(); +test(); diff --git a/js/src/jit-test/tests/SIMD/bug1130845.js b/js/src/jit-test/tests/SIMD/bug1130845.js new file mode 100644 index 000000000..2baf3865d --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug1130845.js @@ -0,0 +1,15 @@ +if (!this.hasOwnProperty("SIMD")) + quit(); + +var Int32x4 = SIMD.Int32x4; +function test() { + var a = Int32x4(); + var b = Int32x4(10, 20, 30, 40); + var c = SIMD.Int32x4.and(a, b); + assertEq(Int32x4.extractLane(c, 0), 0); + return 0; +} +test(); +var u = [], v = []; +for (var j=0; j<u.length; ++j) + v[test()] = t; diff --git a/js/src/jit-test/tests/SIMD/bug1241872.js b/js/src/jit-test/tests/SIMD/bug1241872.js new file mode 100644 index 000000000..c36ebcc6b --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug1241872.js @@ -0,0 +1,10 @@ +if (typeof SIMD !== 'object') + quit(0); + +function test() { + return SIMD.Float32x4().toSource(); +} + +var r = ''; +for (var i = 0; i < 10000; i++) + r = test(); diff --git a/js/src/jit-test/tests/SIMD/bug1248503.js b/js/src/jit-test/tests/SIMD/bug1248503.js new file mode 100644 index 000000000..e121cea1d --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug1248503.js @@ -0,0 +1,16 @@ +if (typeof SIMD !== 'object') + quit(0); + +function assertEqVec(v, w) { + [0].forEach(i => v, w); + function assertEqX4(...opts) {} +} +gczeal(1); +function f() { + SIMD.Float32x4(); + var i1 = SIMD.Int32x4(); + for (j = 0; j < 100000; ++j, eval.eval) + assertEqVec(SIMD.Int32x4.check(i1), i1); +} +f(); + diff --git a/js/src/jit-test/tests/SIMD/bug1273483.js b/js/src/jit-test/tests/SIMD/bug1273483.js new file mode 100644 index 000000000..3c9386b4f --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug1273483.js @@ -0,0 +1,9 @@ +if (typeof SIMD === 'undefined') + quit(); + +Int8x16 = SIMD.Int8x16; +var Int32x4 = SIMD.Int32x4; +function testSwizzleForType(type) type(); +testSwizzleForType(Int8x16); +function testSwizzleInt32x4() testSwizzleForType(Int32x4); +testSwizzleInt32x4(); diff --git a/js/src/jit-test/tests/SIMD/bug1296640-gc-args.js b/js/src/jit-test/tests/SIMD/bug1296640-gc-args.js new file mode 100644 index 000000000..4dbe95410 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug1296640-gc-args.js @@ -0,0 +1,9 @@ +if (typeof gczeal === 'undefined' || typeof SIMD === 'undefined') { + quit(); +} + +gczeal(9, 2); +var Int8x16 = SIMD.Int8x16; +var v = Int8x16(); +var good = { valueOf: () => 21 }; +Int8x16.shiftLeftByScalar(v, good); diff --git a/js/src/jit-test/tests/SIMD/bug1303780-gc-args.js b/js/src/jit-test/tests/SIMD/bug1303780-gc-args.js new file mode 100644 index 000000000..a894d532e --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug1303780-gc-args.js @@ -0,0 +1,12 @@ +if (typeof gczeal === 'undefined' || typeof SIMD === 'undefined') { + quit(); +} + +gczeal(14,2); +var Float32x4 = SIMD.Float32x4; +function test() { + var v = Float32x4(1,2,3,4); + var good = {valueOf: () => 42}; + Float32x4.replaceLane(v, 0, good); +} +test(); diff --git a/js/src/jit-test/tests/SIMD/bug953108.js b/js/src/jit-test/tests/SIMD/bug953108.js new file mode 100644 index 000000000..a8ae80e17 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/bug953108.js @@ -0,0 +1,10 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +if (!this.hasOwnProperty("TypedObject") || !this.hasOwnProperty("SIMD")) + quit(); + +var Float32x4 = SIMD.Float32x4; +Float32x4.array(1); diff --git a/js/src/jit-test/tests/SIMD/check.js b/js/src/jit-test/tests/SIMD/check.js new file mode 100644 index 000000000..bef0b6c68 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/check.js @@ -0,0 +1,25 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var f1 = SIMD.Float32x4(1, 2, 3, 4); + var i1 = SIMD.Int32x4(1, 2, -3, 4); + var b1 = SIMD.Bool32x4(true, true, false, true); + var i = 0; + try { + for (; i < 150; i++) { + if (i > 148) + i1 = f1; + assertEqVec(SIMD.Int32x4.check(i1), i1); + assertEqVec(SIMD.Float32x4.check(f1), f1); + assertEqVec(SIMD.Bool32x4.check(b1), b1); + } + } catch (ex) { + assertEq(i, 149); + assertEq(ex instanceof TypeError, true); + } +} + +f(); + diff --git a/js/src/jit-test/tests/SIMD/compare.js b/js/src/jit-test/tests/SIMD/compare.js new file mode 100644 index 000000000..21dca20cd --- /dev/null +++ b/js/src/jit-test/tests/SIMD/compare.js @@ -0,0 +1,39 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var f1 = SIMD.Float32x4(1, 2, 3, 4); + var f2 = SIMD.Float32x4(NaN, Infinity, 3.14, -0); + + var i1 = SIMD.Int32x4(1, 2, -3, 4); + var i2 = SIMD.Int32x4(1, -2, 3, 0); + + var u1 = SIMD.Uint32x4(1, 2, -3, 4); + var u2 = SIMD.Uint32x4(1, -2, 3, 0x80000000); + + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Int32x4.lessThan(i1, i2), [false, false, true, false]); + assertEqX4(SIMD.Int32x4.lessThanOrEqual(i1, i2), [true, false, true, false]); + assertEqX4(SIMD.Int32x4.equal(i1, i2), [true, false, false, false]); + assertEqX4(SIMD.Int32x4.notEqual(i1, i2), [false, true, true, true]); + assertEqX4(SIMD.Int32x4.greaterThan(i1, i2), [false, true, false, true]); + assertEqX4(SIMD.Int32x4.greaterThanOrEqual(i1, i2), [true, true, false, true]); + + assertEqX4(SIMD.Uint32x4.lessThan(u1, u2), [false, true, false, true]); + assertEqX4(SIMD.Uint32x4.lessThanOrEqual(u1, u2), [true, true, false, true]); + assertEqX4(SIMD.Uint32x4.equal(u1, u2), [true, false, false, false]); + assertEqX4(SIMD.Uint32x4.notEqual(u1, u2), [false, true, true, true]); + assertEqX4(SIMD.Uint32x4.greaterThan(u1, u2), [false, false, true, false]); + assertEqX4(SIMD.Uint32x4.greaterThanOrEqual(u1, u2), [true, false, true, false]); + + assertEqX4(SIMD.Float32x4.lessThan(f1, f2), [false, true, true, false]); + assertEqX4(SIMD.Float32x4.lessThanOrEqual(f1, f2), [false, true, true, false]); + assertEqX4(SIMD.Float32x4.equal(f1, f2), [false, false, false, false]); + assertEqX4(SIMD.Float32x4.notEqual(f1, f2), [true, true, true, true]); + assertEqX4(SIMD.Float32x4.greaterThan(f1, f2), [false, false, false, true]); + assertEqX4(SIMD.Float32x4.greaterThanOrEqual(f1, f2), [false, false, false, true]); + } +} + +f(); diff --git a/js/src/jit-test/tests/SIMD/complex-4.js b/js/src/jit-test/tests/SIMD/complex-4.js new file mode 100644 index 000000000..ca5e8b0f6 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/complex-4.js @@ -0,0 +1,70 @@ +load(libdir + 'simd.js'); + +if (typeof SIMD === "undefined") + quit(); + +setJitCompilerOption("baseline.warmup.trigger", 10); +setJitCompilerOption("ion.warmup.trigger", 90); +var max = 100; // Make have the warm-up counter high enough to + // consider inlining functions. + +var f4 = SIMD.Int32x4; // :TODO: Support Float32x4 arith. +var f4add = f4.add; +var f4sub = f4.sub; +var f4mul = f4.mul; + +function c4mul(z1, z2) { + var { re: re1, im: im1 } = z1; + var { re: re2, im: im2 } = z2; + var rere = f4mul(re1, re2); + var reim = f4mul(re1, im2); + var imre = f4mul(im1, re2); + var imim = f4mul(im1, im2); + return { re: f4sub(rere, imim), im: f4add(reim, imre) }; +} + +function c4inv(z) { + var { re: re, im: im } = z; + var minus = f4(-1, -1, -1, -1); + return { re: re, im: f4mul(im, minus) }; +} + +function c4inv_inplace(z) { + var res = c4inv(z); + z.re = res.re; + z.im = res.im; +} + +function c4norm(z) { + var { re: re, im: im } = c4mul(z, c4inv(z)); + return re; +} + +function c4scale(z, s) { + var { re: re, im: im } = z; + var f4s = f4(s, s, s, s); + return { re: f4mul(re, f4s), im: f4mul(im, f4s) }; +} + +var rotate90 = { re: f4(0, 0, 0, 0), im: f4(1, 1, 1, 1) }; +var cardinals = { re: f4(1, 0, -1, 0), im: f4(0, 1, 0, -1) }; + +function test(dots) { + for (var j = 0; j < 4; j++) { + dots = c4mul(rotate90, dots); + if (j % 2 == 0) // Magic ! + c4inv_inplace(dots); + dots = c4scale(dots, 2); + } + return dots; +} + +assertEqX4(c4norm(cardinals), simdToArray(f4.splat(1))); +var cardinals16 = c4scale(cardinals, 16); + +for (var i = 0; i < max; i++) { + var res = test(cardinals); + assertEqX4(c4norm(res), simdToArray(f4.splat(16 * 16))); + assertEqX4(res.re, simdToArray(cardinals16.re)); + assertEqX4(res.im, simdToArray(cardinals16.im)); +} diff --git a/js/src/jit-test/tests/SIMD/convert.js b/js/src/jit-test/tests/SIMD/convert.js new file mode 100644 index 000000000..b27a041e7 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/convert.js @@ -0,0 +1,68 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 30); + +var cast = (function() { + var i32 = new Int32Array(1); + var f32 = new Float32Array(i32.buffer); + return { + fromInt32Bits(x) { + i32[0] = x; + return f32[0]; + }, + + fromFloat32Bits(x) { + f32[0] = x; + return i32[0]; + } + } +})(); + +function f() { + // No bailout here. + var f4 = SIMD.Float32x4(1, 2, 3, 4); + var i4 = SIMD.Int32x4(1, 2, 3, 4); + var BitOrZero = (x) => x | 0; + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Float32x4.fromInt32x4(i4), unaryX4(BitOrZero, f4, Math.fround)); + assertEqX4(SIMD.Float32x4.fromInt32x4Bits(i4), unaryX4(cast.fromInt32Bits, f4, Math.fround)); + assertEqX4(SIMD.Int32x4.fromFloat32x4(f4), unaryX4(Math.fround, i4, BitOrZero)); + assertEqX4(SIMD.Int32x4.fromFloat32x4Bits(f4), unaryX4(cast.fromFloat32Bits, i4, BitOrZero)); + } +} + +function uglyDuckling(val) { + // We bail out when i == 149 because the conversion will return + // 0x80000000 and the input actually wasn't in bounds. + val = Math.fround(val); + for (var i = 0; i < 150; i++) { + var caught = false; + try { + var v = SIMD.Float32x4(i < 149 ? 0 : val, 0, 0, 0) + SIMD.Int32x4.fromFloat32x4(v); + } catch(e) { + assertEq(e instanceof RangeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } +} + +function dontBail() { + // On x86, the conversion will return 0x80000000, which will imply that we + // check the input values. However, we shouldn't bail out in this case. + for (var i = 0; i < 150; i++) { + var v = SIMD.Float32x4(i < 149 ? 0 : -Math.pow(2, 31), 0, 0, 0) + SIMD.Int32x4.fromFloat32x4(v); + } +} + +f(); + +dontBail(); +dontBail(); + +uglyDuckling(Math.pow(2, 31)); +uglyDuckling(NaN); +uglyDuckling(-Math.pow(2, 32)); diff --git a/js/src/jit-test/tests/SIMD/float32x4-binary-arith.js b/js/src/jit-test/tests/SIMD/float32x4-binary-arith.js new file mode 100644 index 000000000..63e9215d9 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/float32x4-binary-arith.js @@ -0,0 +1,33 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function maxNum(x, y) { + if (x != x) + return y; + if (y != y) + return x; + return Math.max(x, y); +} + +function minNum(x, y) { + if (x != x) + return y; + if (y != y) + return x; + return Math.min(x, y); +} + +function f() { + var f1 = SIMD.Float32x4(1, 2, 3, 4); + var f2 = SIMD.Float32x4(4, 3, 2, 1); + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Float32x4.div(f1, f2), binaryX((x, y) => x / y, f1, f2)); + assertEqX4(SIMD.Float32x4.min(f1, f2), binaryX(Math.min, f1, f2)); + assertEqX4(SIMD.Float32x4.max(f1, f2), binaryX(Math.max, f1, f2)); + assertEqX4(SIMD.Float32x4.minNum(f1, f2), binaryX(minNum, f1, f2)); + assertEqX4(SIMD.Float32x4.maxNum(f1, f2), binaryX(maxNum, f1, f2)); + } +} + +f(); diff --git a/js/src/jit-test/tests/SIMD/getters.js b/js/src/jit-test/tests/SIMD/getters.js new file mode 100644 index 000000000..5a895bbe2 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/getters.js @@ -0,0 +1,48 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var i4 = SIMD.Int32x4(1, -2, 3, -4); + var u4 = SIMD.Uint32x4(1, -2, 3, 0x88000000); + var b4 = SIMD.Bool32x4(true, true, false, true); + + + var bt4 = SIMD.Bool32x4(true, true, true, true); + var bf4 = SIMD.Bool32x4(false, false, false, false); + + var v = Math.fround(13.37); + var f4 = SIMD.Float32x4(13.37, NaN, Infinity, -0); + + for (var i = 0; i < 150; i++) { + assertEq(SIMD.Int32x4.extractLane(i4, 0), 1); + assertEq(SIMD.Int32x4.extractLane(i4, 1), -2); + assertEq(SIMD.Int32x4.extractLane(i4, 2), 3); + assertEq(SIMD.Int32x4.extractLane(i4, 3), -4); + + assertEq(SIMD.Uint32x4.extractLane(u4, 0), 1); + assertEq(SIMD.Uint32x4.extractLane(u4, 1), -2 >>> 0); + assertEq(SIMD.Uint32x4.extractLane(u4, 2), 3); + assertEq(SIMD.Uint32x4.extractLane(u4, 3), 0x88000000); + + assertEq(SIMD.Float32x4.extractLane(f4, 0), v); + assertEq(SIMD.Float32x4.extractLane(f4, 1), NaN); + assertEq(SIMD.Float32x4.extractLane(f4, 2), Infinity); + assertEq(SIMD.Float32x4.extractLane(f4, 3), -0); + + assertEq(SIMD.Bool32x4.extractLane(b4, 0), true); + assertEq(SIMD.Bool32x4.extractLane(b4, 1), true); + assertEq(SIMD.Bool32x4.extractLane(b4, 2), false); + assertEq(SIMD.Bool32x4.extractLane(b4, 3), true); + + assertEq(SIMD.Bool32x4.anyTrue(b4), true); + assertEq(SIMD.Bool32x4.allTrue(b4), false); + + assertEq(SIMD.Bool32x4.anyTrue(bt4), true); + assertEq(SIMD.Bool32x4.allTrue(bt4), true); + assertEq(SIMD.Bool32x4.anyTrue(bf4), false); + assertEq(SIMD.Bool32x4.allTrue(bf4), false); + } +} + +f(); diff --git a/js/src/jit-test/tests/SIMD/inline-missing-arguments.js b/js/src/jit-test/tests/SIMD/inline-missing-arguments.js new file mode 100644 index 000000000..5ef91d072 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/inline-missing-arguments.js @@ -0,0 +1,81 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function test(i) { + assertEqX4(SIMD.Int32x4(), [0, 0, 0, 0]); + assertEqX4(SIMD.Int32x4(i), [i, 0, 0, 0]); + assertEqX4(SIMD.Int32x4(i, 1), [i, 1, 0, 0]); + assertEqX4(SIMD.Int32x4(i, 1, 2), [i, 1, 2, 0]); + assertEqX4(SIMD.Int32x4(i, 1, 2, 3), [i, 1, 2, 3]); + assertEqX4(SIMD.Int32x4(i, 1, 2, 3, 4), [i, 1, 2, 3]); + + assertEqVecArr(SIMD.Int16x8(), [0, 0, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int16x8(i), [i, 0, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int16x8(i, 1), [i, 1, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int16x8(i, 1, 2), [i, 1, 2, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int16x8(i, 1, 2, 3), [i, 1, 2, 3, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int16x8(i, 1, 2, 3, 4), [i, 1, 2, 3, 4, 0, 0, 0]); + assertEqVecArr(SIMD.Int16x8(i, 1, 2, 3, 4, 5, 6), + [i, 1, 2, 3, 4, 5, 6, 0]); + j = i & 32 + assertEqVecArr(SIMD.Int8x16(), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int8x16(j), [j, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int8x16(j, 1), [j, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int8x16(j, 1, 2), [j, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int8x16(j, 1, 2, 3), [j, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int8x16(j, 1, 2, 3, 4), [j, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int8x16(j, 1, 2, 3, 4, 5, 6), + [j, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + assertEqVecArr(SIMD.Int8x16(j, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), + [j, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0]); + + assertEqX4(SIMD.Float32x4(), [NaN, NaN, NaN, NaN]); + assertEqX4(SIMD.Float32x4(i), [i, NaN, NaN, NaN]); + assertEqX4(SIMD.Float32x4(i, 1), [i, 1, NaN, NaN]); + assertEqX4(SIMD.Float32x4(i, 1, 2), [i, 1, 2, NaN]); + assertEqX4(SIMD.Float32x4(i, 1, 2, 3), [i, 1, 2, 3 ]); + assertEqX4(SIMD.Float32x4(i, 1, 2, 3, 4), [i, 1, 2, 3 ]); + + var b = i % 2 > 0 ; + assertEqX4(SIMD.Bool32x4(), [false, false, false, false]); + assertEqX4(SIMD.Bool32x4(b), [b, false, false, false]); + assertEqX4(SIMD.Bool32x4(b, true), [b, true, false, false]); + assertEqX4(SIMD.Bool32x4(b, false, true), [b, false, true, false]); + assertEqX4(SIMD.Bool32x4(b, false, true, true), [b, false, true, true ]); + assertEqX4(SIMD.Bool32x4(b, false, true, true, true), [b, false, true, true ]); + + assertEqVecArr(SIMD.Bool16x8(), + [false, false, false, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool16x8(b), + [b, false, false, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool16x8(b, true), + [b, true, false, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool16x8(b, false, true), + [b, false, true, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool16x8(b, false, true, true), + [b, false, true, true, false, false, false, false]); + assertEqVecArr(SIMD.Bool16x8(b, false, true, true, true), + [b, false, true, true, true, false, false, false]); + assertEqVecArr(SIMD.Bool16x8(b, false, true, true, true, true), + [b, false, true, true, true, true, false, false]); + + assertEqVecArr(SIMD.Bool8x16(), + [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool8x16(b), + [b, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool8x16(b, true), + [b, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool8x16(b, false, true), + [b, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool8x16(b, false, true, true), + [b, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool8x16(b, false, true, true, true), + [b, false, true, true, true, false, false, false, false, false, false, false, false, false, false, false]); + assertEqVecArr(SIMD.Bool8x16(b, false, true, true, true, true, false, true, true, true), + [b, false, true, true, true, true, false, true, true, true, false, false, false, false, false, false]); +} + +for(var i=0; i<300; i++) { + test(i); +} diff --git a/js/src/jit-test/tests/SIMD/load.js b/js/src/jit-test/tests/SIMD/load.js new file mode 100644 index 000000000..5cdb8cce6 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/load.js @@ -0,0 +1,123 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 40); + +function f() { + var f32 = new Float32Array(16); + for (var i = 0; i < 16; i++) + f32[i] = i + 1; + + var f64 = new Float64Array(f32.buffer); + var i32 = new Int32Array(f32.buffer); + var u32 = new Uint32Array(f32.buffer); + var i16 = new Int16Array(f32.buffer); + var u16 = new Uint16Array(f32.buffer); + var i8 = new Int8Array(f32.buffer); + var u8 = new Uint8Array(f32.buffer); + + function testLoad() { + assertEqX4(SIMD.Float32x4.load(f64, 0), [1,2,3,4]); + assertEqX4(SIMD.Float32x4.load(f32, 1), [2,3,4,5]); + assertEqX4(SIMD.Float32x4.load(i32, 2), [3,4,5,6]); + assertEqX4(SIMD.Float32x4.load(i16, 3 << 1), [4,5,6,7]); + assertEqX4(SIMD.Float32x4.load(u16, 4 << 1), [5,6,7,8]); + assertEqX4(SIMD.Float32x4.load(i8 , 5 << 2), [6,7,8,9]); + assertEqX4(SIMD.Float32x4.load(u8 , 6 << 2), [7,8,9,10]); + + assertEqX4(SIMD.Float32x4.load(f64, (16 >> 1) - (4 >> 1)), [13,14,15,16]); + assertEqX4(SIMD.Float32x4.load(f32, 16 - 4), [13,14,15,16]); + assertEqX4(SIMD.Float32x4.load(i32, 16 - 4), [13,14,15,16]); + assertEqX4(SIMD.Float32x4.load(i16, (16 << 1) - (4 << 1)), [13,14,15,16]); + assertEqX4(SIMD.Float32x4.load(u16, (16 << 1) - (4 << 1)), [13,14,15,16]); + assertEqX4(SIMD.Float32x4.load(i8, (16 << 2) - (4 << 2)), [13,14,15,16]); + assertEqX4(SIMD.Float32x4.load(u8, (16 << 2) - (4 << 2)), [13,14,15,16]); + } + + function testLoad1() { + assertEqX4(SIMD.Float32x4.load1(f64, 0), [1,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(f32, 1), [2,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(i32, 2), [3,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(i16, 3 << 1), [4,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(u16, 4 << 1), [5,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(i8 , 5 << 2), [6,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(u8 , 6 << 2), [7,0,0,0]); + + assertEqX4(SIMD.Float32x4.load1(f64, (16 >> 1) - (4 >> 1)), [13,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(f32, 16 - 4), [13,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(i32, 16 - 4), [13,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(i16, (16 << 1) - (4 << 1)), [13,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(u16, (16 << 1) - (4 << 1)), [13,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(i8, (16 << 2) - (4 << 2)), [13,0,0,0]); + assertEqX4(SIMD.Float32x4.load1(u8, (16 << 2) - (4 << 2)), [13,0,0,0]); + } + + function testLoad2() { + assertEqX4(SIMD.Float32x4.load2(f64, 0), [1,2,0,0]); + assertEqX4(SIMD.Float32x4.load2(f32, 1), [2,3,0,0]); + assertEqX4(SIMD.Float32x4.load2(i32, 2), [3,4,0,0]); + assertEqX4(SIMD.Float32x4.load2(i16, 3 << 1), [4,5,0,0]); + assertEqX4(SIMD.Float32x4.load2(u16, 4 << 1), [5,6,0,0]); + assertEqX4(SIMD.Float32x4.load2(i8 , 5 << 2), [6,7,0,0]); + assertEqX4(SIMD.Float32x4.load2(u8 , 6 << 2), [7,8,0,0]); + + assertEqX4(SIMD.Float32x4.load2(f64, (16 >> 1) - (4 >> 1)), [13,14,0,0]); + assertEqX4(SIMD.Float32x4.load2(f32, 16 - 4), [13,14,0,0]); + assertEqX4(SIMD.Float32x4.load2(i32, 16 - 4), [13,14,0,0]); + assertEqX4(SIMD.Float32x4.load2(i16, (16 << 1) - (4 << 1)), [13,14,0,0]); + assertEqX4(SIMD.Float32x4.load2(u16, (16 << 1) - (4 << 1)), [13,14,0,0]); + assertEqX4(SIMD.Float32x4.load2(i8, (16 << 2) - (4 << 2)), [13,14,0,0]); + assertEqX4(SIMD.Float32x4.load2(u8, (16 << 2) - (4 << 2)), [13,14,0,0]); + } + + function testLoad3() { + assertEqX4(SIMD.Float32x4.load3(f64, 0), [1,2,3,0]); + assertEqX4(SIMD.Float32x4.load3(f32, 1), [2,3,4,0]); + assertEqX4(SIMD.Float32x4.load3(i32, 2), [3,4,5,0]); + assertEqX4(SIMD.Float32x4.load3(i16, 3 << 1), [4,5,6,0]); + assertEqX4(SIMD.Float32x4.load3(u16, 4 << 1), [5,6,7,0]); + assertEqX4(SIMD.Float32x4.load3(i8 , 5 << 2), [6,7,8,0]); + assertEqX4(SIMD.Float32x4.load3(u8 , 6 << 2), [7,8,9,0]); + + assertEqX4(SIMD.Float32x4.load3(f64, (16 >> 1) - (4 >> 1)), [13,14,15,0]); + assertEqX4(SIMD.Float32x4.load3(f32, 16 - 4), [13,14,15,0]); + assertEqX4(SIMD.Float32x4.load3(i32, 16 - 4), [13,14,15,0]); + assertEqX4(SIMD.Float32x4.load3(i16, (16 << 1) - (4 << 1)), [13,14,15,0]); + assertEqX4(SIMD.Float32x4.load3(u16, (16 << 1) - (4 << 1)), [13,14,15,0]); + assertEqX4(SIMD.Float32x4.load3(i8, (16 << 2) - (4 << 2)), [13,14,15,0]); + assertEqX4(SIMD.Float32x4.load3(u8, (16 << 2) - (4 << 2)), [13,14,15,0]); + } + + for (var i = 0; i < 150; i++) { + testLoad(); + testLoad1(); + testLoad2(); + testLoad3(); + } +} + +f(); + +function testBailout(uglyDuckling) { + var f32 = new Float32Array(16); + for (var i = 0; i < 16; i++) + f32[i] = i + 1; + + var i8 = new Int8Array(f32.buffer); + + for (var i = 0; i < 150; i++) { + var caught = false; + try { + SIMD.Float32x4.load(i8, (i < 149) ? 0 : uglyDuckling); + } catch (e) { + print(e); + assertEq(e instanceof RangeError, true); + caught = true; + } + assertEq(i < 149 || caught, true); + } +} + +print('Testing range checks...'); +testBailout(-1); +testBailout(-15); +testBailout(12 * 4 + 1); diff --git a/js/src/jit-test/tests/SIMD/nursery-overflow.js b/js/src/jit-test/tests/SIMD/nursery-overflow.js new file mode 100644 index 000000000..5aecff908 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/nursery-overflow.js @@ -0,0 +1,29 @@ +load(libdir + 'simd.js'); + +if (typeof SIMD === "undefined") + quit(); + +setJitCompilerOption("baseline.warmup.trigger", 10); +setJitCompilerOption("ion.warmup.trigger", 30); + +var i4 = SIMD.Int32x4; +var i4sub = SIMD.Int32x4.sub; + +function simdbox(i) { + return i4(i, i, i, i); +} + +function test() { + var arr = []; + + // overflow the nursery with live SIMD objects. + for (var i = 0; i < 100000; i++) { + arr.push(simdbox(i)); + } + + return arr; +} + +var arr = test(); +for (var i = 0; i < arr.length; i++) + assertEqX4(arr[i], [i, i, i, i]); diff --git a/js/src/jit-test/tests/SIMD/recover.js b/js/src/jit-test/tests/SIMD/recover.js new file mode 100644 index 000000000..a8fb0002e --- /dev/null +++ b/js/src/jit-test/tests/SIMD/recover.js @@ -0,0 +1,70 @@ +load(libdir + 'simd.js'); + +if (!this.hasOwnProperty("SIMD")) + quit(); + +// This test case ensure that if we are able to optimize SIMD, then we can use +// recover instructions to get rid of the allocations. So, there is no value +// (and the test case would fail) if we are not able to inline SIMD +// constructors. +if (!isSimdAvailable()) + quit(); + +setJitCompilerOption("baseline.warmup.trigger", 10); +setJitCompilerOption("ion.warmup.trigger", 20); + +// This function is used to cause an invalidation after having removed a branch +// after DCE. This is made to check if we correctly recover an array +// allocation. +var uceFault = function (i) { + if (i > 98) + uceFault = function (i) { return true; }; + return false; +}; + +// Check that we can correctly recover a boxed value. +var uceFault_simdBox_i4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_i4')); +function simdBox_i4(i) { + var a = SIMD.Int32x4(i, i, i, i); + if (uceFault_simdBox_i4(i) || uceFault_simdBox_i4(i)) + assertEqX4(a, [i, i, i, i]); + assertRecoveredOnBailout(a, true); + return 0; +} + +var uceFault_simdBox_u4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_u4')); +function simdBox_u4(i) { + var a = SIMD.Uint32x4(i, 98 - i, i + 0x7ffffff0, i + 0xffffff00); + if (uceFault_simdBox_u4(i) || uceFault_simdBox_u4(i)) + assertEqX4(a, [i, 98 - i, i + 0x7ffffff0, i + 0xffffff00].map(x => x >>> 0)); + assertRecoveredOnBailout(a, true); + return 0; +} + +var uceFault_simdBox_f4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_f4')); +function simdBox_f4(i) { + var a = SIMD.Float32x4(i, i + 0.1, i + 0.2, i + 0.3); + if (uceFault_simdBox_f4(i) || uceFault_simdBox_f4(i)) + assertEqX4(a, [i, i + 0.1, i + 0.2, i + 0.3].map(Math.fround)); + assertRecoveredOnBailout(a, true); + return 0; +} + +var uceFault_simdBox_b4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_b4')); +function simdBox_b4(i) { + var val1 = i%2 === 0, + val2 = !val1; + + var a = SIMD.Bool32x4(val1, val2, val1, val2); + if (uceFault_simdBox_b4(i) || uceFault_simdBox_b4(i)) + assertEqX4(a, [val1, val2, val1, val2]); + assertRecoveredOnBailout(a, true); + return 0; +} + +for (var i = 0; i < 100; i++) { + simdBox_i4(i); + simdBox_u4(i); + simdBox_f4(i); + simdBox_b4(i); +} diff --git a/js/src/jit-test/tests/SIMD/replacelane.js b/js/src/jit-test/tests/SIMD/replacelane.js new file mode 100644 index 000000000..c6b37ad5a --- /dev/null +++ b/js/src/jit-test/tests/SIMD/replacelane.js @@ -0,0 +1,181 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var f4 = SIMD.Float32x4(1, 2, 3, 4); + var i4 = SIMD.Int32x4(1, 2, 3, 4); + var b4 = SIMD.Bool32x4(true, false, true, false); + + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Int32x4.replaceLane(i4, 0, 42), [42, 2, 3, 4]); + assertEqX4(SIMD.Int32x4.replaceLane(i4, 1, 42), [1, 42, 3, 4]); + assertEqX4(SIMD.Int32x4.replaceLane(i4, 2, 42), [1, 2, 42, 4]); + assertEqX4(SIMD.Int32x4.replaceLane(i4, 3, 42), [1, 2, 3, 42]); + + assertEqX4(SIMD.Float32x4.replaceLane(f4, 0, 42), [42, 2, 3, 4]); + assertEqX4(SIMD.Float32x4.replaceLane(f4, 1, 42), [1, 42, 3, 4]); + assertEqX4(SIMD.Float32x4.replaceLane(f4, 2, 42), [1, 2, 42, 4]); + assertEqX4(SIMD.Float32x4.replaceLane(f4, 3, 42), [1, 2, 3, 42]); + + assertEqX4(SIMD.Bool32x4.replaceLane(b4, 0, false), [false, false, true, false]); + assertEqX4(SIMD.Bool32x4.replaceLane(b4, 1, true), [true, true, true, false]); + assertEqX4(SIMD.Bool32x4.replaceLane(b4, 2, false), [true, false, false, false]); + assertEqX4(SIMD.Bool32x4.replaceLane(b4, 3, true), [true, false, true, true]); + } +} + +f(); + +function e() { + var f4 = SIMD.Float32x4(1, 2, 3, 4); + var i4 = SIMD.Int32x4(1, 2, 3, 4); + var b4 = SIMD.Bool32x4(true, false, true, false); + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Int32x4.replaceLane(i < 149 ? i4 : f4, 0, 42); + } catch(e) { + assertEq(e instanceof TypeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Int32x4.replaceLane(i < 149 ? i4 : b4, 0, 42); + } catch(e) { + assertEq(e instanceof TypeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Int32x4.replaceLane(i4, i < 149 ? 0 : 4, 42); + } catch(e) { + assertEq(e instanceof RangeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Int32x4.replaceLane(i4, i < 149 ? 0 : 1.1, 42); + } catch(e) { + assertEq(e instanceof RangeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Float32x4.replaceLane(i < 149 ? f4 : i4, 0, 42); + } catch(e) { + assertEq(e instanceof TypeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Float32x4.replaceLane(i < 149 ? f4 : b4, 0, 42); + } catch(e) { + assertEq(e instanceof TypeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Float32x4.replaceLane(f4, i < 149 ? 0 : 4, 42); + } catch(e) { + assertEq(e instanceof RangeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Float32x4.replaceLane(f4, i < 149 ? 0 : 1.1, 42); + } catch(e) { + assertEq(e instanceof RangeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Bool32x4.replaceLane(i < 149 ? b4 : i4, 0, true); + } catch(e) { + assertEq(e instanceof TypeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Bool32x4.replaceLane(i < 149 ? b4 : f4, 0, true); + } catch(e) { + assertEq(e instanceof TypeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Bool32x4.replaceLane(b4, i < 149 ? 0 : 4, true); + } catch(e) { + assertEq(e instanceof RangeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + + for (let i = 0; i < 150; i++) { + let caught = false; + try { + let x = SIMD.Bool32x4.replaceLane(b4, i < 149 ? 0 : 1.1, true); + } catch(e) { + assertEq(e instanceof RangeError, true); + assertEq(i, 149); + caught = true; + } + assertEq(i < 149 || caught, true); + } + +} + +e(); diff --git a/js/src/jit-test/tests/SIMD/saturate.js b/js/src/jit-test/tests/SIMD/saturate.js new file mode 100644 index 000000000..a98cf7ad7 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/saturate.js @@ -0,0 +1,37 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +const INT8_MIN = -128; +const INT8_MAX = 127; +const UINT8_MAX = 255; + +function sat8(x) { + if (x < INT8_MIN) return INT8_MIN; + if (x > INT8_MAX) return INT8_MAX; + return x; +} + +function usat8(x) { + if (x < 0) return 0; + if (x > UINT8_MAX) return UINT8_MAX; + return x; +} + +function f() { + var i1 = SIMD.Int8x16(1, 100, 3, 4); + var i2 = SIMD.Int8x16(4, 30, 2, 1); + + var u1 = SIMD.Uint8x16(1, 2, 3, 4); + var u2 = SIMD.Uint8x16(4, 3, 2, 1); + + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Int8x16.addSaturate(i1, i2), binaryX((x, y) => sat8(x + y), i1, i2)); + assertEqX4(SIMD.Int8x16.subSaturate(i1, i2), binaryX((x, y) => sat8(x - y), i1, i2)); + + assertEqX4(SIMD.Uint8x16.addSaturate(u1, u2), binaryX((x, y) => usat8(x + y), u1, u2)); + assertEqX4(SIMD.Uint8x16.subSaturate(u1, u2), binaryX((x, y) => usat8(x - y), u1, u2)); + } +} + +f(); diff --git a/js/src/jit-test/tests/SIMD/select.js b/js/src/jit-test/tests/SIMD/select.js new file mode 100644 index 000000000..3f0d783da --- /dev/null +++ b/js/src/jit-test/tests/SIMD/select.js @@ -0,0 +1,35 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function select(type, mask, ifTrue, ifFalse) { + var arr = []; + for (var i = 0; i < 4; i++) { + var selector = SIMD.Bool32x4.extractLane(mask, i); + arr.push(type.extractLane(selector ? ifTrue : ifFalse, i)); + } + return arr; +} + +function f() { + var f1 = SIMD.Float32x4(1, 2, 3, 4); + var f2 = SIMD.Float32x4(NaN, Infinity, 3.14, -0); + + var i1 = SIMD.Int32x4(2, 3, 5, 8); + var i2 = SIMD.Int32x4(13, 37, 24, 42); + + var TTFT = SIMD.Bool32x4(true, true, false, true); + var TFTF = SIMD.Bool32x4(true, false, true, false); + + var mask = SIMD.Int32x4(0xdeadbeef, 0xbaadf00d, 0x00ff1ce, 0xdeadc0de); + + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Float32x4.select(TTFT, f1, f2), select(SIMD.Float32x4, TTFT, f1, f2)); + assertEqX4(SIMD.Float32x4.select(TFTF, f1, f2), select(SIMD.Float32x4, TFTF, f1, f2)); + + assertEqX4(SIMD.Int32x4.select(TFTF, i1, i2), select(SIMD.Int32x4, TFTF, i1, i2)); + assertEqX4(SIMD.Int32x4.select(TTFT, i1, i2), select(SIMD.Int32x4, TTFT, i1, i2)); + } +} + +f(); diff --git a/js/src/jit-test/tests/SIMD/shift.js b/js/src/jit-test/tests/SIMD/shift.js new file mode 100644 index 000000000..8448e52ec --- /dev/null +++ b/js/src/jit-test/tests/SIMD/shift.js @@ -0,0 +1,75 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function curry(f, arg) { return f.bind(null, arg); } + +function binaryLsh(count, v) { count &= 31; return (v << count) | 0; } +function lsh(count) { return curry(binaryLsh, count); } + +function binaryRsh(count, v) { count &= 31; return (v >> count) | 0; } +function rsh(count) { return curry(binaryRsh, count); } + +function binaryUlsh(count, v) { count &= 31; return (v << count) >>> 0; } +function ulsh(count) { return curry(binaryUlsh, count); } + +function binaryUrsh(count, v) { count &= 31; return v >>> count; } +function ursh(count) { return curry(binaryUrsh, count); } + +function f() { + var v = SIMD.Int32x4(1, 2, -3, 4); + var u = SIMD.Uint32x4(1, 0x55005500, -3, 0xaa00aa00); + var a = [1, 2, -3, 4]; + var b = [1, 0x55005500, -3, 0xaa00aa00]; + + var shifts = [-2, -1, 0, 1, 31, 32, 33]; + + var r; + for (var i = 0; i < 150; i++) { + // Constant shift counts + assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, -1), a.map(lsh(-1))); + assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 0), a.map(lsh(0))); + assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 1), a.map(lsh(1))); + assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 2), a.map(lsh(2))); + assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 31), a.map(lsh(31))); + assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 32), a.map(lsh(32))); + assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, 33), a.map(lsh(33))); + + assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, -1), a.map(rsh(31))); + assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 0), a.map(rsh(0))); + assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 1), a.map(rsh(1))); + assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 2), a.map(rsh(2))); + assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 31), a.map(rsh(31))); + assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 32), a.map(rsh(32))); + assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, 33), a.map(rsh(33))); + + assertEqX4(SIMD.Uint32x4.shiftLeftByScalar(u, -1), b.map(ulsh(-1))); + assertEqX4(SIMD.Uint32x4.shiftLeftByScalar(u, 0), b.map(ulsh(0))); + assertEqX4(SIMD.Uint32x4.shiftLeftByScalar(u, 1), b.map(ulsh(1))); + assertEqX4(SIMD.Uint32x4.shiftLeftByScalar(u, 2), b.map(ulsh(2))); + assertEqX4(SIMD.Uint32x4.shiftLeftByScalar(u, 31), b.map(ulsh(31))); + assertEqX4(SIMD.Uint32x4.shiftLeftByScalar(u, 32), b.map(ulsh(32))); + assertEqX4(SIMD.Uint32x4.shiftLeftByScalar(u, 33), b.map(ulsh(33))); + + assertEqX4(SIMD.Uint32x4.shiftRightByScalar(u, -1), b.map(ursh(-1))); + assertEqX4(SIMD.Uint32x4.shiftRightByScalar(u, 0), b.map(ursh(0))); + assertEqX4(SIMD.Uint32x4.shiftRightByScalar(u, 1), b.map(ursh(1))); + assertEqX4(SIMD.Uint32x4.shiftRightByScalar(u, 2), b.map(ursh(2))); + assertEqX4(SIMD.Uint32x4.shiftRightByScalar(u, 31), b.map(ursh(31))); + assertEqX4(SIMD.Uint32x4.shiftRightByScalar(u, 32), b.map(ursh(32))); + assertEqX4(SIMD.Uint32x4.shiftRightByScalar(u, 33), b.map(ursh(33))); + + // Non constant shift counts + var c = shifts[i % shifts.length]; + + assertEqX4(SIMD.Int32x4.shiftLeftByScalar(v, c), a.map(lsh(c))); + assertEqX4(SIMD.Int32x4.shiftRightByScalar(v, c), a.map(rsh(c))); + + assertEqX4(SIMD.Uint32x4.shiftLeftByScalar(u, c), b.map(ulsh(c))); + assertEqX4(SIMD.Uint32x4.shiftRightByScalar(u, c), b.map(ursh(c))); + } + return r; +} + +f(); + diff --git a/js/src/jit-test/tests/SIMD/shuffle.js b/js/src/jit-test/tests/SIMD/shuffle.js new file mode 100644 index 000000000..505f01131 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/shuffle.js @@ -0,0 +1,86 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var i1 = SIMD.Int32x4(1, 2, 3, 4); + var i2 = SIMD.Int32x4(5, 6, 7, 8); + + var leet = Math.fround(13.37); + var f1 = SIMD.Float32x4(-.5, -0, Infinity, leet); + var f2 = SIMD.Float32x4(42, .5, 23, -10); + + // computes all rotations of a given array + function *gen(arr) { + var previous = arr.slice().splice(0, 4); + var i = 4; + for (var j = 0; j < 8; j++) { + yield previous.slice(); + previous = previous.splice(1, previous.length - 1); + previous.push(arr[i]); + i = (i + 1) % arr.length; + } + } + + var compI = []; + var baseI = []; + for (var i = 0; i < 8; i++) + baseI.push(SIMD.Int32x4.extractLane(i < 4 ? i1 : i2, i % 4)); + for (var k of gen(baseI)) + compI.push(k); + + var compF = []; + var baseF = []; + for (var i = 0; i < 8; i++) + baseF.push(SIMD.Float32x4.extractLane(i < 4 ? f1 : f2, i % 4)); + for (var k of gen(baseF)) + compF.push(k); + + for (var i = 0; i < 150; i++) { + // Variable lanes + var r = SIMD.Float32x4.shuffle(f1, f2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8); + assertEqX4(r, compF[i % 8]); + + // Constant lanes + assertEqX4(SIMD.Float32x4.shuffle(f1, f2, 3, 2, 4, 5), [leet, Infinity, 42, .5]); + + // Variable lanes + var r = SIMD.Int32x4.shuffle(i1, i2, i % 8, (i + 1) % 8, (i + 2) % 8, (i + 3) % 8); + assertEqX4(r, compI[i % 8]); + + // Constant lanes + assertEqX4(SIMD.Int32x4.shuffle(i1, i2, 3, 2, 4, 5), [4, 3, 5, 6]); + } +} + +function testBailouts(expectException, uglyDuckling) { + var i1 = SIMD.Int32x4(1, 2, 3, 4); + var i2 = SIMD.Int32x4(5, 6, 7, 8); + + for (var i = 0; i < 150; i++) { + // Test bailouts + var value = i == 149 ? uglyDuckling : 0; + var caught = false; + try { + assertEqX4(SIMD.Int32x4.shuffle(i1, i2, value, 2, 4, 5), [1, 3, 5, 6]); + } catch(e) { + print(e); + caught = true; + assertEq(i, 149); + assertEq(e instanceof TypeError || e instanceof RangeError, true); + } + if (i == 149) + assertEq(caught, expectException); + } +} + +f(); +testBailouts(true, -1); +testBailouts(true, 8); +testBailouts(true, 2.5); +testBailouts(true, undefined); +testBailouts(true, {}); +testBailouts(true, 'one'); +testBailouts(false, false); +testBailouts(false, null); +testBailouts(false, " 0.0 "); diff --git a/js/src/jit-test/tests/SIMD/splat.js b/js/src/jit-test/tests/SIMD/splat.js new file mode 100644 index 000000000..38eda3085 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/splat.js @@ -0,0 +1,15 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Int32x4.splat(42), [42, 42, 42, 42]); + assertEqX4(SIMD.Float32x4.splat(42), [42, 42, 42, 42]); + assertEqX4(SIMD.Bool32x4.splat(true), [true, true, true, true]); + assertEqX4(SIMD.Bool32x4.splat(false), [false, false, false, false]); + } +} + +f(); + diff --git a/js/src/jit-test/tests/SIMD/store.js b/js/src/jit-test/tests/SIMD/store.js new file mode 100644 index 000000000..8cfa35427 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/store.js @@ -0,0 +1,143 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 40); + +function f() { + var f32 = new Float32Array(16); + for (var i = 0; i < 16; i++) + f32[i] = i + 1; + + var f64 = new Float64Array(f32.buffer); + var i32 = new Int32Array(f32.buffer); + var u32 = new Uint32Array(f32.buffer); + var i16 = new Int16Array(f32.buffer); + var u16 = new Uint16Array(f32.buffer); + var i8 = new Int8Array(f32.buffer); + var u8 = new Uint8Array(f32.buffer); + + var f4 = SIMD.Float32x4(42, 43, 44, 45); + + function check(n) { + assertEq(f32[0], 42); + assertEq(f32[1], n > 1 ? 43 : 2); + assertEq(f32[2], n > 2 ? 44 : 3); + assertEq(f32[3], n > 3 ? 45 : 4); + + f32[0] = 1; + f32[1] = 2; + f32[2] = 3; + f32[3] = 4; + } + + function testStore() { + SIMD.Float32x4.store(f64, 0, f4); + check(4); + SIMD.Float32x4.store(f32, 0, f4); + check(4); + SIMD.Float32x4.store(i32, 0, f4); + check(4); + SIMD.Float32x4.store(u32, 0, f4); + check(4); + SIMD.Float32x4.store(i16, 0, f4); + check(4); + SIMD.Float32x4.store(u16, 0, f4); + check(4); + SIMD.Float32x4.store(i8, 0, f4); + check(4); + SIMD.Float32x4.store(u8, 0, f4); + check(4); + } + + function testStore1() { + SIMD.Float32x4.store1(f64, 0, f4); + check(1); + SIMD.Float32x4.store1(f32, 0, f4); + check(1); + SIMD.Float32x4.store1(i32, 0, f4); + check(1); + SIMD.Float32x4.store1(u32, 0, f4); + check(1); + SIMD.Float32x4.store1(i16, 0, f4); + check(1); + SIMD.Float32x4.store1(u16, 0, f4); + check(1); + SIMD.Float32x4.store1(i8, 0, f4); + check(1); + SIMD.Float32x4.store1(u8, 0, f4); + check(1); + } + + function testStore2() { + SIMD.Float32x4.store2(f64, 0, f4); + check(2); + SIMD.Float32x4.store2(f32, 0, f4); + check(2); + SIMD.Float32x4.store2(i32, 0, f4); + check(2); + SIMD.Float32x4.store2(u32, 0, f4); + check(2); + SIMD.Float32x4.store2(i16, 0, f4); + check(2); + SIMD.Float32x4.store2(u16, 0, f4); + check(2); + SIMD.Float32x4.store2(i8, 0, f4); + check(2); + SIMD.Float32x4.store2(u8, 0, f4); + check(2); + } + + function testStore3() { + SIMD.Float32x4.store3(f64, 0, f4); + check(3); + SIMD.Float32x4.store3(f32, 0, f4); + check(3); + SIMD.Float32x4.store3(i32, 0, f4); + check(3); + SIMD.Float32x4.store3(u32, 0, f4); + check(3); + SIMD.Float32x4.store3(i16, 0, f4); + check(3); + SIMD.Float32x4.store3(u16, 0, f4); + check(3); + SIMD.Float32x4.store3(i8, 0, f4); + check(3); + SIMD.Float32x4.store3(u8, 0, f4); + check(3); + } + + for (var i = 0; i < 150; i++) { + testStore(); + testStore1(); + testStore2(); + testStore3(); + } +} + +f(); + +function testBailout(uglyDuckling) { + var f32 = new Float32Array(16); + for (var i = 0; i < 16; i++) + f32[i] = i + 1; + + var i8 = new Int8Array(f32.buffer); + + var f4 = SIMD.Float32x4(42, 43, 44, 45); + + for (var i = 0; i < 150; i++) { + var caught = false; + try { + SIMD.Float32x4.store(i8, (i < 149) ? 0 : (16 << 2) - (4 << 2) + 1, f4); + } catch (e) { + print(e); + assertEq(e instanceof RangeError, true); + caught = true; + } + assertEq(i < 149 || caught, true); + } +} + +print('Testing range checks...'); +testBailout(-1); +testBailout(-15); +testBailout(12 * 4 + 1); diff --git a/js/src/jit-test/tests/SIMD/swizzle.js b/js/src/jit-test/tests/SIMD/swizzle.js new file mode 100644 index 000000000..2fd56620b --- /dev/null +++ b/js/src/jit-test/tests/SIMD/swizzle.js @@ -0,0 +1,104 @@ +if (!this.hasOwnProperty("SIMD")) + quit(); + +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function f() { + var i4 = SIMD.Int32x4(1, 2, 3, 4); + + var leet = Math.fround(13.37); + var f4 = SIMD.Float32x4(-.5, -0, Infinity, leet); + + var compI = [ + [1,2,3,4], + [2,3,4,1], + [3,4,1,2], + [4,1,2,3] + ]; + + var compF = [ + [-.5, -0, Infinity, leet], + [-0, Infinity, leet, -.5], + [Infinity, leet, -.5, -0], + [leet, -.5, -0, Infinity] + ]; + + for (var i = 0; i < 150; i++) { + // Variable lanes + var r = SIMD.Float32x4.swizzle(f4, i % 4, (i + 1) % 4, (i + 2) % 4, (i + 3) % 4); + assertEqX4(r, compF[i % 4]); + + // Constant lanes + assertEqX4(SIMD.Float32x4.swizzle(f4, 3, 2, 1, 0), [leet, Infinity, -0, -.5]); + + // Variable lanes + var r = SIMD.Int32x4.swizzle(i4, i % 4, (i + 1) % 4, (i + 2) % 4, (i + 3) % 4); + assertEqX4(r, compI[i % 4]); + + // Constant lanes + assertEqX4(SIMD.Int32x4.swizzle(i4, 3, 2, 1, 0), [4, 3, 2, 1]); + } +} + +function testBailouts(expectException, uglyDuckling) { + var i4 = SIMD.Int32x4(1, 2, 3, 4); + for (var i = 0; i < 150; i++) { + // Test bailouts + var value = i == 149 ? uglyDuckling : 0; + var caught = false; + try { + assertEqX4(SIMD.Int32x4.swizzle(i4, value, 3, 2, 0), [1, 4, 3, 1]); + } catch(e) { + print(e); + caught = true; + assertEq(i, 149); + assertEq(e instanceof TypeError || e instanceof RangeError, true); + } + if (i == 149) + assertEq(caught, expectException); + } +} + +function testInt32x4SwizzleBailout() { + // Test out-of-bounds non-constant indices. This is expected to throw. + var i4 = SIMD.Int32x4(1, 2, 3, 4); + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Int32x4.swizzle(i4, i, 3, 2, 0), [i + 1, 4, 3, 1]); + } +} + +f(); +testBailouts(true, -1); +testBailouts(true, 4); +testBailouts(true, 2.5); +testBailouts(true, undefined); +testBailouts(true, {}); +testBailouts(true, 'one'); +testBailouts(false, false); +testBailouts(false, null); +testBailouts(false, " 0.0 "); + +try { + testInt32x4SwizzleBailout(); + throw 'not caught'; +} catch(e) { + assertEq(e instanceof RangeError, true); +} + +(function() { + var zappa = 0; + + function testBailouts() { + var i4 = SIMD.Int32x4(1, 2, 3, 4); + for (var i = 0; i < 300; i++) { + var value = i == 299 ? 2.5 : 1; + SIMD.Int32x4.swizzle(i4, value, 3, 2, 0); + zappa = i; + } + } + + try { testBailouts(); } catch (e) {} + assertEq(zappa, 298); +})(); diff --git a/js/src/jit-test/tests/SIMD/uconvert.js b/js/src/jit-test/tests/SIMD/uconvert.js new file mode 100644 index 000000000..a45fd7af9 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/uconvert.js @@ -0,0 +1,86 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 30); + +// Testing Uint32 <-> Float32 conversions. +// These conversions deserve special attention because SSE doesn't provide +// simple conversion instructions. + +// Convert an Uint32Array to a Float32Array using scalar conversions. +function cvt_utof_scalar(u32s, f32s) { + assertEq(u32s.length, f32s.length); + for (var i = 0; i < u32s.length; i++) { + f32s[i] = u32s[i]; + } +} + +// Convert an Uint32Array to a Float32Array using simd conversions. +function cvt_utof_simd(u32s, f32s) { + assertEq(u32s.length, f32s.length); + for (var i = 0; i < u32s.length; i += 4) { + SIMD.Float32x4.store(f32s, i, SIMD.Float32x4.fromUint32x4(SIMD.Uint32x4.load(u32s, i))); + } +} + +// Convert a Float32Array to an Uint32Array using scalar conversions. +function cvt_ftou_scalar(f32s, u32s) { + assertEq(f32s.length, u32s.length); + for (var i = 0; i < f32s.length; i++) { + u32s[i] = f32s[i]; + } +} + +// Convert a Float32Array to an Uint32Array using simd conversions. +function cvt_ftou_simd(f32s, u32s) { + assertEq(f32s.length, u32s.length); + for (var i = 0; i < f32s.length; i += 4) { + SIMD.Uint32x4.store(u32s, i, SIMD.Uint32x4.fromFloat32x4(SIMD.Float32x4.load(f32s, i))); + } +} + +function check(a, b) { + assertEq(a.length, b.length); + for (var i = 0; i < a.length; i++) { + assertEq(a[i], b[i]); + } +} + +// Uint32x4 --> Float32x4 tests. +var src = new Uint32Array(8000); +var dst1 = new Float32Array(8000); +var dst2 = new Float32Array(8000); + +for (var i = 0; i < 2000; i++) { + src[i] = i; + src[i + 2000] = 0x7fffffff - i; + src[i + 4000] = 0x80000000 + i; + src[i + 6000] = 0xffffffff - i; +} + +for (var n = 0; n < 10; n++) { + cvt_utof_scalar(src, dst1); + cvt_utof_simd(src, dst2); + check(dst1, dst2); +} + +// Float32x4 --> Uint32x4 tests. +var fsrc = dst1; +var fdst1 = new Uint32Array(8000); +var fdst2 = new Uint32Array(8000); + +// The 0xffffffff entries in fsrc round to 0x1.0p32f which throws. +// Go as high as 0x0.ffffffp32f. +for (var i = 0; i < 2000; i++) { + fsrc[i + 6000] = 0xffffff7f - i; +} + +// Truncation towards 0. +fsrc[1990] = -0.9 +fsrc[1991] = 0.9 +fsrc[1992] = 1.9 + +for (var n = 0; n < 10; n++) { + cvt_ftou_scalar(fsrc, fdst1); + cvt_ftou_simd(fsrc, fdst2); + check(fdst1, fdst2); +} diff --git a/js/src/jit-test/tests/SIMD/unary.js b/js/src/jit-test/tests/SIMD/unary.js new file mode 100644 index 000000000..34ec3fb10 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/unary.js @@ -0,0 +1,35 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("ion.warmup.trigger", 50); + +var notf = (function() { + var i32 = new Int32Array(1); + var f32 = new Float32Array(i32.buffer); + return function(x) { + f32[0] = x; + i32[0] = ~i32[0]; + return f32[0]; + } +})(); + +function f() { + var f4 = SIMD.Float32x4(1, 2, 3, 4); + var i4 = SIMD.Int32x4(1, 2, 3, 4); + var b4 = SIMD.Bool32x4(true, false, true, false); + var BitOrZero = (x) => x | 0; + for (var i = 0; i < 150; i++) { + assertEqX4(SIMD.Float32x4.neg(f4), unaryX4((x) => -x, f4, Math.fround)); + assertEqX4(SIMD.Float32x4.abs(f4), unaryX4(Math.abs, f4, Math.fround)); + assertEqX4(SIMD.Float32x4.sqrt(f4), unaryX4(Math.sqrt, f4, Math.fround)); + + assertEqX4(SIMD.Float32x4.reciprocalApproximation(f4), unaryX4((x) => 1 / x, f4, Math.fround), assertNear); + assertEqX4(SIMD.Float32x4.reciprocalSqrtApproximation(f4), unaryX4((x) => 1 / Math.sqrt(x), f4, Math.fround), assertNear); + + assertEqX4(SIMD.Int32x4.not(i4), unaryX4((x) => ~x, i4, BitOrZero)); + assertEqX4(SIMD.Int32x4.neg(i4), unaryX4((x) => -x, i4, BitOrZero)); + + assertEqX4(SIMD.Bool32x4.not(b4), unaryX4((x) => !x, b4, (x) => x )); + } +} + +f(); diff --git a/js/src/jit-test/tests/SIMD/unbox.js b/js/src/jit-test/tests/SIMD/unbox.js new file mode 100644 index 000000000..2fffddd06 --- /dev/null +++ b/js/src/jit-test/tests/SIMD/unbox.js @@ -0,0 +1,144 @@ +load(libdir + 'simd.js'); + +setJitCompilerOption("baseline.warmup.trigger", 10); +setJitCompilerOption("ion.warmup.trigger", 30); + +var max = 40, pivot = 35; + +var i32x4 = SIMD.Int32x4; +var f32x4 = SIMD.Float32x4; +var i32x4Add = SIMD.Int32x4.add; + +var FakeSIMDType = function (o) { this.x = o.x; this.y = o.y; this.z = o.z; this.w = o.w; }; +if (this.hasOwnProperty("TypedObject")) { + var TO = TypedObject; + FakeSIMDType = new TO.StructType({ x: TO.int32, y: TO.int32, z: TO.int32, w: TO.int32 }); +} + +function simdunbox_bail_undef(i, lhs, rhs) { + return i32x4Add(lhs, rhs); +} + +function simdunbox_bail_object(i, lhs, rhs) { + return i32x4Add(lhs, rhs); +} + +function simdunbox_bail_typeobj(i, lhs, rhs) { + return i32x4Add(lhs, rhs); +} + +function simdunbox_bail_badsimd(i, lhs, rhs) { + return i32x4Add(lhs, rhs); +} + +var arr_undef = [ i32x4(0, 1, 1, 2), i32x4(1, 1, 2, 3) ]; +var fail_undef = 0; +var arr_object = [ i32x4(0, 1, 1, 2), i32x4(1, 1, 2, 3) ]; +var fail_object = 0; +var arr_typeobj = [ i32x4(0, 1, 1, 2), i32x4(1, 1, 2, 3) ]; +var fail_typeobj = 0; +var arr_badsimd = [ i32x4(0, 1, 1, 2), i32x4(1, 1, 2, 3) ]; +var fail_badsimd = 0; +for (var i = 0; i < max; i++) { + try { + arr_undef[i + 2] = simdunbox_bail_undef(i, arr_undef[i], arr_undef[i + 1]); + } catch (x) { + arr_undef[i + 2] = arr_undef[i - 1]; + fail_undef++; + } + + try { + arr_object[i + 2] = simdunbox_bail_object(i, arr_object[i], arr_object[i + 1]); + } catch (x) { + arr_object[i + 2] = arr_object[i - 1]; + fail_object++; + } + + try { + arr_typeobj[i + 2] = simdunbox_bail_typeobj(i, arr_typeobj[i], arr_typeobj[i + 1]); + } catch (x) { + arr_typeobj[i + 2] = arr_typeobj[i - 1]; + fail_typeobj++; + } + + try { + arr_badsimd[i + 2] = simdunbox_bail_badsimd(i, arr_badsimd[i], arr_badsimd[i + 1]); + } catch (x) { + arr_badsimd[i + 2] = arr_badsimd[i - 1]; + fail_badsimd++; + } + + if (i + 2 == pivot) { + arr_undef[pivot] = undefined; + arr_object[pivot] = { x: 0, y: 1, z: 2, w: 3 }; + arr_typeobj[pivot] = new FakeSIMDType({ x: 0, y: 1, z: 2, w: 3 }); + arr_badsimd[pivot] = f32x4(0, 1, 2, 3); + } +} + +assertEq(fail_undef, 2); +assertEq(fail_object, 2); +assertEq(fail_typeobj, 2); +assertEq(fail_badsimd, 2); + +// Assert that all SIMD values are correct. +function assertEqX4(real, expected, assertFunc) { + if (typeof assertFunc === 'undefined') + assertFunc = assertEq; + + assertFunc(real.x, expected[0]); + assertFunc(real.y, expected[1]); + assertFunc(real.z, expected[2]); + assertFunc(real.w, expected[3]); +} + +var fib = [0, 1]; +for (i = 0; i < max + 5; i++) + fib[i+2] = (fib[i] + fib[i+1]) | 0; + +for (i = 0; i < max; i++) { + if (i == pivot) + continue; + var ref = fib.slice(i < pivot ? i : i - 3); + assertEqX4(arr_undef[i], ref); + assertEqX4(arr_object[i], ref); + assertEqX4(arr_typeobj[i], ref); + assertEqX4(arr_badsimd[i], ref); +} + +// Check that unbox operations aren't removed +(function() { + + function add(i, v, w) { + if (i % 2 == 0) { + SIMD.Int32x4.add(v, w); + } else { + SIMD.Float32x4.add(v, w); + } + } + + var i = 0; + var caught = false; + var f4 = SIMD.Float32x4(1,2,3,4); + var i4 = SIMD.Int32x4(1,2,3,4); + try { + for (; i < 200; i++) { + if (i % 2 == 0) { + add(i, i4, i4); + } else if (i == 199) { + add(i, i4, f4); + } else { + add(i, f4, f4); + } + } + } catch(e) { + print(e); + assertEq(e instanceof TypeError, true); + assertEq(i, 199); + caught = true; + } + + assertEq(i < 199 || caught, true); + +})(); + |