Ignore:
Timestamp:
May 17, 2017, 12:25:18 PM (8 years ago)
Author:
[email protected]
Message:

PinnedRegisters should be better modeled in IRC/Briggs
https://bugs.webkit.org/show_bug.cgi?id=171955

Reviewed by Filip Pizlo.

This patch fixes a bug in Briggs/IRC with respect to pinned registers.
Pinned registers were not part of the assignable register file in IRC/Briggs,
and this would lead to an asymmetry because they were modeled in the
interference graph. The bug is that we use registerCount() to move various
Tmps between various lists in the different allocators, and if a Tmp
interfered with a pinned register (usually via a Patchpoint's clobbered set),
we'd have an interference edge modeled in the degree for that Tmp, but the registerCount()
would make us think that this particular Tmp is not assignable. This would
lead us to fail to color a colorable graph. Specifically, this happened in
our various patchpoint tests that stress the register allocator by forcing
the entire register file into arguments for the patchpoint and then doing
interesting things with the result, arguments, etc.

This patch fixes the bug by coming up with an more natural way to model pinned
registers. Pinned registers are now part of the register file. However,
pinned registers are live at every point in the program (this is a defining
property of a pinned register). In practice, this means that the only Tmps
that can be assigned to pinned registers are ones that are coalescing
candidates. This means the program has some number of defs for a Tmp T like:
MoveType pinnedReg, T

Note, if any other defs for T happen, like:
Add32, t1, t2, T
T will have an interference edge with pinnedReg, since pinnedReg is live
at every point in the program. Modeling pinned registers this way allows
IRC/Briggs to have no special casing for them. It treats it like any other
precolored Tmp. This allows us to do coalescing, biased coloring, etc, which
could all lead to a Tmp being assigned to a pinned register.

Interestingly, we used to have special handling for the frame pointer
register, which in many ways, acts like a pinned register, since FP is
always live, and we wanted it to take place in coalescing. The allocator
had a side-table interference graph with FP. Interestingly, we didn't even
handle this properly everywhere since we could rely on a patchpoint never
claiming to clobber FP (this would be illegal). So the code only handled
the pseudo-pinned register properties of FP in various places. This patch
drops this special casing and pins FP since all pinned registers can take
part in coalescing.

  • b3/B3PatchpointSpecial.h:
  • b3/B3Procedure.cpp:

(JSC::B3::Procedure::mutableGPRs):
(JSC::B3::Procedure::mutableFPRs):

  • b3/B3Procedure.h:
  • b3/air/AirAllocateRegistersByGraphColoring.cpp:
  • b3/air/AirCode.cpp:

(JSC::B3::Air::Code::Code):
(JSC::B3::Air::Code::pinRegister):
(JSC::B3::Air::Code::mutableGPRs):
(JSC::B3::Air::Code::mutableFPRs):

  • b3/air/AirCode.h:

(JSC::B3::Air::Code::pinnedRegisters):

  • b3/air/AirSpecial.h:
  • b3/air/testair.cpp:
  • b3/testb3.cpp:

(JSC::B3::testSimplePatchpointWithOuputClobbersGPArgs):
(JSC::B3::testSpillDefSmallerThanUse):
(JSC::B3::testLateRegister):
(JSC::B3::testTerminalPatchpointThatNeedsToBeSpilled):
(JSC::B3::testTerminalPatchpointThatNeedsToBeSpilled2):
(JSC::B3::testMoveConstants):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/b3/testb3.cpp

    r216734 r216989  
    81308130void testSimplePatchpointWithOuputClobbersGPArgs()
    81318131{
    8132     if (isARM64()) {
    8133         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=171826
    8134         return;
    8135     }
    8136 
    81378132    // We can't predict where the output will be but we want to be sure it is not
    81388133    // one of the clobbered registers which is a bit hard to test.
     
    1278012775void testSpillDefSmallerThanUse()
    1278112776{
    12782     if (isARM64()) {
    12783         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=171826
    12784         return;
    12785     }
    12786 
    1278712777    Procedure proc;
    1278812778    BasicBlock* root = proc.addBlock();
     
    1287612866void testLateRegister()
    1287712867{
    12878     if (isARM64()) {
    12879         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=171826
    12880         return;
    12881     }
    12882 
    1288312868    Procedure proc;
    1288412869    BasicBlock* root = proc.addBlock();
     
    1369313678void testTerminalPatchpointThatNeedsToBeSpilled()
    1369413679{
    13695     if (isARM64()) {
    13696         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=171826
    13697         return;
    13698     }
    1369913680    // This is a unit test for how FTL's heap allocation fast paths behave.
    1370013681    Procedure proc;
     
    1373113712    Vector<Value*> args;
    1373213713    {
    13733         RegisterSet fillAllGPRsSet = RegisterSet::allGPRs();
    13734         fillAllGPRsSet.exclude(RegisterSet::stackRegisters());
    13735         fillAllGPRsSet.exclude(RegisterSet::reservedHardwareRegisters());
    13736 
     13714        RegisterSet fillAllGPRsSet = proc.mutableGPRs();
    1373713715        for (unsigned i = 0; i < fillAllGPRsSet.numberOfSetRegisters(); i++)
    1373813716            args.append(success->appendNew<Const32Value>(proc, Origin(), i));
     
    1376413742void testTerminalPatchpointThatNeedsToBeSpilled2()
    1376513743{
    13766     if (isARM64()) {
    13767         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=171826
    13768         return;
    13769     }
    13770 
    1377113744    // This is a unit test for how FTL's heap allocation fast paths behave.
    1377213745    Procedure proc;
     
    1381613789    Vector<Value*> args;
    1381713790    {
    13818         RegisterSet fillAllGPRsSet = RegisterSet::allGPRs();
    13819         fillAllGPRsSet.exclude(RegisterSet::stackRegisters());
    13820         fillAllGPRsSet.exclude(RegisterSet::reservedHardwareRegisters());
     13791        RegisterSet fillAllGPRsSet = proc.mutableGPRs();
    1382113792        for (unsigned i = 0; i < fillAllGPRsSet.numberOfSetRegisters(); i++)
    1382213793            args.append(success->appendNew<Const32Value>(proc, Origin(), i));
     
    1412114092void testMoveConstants()
    1412214093{
    14123     if (isARM64()) {
    14124         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=171826
    14125         return;
    14126     }
    14127 
    1412814094    auto check = [] (Procedure& proc) {
    1412914095        proc.resetReachability();
Note: See TracChangeset for help on using the changeset viewer.