RFR: 8350578: Refactor useless Parse and Template Assertion Predicate elimination code by using a PredicateVisitor
Christian Hagedorn
chagedorn at openjdk.org
Thu Mar 13 06:55:05 UTC 2025
On Wed, 12 Mar 2025 16:18:53 GMT, Christian Hagedorn <chagedorn at openjdk.org> wrote:
> This patch cleans the Parse and Template Assertion Predicate elimination code up. We now use a single `PredicateVisitor` and share code in a new `EliminateUselessPredicates` class which contains the code previously found in `PhaseIdealLoop::eliminate_useless_predicates()`.
>
> ### Unified Logic to Clean Up Parse and Template Assertion Predicates
> We now use the following algorithm:
> https://github.com/openjdk/jdk/blob/5e4b6ca0ddafa80eee60690caacd257b74305d4e/src/hotspot/share/opto/predicates.cpp#L1174-L1179
>
> This is different from the old algorithm where we used a single boolean state `_useless`. But that does no longer work because when we first mark Template Assertion Predicates useless, we are no longer visiting them when iterating through predicates:
>
> https://github.com/openjdk/jdk/blob/a21fa463c4f8d067c18c09a072f3cdfa772aea5e/src/hotspot/share/opto/predicates.hpp#L704-L708
>
> We therefore require a third state. Thus, I introduced a new tri-state `PredicateState` that provides a special `MaybeUseful` value which we can set each Predicate to.
>
> #### Ignoring Useless Parse Predicates
> While working on this patch, I've noticed that we are always visiting Parse Predicates - even when they useless. We should change that to align it with what we have for the other Predicates (changed in JDK-8351280). To make this work, we also replace the `_useless` state in `ParsePredicateNode` with a new `PredicateState`.
>
> #### Sharing Code for Parse and Template Assertion Predicates
> With all the mentioned changes in place, I could nicely share code for the elimination of Parse and Template Assertion Predicates in `EliminateUselessPredicates` by using templates. The following additional changes were required:
>
> - Changing the template parameter of `_template_assertion_predicate_opaques` to the more specific `OpaqueTemplateAssertionPredicateNode` type.
> - Adding accessor methods to get the Predicate lists from `Compile`.
> - Updating `ParsePredicate::mark_useless()` to pass in `PhaseIterGVN`, as done for Assertion Predicates
>
> Note that we still do not directly replace the useless Predicates but rather mark them useless as initiated by JDK-8351280.
>
> ### Other Included Changes
> - During the various refactoring steps, I somehow dropped the code to add newly cloned Template Assertion Predicate to the `_template_assertion_predicate_opaques` list. It was done directly in the old cloning methods. This is not relevant for correctness but could hinder some optimizations. I've added the code now i...
src/hotspot/share/opto/cfgnode.hpp line 508:
> 506: void mark_maybe_useful();
> 507: bool is_useful() const;
> 508: void mark_useful();
Needed to move these definitions to the source file because I cannot include `predicates.hpp` here due to circular dependencies. I solved this by forward declaring `PredicateState` and moving the definitions to the source file.
Same for these methods for `OpaqueTemplateAssertionPredicate` further down.
src/hotspot/share/opto/ifnode.cpp line 2220:
> 2218: const Type* ParsePredicateNode::Value(PhaseGVN* phase) const {
> 2219: assert(_predicate_state != PredicateState::MaybeUseful, "should only be MaybeUseful when eliminating useless "
> 2220: "predicates during loop opts");
Best effort assert to ensure we are not seeing `MaybeUseful` anywhere else except during Predicate elimination. Same for `OpaqueTemplateAssertionPredicate`.
src/hotspot/share/opto/ifnode.cpp line 2249:
> 2247: fatal("unknown kind");
> 2248: }
> 2249: if (_predicate_state == PredicateState::Useless) {
I only print `useless` since `MaybeUseful` is only set for a very brief moment and should normally not be visible when dumping/in IGV dumps.
src/hotspot/share/opto/node.cpp line 516:
> 514: if (n->is_OpaqueTemplateAssertionPredicate()) {
> 515: C->add_template_assertion_predicate_opaque(n->as_OpaqueTemplateAssertionPredicate());
> 516: }
See PR description "Other Included Changes".
src/hotspot/share/opto/opaquenode.cpp line 115:
> 113: }
> 114:
> 115: OpaqueTemplateAssertionPredicateNode::OpaqueTemplateAssertionPredicateNode(BoolNode* bol): Node(nullptr, bol),
Moved some methods to source file - see comment above for `ParsePredicateNode`.
src/hotspot/share/opto/opaquenode.hpp line 30:
> 28: #include "opto/node.hpp"
> 29: #include "opto/subnode.hpp"
> 30:
Noticed that `opcodes.hpp` was unused and `subnode.hpp` missed the `opto` prefix. Fixed here as well.
src/hotspot/share/opto/predicates.cpp line 177:
> 175: bool is_template_assertion_predicate = if_node->in(1)->is_OpaqueTemplateAssertionPredicate();
> 176: assert(!is_template_assertion_predicate || AssertionPredicate::has_halt(maybe_success_proj->as_IfTrue()),
> 177: "Template Assertion Predicate must have a Halt Node on the failing path");
New verification - see "Other Included Changes" in PR description.
src/hotspot/share/opto/predicates.cpp line 333:
> 331: // of the Initialized Assertion Predicate (part of the loop body) while the OpaqueInitializedAssertionPredicate is not
> 332: // cloned because it's outside the loop body. We end up sharing the OpaqueInitializedAssertionPredicate between the
> 333: // original and the cloned If. This should be fine.
Reason for not reusing `AssertionPredicate::has_halt()`. I will revisit the `AssertionPredicate` class in a future PR, so I have not tried to unify these methods in a way.
src/hotspot/share/opto/predicates.hpp line 331:
> 329: // the ParsePredicateNode is not marked useless.
> 330: bool is_valid() const {
> 331: return _parse_predicate_node != nullptr && !_parse_predicate_node->is_useless();
Avoids visiting useless Parse Predicates during Predicate iteration.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/24013#discussion_r1992876906
PR Review Comment: https://git.openjdk.org/jdk/pull/24013#discussion_r1992878757
PR Review Comment: https://git.openjdk.org/jdk/pull/24013#discussion_r1992879213
PR Review Comment: https://git.openjdk.org/jdk/pull/24013#discussion_r1992879809
PR Review Comment: https://git.openjdk.org/jdk/pull/24013#discussion_r1992882191
PR Review Comment: https://git.openjdk.org/jdk/pull/24013#discussion_r1992882542
PR Review Comment: https://git.openjdk.org/jdk/pull/24013#discussion_r1992881495
PR Review Comment: https://git.openjdk.org/jdk/pull/24013#discussion_r1992881891
PR Review Comment: https://git.openjdk.org/jdk/pull/24013#discussion_r1992884443
More information about the hotspot-compiler-dev
mailing list