Bug 1538083 - Fix -0 handling in ARM64 visitTrunc(). r=nbp
authorSean Stangl <sean.stangl@gmail.com>
Thu, 11 Apr 2019 22:34:46 +0000
changeset 469118 f14763229806d9678164e11659cd79674adf9816
parent 469117 c1f7767c6896d6d3e4c40b3f32244822fca0bfda
child 469119 47660e04a4f9e098ddf459d05c99b3e68d351e13
push id35856
push usercsabou@mozilla.com
push dateFri, 12 Apr 2019 03:19:48 +0000
treeherdermozilla-central@940684cd1065 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1538083
milestone68.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 1538083 - Fix -0 handling in ARM64 visitTrunc(). r=nbp The existing truncation code did not correctly handle the case of negative zero. The fix is to avoid using FCMP floating-point comparisons, and check the sign bit explicitly in a GPR. Differential Revision: https://phabricator.services.mozilla.com/D26381
js/src/jit-test/tests/ion/bug1538083.js
js/src/jit/arm64/CodeGenerator-arm64.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1538083.js
@@ -0,0 +1,8 @@
+// Crashes with --no-threads --ion-eager.
+x = [8589934592, -0];
+y = [0, 0];
+for (let i = 0; i < 2; ++i) {
+    y[i] = uneval(Math.trunc(Math.tan(x[i])));
+}
+assertEq(y[0].toString(), "1");
+assertEq(y[1].toString(), "-0");
--- a/js/src/jit/arm64/CodeGenerator-arm64.cpp
+++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -1099,16 +1099,17 @@ void CodeGenerator::visitRoundF(LRoundF*
   masm.bind(&done);
 }
 
 void CodeGenerator::visitTrunc(LTrunc* lir) {
   const FloatRegister input = ToFloatRegister(lir->input());
   const ARMFPRegister input64(input, 64);
   const Register output = ToRegister(lir->output());
   const ARMRegister output32(output, 32);
+  const ARMRegister output64(output, 64);
 
   Label done, zeroCase;
 
   // Convert scalar to signed 32-bit fixed-point, rounding toward zero.
   // In the case of overflow, the output is saturated.
   // In the case of NaN and -0, the output is zero.
   masm.Fcvtzs(output32, input64);
 
@@ -1128,16 +1129,21 @@ void CodeGenerator::visitTrunc(LTrunc* l
   {
     masm.bind(&zeroCase);
 
     // If input is a negative number that truncated to zero, the real
     // output should be the non-integer -0.
     // The use of "lt" instead of "lo" also catches unordered NaN input.
     masm.Fcmp(input64, 0.0);
     bailoutIf(vixl::lt, lir->snapshot());
+
+    // Check explicitly for -0, bitwise.
+    masm.Fmov(output64, input64);
+    bailoutTestPtr(Assembler::Signed, output, output, lir->snapshot());
+    masm.movePtr(ImmPtr(0), output);
   }
 
   masm.bind(&done);
 }
 
 void CodeGenerator::visitTruncF(LTruncF* lir) {
   const FloatRegister input = ToFloatRegister(lir->input());
   const ARMFPRegister input32(input, 32);
@@ -1167,16 +1173,21 @@ void CodeGenerator::visitTruncF(LTruncF*
   {
     masm.bind(&zeroCase);
 
     // If input is a negative number that truncated to zero, the real
     // output should be the non-integer -0.
     // The use of "lt" instead of "lo" also catches unordered NaN input.
     masm.Fcmp(input32, 0.0f);
     bailoutIf(vixl::lt, lir->snapshot());
+
+    // Check explicitly for -0, bitwise.
+    masm.Fmov(output32, input32);
+    bailoutTest32(Assembler::Signed, output, output, lir->snapshot());
+    masm.move32(Imm32(0), output);
   }
 
   masm.bind(&done);
 }
 
 void CodeGenerator::visitClzI(LClzI* lir) {
   ARMRegister input = toWRegister(lir->input());
   ARMRegister output = toWRegister(lir->output());