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

Changeset 286045 in webkit


Ignore:
Timestamp:
Nov 18, 2021, 10:06:32 PM (5 years ago)
Author:
rmorisset@apple.com
Message:

[JSC/Air] Optimize enableMovesOnValueAndAdjacents in IRC
https://bugs.webkit.org/show_bug.cgi?id=228615

Reviewed by Saam Barati.

The Iterated Register Coalescing (IRC) register allocator spends a very significant fraction of its time in JS2 in enableMovesOnValueAndAdjacents (816ms out of 2.07s spent in register allocation for Wasm code in one run I looked at with Instruments).
The reason is that if this function is called on N nodes that are neighbors of each other, then enableMovesOnValue (which is kinda expensive as it iterates a SmallSet which is not always small) will be called N times on each of the N nodes. This can trivially be fixed by keeping track of which nodes need enableMovesOnValue called on them and only calling it on them once.

It is a bit tricky to measure the performance impact of this, as it heavily depends on whether some very large functions reach Air or not, so there is a lot of noise.
Here are the numbers out of 4 runs of JS2 (cli version) on an M1 MBP with --airForceIRCAllocator=1:
Baseline : total time in allocateRegistersByGraphColoring ranges from 2090ms to 3018ms, most time for a single function ranges from 631ms to 849ms
With this patch: total time in allocateRegistersByGraphColoring ranges from 1580ms to 2333ms, most time for a single function ranges from 337ms to 560ms
So despite the noise it seems quite clearly a win.

  • b3/air/AirAllocateRegistersByGraphColoring.cpp:
Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r286042 r286045  
     12021-11-18  Robin Morisset  <rmorisset@apple.com>
     2
     3        [JSC/Air] Optimize enableMovesOnValueAndAdjacents in IRC
     4        https://bugs.webkit.org/show_bug.cgi?id=228615
     5
     6        Reviewed by Saam Barati.
     7
     8        The Iterated Register Coalescing (IRC) register allocator spends a very significant fraction of its time in JS2 in enableMovesOnValueAndAdjacents (816ms out of 2.07s spent in register allocation for Wasm code in one run I looked at with Instruments).
     9        The reason is that if this function is called on N nodes that are neighbors of each other, then enableMovesOnValue (which is kinda expensive as it iterates a SmallSet which is not always small) will be called N times on each of the N nodes. This can trivially be fixed by keeping track of which nodes need enableMovesOnValue called on them and only calling it on them once.
     10
     11        It is a bit tricky to measure the performance impact of this, as it heavily depends on whether some very large functions reach Air or not, so there is a lot of noise.
     12        Here are the numbers out of 4 runs of JS2 (cli version) on an M1 MBP with --airForceIRCAllocator=1:
     13        Baseline       : total time in allocateRegistersByGraphColoring ranges from 2090ms to 3018ms, most time for a single function ranges from 631ms to 849ms
     14        With this patch: total time in allocateRegistersByGraphColoring ranges from 1580ms to 2333ms, most time for a single function ranges from 337ms to 560ms
     15        So despite the noise it seems quite clearly a win.
     16
     17        * b3/air/AirAllocateRegistersByGraphColoring.cpp:
     18
    1192021-11-18  Mark Lam  <mark.lam@apple.com>
    220
  • trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByGraphColoring.cpp

    r280689 r286045  
    913913    IRC(Code& code, const Vector<Reg>& regsInPriorityOrder, IndexType lastPrecoloredRegisterIndex, unsigned tmpArraySize, const BitVector& unspillableTmps, const UseCounts& useCounts)
    914914        : Base(code, regsInPriorityOrder, lastPrecoloredRegisterIndex, tmpArraySize, unspillableTmps, useCounts)
     915        , m_movesToEnable(tmpArraySize)
    915916    {
    916917    }
     
    942943            if (!m_simplifyWorklist.isEmpty())
    943944                simplify();
     945            else if (!m_movesToEnable.isEmpty())
     946                enableMoves();
    944947            else if (!m_worklistMoves.isEmpty())
    945948                coalesce();
     
    11041107        unsigned oldDegree = m_degrees[tmpIndex]--;
    11051108        if (oldDegree == registerCount()) {
    1106             enableMovesOnValueAndAdjacents(tmpIndex);
     1109            lazyEnableMovesOnValueAndAdjacents(tmpIndex);
    11071110            m_spillWorklist.quickClear(tmpIndex);
    11081111            if (isMoveRelated(tmpIndex))
     
    11471150    }
    11481151
     1152    void lazyEnableMovesOnValueAndAdjacents(IndexType tmpIndex)
     1153    {
     1154        m_movesToEnable.quickSet(tmpIndex);
     1155        forEachAdjacent(tmpIndex, [this] (IndexType adjacentTmpIndex) {
     1156            m_movesToEnable.quickSet(adjacentTmpIndex);
     1157        });
     1158    }
     1159
    11491160    void enableMovesOnValue(IndexType tmpIndex)
    11501161    {
     
    11551166    }
    11561167
    1157     void enableMovesOnValueAndAdjacents(IndexType tmpIndex)
    1158     {
    1159         enableMovesOnValue(tmpIndex);
    1160 
    1161         forEachAdjacent(tmpIndex, [this] (IndexType adjacentTmpIndex) {
    1162             enableMovesOnValue(adjacentTmpIndex);
    1163         });
     1168    void enableMoves()
     1169    {
     1170        for (IndexType tmpIndex : m_movesToEnable)
     1171            enableMovesOnValue(tmpIndex);
     1172        m_movesToEnable.clearAll();
    11641173    }
    11651174
     
    13101319    // Set of "move" not yet ready for coalescing.
    13111320    BitVector m_activeMoves;
     1321    // Set of Tmps whose moves are now ready for possible coalescing.
     1322    BitVector m_movesToEnable;
    13121323};
    13131324
Note: See TracChangeset for help on using the changeset viewer.