JDK-8369902 : C2 SuperWord: wrong result because filterin NaN instead of zero in MemPointerParser::canonicalize_raw_summands
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 26
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2025-10-15
  • Updated: 2025-10-21
  • Resolved: 2025-10-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 26
26 masterFixed
Related Reports
Causes :  
Relates :  
Description
Found by fuzzer.

Looks like one of the values computed is off by one, comparing interpreter vs compiled.

But it does not seem to reproduce with -XX:-UseSuperWord

Update: it seems it does also not reproduce with: -XX:-UseAutoVectorizationSpeculativeAliasingChecks
Also either one of these does it, but but not if both are on: -XX:-UseAutoVectorizationPredicate -XX:-LoopMultiversioning
So probably something with the aliasing runtime check is wrong, probably JDK-8324751.

java -Xbatch -XX:CompileCommand=compileonly,Test::test -XX:CompileCommand=printcompilation,Test::test Test.java

4206   99 %  b  4       Test::test @ 18 (76 bytes)
4233  100    b  4       Test::test (76 bytes)
4253  101 %  b  4       Test::test @ 51 (76 bytes)
sum: 141
sum: 139
at 0: 0 vs 0
at 1: 2 vs 2
...
at 45: 2 vs 2
at 46: 19 vs 17
at 47: 2 vs 2
...
at 62: 2 vs 2
at 63: 0 vs 0
...
at 99: 0 vs 0
Exception in thread "main" java.lang.RuntimeException: wrong result: 141 139
	at Test.main(Test.java:39)

At 46 is where the constant address is pointing. Value should be 19, but it is sometimes 15 and sometimes 17. It is just a bad reordering of the memory ops, which should be prevented by the aliasing runtime check.

And with -Xint or -XX:-UseSuperWord it passes.

------------------------- FROM ORIGINAL REPORT ----------------

java -Xbatch Test_3164.java > comp.txt
java -Xint Test_3164.java > int.txt
diff comp.txt int.txt

24c24
< lArr1 iArr2 Test_3164 = 6209323228939198569,21767,-185
---
> lArr1 iArr2 Test_3164 = 6209323228939198569,21766,-185
34c34
< lArr1 iArr2 Test_3164 = 6209323228939198569,21767,-185
---
> lArr1 iArr2 Test_3164 = 6209323228939198569,21766,-185
44c44
< lArr1 iArr2 Test_3164 = 6209323228939198569,21767,-185
---
> lArr1 iArr2 Test_3164 = 6209323228939198569,21766,-185
54c54
< lArr1 iArr2 Test_3164 = 6209323228939198569,21767,-185
---
> lArr1 iArr2 Test_3164 = 6209323228939198569,21766,-185
64c64
< lArr1 iArr2 Test_3164 = 6209323228939198569,21767,-185
---
> lArr1 iArr2 Test_3164 = 6209323228939198569,21766,-185
74c74
< lArr1 iArr2 Test_3164 = 6209323228939198569,21767,-185
---
> lArr1 iArr2 Test_3164 = 6209323228939198569,21766,-185
84c84
< lArr1 iArr2 Test_3164 = 6209323228939198569,21767,-185
---
> lArr1 iArr2 Test_3164 = 6209323228939198569,21766,-185
94c94
< lArr1 iArr2 Test_3164 = 6209323228939198569,21767,-185
---
> lArr1 iArr2 Test_3164 = 6209323228939198569,21766,-185
Comments
Changeset: 207fe55d Branch: master Author: Emanuel Peter <epeter@openjdk.org> Date: 2025-10-21 05:42:50 +0000 URL: https://git.openjdk.org/jdk/commit/207fe55d90fd4fa1a53c876865b1c227518c170e
21-10-2025

ILW = Wrong result due to wrong filtering in Superword, edge case, use -XX:-UseAutoVectorizationSpeculativeAliasingChecks or "-XX:-UseAutoVectorizationPredicate -XX:-LoopMultiversioning" = HLM = P3
17-10-2025

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/27848 Date: 2025-10-16 14:20:29 +0000
17-10-2025

It seems the issue is in: MemPointerParser::canonicalize_raw_summands // Keep summands with non-zero scale. if (!scaleI.is_zero() && !scaleL.is_NaN()) { _raw_summands.at_put(pos_put++, MemPointerRawSummand(variable, scaleI, scaleL, int_group)); } We are wrongly rejecting scaleL for NaN, and not for zero. There are now 2 issues: - If we have a scaleL that is NaN, it just gets filtered out, and we get a "valid" MemPointer / VPointer, instead of an invalid one. That can lead to wrong results, as we have seen with Test.java - If we have a zero scaleL, we don't filter it out, and hit an assert later, see JDK-8368578. I have a nice reproducer for JDK-8368578: ./java -XX:CompileCommand=compileonly,Test2::test -XX:CompileCommand=printcompilation,Test2::test -XX:+TraceLoopOpts -XX:CompileCommand=TraceAutoVectorization,Test2::test,POINTERS,POINTER_PARSING,SW_INFO Test2.java Loop: N0/N0 has_sfpt Loop: N2101/N2106 limit_check short_running profile_predicated predicated auto_vectorization_check_predicate counted [0,int),+1 (4 iters) pre Loop: N1829/N1828 limit_check sfpts={ 1831 } Loop: N2249/N1511 limit_check counted [int,int),+2 (8008 iters) main has_sfpt strip_mined Loop: N1971/N1976 limit_check counted [int,int),+1 (4 iters) post MemPointerParser::parse: size=1 mem: 1473 StoreB === 2249 2242 1931 803 [[ 1832 2252 1499 2114 ]] @rawptr:BotPTR, idx=Raw; unsafe Memory: @rawptr:BotPTR, idx=Raw; !orig=2258 !jvms: ScopedMemoryAccess::putByteInternal @ bci:15 (line 1121) ScopedMemoryAccess::putByte @ bci:6 (line 1109) VarHandleSegmentAsBytes::set @ bci:39 (line 70) VarHandleSegmentAsBytes::set @ bci:12 (line 63) VarHandleGuards::guard_LJI_V @ bci:51 (line 612) AbstractMemorySegmentImpl::set @ bci:10 (line 700) Test2::test @ bci:83 (line 34) pointer: 1931 AddP === _ 1 2350 404 [[ 1473 ]] !orig=[1471] !jvms: ScopedMemoryAccess::putByteInternal @ bci:15 (line 1121) ScopedMemoryAccess::putByte @ bci:6 (line 1109) VarHandleSegmentAsBytes::set @ bci:39 (line 70) VarHandleSegmentAsBytes::set @ bci:12 (line 63) VarHandleGuards::guard_LJI_V @ bci:51 (line 612) AbstractMemorySegmentImpl::set @ bci:10 (line 700) Test2::test @ bci:83 (line 34) Raw Summands (11): <0: 1 * 1> + <1: 1 * 1 * [2251 Phi]> + <0: 1 * 1 * [1256 LoadL]> + <0: 1 * 1 * [54 LoadL]> + <0: -1 * 1 * [27 LoadL]> + <0: 1 * 1 * [47 LoadL]> + <0: 1 * 1 * [43 LoadL]> + <0: 1 * 1 * [39 LoadL]> + <0: 1 * 1 * [35 LoadL]> + <0: 1 * 1 * [31 LoadL]> + <0: 1 * 1 * [27 LoadL]> Raw Summands (10): <0: 0 * 1 * [27 LoadL]> + <0: 1 * 1 * [31 LoadL]> + <0: 1 * 1 * [35 LoadL]> + <0: 1 * 1 * [39 LoadL]> + <0: 1 * 1 * [43 LoadL]> + <0: 1 * 1 * [47 LoadL]> + <0: 1 * 1 * [54 LoadL]> + <0: 1 * 1 * [1256 LoadL]> + <0: 1 * 1> + <1: 1 * 1 * [2251 Phi]> # # A fatal error has been detected by the Java Runtime Environment: # # Internal Error (/home/empeter/Documents/oracle/jdk-fork4/open/src/hotspot/share/opto/mempointer.hpp:611), pid=2620092, tid=2620107 # assert(!_scale.is_zero()) failed: non-zero scale Similarly, I was able to extract a nice reproducer for the wrong values, reported originally above with the fuzzer: ./java -XX:CompileCommand=compileonly,Test3::test -XX:CompileCommand=printcompilation,Test3::test -XX:+TraceLoopOpts -XX:CompileCommand=TraceAutoVectorization,Test3::test,POINTERS,POINTER_PARSING,SW_INFO,SPECULATIVE_ALIASING_ANALYSIS Test3.java ... mem: 109 StoreI === 1386 215 216 201 [[ 1389 68 917 ]] @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):exact+any *, idx=16; unaligned mismatched unsafe Memory: @byte[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=16; !orig=1012 !jvms: Unsafe::putIntUnaligned @ bci:10 (line 3740) ScopedMemoryAccess::putIntUnalignedInternal @ bci:17 (line 3192) ScopedMemoryAccess::putIntUnaligned @ bci:8 (line 3180) VarHandleSegmentAsInts::set @ bci:44 (line 75) VarHandleSegmentAsInts::set @ bci:12 (line 68) VarHandleGuards::guard_LJI_V @ bci:51 (line 612) AbstractMemorySegmentImpl::set @ bci:10 (line 748) Test3::test @ bci:59 (line 37) pointer: 216 AddP === _ 190 288 116 [[ 276 109 808 810 894 896 994 996 1101 1103 1105 1107 1196 1198 1200 1202 1204 1206 1208 1210 1319 1321 1323 1325 1327 1329 1331 1333 1335 1337 1339 1341 1343 1345 1347 1349 ]] !jvms: Unsafe::getIntUnaligned @ bci:5 (line 3617) ScopedMemoryAccess::getIntUnalignedInternal @ bci:15 (line 3171) ScopedMemoryAccess::getIntUnaligned @ bci:6 (line 3159) VarHandleSegmentAsInts::get @ bci:42 (line 60) VarHandleSegmentAsInts::get @ bci:10 (line 53) VarHandleGuards::guard_LJ_I @ bci:49 (line 254) AbstractMemorySegmentImpl::get @ bci:8 (line 742) Test3::test @ bci:43 (line 36) Raw Summands (4): <0: NaN * 1> + <0: 1 * 1 * [328 LoadL]> + <0: 1 * 1 * [224 LoadL]> + <0: 1 * 1 * [190 CheckCastPP]> Raw Summands (3): <0: 1 * 1 * [190 CheckCastPP]> + <0: 1 * 1 * [224 LoadL]> + <0: 1 * 1 * [328 LoadL]> Summands (3): con(0) + 1 * [190 CheckCastPP] + 1 * [224 LoadL] + 1 * [328 LoadL] Summands (3): con(0) + 1 * [190 CheckCastPP] + 1 * [224 LoadL] + 1 * [328 LoadL] ... Union of 32 weak aliasing edges: VPointer[size: 64, object, base(164 CheckCastPP) + con( 0) + iv_scale( 4) * iv + invar(4 * [124 LoadL] + 1 * [251 LoadL])] VPointer[size: 4, object, base(190 CheckCastPP) + con( 0) + iv_scale( 0) * iv + invar(1 * [224 LoadL] + 1 * [328 LoadL])] ... sum: 4000 sum: 4000 sum: 3984 Exception in thread "main" java.lang.RuntimeException: wrong value at Test3.main(Test3.java:18) Specifically, we can see here that the <0: NaN * 1> summand just gets filtered out, and then we are missing the long-constant "BIG" when computing the aliasing check, and we wrongly answer that there is no overlap, because the range is now shifted by BIG for the access to "b".
16-10-2025