⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 197655 in webkit


Ignore:
Timestamp:
Mar 6, 2016, 7:21:08 PM (11 years ago)
Author:
benjamin@webkit.org
Message:

[JSC] Improve DFG's Int32 ArithMul if one operand is a constant
https://bugs.webkit.org/show_bug.cgi?id=155066

Reviewed by Filip Pizlo.

When multiplying an integer by a constant, DFG was doing quite
a bit worse than baseline JIT.
We were loading the constant into a register, doing the multiply,
the checking the result and both operands for negative zero.

This patch changes:
-Use the multiply-by-immediate form on x86.
-Do as few checks as possible to detect negative-zero.

In most cases, this reduce the negative-zero checks
to zero or one TEST+JUMP.

  • assembler/MacroAssembler.h:

(JSC::MacroAssembler::mul32):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileArithMul):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r197654 r197655  
     12016-03-06  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        [JSC] Improve DFG's Int32 ArithMul if one operand is a constant
     4        https://bugs.webkit.org/show_bug.cgi?id=155066
     5
     6        Reviewed by Filip Pizlo.
     7
     8        When multiplying an integer by a constant, DFG was doing quite
     9        a bit worse than baseline JIT.
     10        We were loading the constant into a register, doing the multiply,
     11        the checking the result and both operands for negative zero.
     12
     13        This patch changes:
     14        -Use the multiply-by-immediate form on x86.
     15        -Do as few checks as possible to detect negative-zero.
     16
     17        In most cases, this reduce the negative-zero checks
     18        to zero or one TEST+JUMP.
     19
     20        * assembler/MacroAssembler.h:
     21        (JSC::MacroAssembler::mul32):
     22        * dfg/DFGSpeculativeJIT.cpp:
     23        (JSC::DFG::SpeculativeJIT::compileArithMul):
     24
    1252016-03-06  Benjamin Poulain  <benjamin@webkit.org>
    226
  • trunk/Source/JavaScriptCore/assembler/MacroAssembler.h

    r197653 r197655  
    116116    using MacroAssemblerBase::move;
    117117    using MacroAssemblerBase::add32;
     118    using MacroAssemblerBase::mul32;
    118119    using MacroAssemblerBase::and32;
    119120    using MacroAssemblerBase::branchAdd32;
     
    14891490    }
    14901491
     1492    void mul32(Imm32 imm, RegisterID src, RegisterID dest)
     1493    {
     1494        if (shouldBlind(imm)) {
     1495            if (src != dest || haveScratchRegisterForBlinding()) {
     1496                if (src == dest) {
     1497                    move(src, scratchRegisterForBlinding());
     1498                    src = scratchRegisterForBlinding();
     1499                }
     1500                loadXorBlindedConstant(xorBlindConstant(imm), dest);
     1501                mul32(src, dest);
     1502                return;
     1503            }
     1504            // If we don't have a scratch register available for use, we'll just
     1505            // place a random number of nops.
     1506            uint32_t nopCount = random() & 3;
     1507            while (nopCount--)
     1508                nop();
     1509        }
     1510        mul32(imm.asTrustedImm32(), src, dest);
     1511    }
     1512
    14911513    void and32(Imm32 imm, RegisterID dest)
    14921514    {
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r197654 r197655  
    36723672    switch (node->binaryUseKind()) {
    36733673    case Int32Use: {
     3674        if (node->child2()->isInt32Constant()) {
     3675            SpeculateInt32Operand op1(this, node->child1());
     3676            GPRTemporary result(this);
     3677
     3678            int32_t imm = node->child2()->asInt32();
     3679            GPRReg op1GPR = op1.gpr();
     3680            GPRReg resultGPR = result.gpr();
     3681
     3682            if (!shouldCheckOverflow(node->arithMode()))
     3683                m_jit.mul32(Imm32(imm), op1GPR, resultGPR);
     3684            else {
     3685                speculationCheck(Overflow, JSValueRegs(), 0,
     3686                    m_jit.branchMul32(MacroAssembler::Overflow, op1GPR, Imm32(imm), resultGPR));
     3687            }
     3688
     3689            // The only way to create negative zero with a constant is:
     3690            // -negative-op1 * 0.
     3691            // -zero-op1 * negative constant.
     3692            if (shouldCheckNegativeZero(node->arithMode())) {
     3693                if (!imm)
     3694                    speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Signed, op1GPR));
     3695                else if (imm < 0) {
     3696                    if (shouldCheckOverflow(node->arithMode()))
     3697                        speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
     3698                    else
     3699                        speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Zero, op1GPR));
     3700                }
     3701            }
     3702
     3703            int32Result(resultGPR, node);
     3704            return;
     3705        }
    36743706        SpeculateInt32Operand op1(this, node->child1());
    36753707        SpeculateInt32Operand op2(this, node->child2());
     
    36943726        if (shouldCheckNegativeZero(node->arithMode())) {
    36953727            MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
    3696             speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
    3697             speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
     3728            speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Signed, reg1));
     3729            speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Signed, reg2));
    36983730            resultNonZero.link(&m_jit);
    36993731        }
     
    37023734        return;
    37033735    }
    3704    
    3705 #if USE(JSVALUE64)   
     3736
     3737#if USE(JSVALUE64)
    37063738    case Int52RepUse: {
    37073739        ASSERT(shouldCheckOverflow(node->arithMode()));
Note: See TracChangeset for help on using the changeset viewer.