Changeset 156746 in webkit


Ignore:
Timestamp:
Oct 1, 2013 4:18:47 PM (11 years ago)
Author:
commit-queue@webkit.org
Message:

FTL: split overflow checks into non-overflow arithmetic and an additional call to the overflow intrinsic check.
https://bugs.webkit.org/show_bug.cgi?id=122170

Patch by Nadav Rotem <nrotem@apple.com> on 2013-10-01
Reviewed by Filip Pizlo.

Overflow intrinsics are preventing SCEV and other LLVM analysis passes from analyzing loops. This patch changes the FTL-IR gen by splitting arithmetic calculations into two parts:

  1. Generate the arithmetic calculation (that may overflow)
  2. Generate the overflow check (that is only used by the OSR-exit logic).

We trust LLVM (SelectionDAG) to merge these calculations into a single opcode.

This JS function:

function foo() {

for (i=0; i < 10000000; i++) { }

}

Is now compiled into this LLVM-IR:

"OSR exit continuation for @24<Int32>": ; preds = %"Block #0", %"OSR exit continuation for @24<Int32>2"

%4 = phi i64 [ %10, %"OSR exit continuation for @24<Int32>2" ], [ -281474976710656, %"Block #0" ]
%5 = trunc i64 %4 to i32
%6 = add i32 %5, 1
%7 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %5, i32 1)
%8 = extractvalue { i32, i1 } %7, 1
br i1 %8, label %"OSR exit failCase for @24<Int32>1", label %"OSR exit continuation for @24<Int32>2"

And into this assembly:

LBB0_1: ## %OSR exit continuation for @24<Int32>

## =>This Inner Loop Header: Depth=1

movl %ecx, %esi
incl %esi
jo LBB0_4

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::LowerDFGToLLVM::compileAddSub):
(JSC::FTL::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::LowerDFGToLLVM::compileArithNegate):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r156734 r156746  
     12013-10-01  Nadav Rotem  <nrotem@apple.com>
     2
     3        FTL: split overflow checks into non-overflow arithmetic and an additional call to the overflow intrinsic check.
     4        https://bugs.webkit.org/show_bug.cgi?id=122170
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Overflow intrinsics are preventing SCEV and other LLVM analysis passes from analyzing loops. This patch changes the FTL-IR gen by splitting arithmetic calculations into two parts:
     9        1. Generate the arithmetic calculation (that may overflow)
     10        2. Generate the overflow check (that is only used by the OSR-exit logic).
     11
     12        We trust LLVM (SelectionDAG) to merge these calculations into a single opcode.
     13
     14        This JS function:
     15
     16        function foo() {
     17            for (i=0; i < 10000000; i++) { }
     18        }
     19
     20        Is now compiled into this LLVM-IR:
     21
     22        "OSR exit continuation for @24<Int32>":           ; preds = %"Block #0", %"OSR exit continuation for @24<Int32>2"
     23          %4 = phi i64 [ %10, %"OSR exit continuation for @24<Int32>2" ], [ -281474976710656, %"Block #0" ]
     24          %5 = trunc i64 %4 to i32
     25          %6 = add i32 %5, 1
     26          %7 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %5, i32 1)
     27          %8 = extractvalue { i32, i1 } %7, 1
     28          br i1 %8, label %"OSR exit failCase for @24<Int32>1", label %"OSR exit continuation for @24<Int32>2"
     29
     30         And into this assembly:
     31
     32        LBB0_1:                                 ## %OSR exit continuation for @24<Int32>
     33                                        ## =>This Inner Loop Header: Depth=1
     34            movl  %ecx, %esi
     35            incl  %esi
     36            jo  LBB0_4
     37
     38        * ftl/FTLLowerDFGToLLVM.cpp:
     39        (JSC::FTL::LowerDFGToLLVM::compileAddSub):
     40        (JSC::FTL::LowerDFGToLLVM::compileArithMul):
     41        (JSC::FTL::LowerDFGToLLVM::compileArithNegate):
     42
    1432013-10-01  Nadav Rotem  <nrotem@apple.com>
    244
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r156734 r156746  
    663663            LValue left = lowInt32(m_node->child1());
    664664            LValue right = lowInt32(m_node->child2());
    665            
     665            LValue result = isSub ? m_out.sub(left, right) : m_out.add(left, right);
     666
    666667            if (bytecodeCanTruncateInteger(m_node->arithNodeFlags())) {
    667                 setInt32(isSub ? m_out.sub(left, right) : m_out.add(left, right));
     668                setInt32(result);
    668669                break;
    669670            }
    670671
    671             LValue result = isSub ? m_out.subWithOverflow32(left, right) : m_out.addWithOverflow32(left, right);
    672 
    673             speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1));
    674             setInt32(m_out.extractValue(result, 0));
     672            LValue overflow = isSub ? m_out.subWithOverflow32(left, right) : m_out.addWithOverflow32(left, right);
     673
     674            speculate(Overflow, noValue(), 0, m_out.extractValue(overflow, 1));
     675            setInt32(result);
    675676            break;
    676677        }
     
    688689            LValue left = lowInt52(m_node->child1());
    689690            LValue right = lowInt52(m_node->child2());
    690             LValue result = isSub ? m_out.subWithOverflow64(left, right) : m_out.addWithOverflow64(left, right);
    691             speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1));
    692             setInt52(m_out.extractValue(result, 0));
     691            LValue result = isSub ? m_out.sub(left, right) : m_out.add(left, right);
     692
     693            LValue overflow = isSub ? m_out.subWithOverflow64(left, right) : m_out.addWithOverflow64(left, right);
     694            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflow, 1));
     695            setInt52(result);
    693696            break;
    694697        }
     
    714717            LValue left = lowInt32(m_node->child1());
    715718            LValue right = lowInt32(m_node->child2());
    716            
    717             LValue result;
    718             if (bytecodeCanTruncateInteger(m_node->arithNodeFlags()))
    719                 result = m_out.mul(left, right);
    720             else {
     719            LValue result = m_out.mul(left, right);
     720
     721            if (!bytecodeCanTruncateInteger(m_node->arithNodeFlags())) {
    721722                LValue overflowResult = m_out.mulWithOverflow32(left, right);
    722723                speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
    723                 result = m_out.extractValue(overflowResult, 0);
    724724            }
    725725           
     
    745745            LValue left = lowWhicheverInt52(m_node->child1(), kind);
    746746            LValue right = lowInt52(m_node->child2(), opposite(kind));
    747            
     747            LValue result = m_out.mul(left, right);
     748
     749
    748750            LValue overflowResult = m_out.mulWithOverflow64(left, right);
    749751            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
    750             LValue result = m_out.extractValue(overflowResult, 0);
    751            
     752
    752753            if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
    753754                LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case"));
     
    10511052            LValue value = lowInt32(m_node->child1());
    10521053           
    1053             LValue result;
    1054             if (bytecodeCanTruncateInteger(m_node->arithNodeFlags()))
    1055                 result = m_out.neg(value);
    1056             else if (bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
    1057                 // We don't have a negate-with-overflow intrinsic. Hopefully this
    1058                 // does the trick, though.
    1059                 LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
    1060                 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
    1061                 result = m_out.extractValue(overflowResult, 0);
    1062             } else {
    1063                 speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff)));
    1064                 result = m_out.neg(value);
    1065             }
    1066            
     1054            LValue result = m_out.neg(value);
     1055            if (!bytecodeCanTruncateInteger(m_node->arithNodeFlags())) {
     1056                if (bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) {
     1057                    // We don't have a negate-with-overflow intrinsic. Hopefully this
     1058                    // does the trick, though.
     1059                    LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
     1060                    speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
     1061                } else
     1062                    speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff)));
     1063
     1064            }
     1065
    10671066            setInt32(result);
    10681067            break;
     
    10831082            LValue overflowResult = m_out.subWithOverflow64(m_out.int64Zero, value);
    10841083            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
    1085             LValue result = m_out.extractValue(overflowResult, 0);
     1084            LValue result = m_out.neg(value);
    10861085            speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
    10871086            setInt52(result);
Note: See TracChangeset for help on using the changeset viewer.