8374043: C2: assert(_base >= VectorMask && _base <= VectorZ) failed: Not a Vector #29057
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem:
Test
compiler/vectorapi/VectorMaskToLongTest.javacrashes intermittently (approximately once per 200+ runs) with stress VM options such as-XX:+StressIGVN:The crash occurs in following code when calling
is_vect()in the assertion added by JDK-8367292 [1]:jdk/src/hotspot/share/opto/vectornode.cpp
Lines 1920 to 1924 in 2cb228e
Root Cause:
The mask's type becomes TOP (unreachable) during compiler optimizations when the mask node is marked as dead before all its users are removed from the ideal graph. If
Ideal()is subsequently called on a user node, it may access the TOP type, triggering the assertion.Here is the simplified ideal graph showing the crash scenario:
Detailed Scenario:
Following is the method in the test case that hits the assertion:
jdk/test/hotspot/jtreg/compiler/vectorapi/VectorMaskToLongTest.java
Lines 65 to 70 in 2cb228e
This method accepts a
VectorSpecies<?>parameter and calls vector APIsVectorMask.fromLong()andtoLong(). It is called with species ranging fromByteVector.SPECIES_MAXtoDoubleVector.SPECIES_MAX. During compilation, C2 speculatively generates fast paths fortoLong()for all possible species.When compiling a specific test case such as:
jdk/test/hotspot/jtreg/compiler/vectorapi/VectorMaskToLongTest.java
Lines 177 to 179 in 6eaabed
the compiler inlines the method and attempts to optimize away unreachable branches. The following graph shows the situation before the mask becomes
TOP:The generated mask (
VectorBox) is aDoubleMaxMask, but the code path expects anIntMaxMaskforIntMaxMask::toLong(). Since this is an unreachable branch, the control input ofCheckCastPPbecomesTOPduring IGVN, propagating theTOPtype to subsequent data nodes until reachingVectorStoreMask.VectorStoreMaskhas another non-TOP input (ConI), which stops furtherTOPpropagation.With stress VM options, the IGVN worklist order is shuffled, causing
VectorMaskToLongNode::Ideal()to be invoked before dead path cleanup completes, which triggers the assertion failure.Solution:
Replace
is_vect()with the saferisa_vect(), which checks whether the type is a vector type before casting and returnsnullptrif it is not. Additionally, check fornullptrand skip the optimization if the type check fails.An alternative solution would be to detect
topinputs during IGVN for the relevant vector nodes and skip certain optimizations when such inputs are encountered. That is probably the right long-term direction. However, because this handling is currently missing for all vector nodes, I'd like to leave it as a separate follow-up topic for discussion.Testing:
Ran the test 800 times on SVE/NEON/AVX2 systems with no failures observed.
Note that no new test case was added because it is so challenging to me to reproduce this issue reliably. The issue depends on a specific IGVN optimization sequence that occurs non-deterministically due to the worklist shuffling behavior under stress VM options.
[1] https://bugs.openjdk.org/browse/JDK-8367292
Progress
Issue
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/29057/head:pull/29057$ git checkout pull/29057Update a local copy of the PR:
$ git checkout pull/29057$ git pull https://git.openjdk.org/jdk.git pull/29057/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 29057View PR using the GUI difftool:
$ git pr show -t 29057Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/29057.diff
Using Webrev
Link to Webrev Comment