JDK-8202949 : Over-unrolled loop with negative stride is partially removed
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9,10,11
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2018-05-11
  • Updated: 2018-08-16
  • Resolved: 2018-05-25
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 11
11 b16Fixed
Related Reports
Relates :  
Relates :  
Description
During compilation C2 fails with 
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/scratch/opt/mach5/mesos/work_dir/slaves/9190d864-6621-4810-ba08-d8d8c75ba674-S395/frameworks/1735e8a2-a1db-478c-8104-60c8b0af87dd-0196/executors/b528528e-501d-44e6-b294-995b8b2b1881/runs/3f528bbf-2970-4319-80de-390e34a632b0/workspace/open/src/hotspot/share/opto/loopnode.cpp:4153), pid=8856, tid=8867
#  assert(false) failed: Bad graph detected in build_loop_late
#
# JRE version: Java(TM) SE Runtime Environment (11.0+7) (fastdebug build 11-ea+7)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 11-ea+7, compiled mode, compressed oops, g1 gc, linux-amd64)
# Core dump will be written. Default location: Core dumps may be processed with "/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e %P %I %h" (or dumping to /tmp/fuzzer.tmp.XWph5hV3Hg/core.8856)
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#

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

Command Line: -Xmx1G -Xcomp -Xbatch -XX:-TieredCompilation -XX:CompileOnly= Test

Host: slc16ijb, Intel Core Processor (Haswell, no TSX), 4 cores, 14G, Oracle Linux Server release 7.4
Time: Sun Apr 29 11:54:38 2018 PDT elapsed time: 7 seconds (0d 0h 0m 7s)

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

Current thread (0x00007f2fd0267000):  JavaThread "C2 CompilerThread0" daemon [_thread_in_native, id=8867, stack(0x00007f2fb8a08000,0x00007f2fb8b09000)]


Current CompileTask:
C2:   7487 1368    b        Test::vMeth1 (325 bytes)

Stack: [0x00007f2fb8a08000,0x00007f2fb8b09000],  sp=0x00007f2fb8b03330,  free space=1004k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x180fd12]  VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x162
V  [libjvm.so+0x1810baf]  VMError::report_and_die(Thread*, char const*, int, char const*, char const*, __va_list_tag*)+0x2f
V  [libjvm.so+0xb28abd]  report_vm_error(char const*, int, char const*, char const*, ...)+0xdd
V  [libjvm.so+0x1260095]  PhaseIdealLoop::build_loop_late_post(Node*)+0x285
V  [libjvm.so+0x126062b]  PhaseIdealLoop::build_loop_late(VectorSet&, Node_List&, Node_Stack&)+0x10b
V  [libjvm.so+0x1264da4]  PhaseIdealLoop::build_and_optimize(bool, bool)+0x904
V  [libjvm.so+0xa8df29]  Compile::Optimize()+0xcd9
V  [libjvm.so+0xa8f4ee]  Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool, DirectiveSet*)+0x124e
V  [libjvm.so+0x8b27d2]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, DirectiveSet*)+0x2e2
V  [libjvm.so+0xa99d48]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x3b8
V  [libjvm.so+0xa9a9d1]  CompileBroker::compiler_thread_loop()+0x281
V  [libjvm.so+0x17635f2]  JavaThread::thread_main_inner()+0x242
V  [libjvm.so+0x17637f4]  JavaThread::run()+0x144
V  [libjvm.so+0x1495212]  thread_native_entry(Thread*)+0x112


Comments
EDIT: It's basically the same problem I've already fixed with JDK-8159016 [1] some time ago but my fix is incomplete because it does not work for loops with negative stride. What happens is that the inner for-loop is unrolled 4 times because we fail to determine the constant lower and upper bound (6,8] when computing the trip count. After unrolling, the range check dependent CastII/ConvI2L emitted for the iArr access become TOP because index 'j' is out of these bounds. As a result, the memory graph is corrupted with nodes consuming memory from a non-dominating (dead) region. The fix is to handle a negative stride: http://cr.openjdk.java.net/~thartmann/8202949/webrev.01/
24-05-2018

Attached simplified version of the test (SimpleTest.java).
18-05-2018

The bug is hidden by switch profiling that was introduced in JDK 11 b11 (JDK-8200303). I can reproduce the crash with the lastest jdk/jdk build and java -Xcomp -XX:+UnlockExperimentalVMOptions -XX:-UseSwitchProfiling Test
18-05-2018

I can only reproduce this with JDK 10.0+46 (I've attached the replay_pid11831.log).
11-05-2018

ILW = Crash during compilation in C2 loopopts, with javafuzzer test, disable compilation of affected method = HMM = P2
11-05-2018

To reproduce run: export JAVA_HOME=<fastdebug> build $JAVA_HOME/bin/javac Test.java $JAVA_HOME/bin/java -Xcomp -Xbatch -XX:CompileOnly=Test -XX:-TieredCompilation Test
11-05-2018