Bug 931489 - IonMonkey: Omit the NaN check for LNotD if range analysis says there are no NaNs. r=nbp
authorDan Gohman <sunfish@google.com>
Sat, 02 Nov 2013 14:29:44 -0700
changeset 153269 3d175be0fcb0e51946459cdca3abd3917ef3c60e
parent 153268 e9ff16009983c0f79efa0f86f65f11f46c857e44
child 153270 238b3c81f42c11f3f0d9dd9c27d6ed7238523c2b
push id25578
push userphilringnalda@gmail.com
push dateSun, 03 Nov 2013 21:05:48 +0000
treeherdermozilla-central@fc3414dda755 [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: Omit the NaN check for LNotD if range analysis says there are no NaNs. r=nbp
js/src/jit/LIR-Common.h
js/src/jit/MIR.h
js/src/jit/RangeAnalysis.cpp
js/src/jit/shared/CodeGenerator-x86-shared.cpp
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -2013,27 +2013,35 @@ class LNotI : public LInstructionHelper<
 class LNotD : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NotD)
 
     LNotD(const LAllocation &input) {
         setOperand(0, input);
     }
+
+    MNot *mir() {
+        return mir_->toNot();
+    }
 };
 
 // Not operation on a float32.
 class LNotF : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NotF)
 
     LNotF(const LAllocation &input) {
         setOperand(0, input);
     }
+
+    MNot *mir() {
+        return mir_->toNot();
+    }
 };
 
 // Boolean complement operation on an object.
 class LNotO : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(NotO)
 
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -5154,21 +5154,23 @@ class MTypedObjectElements
 };
 
 // Perform !-operation
 class MNot
   : public MUnaryInstruction,
     public TestPolicy
 {
     bool operandMightEmulateUndefined_;
+    bool operandIsNeverNaN_;
 
   public:
     MNot(MDefinition *input)
       : MUnaryInstruction(input),
-        operandMightEmulateUndefined_(true)
+        operandMightEmulateUndefined_(true),
+        operandIsNeverNaN_(false)
     {
         setResultType(MIRType_Boolean);
         setMovable();
     }
 
     static MNot *New(MDefinition *elements) {
         return new MNot(elements);
     }
@@ -5184,27 +5186,31 @@ class MNot
     MDefinition *foldsTo(bool useValueNumbers);
 
     void markOperandCantEmulateUndefined() {
         operandMightEmulateUndefined_ = false;
     }
     bool operandMightEmulateUndefined() const {
         return operandMightEmulateUndefined_;
     }
+    bool operandIsNeverNaN() const {
+        return operandIsNeverNaN_;
+    }
 
     MDefinition *operand() const {
         return getOperand(0);
     }
 
     virtual AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     TypePolicy *typePolicy() {
         return this;
     }
+    void collectRangeInfo();
 
     void trySpecializeFloat32();
     bool isFloat32Commutative() const { return true; }
 #ifdef DEBUG
     bool isConsistentFloat32Use() const {
         return true;
     }
 #endif
--- a/js/src/jit/RangeAnalysis.cpp
+++ b/js/src/jit/RangeAnalysis.cpp
@@ -2408,8 +2408,14 @@ MBoundsCheckLower::collectRangeInfo()
     fallible_ = !indexRange.hasInt32LowerBound() || indexRange.lower() < minimum_;
 }
 
 void
 MCompare::collectRangeInfo()
 {
     operandsAreNeverNaN_ = !Range(lhs()).canBeNaN() && !Range(rhs()).canBeNaN();
 }
+
+void
+MNot::collectRangeInfo()
+{
+    operandIsNeverNaN_ = !Range(operand()).canBeNaN();
+}
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -229,30 +229,42 @@ CodeGeneratorX86Shared::visitNotI(LNotI 
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::visitNotD(LNotD *ins)
 {
     FloatRegister opd = ToFloatRegister(ins->input());
 
+    // Not returns true if the input is a NaN. We don't have to worry about
+    // it if we know the input is never NaN though.
+    Assembler::NaNCond nanCond = Assembler::NaN_IsTrue;
+    if (ins->mir()->operandIsNeverNaN())
+        nanCond = Assembler::NaN_HandledByCond;
+
     masm.xorpd(ScratchFloatReg, ScratchFloatReg);
     masm.compareDouble(Assembler::DoubleEqualOrUnordered, opd, ScratchFloatReg);
-    masm.emitSet(Assembler::Equal, ToRegister(ins->output()), Assembler::NaN_IsTrue);
+    masm.emitSet(Assembler::Equal, ToRegister(ins->output()), nanCond);
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::visitNotF(LNotF *ins)
 {
     FloatRegister opd = ToFloatRegister(ins->input());
 
+    // Not returns true if the input is a NaN. We don't have to worry about
+    // it if we know the input is never NaN though.
+    Assembler::NaNCond nanCond = Assembler::NaN_IsTrue;
+    if (ins->mir()->operandIsNeverNaN())
+        nanCond = Assembler::NaN_HandledByCond;
+
     masm.xorps(ScratchFloatReg, ScratchFloatReg);
     masm.compareFloat(Assembler::DoubleEqualOrUnordered, opd, ScratchFloatReg);
-    masm.emitSet(Assembler::Equal, ToRegister(ins->output()), Assembler::NaN_IsTrue);
+    masm.emitSet(Assembler::Equal, ToRegister(ins->output()), nanCond);
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::visitCompareDAndBranch(LCompareDAndBranch *comp)
 {
     FloatRegister lhs = ToFloatRegister(comp->left());
     FloatRegister rhs = ToFloatRegister(comp->right());