summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/SIMD
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/SIMD')
-rw-r--r--js/src/jit-test/tests/SIMD/binary-arith.js30
-rw-r--r--js/src/jit-test/tests/SIMD/bool32x4-arith.js15
-rw-r--r--js/src/jit-test/tests/SIMD/bool32x4-const.js65
-rw-r--r--js/src/jit-test/tests/SIMD/bug1109911.js11
-rw-r--r--js/src/jit-test/tests/SIMD/bug1121299.js31
-rw-r--r--js/src/jit-test/tests/SIMD/bug1123631.js9
-rw-r--r--js/src/jit-test/tests/SIMD/bug1130845.js15
-rw-r--r--js/src/jit-test/tests/SIMD/bug1241872.js10
-rw-r--r--js/src/jit-test/tests/SIMD/bug1248503.js16
-rw-r--r--js/src/jit-test/tests/SIMD/bug1273483.js9
-rw-r--r--js/src/jit-test/tests/SIMD/bug1296640-gc-args.js9
-rw-r--r--js/src/jit-test/tests/SIMD/bug1303780-gc-args.js12
-rw-r--r--js/src/jit-test/tests/SIMD/bug953108.js10
-rw-r--r--js/src/jit-test/tests/SIMD/check.js25
-rw-r--r--js/src/jit-test/tests/SIMD/compare.js39
-rw-r--r--js/src/jit-test/tests/SIMD/complex-4.js70
-rw-r--r--js/src/jit-test/tests/SIMD/convert.js68
-rw-r--r--js/src/jit-test/tests/SIMD/float32x4-binary-arith.js33
-rw-r--r--js/src/jit-test/tests/SIMD/getters.js48
-rw-r--r--js/src/jit-test/tests/SIMD/inline-missing-arguments.js81
-rw-r--r--js/src/jit-test/tests/SIMD/load.js123
-rw-r--r--js/src/jit-test/tests/SIMD/nursery-overflow.js29
-rw-r--r--js/src/jit-test/tests/SIMD/recover.js70
-rw-r--r--js/src/jit-test/tests/SIMD/replacelane.js181
-rw-r--r--js/src/jit-test/tests/SIMD/saturate.js37
-rw-r--r--js/src/jit-test/tests/SIMD/select.js35
-rw-r--r--js/src/jit-test/tests/SIMD/shift.js75
-rw-r--r--js/src/jit-test/tests/SIMD/shuffle.js86
-rw-r--r--js/src/jit-test/tests/SIMD/splat.js15
-rw-r--r--js/src/jit-test/tests/SIMD/store.js143
-rw-r--r--js/src/jit-test/tests/SIMD/swizzle.js104
-rw-r--r--js/src/jit-test/tests/SIMD/uconvert.js86
-rw-r--r--js/src/jit-test/tests/SIMD/unary.js35
-rw-r--r--js/src/jit-test/tests/SIMD/unbox.js144
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);
+
+})();
+