Shopify / seafoam

A tool for working with compiler graphs dumped by the GraalVM compiler
MIT License
126 stars 22 forks source link

Fix Truffle args simplification #69

Closed nirvdrum closed 1 year ago

nirvdrum commented 1 year ago

The Truffle arg simplification pass could miss edges, leading to graphs that were larger than we'd like. There was no loss of data, but we would have edges that weren't simplified which could be a bit confusing to read. Unfortunately, none of our existing examples could illustrate the error, so I added a new one that does along with a test that will fail if any LoadIndexed edges weren't simplified.

I removed our Graal patch since that patch has been merged upstream. I updated the comment on how to generate the examples using the new Graal option from our patch. I did end up generating nodes with a different number of phases than what the previous examples have. I think it's just due to running with a different version of Graal, but would appreciate if someone could double-check that I didn't run the examples wrong. We can drop the commit that removes the Graal patch without affecting the Truffle arg simplification, if you'd rather push that out as a separate change.

chrisseaton commented 1 year ago

What's the actual before and after of this patch in terms of the output? (Use Mermaid to post on the PR.)

nirvdrum commented 1 year ago

Here are the requested graphs. The easiest one to see is right at the top. The 168 LoadIndexed -> 830 InstanceOf a! org.truffleruby.language.RubyDynamicObject edge becomes 1468 T(8) -> 830 InstanceOf a! org.truffleruby.language.RubyDynamicObject. You can see the 1468 T(8) in the before graph as well, but it has fewer outgoing edges because not all of the LoadIndexed edges were replaced previously.

FYI, I changed the example since the original commit. That example in my original commit showed the issue, but you needed to enable rendering of frame states and that made the graph too large to render here. The test stayed the same, I just had to adjust the example to produce a smaller graph.

Before:

flowchart TD
  node0("0 Start")
  style node0 fill:#e98693,stroke:black,color:#1a1919;
  node168("168 LoadIndexed")
  style node168 fill:#c39bd3,stroke:black,color:#1a1919;
  node647("647 If")
  style node647 fill:#e98693,stroke:black,color:#1a1919;
  node648("648 InstanceOf a!# java.lang.Integer")
  style node648 fill:#f9f9f9,stroke:black,color:#1a1919;
  node830("830 InstanceOf a! org.truffleruby.language.RubyDynamicObject")
  style node830 fill:#f9f9f9,stroke:black,color:#1a1919;
  node847("847 LoadField RubyDynamicObject.metaClass")
  style node847 fill:#c39bd3,stroke:black,color:#1a1919;
  node854("854 Merge")
  style node854 fill:#e98693,stroke:black,color:#1a1919;
  node857("857 ϕ")
  style node857 fill:#f9f9f9,stroke:black,color:#1a1919;
  node900("900 If")
  style node900 fill:#e98693,stroke:black,color:#1a1919;
  node902{{"902 =="}}
  style node902 fill:#3cb4a4,stroke:black,color:#1a1919;
  node947{{"947 =="}}
  style node947 fill:#3cb4a4,stroke:black,color:#1a1919;
  node988("988 Merge")
  style node988 fill:#e98693,stroke:black,color:#1a1919;
  node991("991 ϕ")
  style node991 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1053("1053 LoadField InternalMethod.callTarget")
  style node1053 fill:#c39bd3,stroke:black,color:#1a1919;
  node1054("1054 Guard not, else TransferToInterpreter")
  style node1054 fill:#ffa500,stroke:black,color:#1a1919;
  node1055{{"1055 IsNull"}}
  style node1055 fill:#3cb4a4,stroke:black,color:#1a1919;
  node1059("1059 If")
  style node1059 fill:#e98693,stroke:black,color:#1a1919;
  node1061{{"1061 =="}}
  style node1061 fill:#3cb4a4,stroke:black,color:#1a1919;
  node1083("1083 Guard, else TransferToInterpreter")
  style node1083 fill:#ffa500,stroke:black,color:#1a1919;
  node1224("1224 Merge")
  style node1224 fill:#e98693,stroke:black,color:#1a1919;
  node1227("1227 ϕ")
  style node1227 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1255("1255 Return")
  style node1255 fill:#e98693,stroke:black,color:#1a1919;
  node1257("1257 Guard, else TransferToInterpreter")
  style node1257 fill:#ffa500,stroke:black,color:#1a1919;
  node1258("1258 Guard, else TransferToInterpreter")
  style node1258 fill:#ffa500,stroke:black,color:#1a1919;
  node1265{{"1265 =="}}
  style node1265 fill:#3cb4a4,stroke:black,color:#1a1919;
  node1298("1298 Unbox")
  style node1298 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1302("1302 Guard, else TransferToInterpreter")
  style node1302 fill:#ffa500,stroke:black,color:#1a1919;
  node1322("1322 InstanceOf a!# org.truffleruby.core.string.RubyString")
  style node1322 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1370("1370 LoadField RubyString.tstring")
  style node1370 fill:#c39bd3,stroke:black,color:#1a1919;
  node1371("1371 Guard not, else NullCheckException")
  style node1371 fill:#ffa500,stroke:black,color:#1a1919;
  node1372{{"1372 IsNull"}}
  style node1372 fill:#3cb4a4,stroke:black,color:#1a1919;
  node1373("1373 LoadField AbstractTruffleString.data")
  style node1373 fill:#c39bd3,stroke:black,color:#1a1919;
  node1374("1374 InstanceOf a!# com.oracle.truffle.api.strings.AbstractTruffleString$LazyLong")
  style node1374 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1378("1378 LoadField AbstractTruffleString$LazyLong.value")
  style node1378 fill:#c39bd3,stroke:black,color:#1a1919;
  node1382("1382 Guard, else TransferToInterpreter")
  style node1382 fill:#ffa500,stroke:black,color:#1a1919;
  node1388("1388 Guard, else TransferToInterpreter")
  style node1388 fill:#ffa500,stroke:black,color:#1a1919;
  node1457("1457 BoxNode$AllocatingBox")
  style node1457 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1459("1459 BoxNode$AllocatingBox")
  style node1459 fill:#f9f9f9,stroke:black,color:#1a1919;
  inline164x168(["164 C(8)"])
  style inline164x168 fill:#d7ede7,stroke:black,color:#1a1919;
  inline164x168 --> node168
  linkStyle 0 stroke:#3cb4a4,stroke-width:px;
  node648 --> node647
  linkStyle 1 stroke:#3cb4a4,stroke-width:px;
  node168 --> node830
  linkStyle 2 stroke:#3cb4a4,stroke-width:px;
  node854 --> node900
  linkStyle 3 stroke:#da2d4f,stroke-width:2px;
  node854 --> node857
  linkStyle 4 stroke:#343d46,stroke-width:px;
  inline793x857(["793 C(RubyClass@790461d)"])
  style inline793x857 fill:#d7ede7,stroke:black,color:#1a1919;
  inline793x857 --> node857
  linkStyle 5 stroke:#3cb4a4,stroke-width:px;
  node847 --> node857
  linkStyle 6 stroke:#3cb4a4,stroke-width:px;
  node902 --> node900
  linkStyle 7 stroke:#3cb4a4,stroke-width:px;
  node857 --> node902
  linkStyle 8 stroke:#3cb4a4,stroke-width:px;
  inline901x902(["901 C(RubyClass@1b32cd16)"])
  style inline901x902 fill:#d7ede7,stroke:black,color:#1a1919;
  inline901x902 --> node902
  linkStyle 9 stroke:#3cb4a4,stroke-width:px;
  node857 --> node947
  linkStyle 10 stroke:#3cb4a4,stroke-width:px;
  inline793x947(["793 C(RubyClass@790461d)"])
  style inline793x947 fill:#d7ede7,stroke:black,color:#1a1919;
  inline793x947 --> node947
  linkStyle 11 stroke:#3cb4a4,stroke-width:px;
  node988 --> node1053
  linkStyle 12 stroke:#da2d4f,stroke-width:2px;
  node988 --> node991
  linkStyle 13 stroke:#343d46,stroke-width:px;
  inline973x991(["973 C(InternalMethod@3fdf633c)"])
  style inline973x991 fill:#d7ede7,stroke:black,color:#1a1919;
  inline973x991 --> node991
  linkStyle 14 stroke:#3cb4a4,stroke-width:px;
  inline982x991(["982 C(InternalMethod@1081b56d)"])
  style inline982x991 fill:#d7ede7,stroke:black,color:#1a1919;
  inline982x991 --> node991
  linkStyle 15 stroke:#3cb4a4,stroke-width:px;
  node991 --> node1053
  linkStyle 16 stroke:#3cb4a4,stroke-width:px;
  node1053 --> node1054
  linkStyle 17 stroke:#da2d4f,stroke-width:2px;
  node1055 --> node1054
  linkStyle 18 stroke:#3cb4a4,stroke-width:px;
  node1054 --> node1059
  linkStyle 19 stroke:#da2d4f,stroke-width:2px;
  node1053 --> node1055
  linkStyle 20 stroke:#3cb4a4,stroke-width:px;
  node1061 --> node1059
  linkStyle 21 stroke:#3cb4a4,stroke-width:px;
  node1053 --> node1061
  linkStyle 22 stroke:#3cb4a4,stroke-width:px;
  inline1060x1061(["1060 C(String#to_i)"])
  style inline1060x1061 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1060x1061 --> node1061
  linkStyle 23 stroke:#3cb4a4,stroke-width:px;
  node1265 --> node1083
  linkStyle 24 stroke:#3cb4a4,stroke-width:px;
  node1083 --> node1302
  linkStyle 25 stroke:#da2d4f,stroke-width:2px;
  node1224 --> node1255
  linkStyle 26 stroke:#da2d4f,stroke-width:2px;
  node1224 --> node1227
  linkStyle 27 stroke:#343d46,stroke-width:px;
  node1457 --> node1227
  linkStyle 28 stroke:#3cb4a4,stroke-width:px;
  node1459 --> node1227
  linkStyle 29 stroke:#3cb4a4,stroke-width:px;
  node1227 --> node1255
  linkStyle 30 stroke:#3cb4a4,stroke-width:px;
  node830 --> node1257
  linkStyle 31 stroke:#3cb4a4,stroke-width:px;
  node1257 --> node847
  linkStyle 32 stroke:#da2d4f,stroke-width:2px;
  node947 --> node1258
  linkStyle 33 stroke:#3cb4a4,stroke-width:px;
  node1053 --> node1265
  linkStyle 34 stroke:#3cb4a4,stroke-width:px;
  inline1089x1265(["1089 C(Integer#to_i)"])
  style inline1089x1265 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1089x1265 --> node1265
  linkStyle 35 stroke:#3cb4a4,stroke-width:px;
  node1298 --> node1459
  linkStyle 36 stroke:#da2d4f,stroke-width:2px;
  node648 --> node1302
  linkStyle 37 stroke:#3cb4a4,stroke-width:px;
  node1302 --> node1298
  linkStyle 38 stroke:#da2d4f,stroke-width:2px;
  node1370 --> node1371
  linkStyle 39 stroke:#da2d4f,stroke-width:2px;
  node1372 --> node1371
  linkStyle 40 stroke:#3cb4a4,stroke-width:px;
  node1371 --> node1373
  linkStyle 41 stroke:#da2d4f,stroke-width:2px;
  node1370 --> node1372
  linkStyle 42 stroke:#3cb4a4,stroke-width:px;
  node1373 --> node1388
  linkStyle 43 stroke:#da2d4f,stroke-width:2px;
  node1373 --> node1374
  linkStyle 44 stroke:#3cb4a4,stroke-width:px;
  node1378 --> node1457
  linkStyle 45 stroke:#da2d4f,stroke-width:2px;
  node1322 --> node1382
  linkStyle 46 stroke:#3cb4a4,stroke-width:px;
  node1382 --> node1370
  linkStyle 47 stroke:#da2d4f,stroke-width:2px;
  node1374 --> node1388
  linkStyle 48 stroke:#3cb4a4,stroke-width:px;
  node1388 --> node1378
  linkStyle 49 stroke:#da2d4f,stroke-width:2px;
  node1378 --> node1457
  linkStyle 50 stroke:#3cb4a4,stroke-width:px;
  node1298 --> node1459
  linkStyle 51 stroke:#3cb4a4,stroke-width:px;
  inline1468x648(["1468 T(8)"])
  style inline1468x648 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1468x648 --> node648
  linkStyle 52 stroke:#3cb4a4,stroke-width:px;
  inline1468x1322(["1468 T(8)"])
  style inline1468x1322 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1468x1322 --> node1322
  linkStyle 53 stroke:#3cb4a4,stroke-width:px;
  node0 --> node647
  linkStyle 54 stroke:#da2d4f,stroke-width:2px;
  inline2x168(["2 P(1)"])
  style inline2x168 fill:#d7ede7,stroke:black,color:#1a1919;
  inline2x168 --> node168
  linkStyle 55 stroke:#3cb4a4,stroke-width:px;
  inline1468x847(["1468 T(8)"])
  style inline1468x847 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1468x847 --> node847
  linkStyle 56 stroke:#3cb4a4,stroke-width:px;
  node168 --> node1298
  linkStyle 57 stroke:#3cb4a4,stroke-width:px;
  node168 --> node1370
  linkStyle 58 stroke:#3cb4a4,stroke-width:px;
  node1370 --> node1373
  linkStyle 59 stroke:#3cb4a4,stroke-width:px;
  node1373 --> node1378
  linkStyle 60 stroke:#3cb4a4,stroke-width:px;
  node647 --> node1257
  linkStyle 61 stroke:#da2d4f,stroke-width:2px;
  node647 --> node854
  linkStyle 62 stroke:#da2d4f,stroke-width:2px;
  node847 --> node854
  linkStyle 63 stroke:#da2d4f,stroke-width:2px;
  node900 --> node1258
  linkStyle 64 stroke:#da2d4f,stroke-width:2px;
  node900 --> node988
  linkStyle 65 stroke:#da2d4f,stroke-width:2px;
  node1258 --> node988
  linkStyle 66 stroke:#da2d4f,stroke-width:2px;
  node1059 --> node1083
  linkStyle 67 stroke:#da2d4f,stroke-width:2px;
  node1059 --> node1382
  linkStyle 68 stroke:#da2d4f,stroke-width:2px;
  node1457 --> node1224
  linkStyle 69 stroke:#da2d4f,stroke-width:2px;
  node1459 --> node1224
  linkStyle 70 stroke:#da2d4f,stroke-width:2px;

After:

flowchart TD
  node0("0 Start")
  style node0 fill:#e98693,stroke:black,color:#1a1919;
  node647("647 If")
  style node647 fill:#e98693,stroke:black,color:#1a1919;
  node648("648 InstanceOf a!# java.lang.Integer")
  style node648 fill:#f9f9f9,stroke:black,color:#1a1919;
  node830("830 InstanceOf a! org.truffleruby.language.RubyDynamicObject")
  style node830 fill:#f9f9f9,stroke:black,color:#1a1919;
  node847("847 LoadField RubyDynamicObject.metaClass")
  style node847 fill:#c39bd3,stroke:black,color:#1a1919;
  node854("854 Merge")
  style node854 fill:#e98693,stroke:black,color:#1a1919;
  node857("857 ϕ")
  style node857 fill:#f9f9f9,stroke:black,color:#1a1919;
  node900("900 If")
  style node900 fill:#e98693,stroke:black,color:#1a1919;
  node902{{"902 =="}}
  style node902 fill:#3cb4a4,stroke:black,color:#1a1919;
  node947{{"947 =="}}
  style node947 fill:#3cb4a4,stroke:black,color:#1a1919;
  node988("988 Merge")
  style node988 fill:#e98693,stroke:black,color:#1a1919;
  node991("991 ϕ")
  style node991 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1053("1053 LoadField InternalMethod.callTarget")
  style node1053 fill:#c39bd3,stroke:black,color:#1a1919;
  node1054("1054 Guard not, else TransferToInterpreter")
  style node1054 fill:#ffa500,stroke:black,color:#1a1919;
  node1055{{"1055 IsNull"}}
  style node1055 fill:#3cb4a4,stroke:black,color:#1a1919;
  node1059("1059 If")
  style node1059 fill:#e98693,stroke:black,color:#1a1919;
  node1061{{"1061 =="}}
  style node1061 fill:#3cb4a4,stroke:black,color:#1a1919;
  node1083("1083 Guard, else TransferToInterpreter")
  style node1083 fill:#ffa500,stroke:black,color:#1a1919;
  node1224("1224 Merge")
  style node1224 fill:#e98693,stroke:black,color:#1a1919;
  node1227("1227 ϕ")
  style node1227 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1255("1255 Return")
  style node1255 fill:#e98693,stroke:black,color:#1a1919;
  node1257("1257 Guard, else TransferToInterpreter")
  style node1257 fill:#ffa500,stroke:black,color:#1a1919;
  node1258("1258 Guard, else TransferToInterpreter")
  style node1258 fill:#ffa500,stroke:black,color:#1a1919;
  node1265{{"1265 =="}}
  style node1265 fill:#3cb4a4,stroke:black,color:#1a1919;
  node1298("1298 Unbox")
  style node1298 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1302("1302 Guard, else TransferToInterpreter")
  style node1302 fill:#ffa500,stroke:black,color:#1a1919;
  node1322("1322 InstanceOf a!# org.truffleruby.core.string.RubyString")
  style node1322 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1370("1370 LoadField RubyString.tstring")
  style node1370 fill:#c39bd3,stroke:black,color:#1a1919;
  node1371("1371 Guard not, else NullCheckException")
  style node1371 fill:#ffa500,stroke:black,color:#1a1919;
  node1372{{"1372 IsNull"}}
  style node1372 fill:#3cb4a4,stroke:black,color:#1a1919;
  node1373("1373 LoadField AbstractTruffleString.data")
  style node1373 fill:#c39bd3,stroke:black,color:#1a1919;
  node1374("1374 InstanceOf a!# com.oracle.truffle.api.strings.AbstractTruffleString$LazyLong")
  style node1374 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1378("1378 LoadField AbstractTruffleString$LazyLong.value")
  style node1378 fill:#c39bd3,stroke:black,color:#1a1919;
  node1382("1382 Guard, else TransferToInterpreter")
  style node1382 fill:#ffa500,stroke:black,color:#1a1919;
  node1388("1388 Guard, else TransferToInterpreter")
  style node1388 fill:#ffa500,stroke:black,color:#1a1919;
  node1457("1457 BoxNode$AllocatingBox")
  style node1457 fill:#f9f9f9,stroke:black,color:#1a1919;
  node1459("1459 BoxNode$AllocatingBox")
  style node1459 fill:#f9f9f9,stroke:black,color:#1a1919;
  node648 --> node647
  linkStyle 0 stroke:#3cb4a4,stroke-width:px;
  node854 --> node900
  linkStyle 1 stroke:#da2d4f,stroke-width:2px;
  node854 --> node857
  linkStyle 2 stroke:#343d46,stroke-width:px;
  inline793x857(["793 C(RubyClass@790461d)"])
  style inline793x857 fill:#d7ede7,stroke:black,color:#1a1919;
  inline793x857 --> node857
  linkStyle 3 stroke:#3cb4a4,stroke-width:px;
  node847 --> node857
  linkStyle 4 stroke:#3cb4a4,stroke-width:px;
  node902 --> node900
  linkStyle 5 stroke:#3cb4a4,stroke-width:px;
  node857 --> node902
  linkStyle 6 stroke:#3cb4a4,stroke-width:px;
  inline901x902(["901 C(RubyClass@1b32cd16)"])
  style inline901x902 fill:#d7ede7,stroke:black,color:#1a1919;
  inline901x902 --> node902
  linkStyle 7 stroke:#3cb4a4,stroke-width:px;
  node857 --> node947
  linkStyle 8 stroke:#3cb4a4,stroke-width:px;
  inline793x947(["793 C(RubyClass@790461d)"])
  style inline793x947 fill:#d7ede7,stroke:black,color:#1a1919;
  inline793x947 --> node947
  linkStyle 9 stroke:#3cb4a4,stroke-width:px;
  node988 --> node1053
  linkStyle 10 stroke:#da2d4f,stroke-width:2px;
  node988 --> node991
  linkStyle 11 stroke:#343d46,stroke-width:px;
  inline973x991(["973 C(InternalMethod@3fdf633c)"])
  style inline973x991 fill:#d7ede7,stroke:black,color:#1a1919;
  inline973x991 --> node991
  linkStyle 12 stroke:#3cb4a4,stroke-width:px;
  inline982x991(["982 C(InternalMethod@1081b56d)"])
  style inline982x991 fill:#d7ede7,stroke:black,color:#1a1919;
  inline982x991 --> node991
  linkStyle 13 stroke:#3cb4a4,stroke-width:px;
  node991 --> node1053
  linkStyle 14 stroke:#3cb4a4,stroke-width:px;
  node1053 --> node1054
  linkStyle 15 stroke:#da2d4f,stroke-width:2px;
  node1055 --> node1054
  linkStyle 16 stroke:#3cb4a4,stroke-width:px;
  node1054 --> node1059
  linkStyle 17 stroke:#da2d4f,stroke-width:2px;
  node1053 --> node1055
  linkStyle 18 stroke:#3cb4a4,stroke-width:px;
  node1061 --> node1059
  linkStyle 19 stroke:#3cb4a4,stroke-width:px;
  node1053 --> node1061
  linkStyle 20 stroke:#3cb4a4,stroke-width:px;
  inline1060x1061(["1060 C(String#to_i)"])
  style inline1060x1061 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1060x1061 --> node1061
  linkStyle 21 stroke:#3cb4a4,stroke-width:px;
  node1265 --> node1083
  linkStyle 22 stroke:#3cb4a4,stroke-width:px;
  node1083 --> node1302
  linkStyle 23 stroke:#da2d4f,stroke-width:2px;
  node1224 --> node1255
  linkStyle 24 stroke:#da2d4f,stroke-width:2px;
  node1224 --> node1227
  linkStyle 25 stroke:#343d46,stroke-width:px;
  node1457 --> node1227
  linkStyle 26 stroke:#3cb4a4,stroke-width:px;
  node1459 --> node1227
  linkStyle 27 stroke:#3cb4a4,stroke-width:px;
  node1227 --> node1255
  linkStyle 28 stroke:#3cb4a4,stroke-width:px;
  node830 --> node1257
  linkStyle 29 stroke:#3cb4a4,stroke-width:px;
  node1257 --> node847
  linkStyle 30 stroke:#da2d4f,stroke-width:2px;
  node947 --> node1258
  linkStyle 31 stroke:#3cb4a4,stroke-width:px;
  node1053 --> node1265
  linkStyle 32 stroke:#3cb4a4,stroke-width:px;
  inline1089x1265(["1089 C(Integer#to_i)"])
  style inline1089x1265 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1089x1265 --> node1265
  linkStyle 33 stroke:#3cb4a4,stroke-width:px;
  node1298 --> node1459
  linkStyle 34 stroke:#da2d4f,stroke-width:2px;
  node648 --> node1302
  linkStyle 35 stroke:#3cb4a4,stroke-width:px;
  node1302 --> node1298
  linkStyle 36 stroke:#da2d4f,stroke-width:2px;
  node1370 --> node1371
  linkStyle 37 stroke:#da2d4f,stroke-width:2px;
  node1372 --> node1371
  linkStyle 38 stroke:#3cb4a4,stroke-width:px;
  node1371 --> node1373
  linkStyle 39 stroke:#da2d4f,stroke-width:2px;
  node1370 --> node1372
  linkStyle 40 stroke:#3cb4a4,stroke-width:px;
  node1373 --> node1388
  linkStyle 41 stroke:#da2d4f,stroke-width:2px;
  node1373 --> node1374
  linkStyle 42 stroke:#3cb4a4,stroke-width:px;
  node1378 --> node1457
  linkStyle 43 stroke:#da2d4f,stroke-width:2px;
  node1322 --> node1382
  linkStyle 44 stroke:#3cb4a4,stroke-width:px;
  node1382 --> node1370
  linkStyle 45 stroke:#da2d4f,stroke-width:2px;
  node1374 --> node1388
  linkStyle 46 stroke:#3cb4a4,stroke-width:px;
  node1388 --> node1378
  linkStyle 47 stroke:#da2d4f,stroke-width:2px;
  node1378 --> node1457
  linkStyle 48 stroke:#3cb4a4,stroke-width:px;
  node1298 --> node1459
  linkStyle 49 stroke:#3cb4a4,stroke-width:px;
  inline1468x648(["1468 T(8)"])
  style inline1468x648 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1468x648 --> node648
  linkStyle 50 stroke:#3cb4a4,stroke-width:px;
  inline1468x830(["1468 T(8)"])
  style inline1468x830 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1468x830 --> node830
  linkStyle 51 stroke:#3cb4a4,stroke-width:px;
  inline1468x1322(["1468 T(8)"])
  style inline1468x1322 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1468x1322 --> node1322
  linkStyle 52 stroke:#3cb4a4,stroke-width:px;
  node0 --> node647
  linkStyle 53 stroke:#da2d4f,stroke-width:2px;
  inline1468x847(["1468 T(8)"])
  style inline1468x847 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1468x847 --> node847
  linkStyle 54 stroke:#3cb4a4,stroke-width:px;
  inline1468x1298(["1468 T(8)"])
  style inline1468x1298 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1468x1298 --> node1298
  linkStyle 55 stroke:#3cb4a4,stroke-width:px;
  inline1468x1370(["1468 T(8)"])
  style inline1468x1370 fill:#d7ede7,stroke:black,color:#1a1919;
  inline1468x1370 --> node1370
  linkStyle 56 stroke:#3cb4a4,stroke-width:px;
  node1370 --> node1373
  linkStyle 57 stroke:#3cb4a4,stroke-width:px;
  node1373 --> node1378
  linkStyle 58 stroke:#3cb4a4,stroke-width:px;
  node647 --> node1257
  linkStyle 59 stroke:#da2d4f,stroke-width:2px;
  node647 --> node854
  linkStyle 60 stroke:#da2d4f,stroke-width:2px;
  node847 --> node854
  linkStyle 61 stroke:#da2d4f,stroke-width:2px;
  node900 --> node1258
  linkStyle 62 stroke:#da2d4f,stroke-width:2px;
  node900 --> node988
  linkStyle 63 stroke:#da2d4f,stroke-width:2px;
  node1258 --> node988
  linkStyle 64 stroke:#da2d4f,stroke-width:2px;
  node1059 --> node1083
  linkStyle 65 stroke:#da2d4f,stroke-width:2px;
  node1059 --> node1382
  linkStyle 66 stroke:#da2d4f,stroke-width:2px;
  node1457 --> node1224
  linkStyle 67 stroke:#da2d4f,stroke-width:2px;
  node1459 --> node1224
  linkStyle 68 stroke:#da2d4f,stroke-width:2px;