Changeset 89084 in webkit


Ignore:
Timestamp:
Jun 16, 2011 4:40:06 PM (13 years ago)
Author:
barraclough@apple.com
Message:

https://bugs.webkit.org/show_bug.cgi?id=62824
DFG JIT - add support for branch-fusion of compareEq, JSValue comparisons in SpeculativeJIT

Reviewed by Sam Weinig.

CompareEq of non-integer values is the most common cause of speculation failure.

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):

  • Support Equals.

(JSC::DFG::SpeculativeJIT::compilePeepHoleEq):

  • new! - peephole optimized Eq of JSValues.

(JSC::DFG::SpeculativeJIT::compile):

  • Add peephole optimization for CompareEq.
  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::detectPeepHoleBranch):

  • Add support for dead nodes between compare & branch.

(JSC::DFG::SpeculativeJIT::isInteger):

  • Added to determine which form of peephole to do in CompareEq.
Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r89077 r89084  
     12011-06-16  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=62824
     6        DFG JIT - add support for branch-fusion of compareEq, JSValue comparisons in SpeculativeJIT
     7
     8        CompareEq of non-integer values is the most common cause of speculation failure.
     9
     10        * dfg/DFGSpeculativeJIT.cpp:
     11        (JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):
     12            - Support Equals.
     13        (JSC::DFG::SpeculativeJIT::compilePeepHoleEq):
     14            - new! - peephole optimized Eq of JSValues.
     15        (JSC::DFG::SpeculativeJIT::compile):
     16            - Add peephole optimization for CompareEq.
     17        * dfg/DFGSpeculativeJIT.h:
     18        (JSC::DFG::SpeculativeJIT::detectPeepHoleBranch):
     19            - Add support for dead nodes between compare & branch.
     20        (JSC::DFG::SpeculativeJIT::isInteger):
     21            - Added to determine which form of peephole to do in CompareEq.
     22
    1232011-06-16  Geoffrey Garen  <ggaren@apple.com>
    224
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r88280 r89084  
    234234}
    235235
    236 void SpeculativeJIT::compilePeepHoleBranch(Node& node, JITCompiler::RelationalCondition condition)
    237 {
    238     Node& branchNode = m_jit.graph()[m_compileIndex + 1];
     236void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
     237{
     238    Node& branchNode = m_jit.graph()[branchNodeIndex];
    239239    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    240240    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     
    267267}
    268268
     269void SpeculativeJIT::compilePeepHoleEq(Node& node, NodeIndex branchNodeIndex)
     270{
     271    Node& branchNode = m_jit.graph()[branchNodeIndex];
     272    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
     273    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     274
     275    // The branch instruction will branch to the taken block.
     276    // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
     277    JITCompiler::ResultCondition condition = JITCompiler::NonZero;
     278    if (taken == (m_block + 1)) {
     279        condition = JITCompiler::Zero;
     280        BlockIndex tmp = taken;
     281        taken = notTaken;
     282        notTaken = tmp;
     283    }
     284
     285    JSValueOperand op1(this, node.child1);
     286    JSValueOperand op2(this, node.child2);
     287    GPRReg op1GPR = op1.gpr();
     288    GPRReg op2GPR = op2.gpr();
     289    flushRegisters();
     290
     291    GPRResult result(this);
     292    callOperation(operationCompareEq, result.gpr(), op1GPR, op2GPR);
     293    addBranch(m_jit.branchTest8(condition, result.gpr()), taken);
     294
     295    // Check for fall through, otherwise we need to jump.
     296    if (notTaken != (m_block + 1))
     297        addBranch(m_jit.jump(), notTaken);
     298}
     299
    269300void SpeculativeJIT::compile(Node& node)
    270301{
     
    550581    case CompareLess: {
    551582        // Fused compare & branch.
    552         if (detectPeepHoleBranch()) {
     583        NodeIndex branchNodeIndex = detectPeepHoleBranch();
     584        if (branchNodeIndex != NoNode) {
    553585            // detectPeepHoleBranch currently only permits the branch to be the very next node,
    554586            // so can be no intervening nodes to also reference the compare.
    555587            ASSERT(node.adjustedRefCount() == 1);
    556588
    557             compilePeepHoleBranch(node, JITCompiler::LessThan);
     589            compilePeepHoleIntegerBranch(node, branchNodeIndex, JITCompiler::LessThan);
    558590
    559591            use(node.child1);
    560592            use(node.child2);
    561             ++m_compileIndex;
     593            m_compileIndex = branchNodeIndex;
    562594            return;
    563595        }
     
    578610    case CompareLessEq: {
    579611        // Fused compare & branch.
    580         if (detectPeepHoleBranch()) {
     612        NodeIndex branchNodeIndex = detectPeepHoleBranch();
     613        if (branchNodeIndex != NoNode) {
    581614            // detectPeepHoleBranch currently only permits the branch to be the very next node,
    582615            // so can be no intervening nodes to also reference the compare.
    583616            ASSERT(node.adjustedRefCount() == 1);
    584617
    585             compilePeepHoleBranch(node, JITCompiler::LessThanOrEqual);
     618            compilePeepHoleIntegerBranch(node, branchNodeIndex, JITCompiler::LessThanOrEqual);
    586619
    587620            use(node.child1);
    588621            use(node.child2);
    589             ++m_compileIndex;
     622            m_compileIndex = branchNodeIndex;
    590623            return;
    591624        }
     
    605638
    606639    case CompareEq: {
     640        // Fused compare & branch.
     641        NodeIndex branchNodeIndex = detectPeepHoleBranch();
     642        if (branchNodeIndex != NoNode) {
     643            // detectPeepHoleBranch currently only permits the branch to be the very next node,
     644            // so can be no intervening nodes to also reference the compare.
     645            ASSERT(node.adjustedRefCount() == 1);
     646
     647            if (isInteger(node.child1) || isInteger(node.child2))
     648                compilePeepHoleIntegerBranch(node, branchNodeIndex, JITCompiler::Equal);
     649            else
     650                compilePeepHoleEq(node, branchNodeIndex);
     651
     652            use(node.child1);
     653            use(node.child2);
     654            m_compileIndex = branchNodeIndex;
     655            return;
     656        }
     657
    607658        SpeculateIntegerOperand op1(this, node.child1);
    608659        SpeculateIntegerOperand op2(this, node.child2);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r88280 r89084  
    139139    void initializeVariableTypes();
    140140
    141     bool detectPeepHoleBranch()
    142     {
    143         // Check if the block contains precisely one more node.
    144         if (m_compileIndex + 2 != m_jit.graph().m_blocks[m_block]->end)
    145             return false;
     141    // Returns the node index of the branch node if peephole is okay, NoNode otherwise.
     142    NodeIndex detectPeepHoleBranch()
     143    {
     144        NodeIndex lastNodeIndex = m_jit.graph().m_blocks[m_block]->end - 1;
     145
     146        // Check that no intervening nodes will be generated.
     147        for (NodeIndex index = m_compileIndex + 1; index < lastNodeIndex; ++index) {
     148            if (m_jit.graph()[index].shouldGenerate())
     149                return NoNode;
     150        }
    146151
    147152        // Check if the lastNode is a branch on this node.
    148         Node& lastNode = m_jit.graph()[m_compileIndex + 1];
    149         return lastNode.op == Branch && lastNode.child1 == m_compileIndex;
    150     }
    151 
    152     void compilePeepHoleBranch(Node&, JITCompiler::RelationalCondition);
     153        Node& lastNode = m_jit.graph()[lastNodeIndex];
     154        return lastNode.op == Branch && lastNode.child1 == m_compileIndex ? lastNodeIndex : NoNode;
     155    }
     156
     157    bool isInteger(NodeIndex nodeIndex)
     158    {
     159        Node& node = m_jit.graph()[nodeIndex];
     160        if (node.hasInt32Result())
     161            return true;
     162
     163        VirtualRegister virtualRegister = node.virtualRegister();
     164        GenerationInfo& info = m_generationInfo[virtualRegister];
     165
     166        return (info.registerFormat() | DataFormatJS) == DataFormatJSInteger;
     167    }
     168
     169    void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
     170    void compilePeepHoleEq(Node&, NodeIndex branchNodeIndex);
    153171
    154172    // Add a speculation check without additional recovery.
Note: See TracChangeset for help on using the changeset viewer.