-
Notifications
You must be signed in to change notification settings - Fork 5.8k
8316679: C2 SuperWord: wrong result, load should not be moved before store if not comparable #15864
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
…store if not comparable
👋 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.
Good.
@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 no new commits pushed to the ➡️ To integrate this PR with the above commit message to the |
Thank you for detailed explanation. |
@vnkozlov The issue with knowing if different array references can alias (if they are the same) is something that is currently not implemented for SuperWord. But it could theoretically be solved outside of SuperWord, by putting them on separate memory slices. I think this is definately a separate RFE and would not just benefit SuperWord. Alternatively, we could do special logic inside SuperWord, determining if references can be proven not to be the same. Or even specualte / trap. The last one would be powerful, and probably the most beneficial in general. In most cases different array references are actually different arrays, but we cannot know that at compile time, because they are for example two arguments to a method. |
I like the idea to add loop predicate to check arrays difference. It can be folded by compiler based on EA analysis: we were talking for long time to add instance ID for not global escaping arrays regardless their size. And yes, we can do that outside SuperWord. |
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.
Thanks for the nice summary. The fix looks good to me.
* @test | ||
* @requires vm.compiler2.enabled | ||
* @bug 8316679 | ||
* @summary In SuperWord::output, LoadVector can be moved before StoreVector, but only if it is proven to be safe. |
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 test should have @key randomness
b[inv + i + 0]++; | ||
b[inv + i + 1]++; | ||
b[inv + i + 2]++; | ||
b[inv + i + 3]++; |
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 might want to remove the extra whitespaces in the index expressions.
Thanks @TobiHartmann @vnkozlov for the reviews! |
Going to push as commit 48f1a92.
Your commit was automatically rebased without conflicts. |
Context
In
SuperWord::output
, we replace the scalars with vectors, pack by pack.In JDK-8052081 (changeset) we added an optimization to move the memory state of a LoadVector as early as possible. We go up the memory chain, and skip any
StoreVector
that provably can never alias with theLoadVector
(provably no overlap).Details
For this, we must understand the following function
VPointer::cmp
:jdk/src/hotspot/share/opto/vectorization.hpp
Lines 110 to 120 in 96781ba
We have 4 possible states:
NotComparable
means that we cannot determine the relative offsets between the two memory addresses. We have no guarantee about aliasing at all.Less
means that one address lies before the other,Greater
means that it comes after.Equal
means that the two memory regions have an overlap or are identical. To determine overlap, we must know the position of the pointer, as well as thememory_size
of each memory reference.VPointer::not_equal
is true iff we get statesLess
orGreater
(we know there cannot be overlap).VPointer::comparable
is true iff the state isNotComparable
, hence we have no guarantee about aliasing.Problem
Currently, there are 2 bugs in this "move-load-before-store" logic:
not_equal
but also the!comparable
case. However, when the two pointers are not comparable, that could be due to different invariants for example (seeTestMovingLoadBeforeStore.java
). The two pointers are not comparable, because we do not know the relative position, due to the invariants. But this exactly means that we cannot know at compile-time that there will not be aliasing. Thus, we cannot allow moving a load before such a store. Otherwise we may get wrong results. (*)StoreVector
. This is not correct, we need to compare all elements of the load-pack with theStoreVector
. Otherwise it may be that the first element lays below/before the memory region of theStoreVector
(Less), but the last element of the load-pack for example could have overlap with theStoreVector
(Equal).We could fix both issues at once. But I am fixing them separately, first JDK-8316679, which can be backported to JDK-11, and then JDK-8316594 which only seems to have caused regressions in JDK-22.
Testing
I added correpsonding regression tests.
Tier1-6 + stress-testing.
Performance testing.
(*) We also use
!not_equal
inSuperWord::dependence_graph
to determine if two memrefs need to have a dependency edge. The condition there and the condition here (for move-load-before-store) should be equivalent.jdk/src/hotspot/share/opto/superword.cpp
Lines 1112 to 1116 in 96781ba
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/15864/head:pull/15864
$ git checkout pull/15864
Update a local copy of the PR:
$ git checkout pull/15864
$ git pull https://git.openjdk.org/jdk.git pull/15864/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 15864
View PR using the GUI difftool:
$ git pr show -t 15864
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/15864.diff
Webrev
Link to Webrev Comment