JDK-8205033 : [REDO] Induction variable of over-unrolled loop conflicts with range checks
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9,10,11
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2018-06-14
  • Updated: 2019-09-13
  • Resolved: 2018-06-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 11
11 b19Fixed
Related Reports
Cloners :  
Relates :  
Relates :  
Sub Tasks
JDK-8205034 :  
Description
When running the h2 DaCapo benchmark with -XX:-TieredCompilation -Xcomp, it complains that the AD file is "bad", like this:

Default case invoked for: 
   opcode  = 101, "Con"
o1      Con     === o0  [[]]  #top

--N: o1 Con     === o0  [[]]  #top


Failure modes:

#  Internal Error (/oracle/jdk_jdk/open/src/hotspot/share/opto/loopnode.cpp:3806), pid=19752, tid=19761
#  assert(!had_error) failed: bad dominance

Current CompileTask:
C2:  14351 3470    b        compiler.loopopts.TestOverunrolling::test3 (89 bytes)

Stack: [0x00007f15d14f6000,0x00007f15d15f7000],  sp=0x00007f15d15f10c0,  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+0x19c0d1c]  VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x18c
V  [libjvm.so+0x19c1caf]  VMError::report_and_die(Thread*, void*, char const*, int, char const*, char const*, __va_list_tag*)+0x2f
V  [libjvm.so+0xbbcffa]  report_vm_error(char const*, int, char const*, char const*, ...)+0x12a
V  [libjvm.so+0x13a2a37]  PhaseIdealLoop::compute_lca_of_uses(Node*, Node*, bool)+0x3d7
V  [libjvm.so+0x13a30e0]  PhaseIdealLoop::build_loop_late_post(Node*)+0x140
V  [libjvm.so+0x13a3823]  PhaseIdealLoop::build_loop_late(VectorSet&, Node_List&, Node_Stack&)+0x113
V  [libjvm.so+0x13a7e54]  PhaseIdealLoop::build_and_optimize(bool, bool)+0x934
V  [libjvm.so+0xb15aa7]  Compile::Optimize()+0xf07
V  [libjvm.so+0xb17130]  Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool, DirectiveSet*)+0x1380
V  [libjvm.so+0x8f7532]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, DirectiveSet*)+0x302
V  [libjvm.so+0xb248a0]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x3c0
V  [libjvm.so+0xb25589]  CompileBroker::compiler_thread_loop()+0x269
V  [libjvm.so+0x1902f67]  JavaThread::thread_main_inner()+0x287
V  [libjvm.so+0x19031c1]  JavaThread::run()+0x191
V  [libjvm.so+0x15f7f4a]  thread_native_entry(Thread*)+0xfa


#  Internal Error (/oracle/jdk_jdk/open/src/hotspot/share/opto/matcher.cpp:1575), pid=24470, tid=24479
#  assert(false) failed: bad AD file

Current CompileTask:
C2:  14689 3471    b        compiler.loopopts.TestOverunrolling::test5 (56 bytes)

Stack: [0x00007f93b01bd000,0x00007f93b02be000],  sp=0x00007f93b02b8bf0,  free space=1006k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x19c0d1c]  VMError::report_and_die(int, char const*, char const*, __va_list_tag*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x18c
V  [libjvm.so+0x19c1caf]  VMError::report_and_die(Thread*, void*, char const*, int, char const*, char const*, __va_list_tag*)+0x2f
V  [libjvm.so+0xbbcffa]  report_vm_error(char const*, int, char const*, char const*, ...)+0x12a
V  [libjvm.so+0x1484587]  Matcher::Label_Root(Node const*, State*, Node*, Node const*)+0x717
V  [libjvm.so+0x148412e]  Matcher::Label_Root(Node const*, State*, Node*, Node const*)+0x2be
V  [libjvm.so+0x14847a6]  Matcher::match_tree(Node const*)+0x1b6
V  [libjvm.so+0x1487428]  Matcher::xform(Node*, int)+0xb78
V  [libjvm.so+0x148b894]  Matcher::match()+0xfb4
V  [libjvm.so+0xb12433]  Compile::Code_Gen()+0xc3
V  [libjvm.so+0xb171f1]  Compile::Compile(ciEnv*, C2Compiler*, ciMethod*, int, bool, bool, bool, DirectiveSet*)+0x1441
V  [libjvm.so+0x8f7532]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, DirectiveSet*)+0x302
V  [libjvm.so+0xb248a0]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0x3c0
V  [libjvm.so+0xb25589]  CompileBroker::compiler_thread_loop()+0x269
V  [libjvm.so+0x1902f67]  JavaThread::thread_main_inner()+0x287
V  [libjvm.so+0x19031c1]  JavaThread::run()+0x191
V  [libjvm.so+0x15f7f4a]  thread_native_entry(Thread*)+0xfa
Comments
My initial patch for JDK-8203915 [1] failed because the computation of the value of the loop induction variable at the end of the first iteration of the unrolled loop was wrong. As a result, the predicate was incorrectly found to always fail and we hit a HaltNode (SIGILL) in compiled code. The problem is very easy to reproduce with the jdk/sun/security/tools/keytool/ tests, I therefore did not add an additional regression test. The problematic loop looks like this: for (int i = 20; i > 0; i -= 4) { array[i-1] = ... array[i-2] = ... array[i-3] = ... array[i-4] = ... } To make sure that the last array access is in bounds, we add a skeleton predicate of the form max_i - 4 = (init + stride + 1) - 4 <u array.length before the main loop and update the stride during unrolling. After unrolling 4 times, we know that init <= 16 (because the pre-loop is executed at least once) and the stride is 4*-4 = -16. The predicate is updated to: ( (int,16] - 16 + 1) - 4 = (int,-3] <u array.length which is always false. The computation of max_i is incorrect because the (fully) unrolled loop looks like this: // i <= 16 array[i-1] = ... array[i-2] = ... array[i-3] = ... array[i-4] = ... i -= 4; array[i-1] = ... array[i-2] = ... array[i-3] = ... array[i-4] = ... i -= 4; array[i-1] = ... array[i-2] = ... array[i-3] = ... array[i-4] = ... i -= 4; array[i-1] = ... array[i-2] = ... array[i-3] = ... array[i-4] = ... // i <= 4 And therefore the value of i at the end of the iteration is max_i = init + stride - init_inc (where 'init_inc' is the initial loop increment). The correct predicate looks like this: max_i - 4 = (init + stride - init_inc) - 4 = (16 - 16 + 4) -4 = 0 <u array.length Incremental changes: http://cr.openjdk.java.net/~thartmann/8205033/webrev.inc/ Full webrev: http://cr.openjdk.java.net/~thartmann/8205033/webrev.00/
15-06-2018

The original fix causes SIGILL failures in jdk tier2 testing. This is probably because the skeleton predicate is not removed and always fails.
14-06-2018

ILW = same as JDK-8203915 = P2
14-06-2018