Bug 999764 - Optimize floating-point division into multiplication when safe; r=sunfish
authorSankha Narayan Guria <sankha93@gmail.com>
Wed, 09 Jul 2014 11:37:14 +0200
changeset 193212 b447f4f12410a8f510037348939ef5b2aba26e23
parent 193211 06ecc23ac9e8a93c0b35f3e27e9feecd12313912
child 193213 a61e96de3acb0acba4def22f3bc9f33b70183564
push id27112
push usercbook@mozilla.com
push dateThu, 10 Jul 2014 12:47:23 +0000
treeherdermozilla-central@6e9f72bdd32e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssunfish
bugs999764
milestone33.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 999764 - Optimize floating-point division into multiplication when safe; r=sunfish
js/src/jit/MIR.cpp
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -2,16 +2,17 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/MIR.h"
 
 #include "mozilla/FloatingPoint.h"
+#include "mozilla/MathAlgorithms.h"
 
 #include <ctype.h>
 
 #include "jslibmath.h"
 #include "jsstr.h"
 
 #include "jit/BaselineInspector.h"
 #include "jit/IonBuilder.h"
@@ -129,16 +130,48 @@ EvaluateConstantOperands(TempAllocator &
         if (ptypeChange)
             *ptypeChange = true;
         return nullptr;
     }
 
     return MConstant::New(alloc, ret);
 }
 
+static MMul *
+EvaluateExactReciprocal(TempAllocator &alloc, MDiv *ins)
+{
+    // we should fold only when it is a floating point operation
+    if (!IsFloatingPointType(ins->type()))
+        return nullptr;
+
+    MDefinition *left = ins->getOperand(0);
+    MDefinition *right = ins->getOperand(1);
+
+    if (!right->isConstant())
+        return nullptr;
+
+    Value rhs = right->toConstant()->value();
+
+    int32_t num;
+    if (!mozilla::NumberIsInt32(rhs.toNumber(), &num))
+        return nullptr;
+
+    // check if rhs is a power of two
+    if (mozilla::Abs(num) & (mozilla::Abs(num) - 1))
+        return nullptr;
+
+    Value ret;
+    ret.setDouble(1.0 / (double) num);
+    MConstant *foldedRhs = MConstant::New(alloc, ret);
+    foldedRhs->setResultType(ins->type());
+    ins->block()->insertBefore(ins, foldedRhs);
+
+    return MMul::New(alloc, left, foldedRhs, ins->type());
+}
+
 void
 MDefinition::printName(FILE *fp) const
 {
     PrintOpcodeName(fp, op());
     fprintf(fp, "%u", id());
 }
 
 HashNumber
@@ -1500,16 +1533,19 @@ MDefinition *
 MDiv::foldsTo(TempAllocator &alloc)
 {
     if (specialization_ == MIRType_None)
         return this;
 
     if (MDefinition *folded = EvaluateConstantOperands(alloc, this))
         return folded;
 
+    if (MDefinition *folded = EvaluateExactReciprocal(alloc, this))
+        return folded;
+
     return this;
 }
 
 void
 MDiv::analyzeEdgeCasesForward()
 {
     // This is only meaningful when doing integer division.
     if (specialization_ != MIRType_Int32)