Bug 931489 - IonMonkey: Use range analysis to avoid testing for special cases in PowHalf. r=nbp
authorDan Gohman <sunfish@google.com>
Tue, 12 Nov 2013 05:46:43 -0800
changeset 154515 91d286c5eeccff55469dfd1908369a490fd3955b
parent 154514 5fc52820456de9b83cc271a67942fde75ccbfab0
child 154516 bf086d7163fffb7e2ca2a06ef542d3c34da1e027
push id36115
push usersunfish@google.com
push dateTue, 12 Nov 2013 13:47:30 +0000
treeherdermozilla-inbound@1129630ac08e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs931489
milestone28.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 931489 - IonMonkey: Use range analysis to avoid testing for special cases in PowHalf. r=nbp
js/src/jit/MIR.h
js/src/jit/RangeAnalysis.cpp
js/src/jit/shared/CodeGenerator-x86-shared.cpp
js/src/jit/shared/LIR-x86-shared.h
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3668,37 +3668,54 @@ class MPow
     }
 };
 
 // Inline implementation of Math.pow(x, 0.5), which subtly differs from Math.sqrt(x).
 class MPowHalf
   : public MUnaryInstruction,
     public DoublePolicy<0>
 {
+    bool operandIsNeverNegativeInfinity_;
+    bool operandIsNeverNegativeZero_;
+    bool operandIsNeverNaN_;
+
     MPowHalf(MDefinition *input)
-      : MUnaryInstruction(input)
+      : MUnaryInstruction(input),
+        operandIsNeverNegativeInfinity_(false),
+        operandIsNeverNegativeZero_(false),
+        operandIsNeverNaN_(false)
     {
         setResultType(MIRType_Double);
         setMovable();
     }
 
   public:
     INSTRUCTION_HEADER(PowHalf)
     static MPowHalf *New(MDefinition *input) {
         return new MPowHalf(input);
     }
     bool congruentTo(MDefinition *ins) const {
         return congruentIfOperandsEqual(ins);
     }
+    bool operandIsNeverNegativeInfinity() const {
+        return operandIsNeverNegativeInfinity_;
+    }
+    bool operandIsNeverNegativeZero() const {
+        return operandIsNeverNegativeZero_;
+    }
+    bool operandIsNeverNaN() const {
+        return operandIsNeverNaN_;
+    }
     TypePolicy *typePolicy() {
         return this;
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
+    void collectRangeInfo();
 };
 
 // Inline implementation of Math.random().
 class MRandom : public MNullaryInstruction
 {
     MRandom()
     {
         setResultType(MIRType_Double);
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -2419,8 +2419,18 @@ MCompare::collectRangeInfo()
     operandsAreNeverNaN_ = !Range(lhs()).canBeNaN() && !Range(rhs()).canBeNaN();
 }
 
 void
 MNot::collectRangeInfo()
 {
     operandIsNeverNaN_ = !Range(operand()).canBeNaN();
 }
+
+void
+MPowHalf::collectRangeInfo()
+{
+    Range inputRange(input());
+    operandIsNeverNegativeInfinity_ = !inputRange.canBeInfiniteOrNaN() ||
+                                      inputRange.hasInt32LowerBound();
+    operandIsNeverNegativeZero_ = !inputRange.canBeZero();
+    operandIsNeverNaN_ = !inputRange.canBeNaN();
+}
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -546,29 +546,39 @@ CodeGeneratorX86Shared::visitSqrtF(LSqrt
 bool
 CodeGeneratorX86Shared::visitPowHalfD(LPowHalfD *ins)
 {
     FloatRegister input = ToFloatRegister(ins->input());
     JS_ASSERT(input == ToFloatRegister(ins->output()));
 
     Label done, sqrt;
 
-    // Branch if not -Infinity.
-    masm.loadConstantDouble(NegativeInfinity(), ScratchFloatReg);
-    masm.branchDouble(Assembler::DoubleNotEqualOrUnordered, input, ScratchFloatReg, &sqrt);
+    if (!ins->mir()->operandIsNeverNegativeInfinity()) {
+        // Branch if not -Infinity.
+        masm.loadConstantDouble(NegativeInfinity(), ScratchFloatReg);
+
+        Assembler::DoubleCondition cond = Assembler::DoubleNotEqualOrUnordered;
+        if (ins->mir()->operandIsNeverNaN())
+            cond = Assembler::DoubleNotEqual;
+        masm.branchDouble(cond, input, ScratchFloatReg, &sqrt);
 
-    // Math.pow(-Infinity, 0.5) == Infinity.
-    masm.xorpd(input, input);
-    masm.subsd(ScratchFloatReg, input);
-    masm.jump(&done);
+        // Math.pow(-Infinity, 0.5) == Infinity.
+        masm.xorpd(input, input);
+        masm.subsd(ScratchFloatReg, input);
+        masm.jump(&done);
 
-    // Math.pow(-0, 0.5) == 0 == Math.pow(0, 0.5). Adding 0 converts any -0 to 0.
-    masm.bind(&sqrt);
-    masm.xorpd(ScratchFloatReg, ScratchFloatReg);
-    masm.addsd(ScratchFloatReg, input);
+        masm.bind(&sqrt);
+    }
+
+    if (!ins->mir()->operandIsNeverNegativeZero()) {
+        // Math.pow(-0, 0.5) == 0 == Math.pow(0, 0.5). Adding 0 converts any -0 to 0.
+        masm.xorpd(ScratchFloatReg, ScratchFloatReg);
+        masm.addsd(ScratchFloatReg, input);
+    }
+
     masm.sqrtsd(input, input);
 
     masm.bind(&done);
     return true;
 }
 
 class OutOfLineUndoALUOperation : public OutOfLineCodeBase<CodeGeneratorX86Shared>
 {
--- a/js/src/jit/shared/LIR-x86-shared.h
+++ b/js/src/jit/shared/LIR-x86-shared.h
@@ -166,16 +166,19 @@ class LPowHalfD : public LInstructionHel
     }
 
     const LAllocation *input() {
         return getOperand(0);
     }
     const LDefinition *output() {
         return getDef(0);
     }
+    MPowHalf *mir() const {
+        return mir_->toPowHalf();
+    }
 };
 
 // Takes a tableswitch with an integer to decide
 class LTableSwitch : public LInstructionHelper<0, 1, 2>
 {
   public:
     LIR_HEADER(TableSwitch)