JDK-8356184 : C2 MemorySegment: long RangeCheck with ConvI2L(iv + invar) prevents RCE
  • Type: Sub-task
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 25
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2025-05-05
  • Updated: 2025-07-23
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.
Other
tbdUnresolved
Description
Simple MemorySegment long counted loops where a MemorySegement is accessed at an index computed by the sum of the induction variable and an invariant int offset fails to vectorize. This is due to missing RCE because the cast from int to long for IV offset is not necessarily linear.

See the attached test provided by [~epeter]. Run it with
 java -XX:CompileCommand=compileonly,Test1.\* -XX:CompileCommand=printcompilation,Test1.\* -XX:CompileCommand=TraceAutoVectorization,Test1.\*,SW_REJECTIONS,PRECONDITIONS -XX:+TraceNewVectors -XX:+TraceLoopOpts -Xbatch Test1.java

The IR subgraph of the range check in Test1.test2() that is not removed due to a ConvI2L:
   5  1468  CountedLoop  === 1468 1467 1428  [[ 1468 96 84 1437 ]] stride: 1  strip mined !orig=[1459],[81] !jvms: Test1::test2 @ bci:8 (line 26)
   4    11  Parm  === 3  [[ 1469 1383 733 1110 38 49 60 71 1097 87 120 1056 748 438 452 691 ]] Parm1: int !jvms: Test1::test2 @ bci:-1 (line 25) [ invar ]
   4    84  Phi  === 1468 22 1460  [[ 1383 1418 87 120 1110 1097 438 452 691 733 748 1056 1460 ]]  #int:0..99999:www #tripcount !jvms: Test1::test2 @ bci:8 (line 26)  [ the IV Phi ]
   3    87  AddI  === _ 11 84  [[ 88 458 ]]  !jvms: Test1::test2 @ bci:10 (line 26)
   2   458  CastII  === 447 87  [[ 459 ]]  #int:>=0:www !jvms: AbstractMemorySegmentImpl::checkBounds @ bci:16 (line 403) AbstractMemorySegmentImpl::checkAccess @ bci:9 (line 357) AbstractMemorySegmentImpl::checkEnclosingLayout @ bci:10 (line 362) SegmentVarHandle::checkSegment @ bci:18 (line 92) VarHandleSegmentAsBytes::get @ bci:11 (line 55) VarHandleSegmentAsBytes::get @ bci:10 (line 49) VarHandleGuards::guard_LJ_I @ bci:49 (line 251) AbstractMemorySegmentImpl::get @ bci:8 (line 694) Test1::test2 @ bci:18 (line 27)
   1   459  ConvI2L  === _ 458  [[ 1110 1110 1110 1103 1097 1097 1097 1056 1056 1056 760 532 ]]  #long:0..maxint:www !orig=88 !jvms: Test1::test2 @ bci:11 (line 26)
   0  1103  CmpUL  === _ 459 443  [[ 1104 ]]  !jvms: AbstractMemorySegmentImpl::checkBounds @ bci:16 (line 403) AbstractMemorySegmentImpl::checkAccess @ bci:9 (line 357) AbstractMemorySegmentImpl::checkEnclosingLayout @ bci:10 (line 362) SegmentVarHandle::checkSegment @ bci:18 (line 92) VarHandleSegmentAsBytes::set @ bci:11 (line 69) VarHandleSegmentAsBytes::set @ bci:12 (line 63) VarHandleGuards::guard_LJI_V @ bci:51 (line 609) AbstractMemorySegmentImpl::set @ bci:10 (line 700) Test1::test2 @ bci:35 (line 28)
 
Comments
[~mhassig] To clarify a little: the ConvI2L is not linear, i.e. ConvI2L(i + invar) != ConvI2L(i) + ConvI2L(invar). The int addition may overflow, but the long addition does not overflow. We seem to have a long range check here, which currently does not seem to allow for cases where we are not sure there cannot be an int-overflow. It is also not about a "cast" (CastII, CastLL, CastPP, etc), but rather a "conversion", specifically ConvI2L. Therefore, I would suggest this title instead: C2 MemorySegment: long RangeCheck with ConvI2L(iv + invar) prevents RCE Can you also paste the IR of the long RangeCheck, with the input nodes, so we can see the iv-phi, ConvI2L and invar?
06-05-2025