JDK-8335709 : C2: assert(!loop->is_member(get_loop(useblock))) failed: must be outside loop
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 17,21,22,23,24
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2024-07-04
  • Updated: 2024-10-24
  • Resolved: 2024-07-19
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 17 JDK 21 JDK 23 JDK 24
17.0.14-oracleFixed 21.0.6-oracleFixed 23.0.2Fixed 24 b08Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
I would really appreciate a mention in the PR: I extracted the JASM file from a class-file, reduced it, and was able to recreate a JAVA file from that. This simplifies the debug job and the triaging (class-file would have been limited to JDK22 and newer).

Affected: 23, 22, 21, 17 (did not reproduce with 11)
Assert in debug. Product: infinite loop as expected, but not sure if there is no wrong result possible.

Only reproduced with JDK17 and newer, but you will have to see why it does not reproduce with JDK11.

Looks like a problem with infinite-loops, see java code and the NeverBranch as evidence that there is no loop exit:
(rr) p x_ctrl->dump_bfs(100,x_ctrl,"#cA")
dist apd dump
---------------------------------------------
   7  14   84  IfFalse  === 82  [[ 87 91 ]] #0 !jvms: Test::test @ bci:4 (line 12)
   6   7   87  Region  === 87 84 83  [[ 87 112 92 105 107 130 ]] #reducible  !jvms: Test::test @ bci:11 (line 15)
   5   7  107  SafePoint  === 87 1 108 1 1 112 106  [[ 73 ]]  SafePoint  !jvms: Test::test @ bci:24 (line 16)
   4   7   73  Region  === 73 107 72  [[ 73 119 77 118 117 ]] #reducible  !jvms: Test::test @ bci:2 (line 12)
   3   7  119  NeverBranch  === 73  [[ 120 121 ]] 
   2   7  120  CProj  === 119  [[ 82 ]] #0
   1   7   82  If  === 120 81  [[ 83 84 ]] P=0.500000, C=-1.000000 !jvms: Test::test @ bci:4 (line 12)
   0   0   83  IfTrue  === 82  [[ 87 ]] #1 !jvms: Test::test @ bci:4 (line 12)
We have had many open bugs with infinite-loops: they are quite rare in the wild but tricky to get right with loop-opts.
JDK-8308749: C2 failed: regular loops only (counted loop inside infinite loop)
JDK-8296389: C2: PhaseCFG::convert_NeverBranch_to_Goto must handle both orders of successors
JDK-8297642: PhaseIdealLoop::only_has_infinite_loops must detect all loops that never lead to termination
JDK-8296318: use-def assert: special case undetected loops nested in infinite loops
JDK-8296412: Special case infinite loops with unmerged backedges in IdealLoopTree::check_safepts
Maybe we should just disable PhaseIdealLoop::try_sink_out_of_loop  for infinite loops: they never terminate anyway, and thus their performance is not very important.

/oracle-work/jdk-fork2/build/linux-x64-debug/jdk/bin/java -Xcomp -XX:CompileCommand=compileonly,Test::* -XX:CompileCommand=printcompilation,Test::* -XX:+TraceLoopOpts Test.java

CompileCommand: compileonly Test.* bool compileonly = true
CompileCommand: PrintCompilation Test.* bool PrintCompilation = true
36751   97    b  3       Test::main (4 bytes)
36773   99    b  4       Test::main (4 bytes)
36775  100 %  b  4       Test::test @ 2 (27 bytes)
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/oracle-work/jdk-fork2/open/src/hotspot/share/opto/loopopts.cpp:1266), pid=4119505, tid=4119519
#  assert(!loop->is_member(get_loop(useblock))) failed: must be outside loop
#
# JRE version: Java(TM) SE Runtime Environment (24.0) (fastdebug build 24-internal-2024-07-04-1039391.emanuel...)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 24-internal-2024-07-04-1039391.emanuel..., compiled mode, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x12a2718]  PhaseIdealLoop::place_outside_loop(Node*, IdealLoopTree*) const+0x348
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /oracle-work/xyz/core.4119505)
#
# An error report file with more information is saved as:
# /oracle-work/xyz/hs_err_pid4119505.log
#
# Compiler replay data is saved as:
# /oracle-work/xyz/replay_pid4119505.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#

Current CompileTask:
C2:36803  100 %  b  4       Test::test @ 2 (27 bytes)

Stack: [0x00007f4fc436f000,0x00007f4fc4470000],  sp=0x00007f4fc446ad80,  free space=1007k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x12a2718]  PhaseIdealLoop::place_outside_loop(Node*, IdealLoopTree*) const+0x348  (loopopts.cpp:1266)
V  [libjvm.so+0x12a5bd6]  PhaseIdealLoop::try_sink_out_of_loop(Node*)+0x376  (loopopts.cpp:1753)
V  [libjvm.so+0x12a6603]  PhaseIdealLoop::split_if_with_blocks_post(Node*)+0x83  (loopopts.cpp:1531)
V  [libjvm.so+0x12a6ec6]  PhaseIdealLoop::split_if_with_blocks(VectorSet&, Node_Stack&)+0x96  (loopopts.cpp:1964)
V  [libjvm.so+0x1299519]  PhaseIdealLoop::build_and_optimize()+0xee9  (loopnode.cpp:4815)
V  [libjvm.so+0x9e4770]  PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)+0x390  (loopnode.hpp:1117)
V  [libjvm.so+0x9df283]  Compile::Optimize()+0x4c3  (compile.cpp:2366)
V  [libjvm.so+0x9e3326]  Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0x1b06  (compile.cpp:852)
V  [libjvm.so+0x835575]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x1d5  (c2compiler.cpp:142)
V  [libjvm.so+0x9eef68]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x928  (compileBroker.cpp:2303)
V  [libjvm.so+0x9efbf8]  CompileBroker::compiler_thread_loop()+0x478  (compileBroker.cpp:1961)
V  [libjvm.so+0xe994dc]  JavaThread::thread_main_inner()+0xcc  (javaThread.cpp:757)
V  [libjvm.so+0x17b9076]  Thread::call_run()+0xb6  (thread.cpp:225)
V  [libjvm.so+0x14a1717]  thread_native_entry(Thread*)+0x127  (os_linux.cpp:858)
Comments
Fix request [17u.,21u] I backport this for parity with 17.0.14-oracle,21.0.6-oracle. Medium risk. Simple change, but with the typical C2 risk. Let's go along with Oracle here. Clean backport in 21, trivial resolve in 17. Test passes and reproduces the issue without the fix. SAP nightly testing passed.
24-10-2024

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk21u-dev/pull/1079 Date: 2024-10-23 14:15:41 +0000
23-10-2024

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk17u-dev/pull/2991 Date: 2024-10-23 14:16:11 +0000
23-10-2024

[jdk23u-fix-request] Approval Request from Yagmur Eren Clean backport of the logic fix to sink nodes out of loop.
09-10-2024

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk23u/pull/145 Date: 2024-10-09 08:25:50 +0000
09-10-2024

Changeset: 0ddf54e2 Branch: master Author: Roland Westrelin <roland@openjdk.org> Date: 2024-07-19 07:30:23 +0000 URL: https://git.openjdk.org/jdk/commit/0ddf54e222104469669f611804ae55e2685f54fb
19-07-2024

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/20231 Date: 2024-07-18 09:38:47 +0000
18-07-2024

Might be related to JDK-8336472.
17-07-2024

[~roland], FYI, in case you have time to look at this.
05-07-2024

Code was introduced by JDK-8252372 in JDK 17. ILW = Assert when trying to sink node out of loop, edge case but reproducible, disable split if or compilation of affected method = HLM = P3
04-07-2024