-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8296412: Special case infinite loops with unmerged backedges in IdealLoopTree::check_safepts #11706
Conversation
…LoopTree::check_safepts
👋 Welcome back epeter! A progress list of the required criteria for merging this PR into |
Webrevs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice analysis! That looks reasonable to go with this simpler fix instead of fixing maybe_add_safepoint()
given that this case is rare.
@eme64 This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 23 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
test/hotspot/jtreg/compiler/loopopts/TestInfiniteLoopWithUnmergedBackedgesMain.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me.
…gedBackedgesMain.java remove redundant empty line Co-authored-by: Tobias Hartmann <tobias.hartmann@oracle.com>
Thanks @TobiHartmann @chhagedorn @vnkozlov for the discussions and reviews! |
Going to push as commit da38d43.
Your commit was automatically rebased without conflicts. |
Context
During parsing, we insert SafePoints if we jump from higher to lower bci (
maybe_add_safepoint
is called for every if, goto etc).jdk/src/hotspot/share/opto/parse.hpp
Lines 490 to 494 in 8c472e4
Generally, this alligns with backedges: the assumption is that the loop-head sits at the smallest bci of all blocks in the loop. So every jump back to the loop-head goes from higher to lower bci, hence we place a SafePoint just before the jump.
Also: the first
build_loop_tree
may not attach an infinite loop to the loop-tree. If during the same loop-opts-phase we go tobeautify_loops
and it requires us rebuilding the loop-tree (eg because some other loop didmerge_many_backedges
), we callbuild_loop_tree
again, and this time around we do detect the infinite loop (it now has a NeverBranch exit, so it is attached because of that).Afterwards, we call
IdealLoopTree::check_safepts
, which tries to find SafePoints on all backedges. Normally, we have SafePoints on all backedges, just before we go back to the head.Problem case
My jasm fuzzer produced some infinite loops that have the following form:
The loop head is not at the smallest bci (bytecode index) of all blocks in the loop. So the SafePoints are placed somewhere in the body of the loop, just before an if branches into the two backedges. Because this is an infinite loop, it is only attached to the loop-tree in
build_loop_tree
afterbeautify_loops
, so the two backedges were not merged.When we call
IdealLoopTree::check_safepts
, we start with the inner loop, where we find the SafePoint above the if. Then we go to the outer loop. We don't find a SafePoint before we find the inner body. Now we decide to skip the inner body (which implies skipping the SafePoint in the body). The code assumes after skipping the inner loop, we are still in the outer loop. This is not true, because inner and outer loop have the same loop head (the backedges were not merged). We trigger an assert that checks that we are still in the outer loop (nested loop
).Why did we not find this earlier?
We have not extensively tested infinite loops before. Also, we have not tested loops with loop-heads that are not at the smallest bci of the loop. However, with my bytecode fuzzer I can find these issues. It is also more likely with irreducible loops: there at least one loop-entry cannot be at the smallest bci. Irreducible loops are not processed by
maybe_add_safepoint
, but once it only has a singe entry, it is not irreducible any more, and so it can happen that a loop-entry becomes loop head that does not have the smallest bci.Solution
We could fix
maybe_add_safepoint
to not depend on bci, but rather the loop-tree fromciTypeFlow
. That would be complex, and risky. That is not justified just for infinite loops, and even infinite loops where the loop head is not at the lowest bci.I decided to simply special case infinite loops. I detect if we have an outer loop with the same head as an inner loop. This should not happen, as we must have merged those backedges. Except if it is an infinite loop: We can break the scan, as we have already reached the loop's head.
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/11706/head:pull/11706
$ git checkout pull/11706
Update a local copy of the PR:
$ git checkout pull/11706
$ git pull https://git.openjdk.org/jdk pull/11706/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 11706
View PR using the GUI difftool:
$ git pr show -t 11706
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/11706.diff