Title: [160205] trunk
Revision
160205
Author
[email protected]
Date
2013-12-05 17:47:19 -0800 (Thu, 05 Dec 2013)

Log Message

FTL should use cvttsd2si directly for double-to-int32 conversions
https://bugs.webkit.org/show_bug.cgi?id=125275

Source/_javascript_Core: 

Reviewed by Michael Saboff.
        
Wow. This was an ordeal. Using cvttsd2si was actually easy, but I learned, and
sometimes even fixed, some interesting things:
        
- The llvm.x86.sse2.cvttsd2si intrinsic can actually result in LLVM emitting a
  vcvttsd2si. I guess the intrinsic doesn't actually imply the instruction.
        
- That whole thing about branchTruncateDoubleToUint32? Yeah we don't need that. It's
  better to use branchTruncateDoubleToInt32 instead. It has the right semantics for
  all of its callers (err, its one-and-only caller), and it's more likely to take
  fast path. This patch kills branchTruncateDoubleToUint32.
        
- "a[i] = v; v = a[i]". Does this change v? OK, assume that 'a[i]' is a pure-ish
  operation - like an array access with 'i' being an integer index and we're not
  having a bad time. Now does this change v? CSE assumes that it doesn't. That's
  wrong. If 'a' is a typed array - the most sensible and pure kind of array - then
  this can be a truncating cast. For example 'v' could be a double and 'a' could be
  an integer array.
        
- "v1 = a[i]; v2 = a[i]". Is v1 === v2 assuming that 'a[i]' is pure-ish? The answer
  is no. You could have a different arrayMode in each access. I know this sounds
  weird, but with concurrent JIT that might happen.
        
This patch adds tests for all of this stuff, except for the first issue (it's weird
but probably doesn't matter) and the last issue (it's too much of a freakshow).

* assembler/MacroAssemblerARM64.h:
* assembler/MacroAssemblerARMv7.h:
* assembler/MacroAssemblerX86Common.h:
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::getByValLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
* ftl/FTLAbbreviations.h:
(JSC::FTL::vectorType):
(JSC::FTL::getUndef):
(JSC::FTL::buildInsertElement):
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::doubleToInt32):
(JSC::FTL::LowerDFGToLLVM::doubleToUInt32):
(JSC::FTL::LowerDFGToLLVM::sensibleDoubleToInt32):
* ftl/FTLOutput.h:
(JSC::FTL::Output::insertElement):
(JSC::FTL::Output::hasSensibleDoubleToInt):
(JSC::FTL::Output::sensibleDoubleToInt):

LayoutTests: 

Reviewed by Michael Saboff.

* js/regress/double-to-int32-typed-array-expected.txt: Added.
* js/regress/double-to-int32-typed-array-no-inline-expected.txt: Added.
* js/regress/double-to-int32-typed-array-no-inline.html: Added.
* js/regress/double-to-int32-typed-array.html: Added.
* js/regress/double-to-uint32-typed-array-expected.txt: Added.
* js/regress/double-to-uint32-typed-array-no-inline-expected.txt: Added.
* js/regress/double-to-uint32-typed-array-no-inline.html: Added.
* js/regress/double-to-uint32-typed-array.html: Added.
* js/regress/script-tests/double-to-int32-typed-array-no-inline.js: Added.
(foo):
(test):
* js/regress/script-tests/double-to-int32-typed-array.js: Added.
(foo):
(test):
* js/regress/script-tests/double-to-uint32-typed-array-no-inline.js: Added.
(foo):
(test):
* js/regress/script-tests/double-to-uint32-typed-array.js: Added.
(foo):
(test):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (160204 => 160205)


--- trunk/LayoutTests/ChangeLog	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/LayoutTests/ChangeLog	2013-12-06 01:47:19 UTC (rev 160205)
@@ -1,3 +1,31 @@
+2013-12-04  Filip Pizlo  <[email protected]>
+
+        FTL should use cvttsd2si directly for double-to-int32 conversions
+        https://bugs.webkit.org/show_bug.cgi?id=125275
+
+        Reviewed by Michael Saboff.
+
+        * js/regress/double-to-int32-typed-array-expected.txt: Added.
+        * js/regress/double-to-int32-typed-array-no-inline-expected.txt: Added.
+        * js/regress/double-to-int32-typed-array-no-inline.html: Added.
+        * js/regress/double-to-int32-typed-array.html: Added.
+        * js/regress/double-to-uint32-typed-array-expected.txt: Added.
+        * js/regress/double-to-uint32-typed-array-no-inline-expected.txt: Added.
+        * js/regress/double-to-uint32-typed-array-no-inline.html: Added.
+        * js/regress/double-to-uint32-typed-array.html: Added.
+        * js/regress/script-tests/double-to-int32-typed-array-no-inline.js: Added.
+        (foo):
+        (test):
+        * js/regress/script-tests/double-to-int32-typed-array.js: Added.
+        (foo):
+        (test):
+        * js/regress/script-tests/double-to-uint32-typed-array-no-inline.js: Added.
+        (foo):
+        (test):
+        * js/regress/script-tests/double-to-uint32-typed-array.js: Added.
+        (foo):
+        (test):
+
 2013-12-05  Bear Travis  <[email protected]>
 
         [CSS Shapes] Enable CSS Shapes on Windows

Added: trunk/LayoutTests/js/regress/double-to-int32-typed-array-expected.txt (0 => 160205)


--- trunk/LayoutTests/js/regress/double-to-int32-typed-array-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-int32-typed-array-expected.txt	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,10 @@
+JSRegress/double-to-int32-typed-array
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline-expected.txt (0 => 160205)


--- trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline-expected.txt	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,10 @@
+JSRegress/double-to-int32-typed-array-no-inline
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline.html (0 => 160205)


--- trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline.html	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/double-to-int32-typed-array.html (0 => 160205)


--- trunk/LayoutTests/js/regress/double-to-int32-typed-array.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-int32-typed-array.html	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/double-to-uint32-typed-array-expected.txt (0 => 160205)


--- trunk/LayoutTests/js/regress/double-to-uint32-typed-array-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-uint32-typed-array-expected.txt	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,10 @@
+JSRegress/double-to-uint32-typed-array
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline-expected.txt (0 => 160205)


--- trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline-expected.txt	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,10 @@
+JSRegress/double-to-uint32-typed-array-no-inline
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline.html (0 => 160205)


--- trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline.html	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/double-to-uint32-typed-array.html (0 => 160205)


--- trunk/LayoutTests/js/regress/double-to-uint32-typed-array.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-uint32-typed-array.html	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array-no-inline.js (0 => 160205)


--- trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array-no-inline.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array-no-inline.js	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,24 @@
+var array = new Int32Array(1);
+
+function foo(value) {
+    array[0] = value;
+    return array[0];
+}
+
+noInline(foo);
+
+function test(input, output) {
+    var result = foo(input);
+    if (result != output)
+        throw "Error: " + input + " was supposed to result in " + output + " but instead got " + result;
+}
+
+for (var i = 0; i < 100000; ++i)
+    test(i + 0.5, i);
+
+test(0, 0);
+test(100.5, 100);
+test(-100.5, -100);
+test(3000000000, -1294967296);
+test(-3000000000, 1294967296);
+test(-2147483648, -2147483648);

Added: trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array.js (0 => 160205)


--- trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array.js	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,22 @@
+var array = new Int32Array(1);
+
+function foo(value) {
+    array[0] = value;
+    return array[0];
+}
+
+function test(input, output) {
+    var result = foo(input);
+    if (result != output)
+        throw "Error: " + input + " was supposed to result in " + output + " but instead got " + result;
+}
+
+for (var i = 0; i < 100000; ++i)
+    test(i + 0.5, i);
+
+test(0, 0);
+test(100.5, 100);
+test(-100.5, -100);
+test(3000000000, -1294967296);
+test(-3000000000, 1294967296);
+test(-2147483648, -2147483648);

Added: trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array-no-inline.js (0 => 160205)


--- trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array-no-inline.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array-no-inline.js	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,25 @@
+var array = new Uint32Array(1);
+
+function foo(value) {
+    array[0] = value;
+    return array[0];
+}
+
+noInline(foo);
+
+function test(input, output) {
+    var result = foo(input);
+    if (result != output)
+        throw "Error: " + input + " was supposed to result in " + output + " but instead got " + result;
+}
+
+for (var i = 0; i < 100000; ++i)
+    test(i + 0.5, i);
+
+test(0, 0);
+test(100.5, 100);
+test(-100.5, 4294967196);
+test(3000000000, 3000000000);
+test(6000000000, 1705032704);
+test(-3000000000, 1294967296);
+test(-2147483648, 2147483648);

Added: trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array.js (0 => 160205)


--- trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array.js	                        (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array.js	2013-12-06 01:47:19 UTC (rev 160205)
@@ -0,0 +1,23 @@
+var array = new Uint32Array(1);
+
+function foo(value) {
+    array[0] = value;
+    return array[0];
+}
+
+function test(input, output) {
+    var result = foo(input);
+    if (result != output)
+        throw "Error: " + input + " was supposed to result in " + output + " but instead got " + result;
+}
+
+for (var i = 0; i < 100000; ++i)
+    test(i + 0.5, i);
+
+test(0, 0);
+test(100.5, 100);
+test(-100.5, 4294967196);
+test(3000000000, 3000000000);
+test(6000000000, 1705032704);
+test(-3000000000, 1294967296);
+test(-2147483648, 2147483648);

Modified: trunk/Source/_javascript_Core/ChangeLog (160204 => 160205)


--- trunk/Source/_javascript_Core/ChangeLog	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-12-06 01:47:19 UTC (rev 160205)
@@ -1,3 +1,57 @@
+2013-12-04  Filip Pizlo  <[email protected]>
+
+        FTL should use cvttsd2si directly for double-to-int32 conversions
+        https://bugs.webkit.org/show_bug.cgi?id=125275
+
+        Reviewed by Michael Saboff.
+        
+        Wow. This was an ordeal. Using cvttsd2si was actually easy, but I learned, and
+        sometimes even fixed, some interesting things:
+        
+        - The llvm.x86.sse2.cvttsd2si intrinsic can actually result in LLVM emitting a
+          vcvttsd2si. I guess the intrinsic doesn't actually imply the instruction.
+        
+        - That whole thing about branchTruncateDoubleToUint32? Yeah we don't need that. It's
+          better to use branchTruncateDoubleToInt32 instead. It has the right semantics for
+          all of its callers (err, its one-and-only caller), and it's more likely to take
+          fast path. This patch kills branchTruncateDoubleToUint32.
+        
+        - "a[i] = v; v = a[i]". Does this change v? OK, assume that 'a[i]' is a pure-ish
+          operation - like an array access with 'i' being an integer index and we're not
+          having a bad time. Now does this change v? CSE assumes that it doesn't. That's
+          wrong. If 'a' is a typed array - the most sensible and pure kind of array - then
+          this can be a truncating cast. For example 'v' could be a double and 'a' could be
+          an integer array.
+        
+        - "v1 = a[i]; v2 = a[i]". Is v1 === v2 assuming that 'a[i]' is pure-ish? The answer
+          is no. You could have a different arrayMode in each access. I know this sounds
+          weird, but with concurrent JIT that might happen.
+        
+        This patch adds tests for all of this stuff, except for the first issue (it's weird
+        but probably doesn't matter) and the last issue (it's too much of a freakshow).
+
+        * assembler/MacroAssemblerARM64.h:
+        * assembler/MacroAssemblerARMv7.h:
+        * assembler/MacroAssemblerX86Common.h:
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::getByValLoadElimination):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+        * ftl/FTLAbbreviations.h:
+        (JSC::FTL::vectorType):
+        (JSC::FTL::getUndef):
+        (JSC::FTL::buildInsertElement):
+        * ftl/FTLIntrinsicRepository.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::doubleToInt32):
+        (JSC::FTL::LowerDFGToLLVM::doubleToUInt32):
+        (JSC::FTL::LowerDFGToLLVM::sensibleDoubleToInt32):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::insertElement):
+        (JSC::FTL::Output::hasSensibleDoubleToInt):
+        (JSC::FTL::Output::sensibleDoubleToInt):
+
 2013-12-05  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r160133.

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (160204 => 160205)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2013-12-06 01:47:19 UTC (rev 160205)
@@ -1196,15 +1196,6 @@
         return Jump(makeBranch(branchType == BranchIfTruncateSuccessful ? Equal : NotEqual));
     }
 
-    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
-    {
-        // Truncate to a 64-bit integer in dataTempRegister, copy the low 32-bit to dest.
-        m_assembler.fcvtzs<64, 64>(dest, src);
-        // Check thlow 32-bits zero extend to be equal to the full value.
-        m_assembler.cmp<64>(dest, dest, ARM64Assembler::UXTW, 0);
-        return Jump(makeBranch(branchType == BranchIfTruncateSuccessful ? Equal : NotEqual));
-    }
-
     void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest)
     {
         m_assembler.fcvt<32, 64>(dest, src);

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (160204 => 160205)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2013-12-06 01:47:19 UTC (rev 160205)
@@ -1074,23 +1074,6 @@
         return failure;
     }
 
-    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
-    {
-        m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
-        m_assembler.vmov(dest, fpTempRegisterAsSingle());
-        
-        Jump overflow = branch32(Equal, dest, TrustedImm32(0x7fffffff));
-        Jump success = branch32(GreaterThanOrEqual, dest, TrustedImm32(0));
-        overflow.link(this);
-
-        if (branchType == BranchIfTruncateSuccessful)
-            return success;
-        
-        Jump failure = jump();
-        success.link(this);
-        return failure;
-    }
-
     // Result is undefined if the value is outside of the integer range.
     void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     {

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (160204 => 160205)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2013-12-06 01:47:19 UTC (rev 160205)
@@ -885,13 +885,6 @@
         return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
     }
 
-    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
-    {
-        ASSERT(isSSE2Present());
-        m_assembler.cvttsd2si_rr(src, dest);
-        return branch32(branchType ? GreaterThanOrEqual : LessThan, dest, TrustedImm32(0));
-    }
-
     void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     {
         ASSERT(isSSE2Present());

Modified: trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp (160204 => 160205)


--- trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/dfg/DFGCSEPhase.cpp	2013-12-06 01:47:19 UTC (rev 160205)
@@ -331,7 +331,7 @@
         return 0;
     }
     
-    Node* getByValLoadElimination(Node* child1, Node* child2)
+    Node* getByValLoadElimination(Node* child1, Node* child2, ArrayMode arrayMode)
     {
         for (unsigned i = m_indexInBlock; i--;) {
             Node* node = m_currentBlock->at(i);
@@ -342,7 +342,9 @@
             case GetByVal:
                 if (!m_graph.byValIsPure(node))
                     return 0;
-                if (node->child1() == child1 && node->child2() == child2)
+                if (node->child1() == child1
+                    && node->child2() == child2
+                    && node->arrayMode().type() == arrayMode.type())
                     return node;
                 break;
                     
@@ -351,7 +353,12 @@
             case PutByValAlias: {
                 if (!m_graph.byValIsPure(node))
                     return 0;
-                if (m_graph.varArgChild(node, 0) == child1 && m_graph.varArgChild(node, 1) == child2)
+                // Typed arrays 
+                if (arrayMode.typedArrayType() != NotTypedArray)
+                    return 0;
+                if (m_graph.varArgChild(node, 0) == child1
+                    && m_graph.varArgChild(node, 1) == child2
+                    && node->arrayMode().type() == arrayMode.type())
                     return m_graph.varArgChild(node, 2).node();
                 // We must assume that the PutByVal will clobber the location we're getting from.
                 // FIXME: We can do better; if we know that the PutByVal is accessing an array of a
@@ -1216,7 +1223,7 @@
             if (cseMode == StoreElimination)
                 break;
             if (m_graph.byValIsPure(node))
-                setReplacement(getByValLoadElimination(node->child1().node(), node->child2().node()));
+                setReplacement(getByValLoadElimination(node->child1().node(), node->child2().node(), node->arrayMode()));
             break;
                 
         case PutByValDirect:
@@ -1226,7 +1233,7 @@
             Edge child1 = m_graph.varArgChild(node, 0);
             Edge child2 = m_graph.varArgChild(node, 1);
             if (node->arrayMode().canCSEStorage()) {
-                Node* replacement = getByValLoadElimination(child1.node(), child2.node());
+                Node* replacement = getByValLoadElimination(child1.node(), child2.node(), node->arrayMode());
                 if (!replacement)
                     break;
                 node->setOp(PutByValAlias);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (160204 => 160205)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2013-12-06 01:47:19 UTC (rev 160205)
@@ -2506,11 +2506,8 @@
                 MacroAssembler::Jump fixed = m_jit.jump();
                 notNaN.link(&m_jit);
                 
-                MacroAssembler::Jump failed;
-                if (isSigned(type))
-                    failed = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
-                else
-                    failed = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
+                MacroAssembler::Jump failed = m_jit.branchTruncateDoubleToInt32(
+                    fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
                 
                 addSlowPathGenerator(slowPathCall(failed, this, toInt32, gpr, fpr));
                 

Modified: trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h (160204 => 160205)


--- trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/ftl/FTLAbbreviations.h	2013-12-06 01:47:19 UTC (rev 160205)
@@ -58,6 +58,7 @@
 static inline LType doubleType(LContext context) { return llvm->DoubleTypeInContext(context); }
 
 static inline LType pointerType(LType type) { return llvm->PointerType(type, 0); }
+static inline LType vectorType(LType type, unsigned count) { return llvm->VectorType(type, count); }
 
 enum PackingMode { NotPacked, Packed };
 static inline LType structType(LContext context, LType* elementTypes, unsigned elementCount, PackingMode packing = NotPacked)
@@ -140,6 +141,7 @@
 }
 
 static inline LValue getParam(LValue function, unsigned index) { return llvm->GetParam(function, index); }
+static inline LValue getUndef(LType type) { return llvm->GetUndef(type); }
 
 enum BitExtension { ZeroExtend, SignExtend };
 static inline LValue constInt(LType type, unsigned long long value, BitExtension extension = ZeroExtend) { return llvm->ConstInt(type, value, extension == SignExtend); }
@@ -217,6 +219,7 @@
 static inline LValue buildBitCast(LBuilder builder, LValue value, LType type) { return llvm->BuildBitCast(builder, value, type, ""); }
 static inline LValue buildICmp(LBuilder builder, LIntPredicate cond, LValue left, LValue right) { return llvm->BuildICmp(builder, cond, left, right, ""); }
 static inline LValue buildFCmp(LBuilder builder, LRealPredicate cond, LValue left, LValue right) { return llvm->BuildFCmp(builder, cond, left, right, ""); }
+static inline LValue buildInsertElement(LBuilder builder, LValue vector, LValue element, LValue index) { return llvm->BuildInsertElement(builder, vector, element, index, ""); }
 
 enum SynchronizationScope { SingleThread, CrossThread };
 static inline LValue buildFence(LBuilder builder, LAtomicOrdering ordering, SynchronizationScope scope = CrossThread)

Modified: trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h (160204 => 160205)


--- trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/ftl/FTLIntrinsicRepository.h	2013-12-06 01:47:19 UTC (rev 160205)
@@ -42,12 +42,13 @@
     macro(doubleAbs, "llvm.fabs.f64", functionType(doubleType, doubleType)) \
     macro(mulWithOverflow32, "llvm.smul.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \
     macro(mulWithOverflow64, "llvm.smul.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \
-    macro(subWithOverflow32, "llvm.ssub.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \
-    macro(subWithOverflow64, "llvm.ssub.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \
     macro(patchpointInt64, "llvm.experimental.patchpoint.i64", functionType(int64, int32, int32, ref8, int32, Variadic)) \
     macro(patchpointVoid, "llvm.experimental.patchpoint.void", functionType(voidType, int32, int32, ref8, int32, Variadic)) \
     macro(stackmap, "llvm.experimental.stackmap", functionType(voidType, int32, int32, Variadic)) \
-    macro(trap, "llvm.trap", functionType(voidType))
+    macro(subWithOverflow32, "llvm.ssub.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \
+    macro(subWithOverflow64, "llvm.ssub.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \
+    macro(trap, "llvm.trap", functionType(voidType)) \
+    macro(x86SSE2CvtTSD2SI, "llvm.x86.sse2.cvttsd2si", functionType(int32, vectorType(doubleType, 2)))
 
 #define FOR_EACH_FUNCTION_TYPE(macro) \
     macro(C_JITOperation_ESt, functionType(intPtr, intPtr, intPtr)) \

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (160204 => 160205)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp	2013-12-06 01:47:19 UTC (rev 160205)
@@ -3011,15 +3011,41 @@
     
     LValue doubleToInt32(LValue doubleValue)
     {
+        if (Output::hasSensibleDoubleToInt())
+            return sensibleDoubleToInt32(doubleValue);
+        
         double limit = pow(2, 31) - 1;
         return doubleToInt32(doubleValue, -limit, limit);
     }
     
     LValue doubleToUInt32(LValue doubleValue)
     {
+        if (Output::hasSensibleDoubleToInt())
+            return sensibleDoubleToInt32(doubleValue);
+        
         return doubleToInt32(doubleValue, 0, pow(2, 32) - 1, false);
     }
     
+    LValue sensibleDoubleToInt32(LValue doubleValue)
+    {
+        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("sensible doubleToInt32 slow path"));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("sensible doubleToInt32 continuation"));
+        
+        ValueFromBlock fastResult = m_out.anchor(
+            m_out.sensibleDoubleToInt(doubleValue));
+        m_out.branch(
+            m_out.equal(fastResult.value(), m_out.constInt32(0x80000000)),
+            slowPath, continuation);
+        
+        LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
+        ValueFromBlock slowResult = m_out.anchor(
+            m_out.call(m_out.operation(toInt32), doubleValue));
+        m_out.jump(continuation);
+        
+        m_out.appendTo(continuation, lastNext);
+        return m_out.phi(m_out.int32, fastResult, slowResult);
+    }
+    
     void speculateBackward(
         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
     {

Modified: trunk/Source/_javascript_Core/ftl/FTLOutput.h (160204 => 160205)


--- trunk/Source/_javascript_Core/ftl/FTLOutput.h	2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/_javascript_Core/ftl/FTLOutput.h	2013-12-06 01:47:19 UTC (rev 160205)
@@ -154,6 +154,8 @@
     LValue lShr(LValue left, LValue right) { return buildLShr(m_builder, left, right); }
     LValue bitNot(LValue value) { return buildNot(m_builder, value); }
     
+    LValue insertElement(LValue vector, LValue element, LValue index) { return buildInsertElement(m_builder, vector, element, index); }
+    
     LValue addWithOverflow32(LValue left, LValue right)
     {
         return call(addWithOverflow32Intrinsic(), left, right);
@@ -183,6 +185,17 @@
         return call(doubleAbsIntrinsic(), value);
     }
     
+    static bool hasSensibleDoubleToInt() { return isX86(); }
+    LValue sensibleDoubleToInt(LValue value)
+    {
+        RELEASE_ASSERT(isX86());
+        return call(
+            x86SSE2CvtTSD2SIIntrinsic(),
+            insertElement(
+                insertElement(getUndef(vectorType(doubleType, 2)), value, int32Zero),
+                doubleZero, int32One));
+    }
+    
     LValue signExt(LValue value, LType type) { return buildSExt(m_builder, value, type); }
     LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); }
     LValue fpToInt(LValue value, LType type) { return buildFPToSI(m_builder, value, type); }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to