RFR: 8347901: C2 should remove unused leaf / pure runtime calls [v3]
Tobias Hartmann
thartmann at openjdk.org
Mon Jul 7 08:35:50 UTC 2025
On Mon, 23 Jun 2025 12:39:23 GMT, Marc Chevalier <mchevalier at openjdk.org> wrote:
>> A first part toward a better support of pure functions, but this time, with guidance from @iwanowww.
>>
>> ## Pure Functions
>>
>> Pure functions (considered here) are functions that have no side effects, no effect on the control flow (no exception or such), cannot deopt etc.. It's really a function that you can execute anywhere, with whichever arguments without effect other than wasting time. Integer division is not pure as dividing by zero is throwing. But many floating point functions will just return `NaN` or `+/-infinity` in problematic cases.
>>
>> ## Scope
>>
>> We are not going all powerful for now! It's mostly about identifying some pure functions and being able to remove them if the result is unused. Some other things are not part of this PR, on purpose. Especially, this PR doesn't propose a way to move pure calls around. The reason is that pure calls are later expanded into regular calls, which require a control input. To be able to do the expansion, we just keep the control in the pure call as well.
>>
>> ## Implementation Overview
>>
>> We created here some new node kind for pure calls, inheriting leaf calls, that are expanded into regular leaf calls during final graph reshaping. The possibility to support pure call directly in AD file is left open.
>>
>> This PR also introduces `TupleNode` (largely based on an original idea/implem of @iwanowww), that just tie multiple input together and play well with `ProjNode`: the n-th projection of a `TupleNode` is the n-th input of the tuple. This is a convenient way to skip and remove nodes from the graph while delegating the difficulty of the surgery to the trusted IGVN's implementation.
>>
>> Thanks,
>> Marc
>
> Marc Chevalier has updated the pull request incrementally with one additional commit since the last revision:
>
> mostly comments
Thanks for digging into this Marc. The changes look good to me. I just added a few minor comments / questions.
> this PR doesn't propose a way to move pure calls around
Should we have a separate RFE for that?
src/hotspot/share/opto/divnode.cpp line 1522:
> 1520: Node* super = CallLeafPureNode::Ideal(phase, can_reshape);
> 1521: if (super != nullptr) {
> 1522: return super;
Can't we just do `return CallLeafPureNode::Ideal(phase, can_reshape);` at the end of `ModFNode::Ideal` instead of `return nullptr`? That's what we usually do in C2, for example in `CallStaticJavaNode::Ideal` -> `CallNode::Ideal`. Feels more natural to me and would avoid the `super != nullptr` check. Also for the other `Ideal` methods that you modified.
src/hotspot/share/opto/divnode.cpp line 1528:
> 1526: bool not_dead = proj_out_or_null(TypeFunc::Control) != nullptr;
> 1527: if (result_is_unused && not_dead) {
> 1528: return replace_with_con(igvn, TypeF::make(0.));
Can we replace all the other usages of `ModFloatingNode::replace_with_con` by `TupleNode` and get rid of that method?
src/hotspot/share/opto/graphKit.cpp line 1916:
> 1914: if (call->is_CallLeafPure()) {
> 1915: // Pure function have only control (for now) and data output, in particular
> 1916: // the don't touch the memory, so we don't want a memory proj that is set after.
Suggestion:
// they don't touch the memory, so we don't want a memory proj that is set after.
-------------
Marked as reviewed by thartmann (Reviewer).
PR Review: https://git.openjdk.org/jdk/pull/25760#pullrequestreview-2992602888
PR Review Comment: https://git.openjdk.org/jdk/pull/25760#discussion_r2189268498
PR Review Comment: https://git.openjdk.org/jdk/pull/25760#discussion_r2189357774
PR Review Comment: https://git.openjdk.org/jdk/pull/25760#discussion_r2189261824
More information about the graal-dev
mailing list