@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,18 +23,24 @@
/**
* @test
* @bug 8229855
* @bug 8229855 8238812
* @summary Test jump table with key value that gets out of bounds after loop unrolling.
* @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test*
* -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:-UseSwitchProfiling
* compiler.c2.TestJumpTable
* @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test*
* -Xbatch -XX:-TieredCompilation -XX:-UseOnStackReplacement
* compiler.c2.TestJumpTable
* @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test*
* -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:+StressIGVN
* compiler.c2.TestJumpTable
*/
package compiler .c2 ;
public class TestJumpTable {
public static int test () {
public static int test0 () {
int res = 0 ;
for (int i = 10 ; i < 50 ; ++i ) {
switch (i * 5 ) {
@@ -53,9 +59,195 @@ public static int test() {
return res ;
}
static int field ;
// Original (slightly simplified) fuzzer generated test
public static void test1 () {
int i4 , i5 = 99 , i6 , i9 = 89 ;
for (i4 = 12 ; i4 < 365 ; i4 ++) {
for (i6 = 5 ; i6 > 1 ; i6 --) {
switch ((i6 * 5 ) + 11 ) {
case 13 :
case 19 :
case 26 :
case 31 :
case 35 :
case 41 :
case 43 :
case 61 :
case 71 :
case 83 :
case 314 :
i9 = i5 ;
break ;
}
}
}
}
// This generates the following subgraph:
/*
// i: -10..4
if ((i+min_jint) u<= max_jint) { <- This is always true but not folded by C2
...
} else {
...
CastII(i-5, 0..45) <- Replaced by TOP because i-5 range is -15..-1 but still considered reachable by C2 although it is dead code
...
}
*/
public static void test2 () {
for (int i = 5 ; i > -10 ; i --) {
switch (i ) {
case 0 :
case 4 :
case 10 :
case 20 :
case 30 :
case 40 :
case 50 :
case 100 :
field = 42 ;
break ;
}
}
}
// This generates the following subgraph:
/*
// i: -20..0
if (i != 0) {
// i: -20..-1
if (i < 0) { <- This is always true but not folded by C2
// Fall through
} else {
...
CastII(i-1, 0..4) <- Replaced by TOP because i-1 range is -21..-1 but still considered reachable by C2 although it is dead code
...
}
} else {
StoreI <- Due to this additional store on, IfNode::has_shared_region returns false and the fold compares optimization does not kick in
}
*/
public static void test3 () {
for (int i = 5 ; i > -20 ; i -= 5 ) {
switch (i ) {
case 0 :
case 10 :
case 20 :
case 30 :
case 40 :
case 50 :
case 60 :
case 100 :
field = 42 ;
break ;
}
}
}
// This generates the following subgraph:
/*
// i: -20..0
if (i != 0) {
// i: -20..-1
if (i u< 101) { <- This is always false but not folded by C2 because CmpU is not handled
CastII(i-1, 0..49) <- Replaced by TOP because i-1 range is -21..-1 but still considered reachable by C2 although it is dead code
} else {
...
}
} else {
...
}
*/
public static void test4 () {
int local = 0 ;
for (int i = 5 ; i > -20 ; i -= 5 ) {
switch (i ) {
case 0 :
case 10 :
case 20 :
case 30 :
case 40 :
case 50 :
case 100 :
local = 42 ;
break ;
}
}
}
// This generates the following subgraph:
/*
// i: 0..20
if (i != 20) {
// i: 0..19
if ((i-20) u< 281) { <- This is always false but not folded by C2 because the two ifs compare different values
CastII(i-21, 0..49) <- Replaced by TOP because i-21 range is -21..-1 but still considered reachable by C2 although it is dead code
} else {
...
}
} else {
...
}
*/
public static void test5 () {
int local ;
for (int i = 25 ; i > 0 ; i -= 5 ) {
switch (i ) {
case 20 :
case 30 :
case 40 :
case 50 :
case 60 :
case 70 :
case 300 :
local = 42 ;
break ;
}
}
}
// This generates the following subgraph:
/*
// i: 0..20
if ((i+10) != 30) {
// i: 0..19
if ((i-20) u< 271) { <- This is always false but not folded by C2 because the two ifs compare different values
CastII(i-21, 0..4) <- Replaced by TOP because i-21 range is -21..-1 but still considered reachable by C2 although it is dead code
} else {
...
}
} else {
...
}
*/
public static void test6 () {
int local ;
for (int i = 25 ; i > 0 ; i -= 5 ) {
switch (i + 10 ) {
case 30 :
case 40 :
case 50 :
case 60 :
case 70 :
case 80 :
case 300 :
local = 42 ;
break ;
}
}
}
public static void main (String [] args ) {
for (int i = 0 ; i < 20_000 ; ++i ) {
test ();
for (int i = 0 ; i < 50_000 ; ++i ) {
test0 ();
test1 ();
test2 ();
test3 ();
test4 ();
test5 ();
test6 ();
}
}
}