RFR: 8283775: VM support for graph querying in debugger with BFS traversal and node filtering [v7]
Emanuel Peter
duke at openjdk.java.net
Thu May 12 15:35:27 UTC 2022
> I implemented VM support for BFS traversal of IR nodes, where one can filter for input/output edges, and the node-type (control / data / memory). If one specifies the `target` node, we find a shortest path between `this` and `target`. With the `options` string one can easily select which node types to traverse.
>
> `void Node::print_bfs(const uint max_distance, Node* target, const char* options)`
>
> While a sufficient summary and description is in the comments above the function definition, I want to explain some useful use-cases here.
>
> Please let me know if you would find this helpful, or if you have any feedback to improve it.
> Thanks, Emanuel
>
> **1. Better dump()**
> The function is similar to `dump()`, we can also follow input / output edges up to a certain distance. There are a few improvements/added features:
>
> 1. Display the distance to the specified node. This way I can quickly assess how many nodes I have at a certain distance, and I can traverse edges from one distance to the next. The parent column shows the node one step closer to the BFS root (this).
> 2. Node filtering with types taken from `type->category()` help one limit traversal to control, data or memory flow. The categories are the same as in IGV.
> 3. Probably controversial: coloring of node types in terminal. By default it is off. May not work on all terminals. But I find it very useful to quickly separate memory, data and control - just as in IGV - but in my terminal!
> 4. After matching, we create Mach nodes from the IR nodes. For most Mach nodes, there is an associated old node. Often an assert is triggered for Mach nodes, but the graph already breaks in the IR graph. It is thus very helpful to have the old node idx displayed.
> 5. I also display the head node idx of the block a Mach node is scheduled for. This can be helpful if one gets bad dominance asserts, and needs to see why the blocks were scheduled in a bad way.
>
> Example:
>
> (rr) p find_node(35)->print_bfs(2, 0, "cdmox+")
> No target: perform BFS.
> dis par c dump
> ---------------------------------------------
> 0 35 d 35 CmpP === _ 34 25 [[ 36 ]]
> 1 35 d 34 LoadP === _ 31 33 [[ 35 ]]
> 1 35 d 25 ConP === 0 [[ 26 27 31 35 41 ]] #NULL
> 2 34 m 31 StoreP === 20 27 29 25 [[ 23 34 41 42 ]]
> 2 34 d 33 AddP === _ 1 12 32 [[ 34 ]]
>
>
> Example with Mach nodes:
>
> (rr) p ctrl->print_bfs(4, 0, "cdmox+OB")
> No target: perform BFS.
> dis [head idom d] old par c dump
> ---------------------------------------------
> 0 159 147 6 _ 159 c 159 Region === 159 57 [[ 159 158 59 ]]
> 1 147 148 5 o183 159 c 57 IfTrue === 8 [[ 159 ]]
> 2 147 148 5 o182 57 c 8 jmpConU === 147 9 [[ 7 57 ]]
> 3 147 148 5 _ 8 c 147 Region === 147 14 [[ 147 8 ]]
> 3 147 148 5 o180 8 d 9 compUL_rReg === _ 10 13 [[ 8 ]]
> 4 148 149 4 o174 147 c 14 IfTrue === 15 [[ 147 ]]
> 4 147 148 5 o203 9 d 10 decL_rReg === _ 11 [[ 12 9 ]]
> 4 147 148 5 o179 9 d 13 convI2L_reg_reg === _ 28 [[ 9 ]]
>
>
> **2. Find loop body**
> When I find myself in a loop, I try to localize the loop head and end, and map out at least one path between them.
> `loop_end->print_bfs(20, loop_head, "cox+")`
> This provides us with a shortest path, given this path has a distance of at most 20.
>
> Example:
>
> (rr) p find_node(158)->print_bfs(20, find_node(160), "cox+")
> Find shortest path: 158 -> 160.
>
> Backtrace target.
> dis c dump
> ---------------------------------------------
> 9 c 160 OuterStripMinedLoop === 160 339 159 [[ 160 358 ]]
> 8 c 358 CountedLoop === 358 160 143 [[ 358 362 363 ]]
> 7 c 363 If === 358 351 [[ 364 367 ]]
> 6 c 364 IfTrue === 363 [[ 128 ]]
> 5 c 128 If === 364 127 [[ 129 130 ]]
> 4 c 129 IfTrue === 128 [[ 155 ]]
> 3 c 155 CountedLoopEnd === 129 154 [[ 157 143 ]] [lt]
> 2 c 157 IfFalse === 155 [[ 162 163 ]]
> 1 c 162 SafePoint === 157 1 7 1 1 163 100 1 1 13 27 133 [[ 158 ]]
> 0 c 158 OuterStripMinedLoopEnd === 162 156 [[ 159 227 ]]
>
> Example with Mach nodes:
>
> (rr) p ctrl->print_bfs(10, val, "cdmox-+OB")
> Find shortest path: 159 -> 27.
>
> Backtrace target.
> dis [head idom d] old e c dump
> ---------------------------------------------
> 2 24 1 2 o10 + d 27 MachProj === 24 [[ 19 28 4 59 95 99 118 ]]
> 1 56 159 7 o239 - d 59 loadB === 159 29 27 60 [[ 55 ]]
> 0 159 147 6 _ c 159 Region === 159 57 [[ 159 158 59 ]]
Emanuel Peter has updated the pull request incrementally with one additional commit since the last revision:
refactoring into class, no lambdas
-------------
Changes:
- all: https://git.openjdk.java.net/jdk/pull/8468/files
- new: https://git.openjdk.java.net/jdk/pull/8468/files/4b7e3b1d..d6d2666d
Webrevs:
- full: https://webrevs.openjdk.java.net/?repo=jdk&pr=8468&range=06
- incr: https://webrevs.openjdk.java.net/?repo=jdk&pr=8468&range=05-06
Stats: 393 lines in 1 file changed: 163 ins; 141 del; 89 mod
Patch: https://git.openjdk.java.net/jdk/pull/8468.diff
Fetch: git fetch https://git.openjdk.java.net/jdk pull/8468/head:pull/8468
PR: https://git.openjdk.java.net/jdk/pull/8468
More information about the hotspot-compiler-dev
mailing list