RFR: 8350864: C2: verify structural invariants of the Ideal graph [v5]

Emanuel Peter epeter at openjdk.org
Mon Sep 8 17:07:32 UTC 2025


On Mon, 8 Sep 2025 15:17:43 GMT, Emanuel Peter <epeter at openjdk.org> wrote:

>> Marc Chevalier has updated the pull request incrementally with one additional commit since the last revision:
>> 
>>   One more ResourceMark
>
> src/hotspot/share/opto/graphInvariants.cpp line 61:
> 
>> 59:  * and compositional to express complex structures from simple properties.
>> 60:  * For instance, we have a pattern for saying "the first input of the center match P" where P is another
>> 61:  * Pattern. We end up with trees of patterns matching the graph.
> 
> `the first input of the center match P` does not sound like a proper assertion.
> Some alternatives I could think of:
> - `match P on the first input of center` ok
> - `the first input of center must match P` ok
> - `match the first input of center with P` meh

Also: are we `check` ing or `match` ing? I would pick one consistently.

> src/hotspot/share/opto/graphInvariants.cpp line 234:
> 
>> 232:   bool check(const Node* center, Node_List& steps, GrowableArray<int>& path, stringStream& ss) const override {
>> 233:     if (!(center->*_type_check)()) {
>> 234:       ss.print_cr("Unexpected type: %s.", center->Name());
> 
> Is there a way we could say what we actually do expect? Not really, right? We'd need to do it via macro again.

Or we pass a string .. not nice but would work with the macro for `NodeClassIsAndBind`. Not sure what's best here.

> src/hotspot/share/opto/graphInvariants.cpp line 378:
> 
>> 376:     return CheckResult::VALID;
>> 377:   }
>> 378: };
> 
> I am wondering if it is really worth it to do the whole pattern matching approach, if we still have to write so much code.
> 
> There is a lot of boiler plate now, that has replaced the procedural code.
> 
> I'm just wondering if we are there yet, or if we need to find some way to make it more concise.
> Maybe we can do something like this:
> 
> return <something>
>        .applies_if(&Node::is_Phi)
>        .check([&]() { return PatternBasedCheck::check(center, reachable_cfg_nodes, steps, path, ss); })
>        .require(...)
>        .finish();
> 
> Just an idea. It would probably be lambda based again, which has its disadvantages.
> Maybe you have an even better idea.
> I'd just like to understand why the Pattern based approach is really super desirable, what are the advantages and disadvantages?

One advantage is definitively reporting. And it is still reasonably debuggable I think, my solution may be a little trickier that way.

I think there are multiple factors:
- Simple: fewer abstractions can be easier to read/debug.
- Concise: few lines of code.
- Reporting: nice output when rules fail.

> src/hotspot/share/opto/graphInvariants.cpp line 547:
> 
>> 545:         return CheckResult::FAILED;
>> 546:       }
>> 547:     }
> 
> If you do add `OuterStripMinedLoop`, make it a swich, and assert in the default case ;)

I just saw that you do the `OuterStripMinedLoop` below. But to capture the parallel structure it may still be good. And to capture possible future extension.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/26362#discussion_r2330614759
PR Review Comment: https://git.openjdk.org/jdk/pull/26362#discussion_r2330713629
PR Review Comment: https://git.openjdk.org/jdk/pull/26362#discussion_r2330793156
PR Review Comment: https://git.openjdk.org/jdk/pull/26362#discussion_r2330826144


More information about the hotspot-compiler-dev mailing list