Bug 1326160 - Omit divide by zero and overflow checks for some constants. r=lth
authorDaniel Naslund <dannas@dannas.name>
Thu, 12 Jan 2017 21:20:32 +0100
changeset 374702 470abd84f5457117de90f9249516ca7022433580
parent 374701 e0ca66f6ac4630da8ad99788658b244e7598ecb4
child 374703 c84ced896f8340813d7321536cc4de86052f1c89
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1326160
milestone53.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 1326160 - Omit divide by zero and overflow checks for some constants. r=lth
js/src/wasm/WasmBaselineCompile.cpp
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -1711,16 +1711,32 @@ class BaseCompiler
         Stk& v = stk_.back();
         if (v.kind() != Stk::ConstI64)
             return false;
         c = v.i64val();
         stk_.popBack();
         return true;
     }
 
+    MOZ_MUST_USE bool peekConstI32(int32_t* c) {
+        Stk& v = stk_.back();
+        if (v.kind() != Stk::ConstI32)
+            return false;
+        *c = v.i32val();
+        return true;
+    }
+
+    MOZ_MUST_USE bool peekConstI64(int64_t* c) {
+        Stk& v = stk_.back();
+        if (v.kind() != Stk::ConstI64)
+            return false;
+        *c = v.i64val();
+        return true;
+    }
+
     MOZ_MUST_USE bool popConstPositivePowerOfTwoI32(int32_t& c,
                                                     uint_fast8_t& power,
                                                     int32_t cutoff)
     {
         Stk& v = stk_.back();
         if (v.kind() != Stk::ConstI32)
             return false;
         c = v.i32val();
@@ -2753,22 +2769,25 @@ class BaseCompiler
             masm.jump(done);
         } else {
             masm.jump(trap(Trap::IntegerOverflow));
         }
         masm.bind(&notmin);
     }
 
 #ifndef INT_DIV_I64_CALLOUT
-    void quotientI64(RegI64 rhs, RegI64 srcDest, IsUnsigned isUnsigned) {
+    void quotientI64(RegI64 rhs, RegI64 srcDest, IsUnsigned isUnsigned,
+                     bool isConst, int64_t c)
+    {
         Label done;
 
-        checkDivideByZeroI64(rhs);
-
-        if (!isUnsigned)
+        if (!isConst || c == 0)
+            checkDivideByZeroI64(rhs);
+
+        if (!isUnsigned && (!isConst || c == -1))
             checkDivideSignedOverflowI64(rhs, srcDest, &done, ZeroOnOverflow(false));
 
 # if defined(JS_CODEGEN_X64)
         // The caller must set up the following situation.
         MOZ_ASSERT(srcDest.reg == rax);
         MOZ_ASSERT(isAvailable(rdx));
         if (isUnsigned) {
             masm.xorq(rdx, rdx);
@@ -2778,22 +2797,25 @@ class BaseCompiler
             masm.idivq(rhs.reg);
         }
 # else
         MOZ_CRASH("BaseCompiler platform hook: quotientI64");
 # endif
         masm.bind(&done);
     }
 
-    void remainderI64(RegI64 rhs, RegI64 srcDest, IsUnsigned isUnsigned) {
+    void remainderI64(RegI64 rhs, RegI64 srcDest, IsUnsigned isUnsigned,
+                      bool isConst, int64_t c)
+    {
         Label done;
 
-        checkDivideByZeroI64(rhs);
-
-        if (!isUnsigned)
+        if (!isConst || c == 0)
+            checkDivideByZeroI64(rhs);
+
+        if (!isUnsigned && (!isConst || c == -1))
             checkDivideSignedOverflowI64(rhs, srcDest, &done, ZeroOnOverflow(true));
 
 # if defined(JS_CODEGEN_X64)
         // The caller must set up the following situation.
         MOZ_ASSERT(srcDest.reg == rax);
         MOZ_ASSERT(isAvailable(rdx));
 
         if (isUnsigned) {
@@ -4179,22 +4201,25 @@ BaseCompiler::emitQuotientI32()
             masm.branchTest32(Assembler::NotSigned, r, r, &positive);
             masm.add32(Imm32(c-1), r);
             masm.bind(&positive);
 
             masm.rshift32Arithmetic(Imm32(power & 31), r);
             pushI32(r);
         }
     } else {
+        bool isConst = peekConstI32(&c);
         RegI32 r0, r1;
         pop2xI32ForIntMulDiv(&r0, &r1);
 
         Label done;
-        checkDivideByZeroI32(r1, r0, &done);
-        checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(false));
+        if (!isConst || c == 0)
+            checkDivideByZeroI32(r1, r0, &done);
+        if (!isConst || c == -1)
+            checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(false));
         masm.quotient32(r1, r0, IsUnsigned(false));
         masm.bind(&done);
 
         freeI32(r1);
         pushI32(r0);
     }
 }
 
@@ -4205,21 +4230,23 @@ BaseCompiler::emitQuotientU32()
     uint_fast8_t power;
     if (popConstPositivePowerOfTwoI32(c, power, 0)) {
         if (power != 0) {
             RegI32 r = popI32();
             masm.rshift32(Imm32(power & 31), r);
             pushI32(r);
         }
     } else {
+        bool isConst = peekConstI32(&c);
         RegI32 r0, r1;
         pop2xI32ForIntMulDiv(&r0, &r1);
 
         Label done;
-        checkDivideByZeroI32(r1, r0, &done);
+        if (!isConst || c == 0)
+            checkDivideByZeroI32(r1, r0, &done);
         masm.quotient32(r1, r0, IsUnsigned(true));
         masm.bind(&done);
 
         freeI32(r1);
         pushI32(r0);
     }
 }
 
@@ -4240,22 +4267,25 @@ BaseCompiler::emitRemainderI32()
 
         masm.rshift32Arithmetic(Imm32(power & 31), temp);
         masm.lshift32(Imm32(power & 31), temp);
         masm.sub32(temp, r);
         freeI32(temp);
 
         pushI32(r);
     } else {
+        bool isConst = peekConstI32(&c);
         RegI32 r0, r1;
         pop2xI32ForIntMulDiv(&r0, &r1);
 
         Label done;
-        checkDivideByZeroI32(r1, r0, &done);
-        checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(true));
+        if (!isConst || c == 0)
+            checkDivideByZeroI32(r1, r0, &done);
+        if (!isConst || c == -1)
+            checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(true));
         masm.remainder32(r1, r0, IsUnsigned(false));
         masm.bind(&done);
 
         freeI32(r1);
         pushI32(r0);
     }
 }
 
@@ -4264,21 +4294,23 @@ BaseCompiler::emitRemainderU32()
 {
     int32_t c;
     uint_fast8_t power;
     if (popConstPositivePowerOfTwoI32(c, power, 1)) {
         RegI32 r = popI32();
         masm.and32(Imm32(c-1), r);
         pushI32(r);
     } else {
+        bool isConst = peekConstI32(&c);
         RegI32 r0, r1;
         pop2xI32ForIntMulDiv(&r0, &r1);
 
         Label done;
-        checkDivideByZeroI32(r1, r0, &done);
+        if (!isConst || c == 0)
+            checkDivideByZeroI32(r1, r0, &done);
         masm.remainder32(r1, r0, IsUnsigned(true));
         masm.bind(&done);
 
         freeI32(r1);
         pushI32(r0);
     }
 }
 
@@ -4297,19 +4329,20 @@ BaseCompiler::emitQuotientI64()
                               &positive);
             masm.add64(Imm32(c-1), r);
             masm.bind(&positive);
 
             masm.rshift64Arithmetic(Imm32(power & 63), r);
             pushI64(r);
         }
     } else {
+        bool isConst = peekConstI64(&c);
         RegI64 r0, r1;
         pop2xI64ForIntDiv(&r0, &r1);
-        quotientI64(r1, r0, IsUnsigned(false));
+        quotientI64(r1, r0, IsUnsigned(false), isConst, c);
         freeI64(r1);
         pushI64(r0);
     }
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitQuotientI64");
 # endif
 }
 
@@ -4321,19 +4354,20 @@ BaseCompiler::emitQuotientU64()
     uint_fast8_t power;
     if (popConstPositivePowerOfTwoI64(c, power, 0)) {
         if (power != 0) {
             RegI64 r = popI64();
             masm.rshift64(Imm32(power & 63), r);
             pushI64(r);
         }
     } else {
+        bool isConst = peekConstI64(&c);
         RegI64 r0, r1;
         pop2xI64ForIntDiv(&r0, &r1);
-        quotientI64(r1, r0, IsUnsigned(true));
+        quotientI64(r1, r0, IsUnsigned(true), isConst, c);
         freeI64(r1);
         pushI64(r0);
     }
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitQuotientU64");
 # endif
 }
 
@@ -4356,19 +4390,20 @@ BaseCompiler::emitRemainderI64()
 
         masm.rshift64Arithmetic(Imm32(power & 63), temp);
         masm.lshift64(Imm32(power & 63), temp);
         masm.sub64(temp, r);
         freeI64(temp);
 
         pushI64(r);
     } else {
+        bool isConst = peekConstI64(&c);
         RegI64 r0, r1;
         pop2xI64ForIntDiv(&r0, &r1);
-        remainderI64(r1, r0, IsUnsigned(false));
+        remainderI64(r1, r0, IsUnsigned(false), isConst, c);
         freeI64(r1);
         pushI64(r0);
     }
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitRemainderI64");
 # endif
 }
 
@@ -4378,19 +4413,20 @@ BaseCompiler::emitRemainderU64()
 # ifdef JS_PUNBOX64
     int64_t c;
     uint_fast8_t power;
     if (popConstPositivePowerOfTwoI64(c, power, 1)) {
         RegI64 r = popI64();
         masm.and64(Imm64(c-1), r);
         pushI64(r);
     } else {
+        bool isConst = peekConstI64(&c);
         RegI64 r0, r1;
         pop2xI64ForIntDiv(&r0, &r1);
-        remainderI64(r1, r0, IsUnsigned(true));
+        remainderI64(r1, r0, IsUnsigned(true), isConst, c);
         freeI64(r1);
         pushI64(r0);
     }
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitRemainderU64");
 # endif
 }
 #endif // INT_DIV_I64_CALLOUT