Bug 996076: Add SIMD.float32x4.{not,and,or,xor} to the interpreter; r=nmatsakis
authorBenjamin Bouvier <benj@benj.me>
Fri, 02 May 2014 13:11:16 +0200
changeset 201652 ab9a69f74b98611067c029d05a72cb340489e5d0
parent 201651 e522c302dd96c6b2f494de8ea7489d232fdd2711
child 201653 8eddc5ea91ba64b346bfe15783c5c4ad58cfbfec
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnmatsakis
bugs996076
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 996076: Add SIMD.float32x4.{not,and,or,xor} to the interpreter; r=nmatsakis
js/src/builtin/SIMD.cpp
js/src/builtin/SIMD.h
js/src/tests/ecma_6/TypedObject/simd/float32x4and.js
js/src/tests/ecma_6/TypedObject/simd/float32x4not.js
js/src/tests/ecma_6/TypedObject/simd/float32x4or.js
js/src/tests/ecma_6/TypedObject/simd/float32x4xor.js
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -558,54 +558,65 @@ struct Shuffle {
 
 static inline bool
 ErrorBadArgs(JSContext *cx)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
     return false;
 }
 
-template<typename V, typename Op, typename Vret>
+// Coerces the inputs of type In to the type Coercion, apply the operator Op
+// and converts the result to the type Out.
+template<typename In, typename Coercion, typename Op, typename Out>
 static bool
-Func(JSContext *cx, unsigned argc, Value *vp)
+CoercedFunc(JSContext *cx, unsigned argc, Value *vp)
 {
-    typedef typename V::Elem Elem;
-    typedef typename Vret::Elem RetElem;
+    typedef typename Coercion::Elem CoercionElem;
+    typedef typename Out::Elem RetElem;
 
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() != 1 && args.length() != 2)
         return ErrorBadArgs(cx);
 
-    RetElem result[Vret::lanes];
+    CoercionElem result[Coercion::lanes];
     if (args.length() == 1) {
-        if (!IsVectorObject<V>(args[0]))
+        if (!IsVectorObject<In>(args[0]))
             return ErrorBadArgs(cx);
 
-        Elem *val = TypedObjectMemory<Elem *>(args[0]);
-        for (unsigned i = 0; i < Vret::lanes; i++)
+        CoercionElem *val = TypedObjectMemory<CoercionElem *>(args[0]);
+        for (unsigned i = 0; i < Coercion::lanes; i++)
             result[i] = Op::apply(val[i], 0);
     } else {
         JS_ASSERT(args.length() == 2);
-        if (!IsVectorObject<V>(args[0]) || !IsVectorObject<V>(args[1]))
+        if (!IsVectorObject<In>(args[0]) || !IsVectorObject<In>(args[1]))
             return ErrorBadArgs(cx);
 
-        Elem *left = TypedObjectMemory<Elem *>(args[0]);
-        Elem *right = TypedObjectMemory<Elem *>(args[1]);
-        for (unsigned i = 0; i < Vret::lanes; i++)
+        CoercionElem *left = TypedObjectMemory<CoercionElem *>(args[0]);
+        CoercionElem *right = TypedObjectMemory<CoercionElem *>(args[1]);
+        for (unsigned i = 0; i < Coercion::lanes; i++)
             result[i] = Op::apply(left[i], right[i]);
     }
 
-    RootedObject obj(cx, Create<Vret>(cx, result));
+    RetElem *coercedResult = reinterpret_cast<RetElem *>(result);
+    RootedObject obj(cx, Create<Out>(cx, coercedResult));
     if (!obj)
         return false;
 
     args.rval().setObject(*obj);
     return true;
 }
 
+// Same as above, with Coercion == Out
+template<typename In, typename Op, typename Out>
+static bool
+Func(JSContext *cx, unsigned argc, Value *vp)
+{
+    return CoercedFunc<In, Out, Op, Out>(cx, argc, vp);
+}
+
 template<typename V, typename OpWith, typename Vret>
 static bool
 FuncWith(JSContext *cx, unsigned argc, Value *vp)
 {
     typedef typename V::Elem Elem;
     typedef typename Vret::Elem RetElem;
 
     CallArgs args = CallArgsFromVp(argc, vp);
--- a/js/src/builtin/SIMD.h
+++ b/js/src/builtin/SIMD.h
@@ -20,41 +20,45 @@
 
 #define FLOAT32X4_NULLARY_FUNCTION_LIST(V)                                                                        \
   V(zero, (FuncZero<Float32x4>), 0, 0, Zero)
 
 #define FLOAT32X4_UNARY_FUNCTION_LIST(V)                                                                          \
   V(abs, (Func<Float32x4, Abs<float, Float32x4>, Float32x4>), 1, 0, Abs)                                          \
   V(bitsToInt32x4, (FuncConvertBits<Float32x4, Int32x4>), 1, 0, BitsToInt32x4)                                    \
   V(neg, (Func<Float32x4, Neg<float, Float32x4>, Float32x4>), 1, 0, Neg)                                          \
+  V(not, (CoercedFunc<Float32x4, Int32x4, Not<int32_t, Int32x4>, Float32x4>), 1, 0, Not)                          \
   V(reciprocal, (Func<Float32x4, Rec<float, Float32x4>, Float32x4>), 1, 0, Reciprocal)                            \
   V(reciprocalSqrt, (Func<Float32x4, RecSqrt<float, Float32x4>, Float32x4>), 1, 0, ReciprocalSqrt)                \
   V(splat, (FuncSplat<Float32x4>), 1, 0, Splat)                                                                   \
   V(sqrt, (Func<Float32x4, Sqrt<float, Float32x4>, Float32x4>), 1, 0, Sqrt)                                       \
   V(toInt32x4, (FuncConvert<Float32x4, Int32x4>), 1, 0, ToInt32x4)
 
 #define FLOAT32X4_BINARY_FUNCTION_LIST(V)                                                                         \
   V(add, (Func<Float32x4, Add<float, Float32x4>, Float32x4>), 2, 0, Add)                                          \
+  V(and, (CoercedFunc<Float32x4, Int32x4, And<int32_t, Int32x4>, Float32x4>), 2, 0, And)                          \
   V(div, (Func<Float32x4, Div<float, Float32x4>, Float32x4>), 2, 0, Div)                                          \
   V(equal, (Func<Float32x4, Equal<float, Int32x4>, Int32x4>), 2, 0, Equal)                                        \
   V(greaterThan, (Func<Float32x4, GreaterThan<float, Int32x4>, Int32x4>), 2, 0, GreaterThan)                      \
   V(greaterThanOrEqual, (Func<Float32x4, GreaterThanOrEqual<float, Int32x4>, Int32x4>), 2, 0, GreaterThanOrEqual) \
   V(lessThan, (Func<Float32x4, LessThan<float, Int32x4>, Int32x4>), 2, 0, LessThan)                               \
   V(lessThanOrEqual, (Func<Float32x4, LessThanOrEqual<float, Int32x4>, Int32x4>), 2, 0, LessThanOrEqual)          \
   V(max, (Func<Float32x4, Maximum<float, Float32x4>, Float32x4>), 2, 0, Max)                                      \
   V(min, (Func<Float32x4, Minimum<float, Float32x4>, Float32x4>), 2, 0, Min)                                      \
   V(mul, (Func<Float32x4, Mul<float, Float32x4>, Float32x4>), 2, 0, Mul)                                          \
   V(notEqual, (Func<Float32x4, NotEqual<float, Int32x4>, Int32x4>), 2, 0, NotEqual)                               \
+  V(or, (CoercedFunc<Float32x4, Int32x4, Or<int32_t, Int32x4>, Float32x4>), 2, 0, Or)                             \
   V(shuffle, (FuncShuffle<Float32x4, Shuffle<float, Float32x4>, Float32x4>), 2, 0, Shuffle)                       \
   V(scale, (FuncWith<Float32x4, Scale<float, Float32x4>, Float32x4>), 2, 0, Scale)                                \
   V(sub, (Func<Float32x4, Sub<float, Float32x4>, Float32x4>), 2, 0, Sub)                                          \
   V(withX, (FuncWith<Float32x4, WithX<float, Float32x4>, Float32x4>), 2, 0, WithX)                                \
   V(withY, (FuncWith<Float32x4, WithY<float, Float32x4>, Float32x4>), 2, 0, WithY)                                \
   V(withZ, (FuncWith<Float32x4, WithZ<float, Float32x4>, Float32x4>), 2, 0, WithZ)                                \
-  V(withW, (FuncWith<Float32x4, WithW<float, Float32x4>, Float32x4>), 2, 0, WithW)
+  V(withW, (FuncWith<Float32x4, WithW<float, Float32x4>, Float32x4>), 2, 0, WithW)                                \
+  V(xor, (CoercedFunc<Float32x4, Int32x4, Xor<int32_t, Int32x4>, Float32x4>), 2, 0, Xor)
 
 #define FLOAT32X4_TERNARY_FUNCTION_LIST(V)                                                                        \
   V(clamp, Float32x4Clamp, 3, 0, Clamp)                                                                           \
   V(shuffleMix, (FuncShuffle<Float32x4, Shuffle<float, Float32x4>, Float32x4>), 3, 0, ShuffleMix)
 
 #define FLOAT32X4_FUNCTION_LIST(V)                                                                                \
   FLOAT32X4_NULLARY_FUNCTION_LIST(V)                                                                              \
   FLOAT32X4_UNARY_FUNCTION_LIST(V)                                                                                \
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4and.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
+var BUGNUMBER = 996076;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 and';
+
+var andf = (function() {
+    var i = new Int32Array(3);
+    var f = new Float32Array(i.buffer);
+    return function(x, y) {
+        f[0] = x;
+        f[1] = y;
+        i[2] = i[0] & i[1];
+        return f[2];
+    }
+})();
+
+function test() {
+  print(BUGNUMBER + ": " + summary);
+
+  // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+  var a = float32x4(1, 2, 3, 4);
+  var b = float32x4(10, 20, 30, 40);
+  var c = SIMD.float32x4.and(a, b);
+  assertEq(c.x, andf(1, 10));
+  assertEq(c.y, andf(2, 20));
+  assertEq(c.z, andf(3, 30));
+  assertEq(c.w, andf(4, 40));
+
+  if (typeof reportCompare === "function")
+    reportCompare(true, true);
+}
+
+test();
+
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4not.js
@@ -0,0 +1,35 @@
+// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
+var BUGNUMBER = 996076;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 not';
+
+var notf = (function() {
+    var i = new Int32Array(1);
+    var f = new Float32Array(i.buffer);
+    return function(x) {
+        f[0] = x;
+        i[0] = ~i[0];
+        return f[0];
+    }
+})();
+
+function test() {
+  print(BUGNUMBER + ": " + summary);
+
+  // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+  var a = float32x4(2, 13, -37, 4.2);
+  var c = SIMD.float32x4.not(a);
+  assertEq(c.x, notf(2));
+  assertEq(c.y, notf(13));
+  assertEq(c.z, notf(-37));
+  assertEq(c.w, notf(4.2));
+
+  if (typeof reportCompare === "function")
+    reportCompare(true, true);
+}
+
+test();
+
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4or.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
+var BUGNUMBER = 996076;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 and';
+
+var orf = (function() {
+    var i = new Int32Array(3);
+    var f = new Float32Array(i.buffer);
+    return function(x, y) {
+        f[0] = x;
+        f[1] = y;
+        i[2] = i[0] | i[1];
+        return f[2];
+    }
+})();
+
+function test() {
+  print(BUGNUMBER + ": " + summary);
+
+  // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+  var a = float32x4(1, 2, 3, 4);
+  var b = float32x4(10, 20, 30, 40);
+  var c = SIMD.float32x4.or(a, b);
+  assertEq(c.x, orf(1, 10));
+  assertEq(c.y, orf(2, 20));
+  assertEq(c.z, orf(3, 30));
+  assertEq(c.w, orf(4, 40));
+
+  if (typeof reportCompare === "function")
+    reportCompare(true, true);
+}
+
+test();
+
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedObject/simd/float32x4xor.js
@@ -0,0 +1,37 @@
+// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
+var BUGNUMBER = 996076;
+var float32x4 = SIMD.float32x4;
+var int32x4 = SIMD.int32x4;
+
+var summary = 'float32x4 and';
+
+var xorf = (function() {
+    var i = new Int32Array(3);
+    var f = new Float32Array(i.buffer);
+    return function(x, y) {
+        f[0] = x;
+        f[1] = y;
+        i[2] = i[0] ^ i[1];
+        return f[2];
+    }
+})();
+
+function test() {
+  print(BUGNUMBER + ": " + summary);
+
+  // FIXME -- Bug 948379: Amend to check for correctness of border cases.
+
+  var a = float32x4(1, 2, 3, 4);
+  var b = float32x4(10, 20, 30, 40);
+  var c = SIMD.float32x4.xor(a, b);
+  assertEq(c.x, xorf(1, 10));
+  assertEq(c.y, xorf(2, 20));
+  assertEq(c.z, xorf(3, 30));
+  assertEq(c.w, xorf(4, 40));
+
+  if (typeof reportCompare === "function")
+    reportCompare(true, true);
+}
+
+test();
+