JDK-8269820 : C2 PhaseIdealLoop::do_unroll get wrong opaque node
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 11,15,16,17,18,20,21
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2021-07-02
  • Updated: 2024-01-16
  • Resolved: 2022-12-07
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 20
20 b27Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Following test crashes in release & debug build

    static void test() {
        int ina8[] = new int[1478];
        int in2 = 136;
        long lo3 = 0L;
        try {
            for (int i = 0; i < 34; i++) {
                Math.log1p(1);
            }
        } catch (Exception e) {
            in2 = 1;
        }

        for (int i = 0; i < in2; i++) {
            if (in2 > 10) {  // split if and create wrong opaque order
                for (int j = 0; j < in2; j++) {
                    lo3 -= 1L;
                }
            }
        }
    }



Release build
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00002afb35bd70bc, pid=5015, tid=5039
#
# JRE version: OpenJDK Runtime Environment (17.0) (build 17-internal+0-adhoc.shihui.jdk17)
# Java VM: OpenJDK 64-Bit Server VM (17-internal+0-adhoc.shihui.jdk17, mixed mode, sharing, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0xc980bc]  Node::set_req_X(unsigned int, Node*, PhaseIterGVN*)+0x4c
Current CompileTask:
C2:     57    7   !b        compiler.loopopts.TestCanonicalLoopEntryOpaqueOrder::test (81 bytes)

Stack: [0x00002afb68404000,0x00002afb68505000],  sp=0x00002afb684ffca0,  free space=1007k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0xc980bc]  Node::set_req_X(unsigned int, Node*, PhaseIterGVN*)+0x4c
V  [libjvm.so+0xacabf3]  PhaseIdealLoop::do_unroll(IdealLoopTree*, Node_List&, bool)+0x903
V  [libjvm.so+0xacf218]  IdealLoopTree::iteration_split_impl(PhaseIdealLoop*, Node_List&)+0x508
V  [libjvm.so+0xacf534]  IdealLoopTree::iteration_split(PhaseIdealLoop*, Node_List&)+0x174
V  [libjvm.so+0xacf4a4]  IdealLoopTree::iteration_split(PhaseIdealLoop*, Node_List&)+0xe4
V  [libjvm.so+0xacf4a4]  IdealLoopTree::iteration_split(PhaseIdealLoop*, Node_List&)+0xe4
V  [libjvm.so+0xae3055]  PhaseIdealLoop::build_and_optimize(LoopOptsMode)+0x9e5
V  [libjvm.so+0x5e07c9]  PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)+0x179
V  [libjvm.so+0x5df0d2]  Compile::Optimize()+0x13b2
V  [libjvm.so+0x5dff9e]  Compile::Compile(ciEnv*, ciMethod*, int, bool, bool, bool, bool, bool, DirectiveSet*)+0xdde
V  [libjvm.so+0x5118da]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0xba
V  [libjvm.so+0x5e9ff4]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0xee4
V  [libjvm.so+0x5ead18]  CompileBroker::compiler_thread_loop()+0x4c8
V  [libjvm.so+0xf10980]  JavaThread::thread_main_inner()+0x180
V  [libjvm.so+0xf13ec2]  Thread::call_run()+0xe2
V  [libjvm.so+0xc4d181]  thread_native_entry(Thread*)+0xe1

debug build
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/data/shihui/codes/jdk17/src/hotspot/share/opto/loopTransform.cpp:1994), pid=16191, tid=16207
#  Error: assert(opaq->outcnt() == 1 && opaq->in(1) == limit) failed
#
# JRE version: OpenJDK Runtime Environment (17.0) (fastdebug build 17-internal+0-adhoc.shihui.jdk17)
# Java VM: OpenJDK 64-Bit Server VM (fastdebug 17-internal+0-adhoc.shihui.jdk17, mixed mode, sharing, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x114d301]  PhaseIdealLoop::do_unroll(IdealLoopTree*, Node_List&, bool)+0xb41
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp

Comments
Changeset: 86270e30 Author: Roland Westrelin <roland@openjdk.org> Date: 2022-12-07 14:16:50 +0000 URL: https://git.openjdk.org/jdk/commit/86270e3068d3b2e80710227ae2dc79719df35788
07-12-2022

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/11391 Date: 2022-11-28 14:02:50 +0000
28-11-2022

Updated ILW = Crash/assert during compilation (old issue), reproducible with single test, disable split if or compilation of affected method = HLM = P3
17-11-2022

Roland agreed to take this over. He already proposed a fix in https://github.com/openjdk/jdk17/pull/208#issuecomment-878257990.
14-11-2022

Note, this is related to StripMining. Before JDK-8281322 changes which always construct outer loop the test passed with Parallel GC which did not use StripMining.
25-10-2022

Still reproduced with latest JDK: java -XX:-CreateCoredumpOnCrash -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+PrintCompilation -XX:+TraceLoopOpts -XX:+UseG1GC TestCanonicalLoopEntryOpaqueOrder # Internal Error /jdk_git/open/src/hotspot/share/opto/loopnode.cpp:5460), pid=1398714, tid=1398727 # assert(found_opaque == res) failed: wrong pattern # # JRE version: Java(TM) SE Runtime Environment (20.0) (fastdebug build 20-internal-2022-10-25-1631070.vkozlov...) # Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 20-internal-2022-10-25-1631070.vkozlov..., mixed mode, sharing, compressed oops, compressed class ptrs, g1 gc, linux-amd64) # Problematic frame: # V [libjvm.so+0x1494115] CountedLoopNode::is_canonical_loop_entry()+0x1e5 #
25-10-2022

Here's the failing stack trace from the jdk-20+15-1019-tier3 sighting: compiler/loopopts/superword/ProdRed_Float.java --------------- T H R E A D --------------- Current thread (0x000002b99e9298e0): JavaThread "C2 CompilerThread1" daemon [_thread_in_native, id=64288, stack(0x000000f7ce500000,0x000000f7ce600000)] Current CompileTask: C2: 862 277 java.net.URI$Parser::parse (243 bytes) Stack: [0x000000f7ce500000,0x000000f7ce600000] Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) V [jvm.dll+0xc0ef11] os::win32::platform_print_native_stack+0xf1 (os_windows_x86.cpp:236) V [jvm.dll+0xe721fe] VMError::report+0x10be (vmError.cpp:841) V [jvm.dll+0xe73d0e] VMError::report_and_die+0x65e (vmError.cpp:1700) V [jvm.dll+0xe74494] VMError::report_and_die+0x64 (vmError.cpp:1481) V [jvm.dll+0x582e37] report_vm_error+0xb7 (debug.cpp:285) V [jvm.dll+0xa88190] PhaseIdealLoop::do_unroll+0x4c0 (loopTransform.cpp:2226) V [jvm.dll+0xa8f321] IdealLoopTree::iteration_split_impl+0x7c1 (loopTransform.cpp:3913) V [jvm.dll+0xa8ea20] IdealLoopTree::iteration_split+0x160 (loopTransform.cpp:3937) V [jvm.dll+0xa8e8ef] IdealLoopTree::iteration_split+0x2f (loopTransform.cpp:3921) V [jvm.dll+0xa8eb40] IdealLoopTree::iteration_split+0x280 (loopTransform.cpp:3953) V [jvm.dll+0xa8eb40] IdealLoopTree::iteration_split+0x280 (loopTransform.cpp:3953) V [jvm.dll+0xa8eb40] IdealLoopTree::iteration_split+0x280 (loopTransform.cpp:3953) V [jvm.dll+0xa8eb40] IdealLoopTree::iteration_split+0x280 (loopTransform.cpp:3953) V [jvm.dll+0xa8eb40] IdealLoopTree::iteration_split+0x280 (loopTransform.cpp:3953) V [jvm.dll+0xa8eb40] IdealLoopTree::iteration_split+0x280 (loopTransform.cpp:3953) V [jvm.dll+0xa9cdf1] PhaseIdealLoop::build_and_optimize+0x1131 (loopnode.cpp:4531) V [jvm.dll+0x5182da] Compile::Optimize+0x10da (compile.cpp:2407) V [jvm.dll+0x5150fd] Compile::Compile+0x14ad (compile.cpp:824) V [jvm.dll+0x43b045] C2Compiler::compile_method+0x145 (c2compiler.cpp:116) V [jvm.dll+0x52ebe6] CompileBroker::invoke_compiler_on_method+0x8a6 (compileBroker.cpp:2246) V [jvm.dll+0x52c33d] CompileBroker::compiler_thread_loop+0x23d (compileBroker.cpp:1918) V [jvm.dll+0x7f9f4b] JavaThread::thread_main_inner+0x2ab (javaThread.cpp:701) V [jvm.dll+0xdeb997] Thread::call_run+0x257 (thread.cpp:229) V [jvm.dll+0xc0d858] thread_native_entry+0xb8 (os_windows.cpp:547) C [ucrtbase.dll+0x1fb80] C [KERNEL32.DLL+0x84d4] C [ntdll.dll+0x51791]
14-09-2022

Defer request. Not new regression in JDK 19 - old releases affected too.
02-08-2022

This crash is showing up in the CI testing for JDK 19. compiler/loopopts/superword/RedTest_long.java
11-05-2022

Defer request. Not new regression in JDK 18 - old releases affected too. No other reports seen. Will be backported later in JDK 18u.
20-01-2022

Sure! Please gohead and fix it in JDK18. Change assign to kvn.
07-08-2021

I dived into the issue and it is complicated and requires time for more investigation. I decided to fix it first in JDK 18 and then backport into 17u.
03-08-2021

Hi [~hshi] do you plan to continue work on it for JDK 17? Less than 2 weeks left.
23-07-2021

After JDK-8269752 , fastdebug still crash, hs_err_pid7632.log is attached. # Internal Error (/data/shihui/codes/jdk17/src/hotspot/share/opto/loopnode.cpp:4960), pid=7632, tid=7649 # assert(found_opaque == res) failed: wrong pattern
19-07-2021

JDK-8269752 fixes releated code. In PhaseIdealLoop::is_canonical_loop_entry(CountedLoopNode* cl), Opaque1 node is getting from fixed input according to if loop is main loop.
19-07-2021

Hi [~hshi], just wanted to let you know that RDP 2 starts on Thursday. This means that you require an additional approval to fix it during that phase [1] if your review does not make it through by then. [1] https://openjdk.java.net/jeps/3#rdp-2
13-07-2021

ILW = HLH = P2
02-07-2021

``` if (!is_canonical_loop_entry(loop_head)) { return; } opaq = loop_head->skip_predicates()->in(0)->in(1)->in(1)->in(2); ``` In PhaseIdealLoop::is_canonical_loop_entry opaque node can be in any input of compare node, but when after is_canonical_loop_entry check, opaq node is getting only from compare node's in(2). This is conflict code. Opque node is expected at compare node's in(2) because 1. In PhaseIdealLoop::insert_pre_post_loops, when insert pre loop, Build a zero-trip guard for the main-loop. - create cmp, opaq holds limit at cmp's in(2) node. 2. In BoolNode::Ideal, it will not switch compare node's in(2) if its type is Op_Opaque1 But this assumption is broken with following transformation. 1. PhaseIdealLoop::split_if_with_blocks clone cmp/bool - cloned cmp's in(1) is con - cloned cmp's in(2) is phi (region, Opaque1, Opaque1) 2. In BoolNode::Ideal, cmp's node is swapped as its firt is con and second is not Opaque1Node 3. After some transformation, phi node is transformed back to Opaque1Node, but now it's at compare node's in(1) Possbile fix could be getting Opaque1Node from compare node's either input.
02-07-2021