Bug 1538083 - Fix -0 handling in ARM64 visitTrunc(). r=nbp a=lizzard
authorSean Stangl <sean.stangl@gmail.com>
Thu, 11 Apr 2019 22:34:46 +0000
changeset 526186 31a6f6acd33fe33e331688cdf7c5ac490e4aa122
parent 526185 fe71267f45ce7c4505287b20f31429257b15fc73
child 526187 afea6a1ebf81281c73025c959c8d40317a6e893f
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp, lizzard
bugs1538083
milestone67.0
Bug 1538083 - Fix -0 handling in ARM64 visitTrunc(). r=nbp a=lizzard 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());