RFR: 8342943: Replace predicate walking and cloning code for main/post loops with a predicate visitor
Christian Hagedorn
chagedorn at openjdk.org
Wed Oct 30 15:37:27 UTC 2024
On Wed, 30 Oct 2024 15:18:56 GMT, Christian Hagedorn <chagedorn at openjdk.org> wrote:
> #### Replacing the Remaining Predicate Walking and Cloning Code
> The goal is to replace and unify all the remaining custom predicate walking and cloning code currently used for:
> - <s>[JDK-8341977](https://bugs.openjdk.org/browse/JDK-8341977): Loop Peeling</s> (integrated with https://github.com/openjdk/jdk/pull/21679))
> - [JDK-8342943](https://bugs.openjdk.org/browse/JDK-8342943): Main and Post Loop (this PR)
> - [JDK-8342945](https://bugs.openjdk.org/browse/JDK-8342945): Loop Unswitching and removing useless Assertion Predicate (upcoming)
> - [JDK-8342946](https://bugs.openjdk.org/browse/JDK-8342946): Main and Post Loop (upcoming)
>
> ---
> (Sections taken over from https://github.com/openjdk/jdk/pull/21679)
>
> #### Single Template Assertion Predicate Check
> This replacement allows us to have a single `TemplateAssertionPredicate::is_predicate()` check that is called for all predicate matching code. This enables the removal of uncommon traps for Template Assertion Predicates with [JDK-8342047](https://bugs.openjdk.org/browse/JDK-8342047) which is a missing piece in order to fix the remaining problems with Assertion Predicates ([JDK-8288981](https://bugs.openjdk.org/browse/JDK-8288981)).
>
> #### Common Refactorings for all the Patches in this Series
> In each of the patch, I will do similar refactoring ideas:
> - Replace the existing code in the corresponding `PhaseIdealLoop` method with call to a new (or existing) predicate visitor which extends the `PredicateVisitor` interface.
> - The visitor implements the Assertion Predicate `visit()` methods to implement the cloning and initialization of the Template Assertion Predicates.
> - The predicate visitor is then passed to the `PredicateIterator` which walks through all predicates found at a loop and applies the visitor for each predicate.
> - The visitor creates new nodes (if there are Template Assertion Predicates) either in place or at the loop entry of a target loop. In the latter case, the calling code of the `PredicateIterator` must make sure to connect the tail of the newly created predicate chain after the old loop entry to the target loop head.
> - Keep the semantics which includes to only apply the Template Assertion Predicate processing if there are Parse Predicates. This limitation should eventually be removed. But I want to do that separately at a later point.
> ---
>
> #### Refactorings of this Patch
> This patch replaces the predicate walking and cloning code for **main and post loops**. The code can reuse the code establishe...
src/hotspot/share/opto/loopTransform.cpp line 1320:
> 1318: // Assertion Predicates ensures that the main-loop is removed if some type ranges of Cast or Convert nodes become
> 1319: // impossible and are replaced by top (i.e. a sign that the main-loop is dead).
> 1320: void PhaseIdealLoop::copy_assertion_predicates_to_main_loop_helper(const PredicateBlock* predicate_block, Node* init,
Replaced with `PhaseIdealLoop::initialize_assertion_predicates_for_main_loop()`
src/hotspot/share/opto/loopTransform.cpp line 1472:
> 1470: // removed after loop opts, these are never executed. We therefore insert a Halt node instead of an uncommon trap.
> 1471: Node* PhaseIdealLoop::clone_template_assertion_predicate(IfNode* iff, Node* new_init, Node* predicate, Node* uncommon_proj,
> 1472: Node* control, IdealLoopTree* outer_loop, Node* new_control) {
Moved to `TemplateAssertionPredicate::clone_and_replace_init()`.
src/hotspot/share/opto/loopTransform.cpp line 1487:
> 1485: }
> 1486:
> 1487: void PhaseIdealLoop::copy_assertion_predicates_to_main_loop(CountedLoopNode* pre_head, Node* init, Node* stride,
Replaced with `PhaseIdealLoop::initialize_assertion_predicates_for_main_loop()`.
src/hotspot/share/opto/loopTransform.cpp line 1852:
> 1850: const uint first_node_index_in_cloned_loop_body) {
> 1851: const NodeInClonedLoopBody node_in_cloned_loop_body(first_node_index_in_cloned_loop_body);
> 1852: create_assertion_predicates_at_loop(main_loop_head, post_loop_head, node_in_cloned_loop_body, false);
With the already refactored code for Loop Peeling, we can simply reuse `create_assertion_predicates_at_loop()` which simplifies the code a lot.
src/hotspot/share/opto/loopTransform.cpp line 1864:
> 1862: Node* target_loop_entry = target_outer_loop_head->in(LoopNode::EntryControl);
> 1863: CreateAssertionPredicatesVisitor create_assertion_predicates_visitor(init, stride, target_loop_entry, this,
> 1864: _node_in_loop_body, clone_template);
Not a very elegant solution to introduce `clone_template` but I'm planning to update this code again at a later point. This was the least invasive way to handle this.
src/hotspot/share/opto/loopTransform.cpp line 1942:
> 1940: // Go over the Assertion Predicates of the main loop and make a copy for the post loop with its initial iv value and
> 1941: // stride as inputs.
> 1942: void PhaseIdealLoop::copy_assertion_predicates_to_post_loop(LoopNode* main_loop_head, CountedLoopNode* post_loop_head,
Replaced with `PhaseIdealLoop::initialize_assertion_predicates_for_post_loop()`.
src/hotspot/share/opto/loopnode.hpp line 947:
> 945: IfTrueNode* create_initialized_assertion_predicate(IfNode* template_assertion_predicate, Node* new_init,
> 946: Node* new_stride, Node* control);
> 947: DEBUG_ONLY(static bool assertion_predicate_has_loop_opaque_node(IfNode* iff);)
Needs to be public since I'm calling it from the `TemplateAssertionPredicate` class. Planning to refactor/move this method at a later point in time.
src/hotspot/share/opto/predicates.cpp line 764:
> 762: }
> 763: if (_clone_template) {
> 764: _new_control = clone_template_and_replace_init_input(template_assertion_predicate);
For the main loop, we need to initialize templates **and** clone them to further create Initialized Assertion Predicates from later when unrolling. Note that in the full fix, we should **always** clone templates since we don't know if the loop is going to split further. However, I don't want to change semantics here as this is a simple refactoring patch. I'm addressing these problems in a later PR.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/21790#discussion_r1822858323
PR Review Comment: https://git.openjdk.org/jdk/pull/21790#discussion_r1822859741
PR Review Comment: https://git.openjdk.org/jdk/pull/21790#discussion_r1822861130
PR Review Comment: https://git.openjdk.org/jdk/pull/21790#discussion_r1822883179
PR Review Comment: https://git.openjdk.org/jdk/pull/21790#discussion_r1822866079
PR Review Comment: https://git.openjdk.org/jdk/pull/21790#discussion_r1822861954
PR Review Comment: https://git.openjdk.org/jdk/pull/21790#discussion_r1822874539
PR Review Comment: https://git.openjdk.org/jdk/pull/21790#discussion_r1822870022
More information about the hotspot-compiler-dev
mailing list