RFR: 8360510: C2: Template Assertion Predicates are not cloned to the inner counted loop with -XX:+StressDuplicateBackedge

Christian Hagedorn chagedorn at openjdk.org
Fri Nov 21 10:45:01 UTC 2025


On Wed, 19 Nov 2025 12:19:02 GMT, Christian Hagedorn <chagedorn at openjdk.org> wrote:

> ### Strong Connection between Template Assertion Predicate and Counted Loop 
> In [JDK-8350579](https://bugs.openjdk.org/browse/JDK-8350579), we fixed the issue that a Template Assertion Predicate for a folded loop A could end up at another loop B. We then created an Initialized Assertion Predicate at loop B from the template of loop A and used the values from the already folded, completely unrelated loop A . As a result, we crashed with a halt because loop B violated the predicate with the wrong values. As a fix, we established a strong connection between Template Assertion Predicates and their associated loop node by adding a direct link from `OpaqueTemplateAssertionPredicate` -> `CountedLoop`.
> 
> #### Maintaining this Property
> In `PhaseIdealLoop::eliminate_useless_predicates()`, we walk through all counted loops and only keep those `OpaqueTemplateAssertionPredicate` nodes that can be found from the loop heads and are actually meant for this loop (using the strong connection):
> https://github.com/openjdk/jdk/blob/d2926dfd9a242928877d0b1e40eac498073975bd/src/hotspot/share/opto/predicates.cpp#L1245-L1249
> 
> All other opaque nodes are removed.
> 
> ### Additional Verification for Useless `OpaqueTemplateAssertionPredicate` Nodes
> As an additional verification for `OpaqueTemplateAssertionPredicate` nodes that are found to be useless in `eliminate_useless_predicates()`, we check that in this case the `CountedLoop` is really dead (otherwise, we should have found the `OpaqueTemplateAssertionPredicate` in our walks through all loop):
> https://github.com/openjdk/jdk/blob/d2926dfd9a242928877d0b1e40eac498073975bd/src/hotspot/share/opto/predicates.cpp#L1294-L1301
> 
> ### Violating the Additional Verification with `-XX:+StressLoopBackedge`
> In `PhaseIdealLoop::duplicate_loop_backedge()`, we convert a loop with a merge point into two loops which should enable us to transform the new inner loop into a counted loop. This only makes sense for a `Loop` that is not a counted loop, yet. However, to stress the transformation, we can also run with `-XX:+StressDuplicateBackedge` that also transforms a counted loop into an inner and an outer loop. This is a problem when we have Template Assertion Predicates above a counted loop to be stressed:
> 
> <img width="581" height="556" alt="image" src="https://github.com/user-attachments/assets/e7948804-e74d-4dd0-a0f8-64eedaa259ba" />
> 
> After duplicate backedge, the Template Assertion Predicates are now at the outer non-counted `Loop`:
> 
> <img width="567" heig...

Thanks Roland for your review!

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

PR Comment: https://git.openjdk.org/jdk/pull/28389#issuecomment-3562450316


More information about the hotspot-compiler-dev mailing list