11/*
2- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2323
2424/**
2525 * @test
26- * @bug 8229855
26+ * @bug 8229855 8238812
2727 * @summary Test jump table with key value that gets out of bounds after loop unrolling.
2828 * @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test*
2929 * -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:-UseSwitchProfiling
3030 * compiler.c2.TestJumpTable
31+ * @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test*
32+ * -Xbatch -XX:-TieredCompilation -XX:-UseOnStackReplacement
33+ * compiler.c2.TestJumpTable
34+ * @run main/othervm -XX:CompileCommand=dontinline,compiler.c2.TestJumpTable::test*
35+ * -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:+StressIGVN
36+ * compiler.c2.TestJumpTable
3137 */
3238
3339package compiler .c2 ;
3440
3541public class TestJumpTable {
3642
37- public static int test () {
43+ public static int test0 () {
3844 int res = 0 ;
3945 for (int i = 10 ; i < 50 ; ++i ) {
4046 switch (i * 5 ) {
@@ -53,9 +59,195 @@ public static int test() {
5359 return res ;
5460 }
5561
62+ static int field ;
63+
64+ // Original (slightly simplified) fuzzer generated test
65+ public static void test1 () {
66+ int i4 , i5 = 99 , i6 , i9 = 89 ;
67+ for (i4 = 12 ; i4 < 365 ; i4 ++) {
68+ for (i6 = 5 ; i6 > 1 ; i6 --) {
69+ switch ((i6 * 5 ) + 11 ) {
70+ case 13 :
71+ case 19 :
72+ case 26 :
73+ case 31 :
74+ case 35 :
75+ case 41 :
76+ case 43 :
77+ case 61 :
78+ case 71 :
79+ case 83 :
80+ case 314 :
81+ i9 = i5 ;
82+ break ;
83+ }
84+ }
85+ }
86+ }
87+
88+ // This generates the following subgraph:
89+ /*
90+ // i: -10..4
91+ if ((i+min_jint) u<= max_jint) { <- This is always true but not folded by C2
92+ ...
93+ } else {
94+ ...
95+ 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
96+ ...
97+ }
98+ */
99+ public static void test2 () {
100+ for (int i = 5 ; i > -10 ; i --) {
101+ switch (i ) {
102+ case 0 :
103+ case 4 :
104+ case 10 :
105+ case 20 :
106+ case 30 :
107+ case 40 :
108+ case 50 :
109+ case 100 :
110+ field = 42 ;
111+ break ;
112+ }
113+ }
114+ }
115+
116+ // This generates the following subgraph:
117+ /*
118+ // i: -20..0
119+ if (i != 0) {
120+ // i: -20..-1
121+ if (i < 0) { <- This is always true but not folded by C2
122+ // Fall through
123+ } else {
124+ ...
125+ 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
126+ ...
127+ }
128+ } else {
129+ StoreI <- Due to this additional store on, IfNode::has_shared_region returns false and the fold compares optimization does not kick in
130+ }
131+ */
132+ public static void test3 () {
133+ for (int i = 5 ; i > -20 ; i -= 5 ) {
134+ switch (i ) {
135+ case 0 :
136+ case 10 :
137+ case 20 :
138+ case 30 :
139+ case 40 :
140+ case 50 :
141+ case 60 :
142+ case 100 :
143+ field = 42 ;
144+ break ;
145+ }
146+ }
147+ }
148+
149+ // This generates the following subgraph:
150+ /*
151+ // i: -20..0
152+ if (i != 0) {
153+ // i: -20..-1
154+ if (i u< 101) { <- This is always false but not folded by C2 because CmpU is not handled
155+ 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
156+ } else {
157+ ...
158+ }
159+ } else {
160+ ...
161+ }
162+ */
163+ public static void test4 () {
164+ int local = 0 ;
165+ for (int i = 5 ; i > -20 ; i -= 5 ) {
166+ switch (i ) {
167+ case 0 :
168+ case 10 :
169+ case 20 :
170+ case 30 :
171+ case 40 :
172+ case 50 :
173+ case 100 :
174+ local = 42 ;
175+ break ;
176+ }
177+ }
178+ }
179+
180+ // This generates the following subgraph:
181+ /*
182+ // i: 0..20
183+ if (i != 20) {
184+ // i: 0..19
185+ if ((i-20) u< 281) { <- This is always false but not folded by C2 because the two ifs compare different values
186+ 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
187+ } else {
188+ ...
189+ }
190+ } else {
191+ ...
192+ }
193+ */
194+ public static void test5 () {
195+ int local ;
196+ for (int i = 25 ; i > 0 ; i -= 5 ) {
197+ switch (i ) {
198+ case 20 :
199+ case 30 :
200+ case 40 :
201+ case 50 :
202+ case 60 :
203+ case 70 :
204+ case 300 :
205+ local = 42 ;
206+ break ;
207+ }
208+ }
209+ }
210+
211+ // This generates the following subgraph:
212+ /*
213+ // i: 0..20
214+ if ((i+10) != 30) {
215+ // i: 0..19
216+ if ((i-20) u< 271) { <- This is always false but not folded by C2 because the two ifs compare different values
217+ 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
218+ } else {
219+ ...
220+ }
221+ } else {
222+ ...
223+ }
224+ */
225+ public static void test6 () {
226+ int local ;
227+ for (int i = 25 ; i > 0 ; i -= 5 ) {
228+ switch (i + 10 ) {
229+ case 30 :
230+ case 40 :
231+ case 50 :
232+ case 60 :
233+ case 70 :
234+ case 80 :
235+ case 300 :
236+ local = 42 ;
237+ break ;
238+ }
239+ }
240+ }
241+
56242 public static void main (String [] args ) {
57- for (int i = 0 ; i < 20_000 ; ++i ) {
58- test ();
243+ for (int i = 0 ; i < 50_000 ; ++i ) {
244+ test0 ();
245+ test1 ();
246+ test2 ();
247+ test3 ();
248+ test4 ();
249+ test5 ();
250+ test6 ();
59251 }
60252 }
61253}
0 commit comments