Changeset 195981 in webkit


Ignore:
Timestamp:
Feb 1, 2016 3:19:26 PM (8 years ago)
Author:
benjamin@webkit.org
Message:

[JSC] IRC can coalesce the frame pointer with a Tmp that is modified
https://bugs.webkit.org/show_bug.cgi?id=153694

Reviewed by Filip Pizlo.

Let's say we have:

Move(FP, Tmp1)
Add64(#1, Tmp1)

If we were to coalesce the Move, we would modify the frame pointer.
Well, that's exactly what was happening with IRC.

Since the epilogue is not know to Air before IRC, the liveness analysis
never discovers that FP is live when Tmp1 is UseDef by Add64. Adding
FP would a be a problem anyway for a bunch of reasons.

I tried two ways to prevent IRC to override IRC:
1) Add an interference edge with FP for all non-duplication Defs.
2) Let coalesce() know about FP and constraint any coalescing with a re-Def.

The two are within margin of error for performance. The second one was considerably
more complicated. This patch implements the first one.

Some extra note:
-It is very important to not increment the degree of a Tmp when making it interfere

with FP. FP is not a valid color, it is not counted in the "K" colors considered
for coloring. Increasing the degree with the edge to FP would make every stage
pessimistic since there is an extra degree that can never be removed.

-I put "interferenceEdges" and "adjacencyList" in an inconsistent state.

This is intentional, "interferenceEdges" is used to test the existence of an edge,
"adjacencyList" is used to go over all the edges. In this case, we don't want
the edge with FP to be considered when pruning the graph.

  • b3/air/AirIteratedRegisterCoalescing.cpp:

One branch could be transformed into an assertion: TmpLiveness is type specific now.

  • b3/testb3.cpp:

(JSC::B3::testOverrideFramePointer):
(JSC::B3::run):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r195956 r195981  
     12016-02-01  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        [JSC] IRC can coalesce the frame pointer with a Tmp that is modified
     4        https://bugs.webkit.org/show_bug.cgi?id=153694
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Let's say we have:
     9            Move(FP, Tmp1)
     10            Add64(#1, Tmp1)
     11
     12        If we were to coalesce the Move, we would modify the frame pointer.
     13        Well, that's exactly what was happening with IRC.
     14
     15        Since the epilogue is not know to Air before IRC, the liveness analysis
     16        never discovers that FP is live when Tmp1 is UseDef by Add64. Adding
     17        FP would a be a problem anyway for a bunch of reasons.
     18
     19        I tried two ways to prevent IRC to override IRC:
     20        1) Add an interference edge with FP for all non-duplication Defs.
     21        2) Let coalesce() know about FP and constraint any coalescing with a re-Def.
     22
     23        The two are within margin of error for performance. The second one was considerably
     24        more complicated. This patch implements the first one.
     25
     26        Some extra note:
     27        -It is very important to not increment the degree of a Tmp when making it interfere
     28         with FP. FP is not a valid color, it is not counted in the "K" colors considered
     29         for coloring. Increasing the degree with the edge to FP would make every stage
     30         pessimistic since there is an extra degree that can never be removed.
     31        -I put "interferenceEdges" and "adjacencyList" in an inconsistent state.
     32         This is intentional, "interferenceEdges" is used to test the existence of an edge,
     33         "adjacencyList" is used to go over all the edges. In this case, we don't want
     34         the edge with FP to be considered when pruning the graph.
     35
     36        * b3/air/AirIteratedRegisterCoalescing.cpp:
     37        One branch could be transformed into an assertion: TmpLiveness is type specific now.
     38        * b3/testb3.cpp:
     39        (JSC::B3::testOverrideFramePointer):
     40        (JSC::B3::run):
     41
    1422016-02-01  Csaba Osztrogonác  <ossy@webkit.org>
    243
  • trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp

    r195788 r195981  
    892892               
    893893                for (const Tmp& liveTmp : liveTmps) {
    894                     if (liveTmp.isGP() == (type == Arg::GP))
    895                         addEdge(arg, liveTmp);
     894                    ASSERT(liveTmp.isGP() == (type == Arg::GP));
     895                    addEdge(arg, liveTmp);
     896                }
     897
     898                if (type == Arg::GP && !arg.isGPR()) {
     899                    m_interferenceEdges.add(InterferenceEdge(
     900                        AbsoluteTmpMapper<type>::absoluteIndex(Tmp(MacroAssembler::framePointerRegister)),
     901                        AbsoluteTmpMapper<type>::absoluteIndex(arg)));
    896902                }
    897903            });
     
    10691075        }
    10701076
    1071         for (const auto& tmp : tmpsWithInterferences)
    1072             out.print("    ", tmp.internalValue(), " [label=\"", tmp, " (", m_degrees[AbsoluteTmpMapper<type>::absoluteIndex(tmp)], ")\"];\n");
     1077        for (const auto& tmp : tmpsWithInterferences) {
     1078            unsigned tmpIndex = AbsoluteTmpMapper<type>::absoluteIndex(tmp);
     1079            if (tmpIndex < m_degrees.size())
     1080                out.print("    ", tmp.internalValue(), " [label=\"", tmp, " (", m_degrees[tmpIndex], ")\"];\n");
     1081            else
     1082                out.print("    ", tmp.internalValue(), " [label=\"", tmp, "\"];\n");
     1083        }
    10731084
    10741085        for (const auto& edge : m_interferenceEdges)
     
    11301141        while (true) {
    11311142            ++m_numIterations;
     1143
     1144            if (traceDebug)
     1145                dataLog("Code at iteration ", m_numIterations, ":\n", m_code);
    11321146
    11331147            // FIXME: One way to optimize this code is to remove the recomputation inside the fixpoint.
     
    11491163            if (!allocator.requiresSpilling()) {
    11501164                assignRegistersToTmp(allocator);
     1165                if (traceDebug)
     1166                    dataLog("Successfull allocation at iteration ", m_numIterations, ":\n", m_code);
     1167
    11511168                return;
    11521169            }
  • trunk/Source/JavaScriptCore/b3/testb3.cpp

    r195906 r195981  
    49824982    CHECK(fp < &proc);
    49834983    CHECK(fp >= bitwise_cast<char*>(&proc) - 10000);
     4984}
     4985
     4986void testOverrideFramePointer()
     4987{
     4988    {
     4989        Procedure proc;
     4990        BasicBlock* root = proc.addBlock();
     4991
     4992        // Add a stack slot to make the frame non trivial.
     4993        root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8, StackSlotKind::Locked));
     4994
     4995        // Sub on x86 UseDef the source. If FP is not protected correctly, it will be overridden since it is the last visible use.
     4996        Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
     4997        Value* fp = root->appendNew<Value>(proc, FramePointer, Origin());
     4998        Value* result = root->appendNew<Value>(proc, Sub, Origin(), fp, offset);
     4999
     5000        root->appendNew<ControlValue>(proc, Return, Origin(), result);
     5001        CHECK(compileAndRun<int64_t>(proc, 1));
     5002    }
     5003    {
     5004        Procedure proc;
     5005        BasicBlock* root = proc.addBlock();
     5006
     5007        root->appendNew<SlotBaseValue>(proc, Origin(), proc.addStackSlot(8, StackSlotKind::Locked));
     5008
     5009        Value* offset = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
     5010        Value* fp = root->appendNew<Value>(proc, FramePointer, Origin());
     5011        Value* offsetFP = root->appendNew<Value>(proc, BitAnd, Origin(), offset, fp);
     5012        Value* arg = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
     5013        Value* offsetArg = root->appendNew<Value>(proc, Add, Origin(), offset, arg);
     5014        Value* result = root->appendNew<Value>(proc, Add, Origin(), offsetArg, offsetFP);
     5015
     5016        root->appendNew<ControlValue>(proc, Return, Origin(), result);
     5017        CHECK(compileAndRun<int64_t>(proc, 1, 2));
     5018    }
    49845019}
    49855020
     
    1076710802    RUN(testLoadAddrShift(3));
    1076810803    RUN(testFramePointer());
     10804    RUN(testOverrideFramePointer());
    1076910805    RUN(testStackSlot());
    1077010806    RUN(testLoadFromFramePointer());
Note: See TracChangeset for help on using the changeset viewer.