Bug 995826 - IonMonkey: Fix bogus behaviour of the negative zero test on x86, r=bbouvier
authorHannes Verschore <hv1989@gmail.com>
Thu, 17 Apr 2014 12:26:23 +0200
changeset 179114 bd09a43b2b21dddce8f0f283dc099cdd209a434f
parent 179113 e57c8c5c2ccde5059a71a570e53ed7c070fa875c
child 179115 e07e0a07d0a5e6e4e7129dd041c7ea98628bfa6d
push id26607
push userryanvm@gmail.com
push dateFri, 18 Apr 2014 02:31:26 +0000
treeherdermozilla-central@7fe3ee0cf8be [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbbouvier
bugs995826
milestone31.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 995826 - IonMonkey: Fix bogus behaviour of the negative zero test on x86, r=bbouvier
js/src/jit-test/tests/ion/bug995826.js
js/src/jit/x86/MacroAssembler-x86.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug995826.js
@@ -0,0 +1,5 @@
+function f(x) {
+        return Math.round(-Math.tan(x > 0))
+}
+f(2)
+assertEq(f(-1), -0);
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -391,26 +391,37 @@ MacroAssemblerX86::testNegativeZero(cons
 {
     // Determines whether the single double contained in the XMM register reg
     // is equal to double-precision -0.
 
     Label nonZero;
 
     // Compare to zero. Lets through {0, -0}.
     xorpd(ScratchFloatReg, ScratchFloatReg);
-    // If reg is non-zero, then a test of Zero is false.
+
+    // If reg is non-zero, jump to nonZero.
+    // Sets ZF=0 and PF=0.
     branchDouble(DoubleNotEqual, reg, ScratchFloatReg, &nonZero);
 
-    // Input register is either zero or negative zero. Test sign bit.
+    // Input register is either zero or negative zero. Retrieve sign of input.
     movmskpd(reg, scratch);
-    // If reg is -0, then a test of Zero is true.
-    cmpl(scratch, Imm32(1));
+
+    // If reg is 1 or 3, input is negative zero.
+    // If reg is 0 or 2, input is a normal zero.
+    // So the following test will set PF=1 for negative zero.
+    orl(Imm32(2), scratch);
 
     bind(&nonZero);
-    return Zero;
+
+    // Here we need to be able to test if the input is a negative zero.
+    // - branchDouble joins here for non-zero values in which case it sets
+    //   ZF=0 and PF=0. In that case the test should fail.
+    // - orl sets PF=1 on negative zero and PF=0 otherwise
+    // => So testing PF=1 will return if input is negative zero or not.
+    return Parity;
 }
 
 Assembler::Condition
 MacroAssemblerX86::testNegativeZeroFloat32(const FloatRegister &reg, const Register &scratch)
 {
     movd(reg, scratch);
     cmpl(scratch, Imm32(1));
     return Overflow;