Bug 1438727: [Part 16] Support shifts in CacheIR r=tcampbell
authorMatthew Gaudet <mgaudet@mozilla.com>
Tue, 08 May 2018 18:32:37 -0400
changeset 483701 8e257791eccf389ed0ef642ce8d46af5f0d93b9f
parent 483700 ede13cd0e89a85e9e1080edc2145f52a79fff72d
child 483702 4b1c6659a5f5a28a54de6ee00caa09265050e8a7
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1438727
milestone63.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 1438727: [Part 16] Support shifts in CacheIR r=tcampbell
js/src/jit-test/tests/cacheir/binaryarith.js
js/src/jit/BaselineIC.cpp
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/CacheIRCompiler.cpp
js/src/jit/CacheIRCompiler.h
--- a/js/src/jit-test/tests/cacheir/binaryarith.js
+++ b/js/src/jit-test/tests/cacheir/binaryarith.js
@@ -172,16 +172,19 @@ var funURsh1 = (a, b) => { return a >>> 
 warmup(funURsh1, [[1,1,0], [5,1,2], [63,31,0], [4294967295,2147483647,1], [-2,10,4194303],
                   [-15,-2,3], [4,128,4], [1,10,0], [1024,2,256], [0, -6, 0], [0, 6, 0],
                   [0x55005500, 2, 0x15401540]]);
 
 //URsh Boolean Int32
 var funURsh2 = (a, b) => { return a >>> b; }
 warmup(funURsh2, [[true,1,0], [5,true,2], [63,false,63], [false, 20, 0]]);
 
+//URsh Int32
+var funURsh3 = (a, b) => { return a >>> b; }
+warmup(funURsh3, [[4294967295, 0, 4294967295]]);
 
 // Other Test cases that Have been useful:
 for (var k=0; k < 30; k++) {
     A="01234567";
     res =""
     for (var i = 0; i < 8; ++i) {
         var v = A[7 - i];
         res+=v;
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -4954,16 +4954,19 @@ DoCacheIRBinaryArithFallback(JSContext* 
       case JSOP_ADD:
       case JSOP_SUB:
       case JSOP_BITOR:
       case JSOP_BITXOR:
       case JSOP_BITAND:
       case JSOP_MUL:
       case JSOP_DIV:
       case JSOP_MOD:
+      case JSOP_URSH:
+      case JSOP_RSH:
+      case JSOP_LSH:
         break;
       default:
         return false; // Fallback to shared IC.
     }
 
     FallbackICSpew(cx, stub, "CacheIRBinaryArith(%s,%d,%d)", CodeName[op],
             int(lhs.isDouble() ? JSVAL_TYPE_DOUBLE : lhs.extractNonDoubleType()),
             int(rhs.isDouble() ? JSVAL_TYPE_DOUBLE : rhs.extractNonDoubleType()));
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -5203,25 +5203,17 @@ BinaryArithIRGenerator::tryAttachDouble(
     }
     writer.returnFromIC();
     return true;
 }
 
 bool
 BinaryArithIRGenerator::tryAttachInt32()
 {
-    if (op_ != JSOP_ADD && op_ != JSOP_SUB &&
-        op_ != JSOP_BITOR && op_ != JSOP_BITAND &&
-        op_ != JSOP_BITXOR && op_ != JSOP_MUL &&
-        op_ != JSOP_DIV && op_ != JSOP_MOD)
-    {
-        return false;
-    }
-
-    if (!lhs_.isInt32() || !rhs_.isInt32())
+    if (!lhs_.isInt32() || !rhs_.isInt32() || op_ == JSOP_POW)
         return false;
 
     ValOperandId lhsId(writer.setInputOperandId(0));
     ValOperandId rhsId(writer.setInputOperandId(1));
 
     Int32OperandId lhsIntId = writer.guardIsInt32(lhsId);
     Int32OperandId rhsIntId = writer.guardIsInt32(rhsId);
 
@@ -5253,16 +5245,28 @@ BinaryArithIRGenerator::tryAttachInt32()
       case JSOP_BITXOR:
         writer.int32BitXOrResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.Int32.BitXOr");
         break;
       case JSOP_BITAND:
         writer.int32BitAndResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.Int32.BitAnd");
         break;
+      case JSOP_LSH:
+        writer.int32LeftShiftResult(lhsIntId, rhsIntId);
+        trackAttached("BinaryArith.Int32.LeftShift");
+        break;
+      case JSOP_RSH:
+        writer.int32RightShiftResult(lhsIntId, rhsIntId);
+        trackAttached("BinaryArith.Int32.RightShift");
+        break;
+      case JSOP_URSH:
+        writer.int32URightShiftResult(lhsIntId, rhsIntId, res_.isDouble());
+        trackAttached("BinaryArith.Int32.UnsignedRightShift");
+        break;
       default:
         MOZ_CRASH("Unhandled op in tryAttachInt32");
     }
 
     writer.returnFromIC();
     return true;
 }
 
@@ -5311,15 +5315,27 @@ BinaryArithIRGenerator::tryAttachBoolean
       case JSOP_BITXOR:
         writer.int32BitXOrResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.BooleanInt32.BitXOr");
         break;
       case JSOP_BITAND:
         writer.int32BitAndResult(lhsIntId, rhsIntId);
         trackAttached("BinaryArith.BooleanInt32.BitAnd");
         break;
+      case JSOP_LSH:
+        writer.int32LeftShiftResult(lhsIntId, rhsIntId);
+        trackAttached("BinaryArith.BooleanInt32.LeftShift");
+        break;
+      case JSOP_RSH:
+        writer.int32RightShiftResult(lhsIntId, rhsIntId);
+        trackAttached("BinaryArith.BooleanInt32.RightShift");
+        break;
+      case JSOP_URSH:
+        writer.int32URightShiftResult(lhsIntId, rhsIntId, res_.isDouble());
+        trackAttached("BinaryArith.BooleanInt32.UnsignedRightShift");
+        break;
       default:
         MOZ_CRASH("Unhandled op in tryAttachInt32");
     }
 
     writer.returnFromIC();
     return true;
 }
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -300,16 +300,19 @@ extern const char* CacheKindNames[];
     _(Int32AddResult)                     \
     _(Int32SubResult)                     \
     _(Int32MulResult)                     \
     _(Int32DivResult)                     \
     _(Int32ModResult)                     \
     _(Int32BitOrResult)                   \
     _(Int32BitXorResult)                  \
     _(Int32BitAndResult)                  \
+    _(Int32LeftShiftResult)               \
+    _(Int32RightShiftResult)              \
+    _(Int32URightShiftResult)             \
     _(Int32NotResult)                     \
     _(Int32NegationResult)                \
     _(DoubleNegationResult)               \
     _(LoadInt32TruthyResult)              \
     _(LoadDoubleTruthyResult)             \
     _(LoadStringTruthyResult)             \
     _(LoadObjectTruthyResult)             \
     _(LoadValueResult)                    \
@@ -1058,16 +1061,29 @@ class MOZ_RAII CacheIRWriter : public JS
     void int32BitXOrResult(Int32OperandId lhs, Int32OperandId rhs) {
         writeOpWithOperandId(CacheOp::Int32BitXorResult, lhs);
         writeOperandId(rhs);
     }
     void int32BitAndResult(Int32OperandId lhs, Int32OperandId rhs) {
         writeOpWithOperandId(CacheOp::Int32BitAndResult, lhs);
         writeOperandId(rhs);
     }
+    void int32LeftShiftResult(Int32OperandId lhs, Int32OperandId rhs) {
+        writeOpWithOperandId(CacheOp::Int32LeftShiftResult, lhs);
+        writeOperandId(rhs);
+    }
+    void int32RightShiftResult(Int32OperandId lhs, Int32OperandId rhs) {
+        writeOpWithOperandId(CacheOp::Int32RightShiftResult, lhs);
+        writeOperandId(rhs);
+    }
+    void int32URightShiftResult(Int32OperandId lhs, Int32OperandId rhs, bool allowDouble) {
+        writeOpWithOperandId(CacheOp::Int32URightShiftResult, lhs);
+        writeOperandId(rhs);
+        buffer_.writeByte(uint32_t(allowDouble));
+    }
     void int32NotResult(Int32OperandId id) {
         writeOpWithOperandId(CacheOp::Int32NotResult, id);
     }
     void int32NegationResult(Int32OperandId id) {
         writeOpWithOperandId(CacheOp::Int32NegationResult, id);
     }
     void doubleNegationResult(ValOperandId val) {
         writeOpWithOperandId(CacheOp::DoubleNegationResult, val);
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -2197,17 +2197,81 @@ CacheIRCompiler::emitInt32BitAndResult()
     Register lhs = allocator.useRegister(masm, reader.int32OperandId());
     Register rhs = allocator.useRegister(masm, reader.int32OperandId());
 
     masm.and32(lhs, rhs);
     EmitStoreResult(masm, rhs, JSVAL_TYPE_INT32, output);
 
     return true;
 }
-
+bool
+CacheIRCompiler::emitInt32LeftShiftResult()
+{
+    AutoOutputRegister output(*this);
+    Register lhs = allocator.useRegister(masm, reader.int32OperandId());
+    Register rhs = allocator.useRegister(masm, reader.int32OperandId());
+
+
+    //Mask shift amount as specified by 12.9.3.1 Step 7
+    masm.and32(Imm32(0x1F), rhs);
+    masm.flexibleLshift32(rhs, lhs);
+    EmitStoreResult(masm, lhs, JSVAL_TYPE_INT32, output);
+
+    return true;
+}
+
+bool
+CacheIRCompiler::emitInt32RightShiftResult()
+{
+    AutoOutputRegister output(*this);
+    Register lhs = allocator.useRegister(masm, reader.int32OperandId());
+    Register rhs = allocator.useRegister(masm, reader.int32OperandId());
+
+    //Mask shift amount as specified by 12.9.4.1 Step 7
+    masm.and32(Imm32(0x1F), rhs);
+    masm.flexibleRshift32Arithmetic(rhs, lhs);
+    EmitStoreResult(masm, lhs, JSVAL_TYPE_INT32, output);
+
+    return true;
+}
+
+bool
+CacheIRCompiler::emitInt32URightShiftResult()
+{
+    AutoOutputRegister output(*this);
+
+    Register lhs = allocator.useRegister(masm, reader.int32OperandId());
+    Register rhs = allocator.useRegister(masm, reader.int32OperandId());
+    bool allowDouble = reader.readBool();
+
+    FailurePath* failure;
+    if (!addFailurePath(&failure))
+        return false;
+
+    //Mask shift amount as specified by 12.9.4.1 Step 7
+    masm.and32(Imm32(0x1F), rhs);
+    masm.flexibleRshift32(rhs, lhs);
+    Label intDone,floatDone;
+    if (allowDouble) {
+        Label toUint;
+        masm.branchTest32(Assembler::Signed, lhs, lhs, &toUint);
+        masm.jump(&intDone);
+
+        masm.bind(&toUint);
+        masm.convertUInt32ToDouble(lhs, ScratchDoubleReg);
+        masm.boxDouble(ScratchDoubleReg, output.valueReg(), ScratchDoubleReg);
+        masm.jump(&floatDone);
+    } else {
+        masm.branchTest32(Assembler::Signed, lhs, lhs, failure->label());
+    }
+    masm.bind(&intDone);
+    EmitStoreResult(masm, lhs, JSVAL_TYPE_INT32, output);
+    masm.bind(&floatDone);
+    return true;
+}
 
 bool
 CacheIRCompiler::emitInt32NegationResult()
 {
     AutoOutputRegister output(*this);
     Register val = allocator.useRegister(masm, reader.int32OperandId());
 
     FailurePath* failure;
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -60,16 +60,19 @@ namespace jit {
     _(Int32AddResult)                     \
     _(Int32SubResult)                     \
     _(Int32MulResult)                     \
     _(Int32DivResult)                     \
     _(Int32ModResult)                     \
     _(Int32BitOrResult)                   \
     _(Int32BitXorResult)                  \
     _(Int32BitAndResult)                  \
+    _(Int32LeftShiftResult)               \
+    _(Int32RightShiftResult)              \
+    _(Int32URightShiftResult)             \
     _(Int32NegationResult)                \
     _(Int32NotResult)                     \
     _(DoubleNegationResult)               \
     _(TruncateDoubleToUInt32)             \
     _(LoadArgumentsObjectLengthResult)    \
     _(LoadFunctionLengthResult)           \
     _(LoadStringLengthResult)             \
     _(LoadStringCharResult)               \