fourthTier: FTL should support ArithDiv
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2013 04:01:08 +0000 (04:01 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Jul 2013 04:01:08 +0000 (04:01 +0000)
https://bugs.webkit.org/show_bug.cgi?id=116771

Reviewed by Oliver Hunt.

* ftl/FTLAbbreviations.h:
(JSC::FTL::buildDiv):
(JSC::FTL::buildRem):
(JSC::FTL::buildFDiv):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLCommonValues.cpp:
(JSC::FTL::CommonValues::CommonValues):
* ftl/FTLCommonValues.h:
(CommonValues):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::LowerDFGToLLVM::compileArithDiv):
(LowerDFGToLLVM):
* ftl/FTLOutput.h:
(JSC::FTL::Output::div):
(JSC::FTL::Output::rem):
(JSC::FTL::Output::doubleDiv):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@153184 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/ftl/FTLAbbreviations.h
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLCommonValues.cpp
Source/JavaScriptCore/ftl/FTLCommonValues.h
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/JavaScriptCore/ftl/FTLOutput.h

index 90d4e2f..99f0eb3 100644 (file)
@@ -1,3 +1,30 @@
+2013-05-25  Filip Pizlo  <fpizlo@apple.com>
+
+        fourthTier: FTL should support ArithDiv
+        https://bugs.webkit.org/show_bug.cgi?id=116771
+
+        Reviewed by Oliver Hunt.
+
+        * ftl/FTLAbbreviations.h:
+        (JSC::FTL::buildDiv):
+        (JSC::FTL::buildRem):
+        (JSC::FTL::buildFDiv):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLCommonValues.cpp:
+        (JSC::FTL::CommonValues::CommonValues):
+        * ftl/FTLCommonValues.h:
+        (CommonValues):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileArithMul):
+        (JSC::FTL::LowerDFGToLLVM::compileArithDiv):
+        (LowerDFGToLLVM):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::div):
+        (JSC::FTL::Output::rem):
+        (JSC::FTL::Output::doubleDiv):
+
 2013-05-25  Mark Lam  <mark.lam@apple.com>
 
         Remove Interpreter::retrieveLastCaller().
index 8e2881c..d4e0ff1 100644 (file)
@@ -170,10 +170,13 @@ static inline LValue buildAlloca(LBuilder builder, LType type) { return LLVMBuil
 static inline LValue buildAdd(LBuilder builder, LValue left, LValue right) { return LLVMBuildAdd(builder, left, right, ""); }
 static inline LValue buildSub(LBuilder builder, LValue left, LValue right) { return LLVMBuildSub(builder, left, right, ""); }
 static inline LValue buildMul(LBuilder builder, LValue left, LValue right) { return LLVMBuildMul(builder, left, right, ""); }
+static inline LValue buildDiv(LBuilder builder, LValue left, LValue right) { return LLVMBuildSDiv(builder, left, right, ""); }
+static inline LValue buildRem(LBuilder builder, LValue left, LValue right) { return LLVMBuildSRem(builder, left, right, ""); }
 static inline LValue buildNeg(LBuilder builder, LValue value) { return LLVMBuildNeg(builder, value, ""); }
 static inline LValue buildFAdd(LBuilder builder, LValue left, LValue right) { return LLVMBuildFAdd(builder, left, right, ""); }
 static inline LValue buildFSub(LBuilder builder, LValue left, LValue right) { return LLVMBuildFSub(builder, left, right, ""); }
 static inline LValue buildFMul(LBuilder builder, LValue left, LValue right) { return LLVMBuildFMul(builder, left, right, ""); }
+static inline LValue buildFDiv(LBuilder builder, LValue left, LValue right) { return LLVMBuildFDiv(builder, left, right, ""); }
 static inline LValue buildFNeg(LBuilder builder, LValue value) { return LLVMBuildFNeg(builder, value, ""); }
 static inline LValue buildAnd(LBuilder builder, LValue left, LValue right) { return LLVMBuildAnd(builder, left, right, ""); }
 static inline LValue buildOr(LBuilder builder, LValue left, LValue right) { return LLVMBuildOr(builder, left, right, ""); }
index 3cc0e21..16aded5 100644 (file)
@@ -66,6 +66,7 @@ inline bool canCompile(Node* node)
     case ArithAdd:
     case ArithSub:
     case ArithMul:
+    case ArithDiv:
     case ArithNegate:
     case UInt32ToNumber:
     case Int32ToDouble:
index 8ee0301..f18bb79 100644 (file)
@@ -47,6 +47,7 @@ CommonValues::CommonValues(LContext context)
     , booleanFalse(constInt(boolean, false, ZeroExtend))
     , int8Zero(constInt(int8, 0, SignExtend))
     , int32Zero(constInt(int32, 0, SignExtend))
+    , int32One(constInt(int32, 1, SignExtend))
     , int64Zero(constInt(int64, 0, SignExtend))
     , intPtrZero(constInt(intPtr, 0, SignExtend))
     , intPtrOne(constInt(intPtr, 1, SignExtend))
index 9e3c757..8e1df69 100644 (file)
@@ -59,6 +59,7 @@ public:
     const LValue booleanFalse;
     const LValue int8Zero;
     const LValue int32Zero;
+    const LValue int32One;
     const LValue int64Zero;
     const LValue intPtrZero;
     const LValue intPtrOne;
index bce23c9..07b5117 100644 (file)
@@ -308,6 +308,9 @@ private:
         case ArithMul:
             compileArithMul();
             break;
+        case ArithDiv:
+            compileArithDiv();
+            break;
         case ArithNegate:
             compileArithNegate();
             break;
@@ -659,6 +662,8 @@ private:
                 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
                 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation"));
                 
+                m_out.branch(m_out.notZero32(result), continuation, slowCase);
+                
                 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation);
                 speculate(NegativeZero, noValue(), 0, m_out.lessThan(left, m_out.int32Zero));
                 speculate(NegativeZero, noValue(), 0, m_out.lessThan(right, m_out.int32Zero));
@@ -683,6 +688,103 @@ private:
         }
     }
     
+    void compileArithDiv()
+    {
+        switch (m_node->binaryUseKind()) {
+        case Int32Use: {
+            LValue numerator = lowInt32(m_node->child1());
+            LValue denominator = lowInt32(m_node->child2());
+            
+            LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithDiv unsafe denominator"));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithDiv continuation"));
+            LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithDiv done"));
+            
+            Vector<ValueFromBlock, 3> results;
+            
+            LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
+            
+            m_out.branch(m_out.above(adjustedDenominator, m_out.int32One), continuation, unsafeDenominator);
+            
+            LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
+            
+            LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
+            
+            if (nodeUsedAsNumber(m_node->arithNodeFlags())) {
+                speculate(Overflow, noValue(), 0, m_out.isZero32(denominator));
+                speculate(Overflow, noValue(), 0, m_out.equal(numerator, neg2ToThe31));
+                m_out.jump(continuation);
+            } else {
+                // This is the case where we convert the result to an int after we're done. So,
+                // if the denominator is zero, then the result should be result should be zero.
+                // If the denominator is not zero (i.e. it's -1 because we're guarded by the
+                // check above) and the numerator is -2^31 then the result should be -2^31.
+                
+                LBasicBlock divByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv divide by zero"));
+                LBasicBlock notDivByZero = FTL_NEW_BLOCK(m_out, ("ArithDiv not divide by zero"));
+                LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithDiv -2^31/-1"));
+                
+                m_out.branch(m_out.isZero32(denominator), divByZero, notDivByZero);
+                
+                m_out.appendTo(divByZero, notDivByZero);
+                results.append(m_out.anchor(m_out.int32Zero));
+                m_out.jump(done);
+                
+                m_out.appendTo(notDivByZero, neg2ToThe31ByNeg1);
+                m_out.branch(m_out.equal(numerator, neg2ToThe31), neg2ToThe31ByNeg1, continuation);
+                
+                m_out.appendTo(neg2ToThe31ByNeg1, continuation);
+                results.append(m_out.anchor(neg2ToThe31));
+                m_out.jump(done);
+            }
+            
+            m_out.appendTo(continuation, done);
+            
+            if (!nodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
+                LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithDiv zero numerator"));
+                LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithDiv numerator continuation"));
+                
+                m_out.branch(m_out.isZero32(numerator), zeroNumerator, numeratorContinuation);
+                
+                LBasicBlock innerLastNext = m_out.appendTo(zeroNumerator, numeratorContinuation);
+                
+                speculate(
+                    NegativeZero, noValue(), 0, m_out.lessThan(denominator, m_out.int32Zero));
+                
+                m_out.jump(numeratorContinuation);
+                
+                m_out.appendTo(numeratorContinuation, innerLastNext);
+            }
+            
+            LValue divisionResult = m_out.div(numerator, denominator);
+            
+            if (nodeUsedAsNumber(m_node->arithNodeFlags())) {
+                speculate(
+                    Overflow, noValue(), 0,
+                    m_out.notEqual(m_out.mul(divisionResult, denominator), numerator));
+            }
+            
+            results.append(m_out.anchor(divisionResult));
+            m_out.jump(done);
+            
+            m_out.appendTo(done, lastNext);
+            
+            m_int32Values.add(m_node, m_out.phi(m_out.int32, results));
+            break;
+        }
+            
+        case NumberUse: {
+            m_doubleValues.add(
+                m_node,
+                m_out.doubleDiv(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
+            break;
+        }
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+    }
+    
     void compileArithNegate()
     {
         switch (m_node->child1().useKind()) {
index f8dbb0a..b5129a7 100644 (file)
@@ -133,11 +133,14 @@ public:
     LValue add(LValue left, LValue right) { return buildAdd(m_builder, left, right); }
     LValue sub(LValue left, LValue right) { return buildSub(m_builder, left, right); }
     LValue mul(LValue left, LValue right) { return buildMul(m_builder, left, right); }
+    LValue div(LValue left, LValue right) { return buildDiv(m_builder, left, right); }
+    LValue rem(LValue left, LValue right) { return buildRem(m_builder, left, right); }
     LValue neg(LValue value) { return buildNeg(m_builder, value); }
 
     LValue doubleAdd(LValue left, LValue right) { return buildFAdd(m_builder, left, right); }
     LValue doubleSub(LValue left, LValue right) { return buildFSub(m_builder, left, right); }
     LValue doubleMul(LValue left, LValue right) { return buildFMul(m_builder, left, right); }
+    LValue doubleDiv(LValue left, LValue right) { return buildFDiv(m_builder, left, right); }
     LValue doubleNeg(LValue value) { return buildFNeg(m_builder, value); }
 
     LValue bitAnd(LValue left, LValue right) { return buildAnd(m_builder, left, right); }