JDK-8370332 : C2 SuperWord: SIGSEGV because PhaseIdealLoop::split_thru_phi left dead nodes in loop _body
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 26
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2025-10-21
  • Updated: 2025-11-11
  • Resolved: 2025-11-04
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 b23Fixed
Related Reports
Relates :  
Relates :  
Description
Found by fuzzer.

Only seems to reproduce with JDK26.

Workaround: -XX:-UseSuperWord

Reproduce:
java -XX:CompileCommand=compileonly,*Test*::* -XX:-TieredCompilation -Xbatch Test.java

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f3785ad7263, pid=3564244, tid=3564574
#
# JRE version: Java(TM) SE Runtime Environment (26.0) (fastdebug build 26-internal-empeter.open)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 26-internal-empeter.open, mixed mode, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x1ad7263]  SuperWordVTransformBuilder::build_scalar_vtnodes_for_non_packed_nodes()+0xc23
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %d" (or dumping to /home/empeter/Documents/oracle/creduce/core.3564244)
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#

---------------  S U M M A R Y ------------

Command Line: -XX:CompileCommand=compileonly,*Test*::* -XX:-TieredCompilation -Xbatch --add-modules=ALL-DEFAULT jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher Test.java

Host: ???, 11th Gen Intel(R) Core(TM) i7-11850H @ 2.50GHz, 16 cores, 29G, Oracle Linux Server release 9.6
Time: Tue Oct 21 15:04:39 2025 CEST elapsed time: 7.471784 seconds (0d 0h 0m 7s)

---------------  T H R E A D  ---------------

Current thread (0x00007f377c1d2b90):  JavaThread "C2 CompilerThread0" daemon [_thread_in_native, id=3564574, stack(0x00007f37701bc000,0x00007f37702bc000) (1024K)]


Current CompileTask:
C2:7471  128    b        Test::mainTest (616 bytes)

Stack: [0x00007f37701bc000,0x00007f37702bc000],  sp=0x00007f37702b5c10,  free space=999k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x1ad7263]  SuperWordVTransformBuilder::build_scalar_vtnodes_for_non_packed_nodes()+0xc23  (node.hpp:953)
V  [libjvm.so+0x1adda33]  SuperWordVTransformBuilder::build()+0x33  (superwordVTransformBuilder.cpp:33)
V  [libjvm.so+0x1acf17d]  SuperWord::do_vtransform() const [clone .part.0]+0x5cd  (superwordVTransformBuilder.hpp:49)
V  [libjvm.so+0x1ad3f9f]  SuperWord::transform_loop()+0x2f  (superword.cpp:413)
V  [libjvm.so+0x15b58b8]  PhaseIdealLoop::auto_vectorize(IdealLoopTree*, VSharedData&)+0xa48  (loopopts.cpp:4484)
V  [libjvm.so+0x1594c2c]  PhaseIdealLoop::build_and_optimize()+0xf3c  (loopnode.cpp:5275)
V  [libjvm.so+0xb8caf0]  PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)+0x4c0  (loopnode.hpp:1189)
V  [libjvm.so+0xb83a24]  Compile::optimize_loops(PhaseIterGVN&, LoopOptsMode)+0xb4  (compile.cpp:2262)
V  [libjvm.so+0xb86971]  Compile::Optimize()+0xcc1  (compile.cpp:2511)
V  [libjvm.so+0xb89b23]  Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0x2023  (compile.cpp:860)
V  [libjvm.so+0x9a3af3]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x4a3  (c2compiler.cpp:147)
V  [libjvm.so+0xb99030]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x780  (compileBroker.cpp:2345)
V  [libjvm.so+0xb9a890]  CompileBroker::compiler_thread_loop()+0x530  (compileBroker.cpp:1989)
V  [libjvm.so+0x10f260b]  JavaThread::thread_main_inner()+0x13b  (javaThread.cpp:771)
V  [libjvm.so+0x1b633e6]  Thread::call_run()+0xb6  (thread.cpp:243)
V  [libjvm.so+0x17d06c8]  thread_native_entry(Thread*)+0x128  (os_linux.cpp:883)
Comments
Changeset: 75e37b06 Branch: master Author: Emanuel Peter <epeter@openjdk.org> Date: 2025-11-04 07:39:11 +0000 URL: https://git.openjdk.org/jdk/commit/75e37b06c3e37ee49719a0c0d6b4ab2c4ff76098
04-11-2025

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/27955 Date: 2025-10-23 14:23:38 +0000
27-10-2025

WIP PR: https://github.com/openjdk/jdk/pull/27955
23-10-2025

ILW = Crash during compilation, reproducible with javafuzzer generated test, -XX:-UseSuperWord or disable compilation of affected method = HLM = P3
22-10-2025

Starting the investigation: It seems we have some dead nodes in the loop body: (rr) p _vloop.lpt()->_body $6 = {<Node_Array> = {<AnyObj> = {_vptr.AnyObj = 0x7fba78ea03b8 <vtable for Node_List+16>, _allocation_t = {18446649640908443383, 0}}, _a = 0x7fba601f9938, _max = 128, _nodes = 0x55e2d98fda28, _nesting = {<StackObj> = {<No data fields>}, _nesting = 5}}, _cnt = 75} (rr) p _vloop.lpt()->_body.dump() 0--> 425 StoreI === 1005 747 423 107 [[ 985 428 683 ]] @int[int:>=0] (java/lang/Cloneable,java/io/Serializable):exact+any *, idx=10; Memory: @int[int:>=0] (java/lang/Cloneable,java/io/Serializable):NotNull:exact+any *, idx=10; !orig=767 !jvms: Reduced::test @ bci:37 (line 27) ... 59--> 435 IfTrue === 498 [[ 1005 ]] #1 !jvms: Reduced::test @ bci:16 (line 25) 60--> 1006 ConvI2F === _ 1125 [[ 996 ]] #float !orig=844,755,374 !jvms: Reduced::test @ bci:22 (line 26) 61--> 1112 ConvF2I === _ _ [[ ]] [1000000001112] !orig=[1087],[1042],[1007],931,[916],[902],[845],[756],[373] 62--> 1111 Phi === _ _ _ [[ ]] [1000000001111] !orig=[1087],[1042],[1007],931,[916],[902],[845],[756],[373] 63--> 1050 ConvI2L === _ 1004 [[ 1061 ]] #long:1..95, widen: 3 ... Well, it seems they are already dead before we enter SuperWord. I see that the phi dies during split_if_with_blocks. (rr) bt #0 0x00007fba768f21c5 in Node::set_req (this=0x55e2d9940e08, i=0, n=0x0) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/node.hpp:463 #1 0x00007fba77a126de in Node::set_req_X (this=0x55e2d9940e08, i=0, n=0x0, igvn=0x7fba601f7320) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/phaseX.cpp:3356 #2 0x00007fba77a128fa in Node::set_req_X (this=0x55e2d9940e08, i=0, n=0x0, gvn=0x7fba601f7320) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/phaseX.cpp:3397 #3 0x00007fba77937a3d in Node::replace_edge (this=0x55e2d9940e08, old=0x55e2d9892d90, neww=0x0, gvn=0x7fba601f7320) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/node.cpp:892 #4 0x00007fba77a0c330 in PhaseIterGVN::remove_globally_dead_node (this=0x7fba601f7320, dead=0x55e2d9940e08) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/phaseX.cpp:2238 #5 0x00007fba76d683b9 in PhaseIterGVN::remove_dead_node (this=0x7fba601f7320, dead=0x55e2d9940ea8) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/phaseX.hpp:526 #6 0x00007fba77a0ce9b in PhaseIterGVN::subsume_node (this=0x7fba601f7320, old=0x55e2d9940ea8, nn=0x55e2d9941fd0) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/phaseX.cpp:2345 #7 0x00007fba76ad7277 in PhaseIterGVN::replace_node (this=0x7fba601f7320, old=0x55e2d9940ea8, nn=0x55e2d9941fd0) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/phaseX.hpp:538 #8 0x00007fba777cb59f in PhaseIdealLoop::split_if_with_blocks_pre (this=0x7fba601f6f70, n=0x55e2d9940ea8) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/loopopts.cpp:1216 #9 0x00007fba777cf25e in PhaseIdealLoop::split_if_with_blocks (this=0x7fba601f6f70, visited=..., nstack=...) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/loopopts.cpp:1984 #10 0x00007fba777b90ef in PhaseIdealLoop::build_and_optimize (this=0x7fba601f6f70) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/loopnode.cpp:5205 #11 0x00007fba76e90387 in PhaseIdealLoop::PhaseIdealLoop (this=0x7fba601f6f70, igvn=..., mode=LoopOptsDefault) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/loopnode.hpp:1189 #12 0x00007fba76e90826 in PhaseIdealLoop::optimize (igvn=..., mode=LoopOptsDefault) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/loopnode.hpp:1289 #13 0x00007fba76e7d583 in Compile::optimize_loops (this=0x7fba601f9670, igvn=..., mode=LoopOptsDefault) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/compile.cpp:2262 #14 0x00007fba76e7ec7d in Compile::Optimize (this=0x7fba601f9670) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/compile.cpp:2511 #15 0x00007fba76e75d59 in Compile::Compile (this=0x7fba601f9670, ci_env=0x7fba601fa640, target=0x55e2d9902910, osr_bci=-1, options=..., directive=0x7fba70629440) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/compile.cpp:860 #16 0x00007fba76d1f5be in C2Compiler::compile_method (this=0x7fba7012ccd0, env=0x7fba601fa640, target=0x55e2d9902910, entry_bci=-1, install_code=true, directive=0x7fba70629440) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/opto/c2compiler.cpp:147 #17 0x00007fba76e9f483 in CompileBroker::invoke_compiler_on_method (task=0x7fba70628950) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/compiler/compileBroker.cpp:2345 #18 0x00007fba76e9d87c in CompileBroker::compiler_thread_loop () at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/compiler/compileBroker.cpp:1989 #19 0x00007fba76ec0b51 in CompilerThread::thread_entry (thread=0x7fba7012d6e0, __the_thread__=0x7fba7012d6e0) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/compiler/compilerThread.cpp:69 #20 0x00007fba7739d064 in JavaThread::thread_main_inner (this=0x7fba7012d6e0) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/runtime/javaThread.cpp:771 #21 0x00007fba7739ceaf in JavaThread::run (this=0x7fba7012d6e0) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/runtime/javaThread.cpp:756 #22 0x00007fba77c95fbb in Thread::call_run (this=0x7fba7012d6e0) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/share/runtime/thread.cpp:243 #23 0x00007fba7799638b in thread_native_entry (thread=0x7fba7012d6e0) at /home/empeter/Documents/oracle/jdk-fork0/open/src/hotspot/os/linux/os_linux.cpp:883 #24 0x00007fba7908a1aa in start_thread () from /lib64/libc.so.6 #25 0x00007fba7910e5b4 in clone () from /lib64/libc.so.6 It happens at the replace_node: (rr) list 1211 Node *phi = split_thru_phi( n, n_blk, policy ); 1212 if (!phi) return n; 1213 1214 // Found a Phi to split thru! 1215 // Replace 'n' with the new phi 1216 _igvn.replace_node( n, phi ); 1217 // Moved a load around the loop, 'en-registering' something. 1218 if (n_blk->is_Loop() && n->is_Load() && 1219 !phi->in(LoopNode::LoopBackControl)->is_Load()) 1220 C->set_major_progress(); It seems we are splitting the ConvF2I out of the loop: 1111 Phi === 1005 668 378 [[ 1112 ]] #float !orig=[1087],[1042],[1007],931,[916],[902],[845],[756],[373] !jvms: Reduced::test @ bci:19 (line 26) 1112 ConvF2I === _ 1111 [[ 1006 ]] #int !orig=[1087],[1042],[1007],931,[916],[902],[845],[756],[373] !jvms: Reduced::test @ bci:19 (line 26) Both of these nodes are then dead, but still in the loop. That seems off, and seems to be the fault of the code from split_if_with_blocks. But the assert was introduced in JDK-8366427: https://github.com/openjdk/jdk/commit/99223eea03e2ed714f7a5408c356fdf06efc9200#diff-b03931396bad5fc090e9c2ff839ea876c0ac8949c31fdeeceaa33d538c76bd00R502 But I suspect that the new assert only reveals the bug from split_if_with_blocks. Now Investigating the details of split_if_with_blocks: We are splitting n=1112 ConvF2I inside n_blk=1005 CountedLoop through 1111 Phi, getting a new phi=1125 Phi. (rr) p n->dump_bfs(2,0,"#") dist dump --------------------------------------------- 2 378 AddF === _ 374 377 [[ 379 1055 1111 ]] !jvms: Reduced::test @ bci:26 (line 26) 2 668 AddF === _ 669 377 [[ 667 1055 1111 ]] !orig=378 !jvms: Reduced::test @ bci:26 (line 26) 2 1005 CountedLoop === 1005 502 435 [[ 969 973 977 978 985 1004 1005 1111 827 831 425 747 498 1125 ]] inner stride: 8 main of N1005 strip mined !orig=[846],[759],[503],[473],[364] !jvms: Reduced::test @ bci:19 (line 26) 1 1111 Phi === 1005 668 378 [[ 1112 ]] #float !orig=[1087],[1042],[1007],931,[916],[902],[845],[756],[373] !jvms: Reduced::test @ bci:19 (line 26) 0 1112 ConvF2I === _ 1111 [[ 1006 ]] #int !orig=[1087],[1042],[1007],931,[916],[902],[845],[756],[373] !jvms: Reduced::test @ bci:19 (line 26) (rr) p n_blk->dump() 1005 CountedLoop === 1005 502 435 [[ 969 973 977 978 985 1004 1005 1111 827 831 425 747 498 1125 ]] inner stride: 8 main of N1005 strip mined !orig=[846],[759],[503],[473],[364] !jvms: Reduced::test @ bci:19 (line 26) (rr) p phi->dump_bfs(2,0,"#") dist dump --------------------------------------------- 2 378 AddF === _ 374 377 [[ 379 1055 1111 ]] !jvms: Reduced::test @ bci:26 (line 26) 2 668 AddF === _ 669 377 [[ 667 1055 1111 ]] !orig=378 !jvms: Reduced::test @ bci:26 (line 26) 2 435 IfTrue === 498 [[ 1005 ]] #1 !jvms: Reduced::test @ bci:16 (line 25) 2 502 OuterStripMinedLoop === 502 1030 501 [[ 502 1005 ]] 1 379 ConvF2I === _ 378 [[ 381 1125 ]] #int !orig=[1015] !jvms: Reduced::test @ bci:27 (line 26) 1 667 ConvF2I === _ 668 [[ 666 908 1125 ]] #int !orig=379,[1015] !jvms: Reduced::test @ bci:27 (line 26) 1 1005 CountedLoop === 1005 502 435 [[ 969 973 977 978 985 1004 1005 1111 827 831 425 747 498 1125 ]] inner stride: 8 main of N1005 strip mined !orig=[846],[759],[503],[473],[364] !jvms: Reduced::test @ bci:19 (line 26) 0 1125 Phi === 1005 667 379 [[ ]] #int So far so good. But it seems that this replacement kills off the two nodes: 1111 Phi === 1005 668 378 [[ 1112 ]] #float !orig=[1087],[1042],[1007],931,[916],[902],[845],[756],[373] !jvms: Reduced::test @ bci:19 (line 26) 1112 ConvF2I === _ 1111 [[ 1006 ]] #int !orig=[1087],[1042],[1007],931,[916],[902],[845],[756],[373] !jvms: Reduced::test @ bci:19 (line 26) The 1111 Phi is only killed implicitly because it has no other use any more. And the new 1125 Phi now probably should end up on the lpt->_body. Does it? Yes indeed, it is added! And also the 379 ConvF2I that was split to the backedge. Ah, it seems that PhaseIdealLoop::split_thru_phi does some pushing and yanking for the _body. Let's see why the yanking does not work for the dead nodes. Ok, well it would only move the old 1112 ConvF2I anyway. But not any inputs that would subsequently also die. Maybe the issue is that we use _igvn.replace_node(n, phi), which is not aware of the loop structures. I'm looking for some _body.yank occurances. There are not many, but these look interesting: PhaseIdealLoop::try_move_store_after_loop _igvn.replace_node(phi, phi->in(LoopNode::EntryControl)); n_loop->_body.yank(phi); PhaseIdealLoop::try_move_store_before_loop _igvn.replace_node(mem, mem->in(LoopNode::EntryControl)); n_loop->_body.yank(mem); IdealLoopTree::reassociate phase->_igvn.replace_node(n1, result); ... _body.yank(n1); That makes me wonder if we should always yank. But what about inputs that also die? I don't see how we could do it without a _body.yank aware replace_node implementation.
21-10-2025

Dies in assertion code introduced by JDK-8366427. But that may only reveal the bug, not introduce it.
21-10-2025

Reduced it: java -XX:CompileCommand=compileonly,Reduced::test -XX:CompileCommand=printcompilation,Reduced::test -Xbatch -XX:+TraceLoopOpts -XX:+TraceSuperWord Reduced.java The crash seems to be happening for this loop: 1007 CountedLoop === 1007 502 435 [[ 971 975 979 980 987 1006 1007 1127 829 833 425 749 498 ]] inner stride: 8 main of N1007 strip mined !orig=[848],[761],[503],[473],[364] !jvms: Reduced::test @ bci:19 (line 26)
21-10-2025