-
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
8297689: Fix incorrect result of Short.reverseBytes() call in loops #11427
Conversation
Recently, we find calling `Short.reverseBytes()` in loops may generate incorrect result if the code is compiled by C2. Below is a simple case to reproduce. ``` class Foo { static final int SIZE = 50; static int a[] = new int[SIZE]; static void test() { for (int i = 0; i < SIZE; i++) { a[i] = Short.reverseBytes((short) a[i]); } } public static void main(String[] args) throws Exception { Class.forName("java.lang.Short"); a[25] = 16; test(); System.out.println(a[25]); } } // $ java -Xint Foo // 4096 // $ java -Xcomp -XX:-TieredCompilation -XX:CompileOnly=Foo.test Foo // 268435456 ``` In this case, the `reverseBytes()` call is intrinsified and transformed into a `ReverseBytesS` node. But then C2 compiler incorrectly vectorizes it into `ReverseBytesV` with int type. C2 `Op_ReverseBytes*` has short, char, int and long versions. Their behaviors are different for different data sizes. In superword, subword operation itself doesn't have precise data size info. Instead, the data size info comes from memory operations in its use-def chain. Hence, vectorization of `reverseBytes()` is valid only if the data size is consistent with the type size of the caller's class. But current C2 compiler code lacks fine-grained type checks for `ReverseBytes*` in vector transformation. It results in `reverseBytes()` call from Short or Character class with int load/store gets vectorized incorrectly in above case. To fix the issue, this patch adds more checks in `VectorNode::opcode()`. T_BYTE is a special case for `Op_ReverseBytes*`. As the Java Byte class doesn't have `reverseBytes()` method so there's no `Op_ReverseBytesB`. But T_BYTE may still appear in VectorAPI calls. In this patch we still use `Op_ReverseBytesI` for T_BYTE to ensure vector intrinsification succeeds. Tested with hotspot::hotspot_all_no_apps, jdk tier1~3 and langtools tier1 on x86 and AArch64, no issue is found.
👋 Welcome back pli! A progress list of the required criteria for merging this PR into |
/cc hotspot-compiler |
@pfustc |
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 looks reasonable to me but I'm not an expert in that code.
/reviewers 2 |
@pfustc 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 98 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 |
@TobiHartmann |
@jatin-bhateja Do you have any comments on this change? |
LGTM. Thanks. |
Thanks @jatin-bhateja for your review. I will integrate this. |
/integrate |
Going to push as commit a613998.
Your commit was automatically rebased without conflicts. |
Recently, we find calling
Short.reverseBytes()
in loops may generate incorrect result if the code is compiled by C2. Below is a simple case to reproduce.In this case, the
reverseBytes()
call is intrinsified and transformed into aReverseBytesS
node. But then C2 compiler incorrectly vectorizes it intoReverseBytesV
with int type. C2Op_ReverseBytes*
has short, char, int and long versions. Their behaviors are different for different data sizes. In superword, subword operation itself doesn't have precise data size info. Instead, the data size info comes from memory operations in its use-def chain. Hence, vectorization ofreverseBytes()
is valid only if the data size is consistent with the type size of the caller's class. But current C2 compiler code lacks fine-grained type checks forReverseBytes*
in vector transformation. It results inreverseBytes()
call from Short or Character class with int load/store gets vectorized incorrectly in above case.To fix the issue, this patch adds more checks in
VectorNode::opcode()
. T_BYTE is a special case forOp_ReverseBytes*
. As the Java Byte class doesn't havereverseBytes()
method so there's noOp_ReverseBytesB
. But T_BYTE may still appear in VectorAPI calls. In this patch we still useOp_ReverseBytesI
for T_BYTE to ensure vector intrinsification succeeds.Tested with hotspot::hotspot_all_no_apps, jdk tier1~3 and langtools tier1 on x86 and AArch64, no issue is found.
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/11427/head:pull/11427
$ git checkout pull/11427
Update a local copy of the PR:
$ git checkout pull/11427
$ git pull https://git.openjdk.org/jdk pull/11427/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 11427
View PR using the GUI difftool:
$ git pr show -t 11427
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/11427.diff