Bug 1010747 - Part 3: Factor out floating-point conversion to int32 and bailout code. r=sunfish, a=sledru
💩💩 backed out by a89aa1e3e367 💩 💩
authorBenjamin Bouvier <benj@benj.me>
Thu, 22 May 2014 12:03:13 +0200
changeset 192366 0db12290df12
parent 192365 80950d72bd71
child 192367 a89aa1e3e367
push id3584
push userryanvm@gmail.com
push date2014-05-22 13:22 +0000
treeherdermozilla-beta@0db12290df12 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssunfish, sledru
bugs1010747
milestone30.0
Bug 1010747 - Part 3: Factor out floating-point conversion to int32 and bailout code. r=sunfish, a=sledru
js/src/jit/shared/CodeGenerator-x86-shared.cpp
js/src/jit/shared/CodeGenerator-x86-shared.h
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -1454,50 +1454,44 @@ CodeGeneratorX86Shared::visitFloor(LFloo
         // Bail on negative-zero.
         Assembler::Condition bailCond = masm.testNegativeZero(input, output);
         if (!bailoutIf(bailCond, lir->snapshot()))
             return false;
 
         // Round toward -Infinity.
         masm.roundsd(input, scratch, JSC::X86Assembler::RoundDown);
 
-        masm.cvttsd2si(scratch, output);
-        masm.cmp32(output, Imm32(INT_MIN));
-        if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+        if (!bailoutCvttsd2si(scratch, output, lir->snapshot()))
             return false;
     } else {
         Label negative, end;
 
         // Branch to a slow path for negative inputs. Doesn't catch NaN or -0.
         masm.xorpd(scratch, scratch);
         masm.branchDouble(Assembler::DoubleLessThan, input, scratch, &negative);
 
         // Bail on negative-zero.
         Assembler::Condition bailCond = masm.testNegativeZero(input, output);
         if (!bailoutIf(bailCond, lir->snapshot()))
             return false;
 
         // Input is non-negative, so truncation correctly rounds.
-        masm.cvttsd2si(input, output);
-        masm.cmp32(output, Imm32(INT_MIN));
-        if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+        if (!bailoutCvttsd2si(input, output, lir->snapshot()))
             return false;
 
         masm.jump(&end);
 
         // Input is negative, but isn't -0.
         // Negative values go on a comparatively expensive path, since no
         // native rounding mode matches JS semantics. Still better than callVM.
         masm.bind(&negative);
         {
             // Truncate and round toward zero.
             // This is off-by-one for everything but integer-valued inputs.
-            masm.cvttsd2si(input, output);
-            masm.cmp32(output, Imm32(INT_MIN));
-            if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+            if (!bailoutCvttsd2si(input, output, lir->snapshot()))
                 return false;
 
             // Test whether the input double was integer-valued.
             masm.convertInt32ToDouble(output, scratch);
             masm.branchDouble(Assembler::DoubleEqualOrUnordered, input, scratch, &end);
 
             // Input is not integer-valued, so we rounded off-by-one in the
             // wrong direction. Correct by subtraction.
@@ -1521,50 +1515,44 @@ CodeGeneratorX86Shared::visitFloorF(LFlo
         // Bail on negative-zero.
         Assembler::Condition bailCond = masm.testNegativeZeroFloat32(input, output);
         if (!bailoutIf(bailCond, lir->snapshot()))
             return false;
 
         // Round toward -Infinity.
         masm.roundss(input, scratch, JSC::X86Assembler::RoundDown);
 
-        masm.cvttss2si(scratch, output);
-        masm.cmp32(output, Imm32(INT_MIN));
-        if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+        if (!bailoutCvttss2si(scratch, output, lir->snapshot()))
             return false;
     } else {
         Label negative, end;
 
         // Branch to a slow path for negative inputs. Doesn't catch NaN or -0.
         masm.xorps(scratch, scratch);
         masm.branchFloat(Assembler::DoubleLessThan, input, scratch, &negative);
 
         // Bail on negative-zero.
         Assembler::Condition bailCond = masm.testNegativeZeroFloat32(input, output);
         if (!bailoutIf(bailCond, lir->snapshot()))
             return false;
 
         // Input is non-negative, so truncation correctly rounds.
-        masm.cvttss2si(input, output);
-        masm.cmp32(output, Imm32(INT_MIN));
-        if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+        if (!bailoutCvttss2si(input, output, lir->snapshot()))
             return false;
 
         masm.jump(&end);
 
         // Input is negative, but isn't -0.
         // Negative values go on a comparatively expensive path, since no
         // native rounding mode matches JS semantics. Still better than callVM.
         masm.bind(&negative);
         {
             // Truncate and round toward zero.
             // This is off-by-one for everything but integer-valued inputs.
-            masm.cvttss2si(input, output);
-            masm.cmp32(output, Imm32(INT_MIN));
-            if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+            if (!bailoutCvttss2si(input, output, lir->snapshot()))
                 return false;
 
             // Test whether the input double was integer-valued.
             masm.convertInt32ToFloat32(output, scratch);
             masm.branchFloat(Assembler::DoubleEqualOrUnordered, input, scratch, &end);
 
             // Input is not integer-valued, so we rounded off-by-one in the
             // wrong direction. Correct by subtraction.
@@ -1597,50 +1585,41 @@ CodeGeneratorX86Shared::visitCeil(LCeil 
     if (!bailoutFrom(&bailout, lir->snapshot()))
         return false;
 
     if (AssemblerX86Shared::HasSSE41()) {
         // x <= -1 or x > -0
         masm.bind(&lessThanMinusOne);
         // Round toward +Infinity.
         masm.roundsd(input, scratch, JSC::X86Assembler::RoundUp);
-
-        masm.cvttsd2si(scratch, output);
-        masm.cmp32(output, Imm32(1));
-        if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
-            return false;
-        return true;
+        return bailoutCvttsd2si(scratch, output, lir->snapshot());
     }
 
     // No SSE4.1
     Label end;
 
     // x >= 0 and x is not -0.0, we can truncate (resp. truncate and add 1) for
     // integer (resp. non-integer) values.
     // Will also work for values >= INT_MAX + 1, as the truncate
     // operation will return INT_MIN and there'll be a bailout.
-    masm.cvttsd2si(input, output);
-    masm.cmp32(output, Imm32(1));
-    if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
+    if (!bailoutCvttsd2si(input, output, lir->snapshot()))
         return false;
     masm.convertInt32ToDouble(output, scratch);
     masm.branchDouble(Assembler::DoubleEqualOrUnordered, input, scratch, &end);
 
     // Input is not integer-valued, add 1 to obtain the ceiling value
     masm.addl(Imm32(1), output);
     // if input > INT_MAX, output == INT_MAX so adding 1 will overflow.
     if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
         return false;
     masm.jump(&end);
 
     // x <= -1, truncation is the way to go.
     masm.bind(&lessThanMinusOne);
-    masm.cvttsd2si(input, output);
-    masm.cmp32(output, Imm32(1));
-    if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
+    if (!bailoutCvttsd2si(input, output, lir->snapshot()))
         return false;
 
     masm.bind(&end);
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::visitCeilF(LCeilF *lir)
@@ -1662,50 +1641,41 @@ CodeGeneratorX86Shared::visitCeilF(LCeil
     if (!bailoutFrom(&bailout, lir->snapshot()))
         return false;
 
     if (AssemblerX86Shared::HasSSE41()) {
         // x <= -1 or x > -0
         masm.bind(&lessThanMinusOne);
         // Round toward +Infinity.
         masm.roundss(input, scratch, JSC::X86Assembler::RoundUp);
-
-        masm.cvttss2si(scratch, output);
-        masm.cmp32(output, Imm32(1));
-        if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
-            return false;
-        return true;
+        return bailoutCvttss2si(scratch, output, lir->snapshot());
     }
 
     // No SSE4.1
     Label end;
 
     // x >= 0 and x is not -0.0, we can truncate (resp. truncate and add 1) for
     // integer (resp. non-integer) values.
     // Will also work for values >= INT_MAX + 1, as the truncate
     // operation will return INT_MIN and there'll be a bailout.
-    masm.cvttss2si(input, output);
-    masm.cmp32(output, Imm32(1));
-    if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
+    if (!bailoutCvttss2si(input, output, lir->snapshot()))
         return false;
     masm.convertInt32ToFloat32(output, scratch);
     masm.branchFloat(Assembler::DoubleEqualOrUnordered, input, scratch, &end);
 
     // Input is not integer-valued, add 1 to obtain the ceiling value
     masm.addl(Imm32(1), output);
     // if input > INT_MAX, output == INT_MAX so adding 1 will overflow.
     if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
         return false;
     masm.jump(&end);
 
     // x <= -1, truncation is the way to go.
     masm.bind(&lessThanMinusOne);
-    masm.cvttss2si(input, output);
-    masm.cmp32(output, Imm32(1));
-    if (!bailoutIf(Assembler::Overflow, lir->snapshot()))
+    if (!bailoutCvttss2si(input, output, lir->snapshot()))
         return false;
 
     masm.bind(&end);
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::visitRound(LRound *lir)
@@ -1728,38 +1698,33 @@ CodeGeneratorX86Shared::visitRound(LRoun
     Assembler::Condition bailCond = masm.testNegativeZero(input, output);
     if (!bailoutIf(bailCond, lir->snapshot()))
         return false;
 
     // Input is non-negative. Add 0.5 and truncate, rounding down. Note that we
     // have to add the input to the temp register (which contains 0.5) because
     // we're not allowed to modify the input register.
     masm.addsd(input, temp);
-
-    masm.cvttsd2si(temp, output);
-    masm.cmp32(output, Imm32(INT_MIN));
-    if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+    if (!bailoutCvttsd2si(temp, output, lir->snapshot()))
         return false;
 
     masm.jump(&end);
 
 
     // Input is negative, but isn't -0.
     masm.bind(&negative);
 
     if (AssemblerX86Shared::HasSSE41()) {
         // Add 0.5 and round toward -Infinity. The result is stored in the temp
         // register (currently contains 0.5).
         masm.addsd(input, temp);
         masm.roundsd(temp, scratch, JSC::X86Assembler::RoundDown);
 
         // Truncate.
-        masm.cvttsd2si(scratch, output);
-        masm.cmp32(output, Imm32(INT_MIN));
-        if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+        if (!bailoutCvttsd2si(scratch, output, lir->snapshot()))
             return false;
 
         // If the result is positive zero, then the actual result is -0. Bail.
         // Otherwise, the truncation will have produced the correct negative integer.
         masm.testl(output, output);
         if (!bailoutIf(Assembler::Zero, lir->snapshot()))
             return false;
 
@@ -1770,19 +1735,17 @@ CodeGeneratorX86Shared::visitRound(LRoun
         {
             // If input + 0.5 >= 0, input is a negative number >= -0.5 and the result is -0.
             masm.compareDouble(Assembler::DoubleGreaterThanOrEqual, temp, scratch);
             if (!bailoutIf(Assembler::DoubleGreaterThanOrEqual, lir->snapshot()))
                 return false;
 
             // Truncate and round toward zero.
             // This is off-by-one for everything but integer-valued inputs.
-            masm.cvttsd2si(temp, output);
-            masm.cmp32(output, Imm32(INT_MIN));
-            if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+            if (!bailoutCvttsd2si(temp, output, lir->snapshot()))
                 return false;
 
             // Test whether the truncated double was integer-valued.
             masm.convertInt32ToDouble(output, scratch);
             masm.branchDouble(Assembler::DoubleEqualOrUnordered, temp, scratch, &end);
 
             // Input is not integer-valued, so we rounded off-by-one in the
             // wrong direction. Correct by subtraction.
@@ -1817,37 +1780,33 @@ CodeGeneratorX86Shared::visitRoundF(LRou
     if (!bailoutIf(bailCond, lir->snapshot()))
         return false;
 
     // Input is non-negative. Add 0.5 and truncate, rounding down. Note that we
     // have to add the input to the temp register (which contains 0.5) because
     // we're not allowed to modify the input register.
     masm.addss(input, temp);
 
-    masm.cvttss2si(temp, output);
-    masm.cmp32(output, Imm32(INT_MIN));
-    if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+    if (!bailoutCvttss2si(temp, output, lir->snapshot()))
         return false;
 
     masm.jump(&end);
 
 
     // Input is negative, but isn't -0.
     masm.bind(&negative);
 
     if (AssemblerX86Shared::HasSSE41()) {
         // Add 0.5 and round toward -Infinity. The result is stored in the temp
         // register (currently contains 0.5).
         masm.addss(input, temp);
         masm.roundss(temp, scratch, JSC::X86Assembler::RoundDown);
 
         // Truncate.
-        masm.cvttss2si(scratch, output);
-        masm.cmp32(output, Imm32(INT_MIN));
-        if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+        if (!bailoutCvttss2si(scratch, output, lir->snapshot()))
             return false;
 
         // If the result is positive zero, then the actual result is -0. Bail.
         // Otherwise, the truncation will have produced the correct negative integer.
         masm.testl(output, output);
         if (!bailoutIf(Assembler::Zero, lir->snapshot()))
             return false;
 
@@ -1857,19 +1816,17 @@ CodeGeneratorX86Shared::visitRoundF(LRou
         {
             // If input + 0.5 >= 0, input is a negative number >= -0.5 and the result is -0.
             masm.compareFloat(Assembler::DoubleGreaterThanOrEqual, temp, scratch);
             if (!bailoutIf(Assembler::DoubleGreaterThanOrEqual, lir->snapshot()))
                 return false;
 
             // Truncate and round toward zero.
             // This is off-by-one for everything but integer-valued inputs.
-            masm.cvttss2si(temp, output);
-            masm.cmp32(output, Imm32(INT_MIN));
-            if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+            if (!bailoutCvttss2si(temp, output, lir->snapshot()))
                 return false;
 
             // Test whether the truncated double was integer-valued.
             masm.convertInt32ToFloat32(output, scratch);
             masm.branchFloat(Assembler::DoubleEqualOrUnordered, temp, scratch, &end);
 
             // Input is not integer-valued, so we rounded off-by-one in the
             // wrong direction. Correct by subtraction.
--- a/js/src/jit/shared/CodeGenerator-x86-shared.h
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.h
@@ -51,16 +51,32 @@ class CodeGeneratorX86Shared : public Co
 
     MoveOperand toMoveOperand(const LAllocation *a) const;
 
     bool bailoutIf(Assembler::Condition condition, LSnapshot *snapshot);
     bool bailoutIf(Assembler::DoubleCondition condition, LSnapshot *snapshot);
     bool bailoutFrom(Label *label, LSnapshot *snapshot);
     bool bailout(LSnapshot *snapshot);
 
+    bool bailoutCvttsd2si(FloatRegister src, Register dest, LSnapshot *snapshot) {
+        // cvttsd2si returns 0x80000000 on failure. Test for it by
+        // subtracting 1 and testing overflow. The other possibility is to test
+        // equality for INT_MIN after a comparison, but 1 costs fewer bytes to
+        // materialize.
+        masm.cvttsd2si(src, dest);
+        masm.cmp32(dest, Imm32(1));
+        return bailoutIf(Assembler::Overflow, snapshot);
+    }
+    bool bailoutCvttss2si(FloatRegister src, Register dest, LSnapshot *snapshot) {
+        // Same trick as explained in the above comment.
+        masm.cvttss2si(src, dest);
+        masm.cmp32(dest, Imm32(1));
+        return bailoutIf(Assembler::Overflow, snapshot);
+    }
+
   protected:
     bool generatePrologue();
     bool generateEpilogue();
     bool generateOutOfLineCode();
 
     Operand createArrayElementOperand(Register elements, const LAllocation *index);
 
     void emitCompare(MCompare::CompareType type, const LAllocation *left, const LAllocation *right);