Bug 1112158 - Optimize MSimdUnbox with GVN. r=bbouvier
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Thu, 26 Feb 2015 16:18:40 +0100
changeset 230997 46d274a6952edfbc427b66b486a1c58a1e8bc5d5
parent 230996 b273c0746faf92c6c21c6a3df295feeead4434c0
child 230998 2a0481539f3828b5d99a651c830f4f332f37cf34
push id28341
push userkwierso@gmail.com
push dateFri, 27 Feb 2015 02:25:40 +0000
treeherdermozilla-central@93707c1b4edb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs1112158
milestone39.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 1112158 - Optimize MSimdUnbox with GVN. r=bbouvier
js/src/jit-test/tests/SIMD/complex-4.js
js/src/jit/MIR.cpp
js/src/jit/MIR.h
new file mode 100644
--- /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));
+}
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -917,16 +917,34 @@ MSimdSplatX4::foldsTo(TempAllocator &all
       }
       default: MOZ_CRASH("unexpected type in MSimdSplatX4::foldsTo");
     }
 
     return MSimdConstant::New(alloc, cst, type());
 }
 
 MDefinition *
+MSimdUnbox::foldsTo(TempAllocator &alloc)
+{
+    MDefinition *in = input();
+
+    if (in->isSimdBox()) {
+        // If the operand is a MSimdBox, then we just reuse the operand of the
+        // MSimdBox as long as the type corresponds to what we are supposed to
+        // unbox.
+        in = in->toSimdBox()->input();
+        if (in->type() != type())
+            return this;
+        return in;
+    }
+
+    return this;
+}
+
+MDefinition *
 MSimdSwizzle::foldsTo(TempAllocator &alloc)
 {
     if (lanesMatch(0, 1, 2, 3))
         return input();
     return this;
 }
 
 MCloneLiteral *
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3051,16 +3051,21 @@ class MSimdUnbox
     INSTRUCTION_HEADER(SimdUnbox)
     ALLOW_CLONE(MSimdUnbox)
 
     static MSimdUnbox *New(TempAllocator &alloc, MDefinition *op, MIRType type)
     {
         return new(alloc) MSimdUnbox(op, type);
     }
 
+    MDefinition *foldsTo(TempAllocator &alloc) MOZ_OVERRIDE;
+    bool congruentTo(const MDefinition *ins) const MOZ_OVERRIDE {
+        return congruentIfOperandsEqual(ins);
+    }
+
     AliasSet getAliasSet() const MOZ_OVERRIDE {
         return AliasSet::None();
     }
 };
 
 // Creates a new derived type object. At runtime, this is just a call
 // to `BinaryBlock::createDerived()`. That is, the MIR itself does not
 // compile to particularly optimized code. However, using a distinct