-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8290432: C2 compilation fails with assert(node->_last_del == _last) failed: must have deleted the edge just produced #9695
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
Conversation
…ailed: must have deleted the edge just produced
/rfr |
👋 Welcome back yyang! A progress list of the required criteria for merging this PR into |
@kelthuzadx Unknown command |
@kelthuzadx The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
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.
From your test I assume internal loop for (long l=
is processed. But val
is updated outside it. Its AddI
node should not be part of loop's body. Could you explain?
src/hotspot/share/opto/loopnode.cpp
Outdated
if (incr2->in(1)->is_ConstraintCast()) { | ||
if (!incr2->in(1)->in(0)->is_RangeCheck()) { |
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.
You can use &&
instead of nested condition.
src/hotspot/share/opto/loopnode.cpp
Outdated
!incr2->in(2)->is_Con()) | ||
continue; |
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.
Since you touch near code, please update style in these lines too to use {}
.
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.
The whole function is formatted.
Hi @vnkozlov, thanks for your review. Here is the (almost) complete IR before replacing additional parallel IVs: Before that, some loop optimizations are applied: static long test(int val, boolean b) {
long ret = 0;
long dArr[] = new long[100];
if (b) {
for (int i = 15; 293 > i; ++i) {
ret = val;
val--;
}
} else {
for (int i = 15; 293 > i; ++i) {
ret = val;
val-=4
}
}
return ret;
} Their corresponding IR are as follows:
|
src/hotspot/share/opto/loopnode.cpp
Outdated
// The form of Phi->CastXX->AddX appears when using Preconditions.checkIndex, and it would | ||
// be recognized as additional IV when 1) Phi != phi2, 2) CastXX is controlled by RangeCheck | ||
// (to reflect changes in LibraryCallKit::inline_preconditions_checkIndex) |
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.
Thank you for updating comment. But it still do not say which issue you are trying to avoid. Yes, this pattern can be generated by inline_preconditions_checkIndex.
Currently your check skip search for parallel IV if CastII is NOT controlled by RangeCheck!
But the comment in the BODY of check talks about using parallel IV.
It is contradicting.
Aslo 1) Phi != phi2
says nothing to me - your check does not have such condition.
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.
Why not just say that we should skip AddI->CastII->Phi
case if CastII is not controlled by local RangeCheck.
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.
Why not just say that we should skip
AddI->CastII->Phi
case if CastII is not controlled by local RangeCheck.
Yes, this is exactly what I want to say. Maybe I should update comments.
About test's loops. I see that C2 recognized that BUT. |
val is type of int! And we are not trying to use it instead of existing |
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.
Could you explain why it's an issue in this case if the control input of the CastII
is not a range check?
src/hotspot/share/opto/loopnode.cpp
Outdated
|
||
if (incr2->in(1)->is_ConstraintCast() && !incr2->in(1)->in(0)->is_RangeCheck()) { | ||
// Skip AddI->CastII->Phi case if CastII is not controlled by local RangeCheck | ||
// to reflect changes in LibraryCallKit::inline_preconditions_checkIndex |
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.
In the valid case, isn't the ConstraintCast control input incr2->in(1)->in(0)
the IfTrue projection of the RangeCheck?
I would remove the second line because it's not clear which "changes" in LibraryCallKit::inline_preconditions_checkIndex
it is referring to.
// to reflect changes in LibraryCallKit::inline_preconditions_checkIndex |
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.
It's still not clear to me how the incr2->in(1)->in(0)->is_RangeCheck()
condition can ever be true. How can the control input of a ConstraintCast be a RangeCheck? Shouldn't there be a projection node in-between?
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.
I missed this comment before... incr2->in(1)->in(0)->in(0)->is_RangeCheck()
is really what I want. I also double-checked this.
incr2->in(1)->in(0)->is_RangeCheck()
prevents JDK-8273585 from optimization - 15s
incr2->in(1)->in(0)->in(0)->is_RangeCheck()
allows JDK-8273585 to optimize further - 8s
I think we should add an IR verification test for JDK-8273585. |
Right. I mixed |
I still think the issue is in some other place. Your change just avoiding the case which triggers it. The java code is legal and compiling next code did not trigger nay issues:
Actually I was not able to reproduce the issue with included test. |
Why? Can you clarify more? The root cause seems clear: the unexpected |
Yes, we need a verification test for it. I'll do this later. |
As I mentioned above, I don't understand how your newly added condition is supposed to work. |
@kelthuzadx This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
Comment to keep this open. @kelthuzadx, any update on this? |
@vnkozlov @TobiHartmann I reviewed the above comments again. I think the proposed fix is good. According to my analysis at #9695 (comment) , we have a parallel IV which formed as As far as this fix itself is concerned, I think the whole process is reasonable, i.e. we accept that form as parallel IV only when it was generated by library_call_preconditions_checkindex. The only thing I'm not sure about is whether this Add-CastII-Phi form itself is really reasonable as an IV, which is why I think adding an IR verification test for JDK-8273585 is reasonable, I will go back to investigate that again after this patch, what do you think? |
/** | ||
* @test | ||
* @bug 8290432 | ||
* @summary Unexpected parallel induction variable pattern was recongized |
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.
This test does not reproduce the issue for me, whereas Test-2.java still works.
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.
You can reset to JDK-8273585, TestUnexpectedParallelIV.java reproduces the crash. Test-2.java can always reproduce without resetting commits. I added both of them as test cases.
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.
The new version looks reasonable to me but please merge the two tests into one. There is also a jcheck whitespace error.
If you don't intend to add an IR verification test for JDK-8273585 with this fix, please file at least a follow-up enhancement.
I filed adding IR verification test as https://bugs.openjdk.org/browse/JDK-8297307. |
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.
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.
@y1yang0 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 1797 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 |
@vnkozlov Can I have a second review? Thanks! |
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.
I may ask to do our internal performance testing for this change too before approval.
Do you mean... oracle internal performance testing or opensource microbenchmark inside openjdk? For the former one, may I ask your help to do that? Thanks. (For the later one, I tested JDK-8273585 attached test, and it works well. After this patch, it takes 8s.) |
I'll run some performance testing in our system and report back once it passed. |
Performance results look good (no measurable difference). A second review would be good though. |
/reviewers 2 |
@TobiHartmann |
Do we really need this bailout? From your very first picture, it does not seem wrong to replace |
If replacing Phi#125 is acceptable, we need to reach a consensus that the form of I’m not sure whether we have such a consensus that the form of |
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.
If replacing Phi#125 is acceptable, we need to reach a consensus that the form of Add->CastII->Phi can be considered as parallel IV
I think it should be safe and we've already done that since JDK-8273585 and haven't seen a crash related to that idea. But given how close we are to the fork, I suggest to go with your bailout fix for JDK 20 which is safer (and performance testing done by Tobias looks good). In this way, we really only optimize the pattern originally intended in JDK-8273585.
For the general case of allowing any cast node, I suggest to file an RFE and investigate again if that is possible/correct. I have the feeling that it is but it would be better to defer that to JDK 21. What do you think?
Thanks,
Christian
That makes sense, you can re-use/extend JDK-8297307 for that. Vladimir should also have a look at this again. |
I think it’s really reasonable. As Tobias said, we can reuse https://bugs.openjdk.org/browse/JDK-8297307 for this purpose. Thanks! |
I agree with this suggestion. |
/integrate |
Going to push as commit acf96c6.
Your commit was automatically rebased without conflicts. |
Hi, can I have a review for this patch? JDK-8273585 recognized the form of
Phi->CastII->AddI
as additional parallel induction variables. In the following program:val
is incorrectly matched with the new parallel IV form:And C2 further replaces it with newly added nodes, which finally leads the crash:
I think we can add more constraints to the new form. The form of
Phi->CastXX->AddX
appears when using Preconditions.checkIndex, and it would be recognized as additional IV when 1) Phi != phi2, 2) CastXX is controlled by RangeCheck(to reflect changes in Preconditions checkindex intrinsic)Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/9695/head:pull/9695
$ git checkout pull/9695
Update a local copy of the PR:
$ git checkout pull/9695
$ git pull https://git.openjdk.org/jdk pull/9695/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 9695
View PR using the GUI difftool:
$ git pr show -t 9695
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/9695.diff