Bug 1321560: Fix codegen for rem_s of 0 by x on arm; r=luke a=jcristau
authorBenjamin Bouvier <benj@benj.me>
Thu, 01 Dec 2016 16:38:19 +0100
changeset 353162 483b3196dc36107f3b9c9b49a92070d3c0d23b59
parent 353161 b0c105fc360fa893453ef47dfe61814f7efa15e7
child 353163 46fdbb0954b9c34f9795361c234077952293cf88
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke, jcristau
bugs1321560
milestone52.0a2
Bug 1321560: Fix codegen for rem_s of 0 by x on arm; r=luke a=jcristau
js/src/jit-test/tests/wasm/integer.js
js/src/jit/arm/CodeGenerator-arm.cpp
--- a/js/src/jit-test/tests/wasm/integer.js
+++ b/js/src/jit-test/tests/wasm/integer.js
@@ -104,16 +104,17 @@ testUnary('i32', 'eqz', 1, 0);
 testUnary('i32', 'eqz', 0xFFFFFFFF, 0);
 
 testBinary32('add', 40, 2, 42);
 testBinary32('sub', 40, 2, 38);
 testBinary32('mul', 40, 2, 80);
 testBinary32('div_s', -40, 2, -20);
 testBinary32('div_u', -40, 2, 2147483628);
 testBinary32('rem_s', 40, -3, 1);
+testBinary32('rem_s', 0, -3, 0);
 testBinary32('rem_u', 40, -3, 40);
 testBinary32('and', 42, 6, 2);
 testBinary32('or', 42, 6, 46);
 testBinary32('xor', 42, 2, 40);
 testBinary32('shl', 40, 2, 160);
 testBinary32('shr_s', -40, 2, -10);
 testBinary32('shr_u', -40, 2, 1073741814);
 
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -687,41 +687,45 @@ CodeGeneratorARM::visitDivPowTwoI(LDivPo
 
 void
 CodeGeneratorARM::modICommon(MMod* mir, Register lhs, Register rhs, Register output,
                              LSnapshot* snapshot, Label& done)
 {
     // 0/X (with X < 0) is bad because both of these values *should* be doubles,
     // and the result should be -0.0, which cannot be represented in integers.
     // X/0 is bad because it will give garbage (or abort), when it should give
-    // either \infty, -\infty or NAN.
+    // either \infty, -\infty or NaN.
 
     // Prevent 0 / X (with X < 0) and X / 0
     // testing X / Y. Compare Y with 0.
     // There are three cases: (Y < 0), (Y == 0) and (Y > 0).
     // If (Y < 0), then we compare X with 0, and bail if X == 0.
     // If (Y == 0), then we simply want to bail. Since this does not set the
     // flags necessary for LT to trigger, we don't test X, and take the bailout
     // because the EQ flag is set.
     // If (Y > 0), we don't set EQ, and we don't trigger LT, so we don't take
     // the bailout.
     if (mir->canBeDivideByZero() || mir->canBeNegativeDividend()) {
+        if (mir->trapOnError()) {
+            // wasm allows negative lhs and return 0 in this case.
+            MOZ_ASSERT(mir->isTruncated());
+            masm.as_cmp(rhs, Imm8(0));
+            masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
+            return;
+        }
+
         masm.as_cmp(rhs, Imm8(0));
         masm.as_cmp(lhs, Imm8(0), Assembler::LessThan);
         if (mir->isTruncated()) {
-            if (mir->trapOnError()) {
-                masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
-            } else {
-                // NaN|0 == 0 and (0 % -X)|0 == 0
-                Label skip;
-                masm.ma_b(&skip, Assembler::NotEqual);
-                masm.ma_mov(Imm32(0), output);
-                masm.ma_b(&done);
-                masm.bind(&skip);
-            }
+            // NaN|0 == 0 and (0 % -X)|0 == 0
+            Label skip;
+            masm.ma_b(&skip, Assembler::NotEqual);
+            masm.ma_mov(Imm32(0), output);
+            masm.ma_b(&done);
+            masm.bind(&skip);
         } else {
             MOZ_ASSERT(mir->fallible());
             bailoutIf(Assembler::Equal, snapshot);
         }
     }
 }
 
 void