RFR: 8350864: C2: verify structural invariants of the Ideal graph
Vladimir Ivanov
vlivanov at openjdk.org
Thu Jul 17 09:45:47 UTC 2025
On Thu, 17 Jul 2025 07:25:10 GMT, Marc Chevalier <mchevalier at openjdk.org> wrote:
> Some crashes are consequences of earlier misshaped ideal graphs, which could be detected earlier, closer to the source, before the possibly many transformations that lead to the crash.
>
> Let's verify that the ideal graph is well-shaped earlier then! I propose here such a feature. This runs after IGVN, because at this point, the graph, should be cleaned up for any weirdness happening earlier or during IGVN.
>
> This feature is enabled with the develop flag `VerifyIdealStructuralInvariants`. Open to renaming. No problem with me! This feature is only available in debug builds, and most of the code is even not compiled in product, since it uses some debug-only functions, such as `Node::dump` or `Node::Name`.
>
> For now, only local checks are implemented: they are checks that only look at a node and its neighborhood, wherever it happens in the graph. Typically: under a `If` node, we have a `IfTrue` and a `IfFalse`. To ease development, each check is implemented in its own class, independently of the others. Nevertheless, one needs to do always the same kind of things: checking there is an output of such type, checking there is N inputs, that the k-th input has such type... To ease writing such checks, in a readable way, and in a less error-prone way than pile of copy-pasted code that manually traverse the graph, I propose a set of compositional helpers to write patterns that can be matched against the ideal graph. Since these patterns are... patterns, so not related to a specific graph, they can be allocated once and forever. When used, one provides the node (called center) around which one want to check if the pattern holds.
>
> On top of making the description of pattern easier, these helpers allows nice printing in case of error, by showing the path from the center to the violating node. For instance (made up for the purpose of showing the formatting), a violation with a path climbing only inputs:
>
> 1 failure for node
> 211 OuterStripMinedLoopEnd === 215 39 [[ 212 198 ]] P=0,948966, C=23799,000000
> At node
> 209 CountedLoopEnd === 182 208 [[ 210 197 ]] [lt] P=0,948966, C=23799,000000 !orig=[196] !jvms: StringLatin1::equals @ bci:12 (line 100)
> From path:
> [center] 211 OuterStripMinedLoopEnd === 215 39 [[ 212 198 ]] P=0,948966, C=23799,000000
> <-(0)- 215 SafePoint === 210 1 7 1 1 216 37 54 185 [[ 211 ]] SafePoint !orig=186 !jvms: StringLatin1::equals @ bci:29 (line 100)
> <-(0)- 210 IfFalse === 209 [[ 215 216 ]] #0 !orig=198 !jvms: StringL...
Very nice!
Some high-level comments:
* IMO it's better to have node-specific invariant checks co-located with corresponding node (as `Node::verify()` maybe?); it would make it clearer what are the expectations when changing the implementation.
* on naming: IMO `VerifyIdealGraph` would clearly describe what the logic does, fits existing conventions well, and easy to find
-------------
PR Review: https://git.openjdk.org/jdk/pull/26362#pullrequestreview-3028766202
More information about the hotspot-compiler-dev
mailing list