Bug 1073576 - Optimize strict compares with equal operands. r=h4writer
☠☠ backed out by a80a2d8bbd47 ☠ ☠
authorTom Schuster <evilpies@gmail.com>
Sun, 05 Oct 2014 15:26:40 +0200
changeset 208893 1724a6c073166de899ba7ce6cf97fa3c93fa8af0
parent 208837 9cafd64208c31616df1df0f135d780edec36d77e
child 208894 a80a2d8bbd47ba91063cacd50c0ed20e1c2c603a
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersh4writer
bugs1073576
milestone35.0a1
Bug 1073576 - Optimize strict compares with equal operands. r=h4writer
js/src/jit-test/tests/basic/strict-compare-same-operands.js
js/src/jit/MIR.cpp
js/src/jit/MIR.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/strict-compare-same-operands.js
@@ -0,0 +1,47 @@
+function f(l) {
+    var a = NaN;
+    var b = 13;
+    var c = "test";
+    var d = undefined;
+    var e = null;
+    var f = 15.7;
+    var g = Math.fround(189777.111);
+    var h = "ABC";
+    var i = String.fromCharCode(65, 65, 65);
+    var j = {};
+    var k = Math.fround("".charCodeAt(15));
+
+    // Special case rigt here:
+    assertEq(a === a, false);
+    assertEq(a !== a, true);
+    assertEq(k === k, false);
+    assertEq(k !== k, true);
+    assertEq(l === l, false);
+    assertEq(l !== l, true);
+
+    assertEq(b === b, true);
+    assertEq(b !== b, false);
+    assertEq(c === c, true);
+    assertEq(c !== c, false);
+    assertEq(d === d, true);
+    assertEq(d !== d, false);
+    assertEq(e === e, true);
+    assertEq(e !== e, false);
+    assertEq(f === f, true);
+    assertEq(f !== f, false);
+    assertEq(g === g, true);
+    assertEq(g !== g, false);
+    assertEq(h === h, true);
+    assertEq(h !== h, false);
+    assertEq(i === i, true);
+    assertEq(i !== i, false);
+    assertEq(j === j, true);
+    assertEq(j !== j, false);
+}
+
+function test() {
+    for (var i = 0; i < 100; i++)
+        f("".charCodeAt(15));
+}
+
+test();
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -2833,16 +2833,52 @@ MClampToUint8::foldsTo(TempAllocator &al
         if (v.isInt32()) {
             int32_t clamped = ClampIntForUint8Array(v.toInt32());
             return MConstant::New(alloc, Int32Value(clamped));
         }
     }
     return this;
 }
 
+ bool
+MCompare::tryFoldEqualOperands(bool *result)
+{
+    if (lhs() != rhs())
+        return false;
+
+    // Intuitively somebody would think that if lhs == rhs,
+    // then we can just return true. (Or false for !==)
+    // However NaN !== NaN is true! So we spend some time trying
+    // to eliminate this case.
+
+    if (jsop() != JSOP_STRICTEQ && jsop() != JSOP_STRICTNE)
+        return false;
+
+    if (compareType_ == Compare_Unknown)
+        return false;
+
+    MOZ_ASSERT(compareType_ == Compare_Undefined || compareType_ == Compare_Null ||
+               compareType_ == Compare_Boolean || compareType_ == Compare_Int32 ||
+               compareType_ == Compare_Int32MaybeCoerceBoth ||
+               compareType_ == Compare_Int32MaybeCoerceLHS ||
+               compareType_ == Compare_Int32MaybeCoerceRHS || compareType_ == Compare_UInt32 ||
+               compareType_ == Compare_Double || compareType_ == Compare_DoubleMaybeCoerceLHS ||
+               compareType_ == Compare_DoubleMaybeCoerceRHS || compareType_ == Compare_Float32 ||
+               compareType_ == Compare_String || compareType_ == Compare_StrictString ||
+               compareType_ == Compare_Object || compareType_ == Compare_Value);
+
+    if (isDoubleComparison() || isFloat32Comparison()) {
+        if (!operandsAreNeverNaN())
+            return false;
+    }
+
+    *result = (jsop() == JSOP_STRICTEQ);
+    return true;
+}
+
 bool
 MCompare::tryFold(bool *result)
 {
     JSOp op = jsop();
 
     if (compareType_ == Compare_Null || compareType_ == Compare_Undefined) {
         MOZ_ASSERT(op == JSOP_EQ || op == JSOP_STRICTEQ ||
                    op == JSOP_NE || op == JSOP_STRICTNE);
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3468,16 +3468,18 @@ class MCompare
         // Both sides of the compare can be Float32
         return compareType_ == Compare_Float32;
     }
 # endif
 
     ALLOW_CLONE(MCompare)
 
   protected:
+    bool tryFoldEqualOperands(bool *result);
+
     bool congruentTo(const MDefinition *ins) const {
         if (!binaryCongruentTo(ins))
             return false;
         return compareType() == ins->toCompare()->compareType() &&
                jsop() == ins->toCompare()->jsop();
     }
 };