blob: 8db7338e40c27b3af3c5581339df7e71d192602e [file] [log] [blame]
Aart Bik22af3be2015-09-10 12:50:58 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//
18// Test on loop optimizations.
19//
20public class Main {
21
22 static int sResult;
23
24 //
Aart Bik9401f532015-09-28 16:25:56 -070025 // Various sequence variables used in bound checks.
Aart Bik22af3be2015-09-10 12:50:58 -070026 //
27
28 /// CHECK-START: int Main.linear(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080029 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080030 //
Aart Bik22af3be2015-09-10 12:50:58 -070031 /// CHECK-START: int Main.linear(int[]) BCE (after)
32 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080033 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070034 private static int linear(int[] x) {
35 int result = 0;
36 for (int i = 0; i < x.length; i++) {
37 result += x[i];
38 }
39 return result;
40 }
41
42 /// CHECK-START: int Main.linearDown(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080043 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080044 //
Aart Bik22af3be2015-09-10 12:50:58 -070045 /// CHECK-START: int Main.linearDown(int[]) BCE (after)
46 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080047 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070048 private static int linearDown(int[] x) {
49 int result = 0;
50 for (int i = x.length - 1; i >= 0; i--) {
51 result += x[i];
52 }
53 return result;
54 }
55
56 /// CHECK-START: int Main.linearObscure(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080057 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080058 //
Aart Bik22af3be2015-09-10 12:50:58 -070059 /// CHECK-START: int Main.linearObscure(int[]) BCE (after)
60 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080061 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070062 private static int linearObscure(int[] x) {
63 int result = 0;
64 for (int i = x.length - 1; i >= 0; i--) {
65 int k = i + 5;
66 result += x[k - 5];
67 }
68 return result;
69 }
70
Aart Bikf475bee2015-09-16 12:50:25 -070071 /// CHECK-START: int Main.linearVeryObscure(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080072 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080073 //
Aart Bikf475bee2015-09-16 12:50:25 -070074 /// CHECK-START: int Main.linearVeryObscure(int[]) BCE (after)
75 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080076 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -070077 private static int linearVeryObscure(int[] x) {
78 int result = 0;
79 for (int i = 0; i < x.length; i++) {
80 int k = (-i) + (i << 5) + i - (32 * i) + 5 + (int) i;
81 result += x[k - 5];
82 }
83 return result;
84 }
85
Aart Bik7d57d7f2015-12-09 14:39:48 -080086 /// CHECK-START: int Main.hiddenStride(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080087 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080088 //
89 /// CHECK-START: int Main.hiddenStride(int[]) BCE (after)
90 /// CHECK-NOT: BoundsCheck
91 /// CHECK-NOT: Deoptimize
92 static int hiddenStride(int[] a) {
93 int result = 0;
94 for (int i = 1; i <= 1; i++) {
95 // Obscured unit stride.
96 for (int j = 0; j < a.length; j += i) {
97 result += a[j];
98 }
99 }
100 return result;
101 }
102
Aart Bik22af3be2015-09-10 12:50:58 -0700103 /// CHECK-START: int Main.linearWhile(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800104 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800105 //
Aart Bik22af3be2015-09-10 12:50:58 -0700106 /// CHECK-START: int Main.linearWhile(int[]) BCE (after)
107 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800108 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700109 private static int linearWhile(int[] x) {
110 int i = 0;
111 int result = 0;
112 while (i < x.length) {
113 result += x[i++];
114 }
115 return result;
116 }
117
Aart Bikf475bee2015-09-16 12:50:25 -0700118 /// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800119 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800120 //
Aart Bikf475bee2015-09-16 12:50:25 -0700121 /// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (after)
122 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800123 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700124 private static int linearThreeWayPhi(int[] x) {
125 int result = 0;
126 for (int i = 0; i < x.length; ) {
127 if (x[i] == 5) {
128 i++;
129 continue;
130 }
131 result += x[i++];
132 }
133 return result;
134 }
135
136 /// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800137 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800138 //
Aart Bikf475bee2015-09-16 12:50:25 -0700139 /// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (after)
140 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800141 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700142 private static int linearFourWayPhi(int[] x) {
143 int result = 0;
144 for (int i = 0; i < x.length; ) {
145 if (x[i] == 5) {
146 i++;
147 continue;
148 } else if (x[i] == 6) {
149 i++;
150 result += 7;
151 continue;
152 }
153 result += x[i++];
154 }
155 return result;
156 }
157
Aart Bik22af3be2015-09-10 12:50:58 -0700158 /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800159 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800160 //
Aart Bik22af3be2015-09-10 12:50:58 -0700161 /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (after)
162 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800163 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700164 private static int wrapAroundThenLinear(int[] x) {
165 // Loop with wrap around (length - 1, 0, 1, 2, ..).
166 int w = x.length - 1;
167 int result = 0;
168 for (int i = 0; i < x.length; i++) {
169 result += x[w];
170 w = i;
171 }
172 return result;
173 }
174
Aart Bikf475bee2015-09-16 12:50:25 -0700175 /// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800176 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800177 //
Aart Bikf475bee2015-09-16 12:50:25 -0700178 /// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (after)
179 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800180 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700181 private static int wrapAroundThenLinearThreeWayPhi(int[] x) {
182 // Loop with wrap around (length - 1, 0, 1, 2, ..).
183 int w = x.length - 1;
184 int result = 0;
185 for (int i = 0; i < x.length; ) {
186 if (x[w] == 1) {
187 w = i++;
188 continue;
189 }
190 result += x[w];
191 w = i++;
192 }
193 return result;
194 }
195
Aart Bik22af3be2015-09-10 12:50:58 -0700196 /// CHECK-START: int[] Main.linearWithParameter(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800197 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800198 //
Aart Bik22af3be2015-09-10 12:50:58 -0700199 /// CHECK-START: int[] Main.linearWithParameter(int) BCE (after)
200 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800201 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700202 private static int[] linearWithParameter(int n) {
203 int[] x = new int[n];
204 for (int i = 0; i < n; i++) {
205 x[i] = i;
206 }
207 return x;
208 }
209
Aart Bikf475bee2015-09-16 12:50:25 -0700210 /// CHECK-START: int[] Main.linearCopy(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800211 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800212 //
Aart Bikf475bee2015-09-16 12:50:25 -0700213 /// CHECK-START: int[] Main.linearCopy(int[]) BCE (after)
214 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800215 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700216 private static int[] linearCopy(int x[]) {
217 int n = x.length;
218 int y[] = new int[n];
219 for (int i = 0; i < n; i++) {
220 y[i] = x[i];
221 }
222 return y;
223 }
224
Aart Bik4a342772015-11-30 10:17:46 -0800225 /// CHECK-START: int Main.linearByTwo(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800226 /// CHECK-DAG: BoundsCheck
227 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800228 //
Aart Bik4a342772015-11-30 10:17:46 -0800229 /// CHECK-START: int Main.linearByTwo(int[]) BCE (after)
230 /// CHECK-NOT: BoundsCheck
231 /// CHECK-NOT: Deoptimize
232 private static int linearByTwo(int x[]) {
233 int n = x.length / 2;
234 int result = 0;
235 for (int i = 0; i < n; i++) {
236 int ii = i << 1;
237 result += x[ii];
238 result += x[ii + 1];
239 }
240 return result;
241 }
242
243 /// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800244 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800245 //
Aart Bik4a342772015-11-30 10:17:46 -0800246 /// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (after)
247 /// CHECK-NOT: BoundsCheck
248 /// CHECK-NOT: Deoptimize
249 private static int linearByTwoSkip1(int x[]) {
250 int result = 0;
251 for (int i = 0; i < x.length / 2; i++) {
252 result += x[2 * i];
253 }
254 return result;
255 }
256
257 /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800258 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800259 //
Aart Bik4a342772015-11-30 10:17:46 -0800260 /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800261 /// CHECK-DAG: BoundsCheck
262 //
263 /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800264 /// CHECK-NOT: Deoptimize
265 private static int linearByTwoSkip2(int x[]) {
266 int result = 0;
267 // This case is not optimized.
268 for (int i = 0; i < x.length; i+=2) {
269 result += x[i];
270 }
271 return result;
272 }
273
Aart Bik22af3be2015-09-10 12:50:58 -0700274 /// CHECK-START: int Main.linearWithCompoundStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800275 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800276 //
Aart Bik22af3be2015-09-10 12:50:58 -0700277 /// CHECK-START: int Main.linearWithCompoundStride() BCE (after)
278 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800279 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700280 private static int linearWithCompoundStride() {
281 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
282 int result = 0;
283 for (int i = 0; i <= 12; ) {
284 i++;
285 result += x[i];
286 i++;
287 }
288 return result;
289 }
290
291 /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800292 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800293 //
Aart Bik22af3be2015-09-10 12:50:58 -0700294 /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (after)
295 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800296 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700297 private static int linearWithLargePositiveStride() {
298 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
299 int result = 0;
300 int k = 0;
301 // Range analysis has no problem with a trip-count defined by a
Aart Bikf475bee2015-09-16 12:50:25 -0700302 // reasonably large positive stride far away from upper bound.
Aart Bik22af3be2015-09-10 12:50:58 -0700303 for (int i = 1; i <= 10 * 10000000 + 1; i += 10000000) {
304 result += x[k++];
305 }
306 return result;
307 }
308
309 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800310 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800311 //
Aart Bik22af3be2015-09-10 12:50:58 -0700312 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800313 /// CHECK-DAG: BoundsCheck
314 //
315 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800316 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700317 private static int linearWithVeryLargePositiveStride() {
318 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
319 int result = 0;
320 int k = 0;
321 // Range analysis conservatively bails due to potential of wrap-around
322 // arithmetic while computing the trip-count for this very large stride.
Aart Bikf475bee2015-09-16 12:50:25 -0700323 for (int i = 1; i < Integer.MAX_VALUE; i += 195225786) {
Aart Bik22af3be2015-09-10 12:50:58 -0700324 result += x[k++];
325 }
326 return result;
327 }
328
329 /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800330 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800331 //
Aart Bik22af3be2015-09-10 12:50:58 -0700332 /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (after)
333 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800334 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700335 private static int linearWithLargeNegativeStride() {
336 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
337 int result = 0;
338 int k = 0;
339 // Range analysis has no problem with a trip-count defined by a
Aart Bikf475bee2015-09-16 12:50:25 -0700340 // reasonably large negative stride far away from lower bound.
Aart Bik22af3be2015-09-10 12:50:58 -0700341 for (int i = -1; i >= -10 * 10000000 - 1; i -= 10000000) {
342 result += x[k++];
343 }
344 return result;
345 }
346
347 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800348 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800349 //
Aart Bik22af3be2015-09-10 12:50:58 -0700350 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800351 /// CHECK-DAG: BoundsCheck
352 //
353 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800354 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700355 private static int linearWithVeryLargeNegativeStride() {
356 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
357 int result = 0;
358 int k = 0;
359 // Range analysis conservatively bails due to potential of wrap-around
360 // arithmetic while computing the trip-count for this very large stride.
Aart Bikf475bee2015-09-16 12:50:25 -0700361 for (int i = -2; i > Integer.MIN_VALUE; i -= 195225786) {
Aart Bik22af3be2015-09-10 12:50:58 -0700362 result += x[k++];
363 }
364 return result;
365 }
366
Aart Bik9401f532015-09-28 16:25:56 -0700367 /// CHECK-START: int Main.linearForNEUp() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800368 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800369 //
Aart Bik9401f532015-09-28 16:25:56 -0700370 /// CHECK-START: int Main.linearForNEUp() BCE (after)
Aart Bikf475bee2015-09-16 12:50:25 -0700371 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800372 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700373 private static int linearForNEUp() {
Aart Bikf475bee2015-09-16 12:50:25 -0700374 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
375 int result = 0;
376 for (int i = 0; i != 10; i++) {
377 result += x[i];
378 }
379 return result;
380 }
381
Aart Bik9401f532015-09-28 16:25:56 -0700382 /// CHECK-START: int Main.linearForNEDown() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800383 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800384 //
Aart Bik9401f532015-09-28 16:25:56 -0700385 /// CHECK-START: int Main.linearForNEDown() BCE (after)
386 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800387 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700388 private static int linearForNEDown() {
389 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
390 int result = 0;
391 for (int i = 9; i != -1; i--) {
392 result += x[i];
393 }
394 return result;
395 }
396
Aart Bik358af832016-02-24 14:17:53 -0800397 /// CHECK-START: int Main.linearForNEArrayLengthUp(int[]) BCE (before)
398 /// CHECK-DAG: BoundsCheck
399 //
400 /// CHECK-START: int Main.linearForNEArrayLengthUp(int[]) BCE (after)
401 /// CHECK-NOT: BoundsCheck
402 /// CHECK-NOT: Deoptimize
403 private static int linearForNEArrayLengthUp(int[] x) {
404 int result = 0;
405 for (int i = 0; i != x.length; i++) {
406 result += x[i];
407 }
408 return result;
409 }
410
411 /// CHECK-START: int Main.linearForNEArrayLengthDown(int[]) BCE (before)
412 /// CHECK-DAG: BoundsCheck
413 //
414 /// CHECK-START: int Main.linearForNEArrayLengthDown(int[]) BCE (after)
415 /// CHECK-NOT: BoundsCheck
416 /// CHECK-NOT: Deoptimize
417 private static int linearForNEArrayLengthDown(int[] x) {
418 int result = 0;
419 for (int i = x.length - 1; i != -1; i--) {
420 result += x[i];
421 }
422 return result;
423 }
424
Aart Bik9401f532015-09-28 16:25:56 -0700425 /// CHECK-START: int Main.linearDoWhileUp() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800426 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800427 //
Aart Bik9401f532015-09-28 16:25:56 -0700428 /// CHECK-START: int Main.linearDoWhileUp() BCE (after)
429 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800430 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700431 private static int linearDoWhileUp() {
Aart Bikf475bee2015-09-16 12:50:25 -0700432 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
433 int result = 0;
434 int i = 0;
Aart Bikf475bee2015-09-16 12:50:25 -0700435 do {
436 result += x[i++];
437 } while (i < 10);
438 return result;
439 }
440
Aart Bik9401f532015-09-28 16:25:56 -0700441 /// CHECK-START: int Main.linearDoWhileDown() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800442 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800443 //
Aart Bik9401f532015-09-28 16:25:56 -0700444 /// CHECK-START: int Main.linearDoWhileDown() BCE (after)
445 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800446 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700447 private static int linearDoWhileDown() {
448 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
449 int result = 0;
450 int i = 9;
451 do {
452 result += x[i--];
453 } while (0 <= i);
454 return result;
455 }
456
Aart Bikf475bee2015-09-16 12:50:25 -0700457 /// CHECK-START: int Main.linearShort() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800458 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800459 //
Aart Bikf475bee2015-09-16 12:50:25 -0700460 /// CHECK-START: int Main.linearShort() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800461 /// CHECK-DAG: BoundsCheck
462 //
463 /// CHECK-START: int Main.linearShort() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800464 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700465 private static int linearShort() {
466 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
467 int result = 0;
468 // TODO: make this work
469 for (short i = 0; i < 10; i++) {
470 result += x[i];
471 }
472 return result;
473 }
474
Aart Bik4a342772015-11-30 10:17:46 -0800475 /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800476 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800477 //
Aart Bik4a342772015-11-30 10:17:46 -0800478 /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (after)
479 /// CHECK-NOT: BoundsCheck
480 /// CHECK-NOT: Deoptimize
481 private static int invariantFromPreLoop(int[] x, int y) {
482 int result = 0;
483 // Strange pre-loop that sets upper bound.
484 int hi;
485 while (true) {
486 y = y % 3;
487 hi = x.length;
488 if (y != 123) break;
489 }
490 for (int i = 0; i < hi; i++) {
491 result += x[i];
492 }
493 return result;
494 }
495
Aart Bikb738d4f2015-12-03 11:23:35 -0800496 /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800497 /// CHECK-DAG: BoundsCheck
498 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800499 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800500 /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (after)
501 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800502 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
Aart Bikb738d4f2015-12-03 11:23:35 -0800503 private static void linearTriangularOnTwoArrayLengths(int n) {
504 int[] a = new int[n];
505 for (int i = 0; i < a.length; i++) {
506 int[] b = new int[i];
507 for (int j = 0; j < b.length; j++) {
508 // Need to know j < b.length < a.length for static bce.
509 a[j] += 1;
510 // Need to know just j < b.length for static bce.
511 b[j] += 1;
512 }
513 verifyTriangular(a, b, i, n);
514 }
515 }
516
517 /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800518 /// CHECK-DAG: BoundsCheck
519 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800520 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800521 /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (after)
522 /// CHECK-NOT: BoundsCheck
Aart Bikb738d4f2015-12-03 11:23:35 -0800523 /// CHECK-NOT: Deoptimize
524 private static void linearTriangularOnOneArrayLength(int n) {
525 int[] a = new int[n];
526 for (int i = 0; i < a.length; i++) {
527 int[] b = new int[i];
528 for (int j = 0; j < i; j++) {
529 // Need to know j < i < a.length for static bce.
530 a[j] += 1;
531 // Need to know just j < i for static bce.
532 b[j] += 1;
533 }
534 verifyTriangular(a, b, i, n);
535 }
536 }
537
538 /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800539 /// CHECK-DAG: BoundsCheck
540 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800541 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800542 /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (after)
543 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800544 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
Aart Bikb738d4f2015-12-03 11:23:35 -0800545 private static void linearTriangularOnParameter(int n) {
546 int[] a = new int[n];
547 for (int i = 0; i < n; i++) {
548 int[] b = new int[i];
549 for (int j = 0; j < i; j++) {
550 // Need to know j < i < n for static bce.
551 a[j] += 1;
552 // Need to know just j < i for static bce.
553 b[j] += 1;
554 }
555 verifyTriangular(a, b, i, n);
556 }
557 }
558
Aart Bik97412c922016-02-19 20:14:38 -0800559 /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800560 /// CHECK-DAG: BoundsCheck
561 /// CHECK-DAG: BoundsCheck
562 /// CHECK-DAG: BoundsCheck
563 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800564 //
Aart Bik97412c922016-02-19 20:14:38 -0800565 /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (after)
Aart Bik7d57d7f2015-12-09 14:39:48 -0800566 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800567 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
568 private static void linearTriangularVariationsInnerStrict(int n) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800569 int[] a = new int[n];
570 for (int i = 0; i < n; i++) {
571 for (int j = 0; j < i; j++) {
572 a[j] += 1;
573 }
Aart Bik97412c922016-02-19 20:14:38 -0800574 for (int j = i - 1; j > -1; j--) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800575 a[j] += 1;
576 }
577 for (int j = i; j < n; j++) {
578 a[j] += 1;
579 }
580 for (int j = n - 1; j > i - 1; j--) {
581 a[j] += 1;
582 }
583 }
584 verifyTriangular(a);
585 }
586
Aart Bik97412c922016-02-19 20:14:38 -0800587 /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (before)
588 /// CHECK-DAG: BoundsCheck
589 /// CHECK-DAG: BoundsCheck
590 /// CHECK-DAG: BoundsCheck
591 /// CHECK-DAG: BoundsCheck
592 //
593 /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (after)
594 /// CHECK-NOT: BoundsCheck
595 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
596 private static void linearTriangularVariationsInnerNonStrict(int n) {
597 int[] a = new int[n];
598 for (int i = 0; i < n; i++) {
599 for (int j = 0; j <= i - 1; j++) {
600 a[j] += 1;
601 }
602 for (int j = i - 1; j >= 0; j--) {
603 a[j] += 1;
604 }
605 for (int j = i; j <= n - 1; j++) {
606 a[j] += 1;
607 }
608 for (int j = n - 1; j >= i; j--) {
609 a[j] += 1;
610 }
611 }
612 verifyTriangular(a);
613 }
614
Aart Bik7d57d7f2015-12-09 14:39:48 -0800615 // Verifier for triangular loops.
Aart Bikb738d4f2015-12-03 11:23:35 -0800616 private static void verifyTriangular(int[] a, int[] b, int m, int n) {
617 expectEquals(n, a.length);
618 for (int i = 0, k = m; i < n; i++) {
619 expectEquals(a[i], k);
620 if (k > 0) k--;
621 }
622 expectEquals(m, b.length);
623 for (int i = 0; i < m; i++) {
624 expectEquals(b[i], 1);
625 }
626 }
627
Aart Bik7d57d7f2015-12-09 14:39:48 -0800628 // Verifier for triangular loops.
629 private static void verifyTriangular(int[] a) {
630 int n = a.length;
631 for (int i = 0; i < n; i++) {
632 expectEquals(a[i], n + n);
633 }
634 }
635
Aart Bikb738d4f2015-12-03 11:23:35 -0800636 /// CHECK-START: void Main.bubble(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800637 /// CHECK-DAG: BoundsCheck
638 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800639 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800640 /// CHECK-START: void Main.bubble(int[]) BCE (after)
641 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800642 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
Aart Bikb738d4f2015-12-03 11:23:35 -0800643 private static void bubble(int[] a) {
644 for (int i = a.length; --i >= 0;) {
645 for (int j = 0; j < i; j++) {
646 if (a[j] > a[j+1]) {
647 int tmp = a[j];
648 a[j] = a[j+1];
649 a[j+1] = tmp;
650 }
651 }
652 }
653 }
654
Aart Bik22af3be2015-09-10 12:50:58 -0700655 /// CHECK-START: int Main.periodicIdiom(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800656 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800657 //
Aart Bik22af3be2015-09-10 12:50:58 -0700658 /// CHECK-START: int Main.periodicIdiom(int) BCE (after)
659 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800660 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700661 private static int periodicIdiom(int tc) {
662 int[] x = { 1, 3 };
663 // Loop with periodic sequence (0, 1).
664 int k = 0;
665 int result = 0;
666 for (int i = 0; i < tc; i++) {
667 result += x[k];
668 k = 1 - k;
669 }
670 return result;
671 }
672
673 /// CHECK-START: int Main.periodicSequence2(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800674 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800675 //
Aart Bik22af3be2015-09-10 12:50:58 -0700676 /// CHECK-START: int Main.periodicSequence2(int) BCE (after)
677 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800678 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700679 private static int periodicSequence2(int tc) {
680 int[] x = { 1, 3 };
681 // Loop with periodic sequence (0, 1).
682 int k = 0;
683 int l = 1;
684 int result = 0;
685 for (int i = 0; i < tc; i++) {
686 result += x[k];
687 int t = l;
688 l = k;
689 k = t;
690 }
691 return result;
692 }
693
694 /// CHECK-START: int Main.periodicSequence4(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800695 /// CHECK-DAG: BoundsCheck
696 /// CHECK-DAG: BoundsCheck
697 /// CHECK-DAG: BoundsCheck
698 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800699 //
Aart Bik22af3be2015-09-10 12:50:58 -0700700 /// CHECK-START: int Main.periodicSequence4(int) BCE (after)
701 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800702 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700703 private static int periodicSequence4(int tc) {
704 int[] x = { 1, 3, 5, 7 };
705 // Loop with periodic sequence (0, 1, 2, 3).
706 int k = 0;
707 int l = 1;
708 int m = 2;
709 int n = 3;
710 int result = 0;
711 for (int i = 0; i < tc; i++) {
712 result += x[k] + x[l] + x[m] + x[n]; // all used at once
713 int t = n;
714 n = k;
715 k = l;
716 l = m;
717 m = t;
718 }
719 return result;
720 }
721
Aart Bikf475bee2015-09-16 12:50:25 -0700722 /// CHECK-START: int Main.justRightUp1() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800723 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800724 //
Aart Bikf475bee2015-09-16 12:50:25 -0700725 /// CHECK-START: int Main.justRightUp1() BCE (after)
726 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800727 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700728 private static int justRightUp1() {
729 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
730 int result = 0;
731 for (int i = Integer.MAX_VALUE - 10, k = 0; i < Integer.MAX_VALUE; i++) {
732 result += x[k++];
733 }
734 return result;
735 }
736
737 /// CHECK-START: int Main.justRightUp2() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800738 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800739 //
Aart Bikf475bee2015-09-16 12:50:25 -0700740 /// CHECK-START: int Main.justRightUp2() BCE (after)
741 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800742 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700743 private static int justRightUp2() {
744 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
745 int result = 0;
746 for (int i = Integer.MAX_VALUE - 10; i < Integer.MAX_VALUE; i++) {
747 result += x[i - Integer.MAX_VALUE + 10];
748 }
749 return result;
750 }
751
752 /// CHECK-START: int Main.justRightUp3() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800753 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800754 //
Aart Bikf475bee2015-09-16 12:50:25 -0700755 /// CHECK-START: int Main.justRightUp3() BCE (after)
756 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800757 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700758 private static int justRightUp3() {
759 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
760 int result = 0;
761 for (int i = Integer.MAX_VALUE - 10, k = 0; i <= Integer.MAX_VALUE - 1; i++) {
762 result += x[k++];
763 }
764 return result;
765 }
766
767 /// CHECK-START: int Main.justOOBUp() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800768 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800769 //
Aart Bikf475bee2015-09-16 12:50:25 -0700770 /// CHECK-START: int Main.justOOBUp() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800771 /// CHECK-DAG: BoundsCheck
772 //
773 /// CHECK-START: int Main.justOOBUp() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800774 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700775 private static int justOOBUp() {
776 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
777 int result = 0;
778 // Infinite loop!
779 for (int i = Integer.MAX_VALUE - 9, k = 0; i <= Integer.MAX_VALUE; i++) {
780 result += x[k++];
781 }
782 return result;
783 }
784
785 /// CHECK-START: int Main.justRightDown1() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800786 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800787 //
Aart Bikf475bee2015-09-16 12:50:25 -0700788 /// CHECK-START: int Main.justRightDown1() BCE (after)
789 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800790 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700791 private static int justRightDown1() {
792 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
793 int result = 0;
794 for (int i = Integer.MIN_VALUE + 10, k = 0; i > Integer.MIN_VALUE; i--) {
795 result += x[k++];
796 }
797 return result;
798 }
799
800 /// CHECK-START: int Main.justRightDown2() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800801 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800802 //
Aart Bikf475bee2015-09-16 12:50:25 -0700803 /// CHECK-START: int Main.justRightDown2() BCE (after)
804 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800805 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700806 private static int justRightDown2() {
807 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
808 int result = 0;
809 for (int i = Integer.MIN_VALUE + 10; i > Integer.MIN_VALUE; i--) {
810 result += x[Integer.MAX_VALUE + i];
811 }
812 return result;
813 }
814
815 /// CHECK-START: int Main.justRightDown3() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800816 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800817 //
Aart Bikf475bee2015-09-16 12:50:25 -0700818 /// CHECK-START: int Main.justRightDown3() BCE (after)
819 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800820 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700821 private static int justRightDown3() {
822 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
823 int result = 0;
824 for (int i = Integer.MIN_VALUE + 10, k = 0; i >= Integer.MIN_VALUE + 1; i--) {
825 result += x[k++];
826 }
827 return result;
828 }
829
830 /// CHECK-START: int Main.justOOBDown() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800831 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800832 //
Aart Bikf475bee2015-09-16 12:50:25 -0700833 /// CHECK-START: int Main.justOOBDown() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800834 /// CHECK-DAG: BoundsCheck
835 //
836 /// CHECK-START: int Main.justOOBDown() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800837 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700838 private static int justOOBDown() {
839 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
840 int result = 0;
841 // Infinite loop!
842 for (int i = Integer.MIN_VALUE + 9, k = 0; i >= Integer.MIN_VALUE; i--) {
843 result += x[k++];
844 }
845 return result;
846 }
847
Aart Bik9401f532015-09-28 16:25:56 -0700848 /// CHECK-START: void Main.lowerOOB(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800849 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800850 //
Aart Bik9401f532015-09-28 16:25:56 -0700851 /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800852 /// CHECK-DAG: BoundsCheck
853 //
854 /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800855 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700856 private static void lowerOOB(int[] x) {
Aart Bik09e8d5f2016-01-22 16:49:55 -0800857 // OOB!
Aart Bik22af3be2015-09-10 12:50:58 -0700858 for (int i = -1; i < x.length; i++) {
859 sResult += x[i];
860 }
861 }
862
Aart Bik9401f532015-09-28 16:25:56 -0700863 /// CHECK-START: void Main.upperOOB(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800864 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800865 //
Aart Bik9401f532015-09-28 16:25:56 -0700866 /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800867 /// CHECK-DAG: BoundsCheck
868 //
869 /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800870 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700871 private static void upperOOB(int[] x) {
Aart Bik09e8d5f2016-01-22 16:49:55 -0800872 // OOB!
Aart Bik22af3be2015-09-10 12:50:58 -0700873 for (int i = 0; i <= x.length; i++) {
874 sResult += x[i];
875 }
876 }
877
Aart Bik9401f532015-09-28 16:25:56 -0700878 /// CHECK-START: void Main.doWhileUpOOB() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800879 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800880 //
Aart Bik9401f532015-09-28 16:25:56 -0700881 /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800882 /// CHECK-DAG: BoundsCheck
883 //
884 /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800885 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700886 private static void doWhileUpOOB() {
887 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
888 int i = 0;
Aart Bik09e8d5f2016-01-22 16:49:55 -0800889 // OOB!
Aart Bik9401f532015-09-28 16:25:56 -0700890 do {
891 sResult += x[i++];
892 } while (i <= x.length);
893 }
894
895 /// CHECK-START: void Main.doWhileDownOOB() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800896 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800897 //
Aart Bik9401f532015-09-28 16:25:56 -0700898 /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800899 /// CHECK-DAG: BoundsCheck
900 //
901 /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800902 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700903 private static void doWhileDownOOB() {
904 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
905 int i = x.length - 1;
Aart Bik09e8d5f2016-01-22 16:49:55 -0800906 // OOB!
Aart Bik9401f532015-09-28 16:25:56 -0700907 do {
908 sResult += x[i--];
909 } while (-1 <= i);
910 }
911
Aart Bik97412c922016-02-19 20:14:38 -0800912 /// CHECK-START: void Main.hiddenOOB1(int) BCE (before)
913 /// CHECK-DAG: BoundsCheck
914 //
915 /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
916 /// CHECK-DAG: Deoptimize
917 //
918 /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
919 /// CHECK-NOT: BoundsCheck
920 private static void hiddenOOB1(int lo) {
921 int[] a = { 1 } ;
922 for (int i = lo; i <= 10; i++) {
923 // Dangerous loop where careless static range analysis would yield strict upper bound
924 // on index j of 5. When, for instance, lo and thus i = -2147483648, the upper bound
925 // becomes really positive due to arithmetic wrap-around, causing OOB.
926 // Dynamic BCE is feasible though, since it checks the range.
927 for (int j = 4; j < i - 5; j++) {
928 sResult += a[j - 4];
929 }
930 }
931 }
932
933 /// CHECK-START: void Main.hiddenOOB2(int) BCE (before)
934 /// CHECK-DAG: BoundsCheck
935 //
936 /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
937 /// CHECK-DAG: Deoptimize
938 //
939 /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
940 /// CHECK-NOT: BoundsCheck
941 private static void hiddenOOB2(int hi) {
942 int[] a = { 1 } ;
943 for (int i = 0; i < hi; i++) {
944 // Dangerous loop where careless static range analysis would yield strict lower bound
Aart Bik6ab903c2016-02-24 15:18:55 -0800945 // on index j of 5. When, for instance, hi and thus i = 2147483647, the upper bound
Aart Bik97412c922016-02-19 20:14:38 -0800946 // becomes really negative due to arithmetic wrap-around, causing OOB.
947 // Dynamic BCE is feasible though, since it checks the range.
948 for (int j = 6; j > i + 5; j--) {
949 sResult += a[j - 6];
950 }
951 }
952 }
953
954 /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (before)
955 /// CHECK-DAG: BoundsCheck
956 //
957 /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
958 /// CHECK-DAG: BoundsCheck
959 //
960 /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
961 /// CHECK-NOT: Deoptimize
962 private static void hiddenInfiniteOOB() {
963 int[] a = { 11 } ;
964 for (int i = -1; i <= 0; i++) {
965 // Dangerous loop where careless static range analysis would yield a safe upper bound
966 // of -3. In reality, due to arithmetic wrap-around (when i = -1, j <= 2147483647;
967 // whereas when i = 0, j <= -3), this is an infinite loop that goes OOB.
968 for (int j = -3; j <= 2147483646 * i - 3; j++) {
969 sResult += a[j + 3];
970 }
971 }
972 }
973
974 /// CHECK-START: void Main.hiddenFiniteOOB() BCE (before)
975 /// CHECK-DAG: BoundsCheck
976 //
977 /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
978 /// CHECK-DAG: Deoptimize
979 //
980 /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
981 /// CHECK-NOT: BoundsCheck
982 private static void hiddenFiniteOOB() {
983 int[] a = { 111 } ;
984 for (int i = -1; i <= 0; i++) {
985 // Dangerous loop similar as above where the loop is now finite, but the
986 // loop still goes out of bounds for i = -1 due to the large upper bound.
987 // Dynamic BCE is feasible though, since it checks the range.
988 for (int j = -4; j < 2147483646 * i - 3; j++) {
989 sResult += a[j + 4];
990 }
991 }
992 }
993
994 /// CHECK-START: int[] Main.add() BCE (before)
995 /// CHECK-DAG: BoundsCheck
996 //
997 /// CHECK-START: int[] Main.add() BCE (after)
998 /// CHECK-NOT: BoundsCheck
999 /// CHECK-NOT: Deoptimize
1000 private static int[] add() {
1001 int[] a = new int[10];
1002 for (int i = 0; i <= 3; i++) {
1003 for (int j = 0; j <= 6; j++) {
1004 a[i + j] += 1;
1005 }
1006 }
1007 return a;
1008 }
1009
Aart Bik7d57d7f2015-12-09 14:39:48 -08001010 /// CHECK-START: int[] Main.multiply1() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001011 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -08001012 //
1013 /// CHECK-START: int[] Main.multiply1() BCE (after)
1014 /// CHECK-NOT: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -08001015 /// CHECK-NOT: Deoptimize
1016 private static int[] multiply1() {
1017 int[] a = new int[10];
1018 try {
1019 for (int i = 0; i <= 3; i++) {
1020 for (int j = 0; j <= 3; j++) {
1021 // Range [0,9]: safe.
1022 a[i * j] += 1;
1023 }
1024 }
1025 } catch (Exception e) {
1026 a[0] += 1000;
1027 }
1028 return a;
1029 }
1030
1031 /// CHECK-START: int[] Main.multiply2() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001032 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -08001033 //
1034 /// CHECK-START: int[] Main.multiply2() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001035 /// CHECK-DAG: BoundsCheck
1036 //
1037 /// CHECK-START: int[] Main.multiply2() BCE (after)
1038 /// CHECK-NOT: Deoptimize
Aart Bik7d57d7f2015-12-09 14:39:48 -08001039 static int[] multiply2() {
1040 int[] a = new int[10];
1041 try {
1042 for (int i = -3; i <= 3; i++) {
1043 for (int j = -3; j <= 3; j++) {
1044 // Range [-9,9]: unsafe.
Aart Bik09e8d5f2016-01-22 16:49:55 -08001045 a[i * j] += 1;
Aart Bik7d57d7f2015-12-09 14:39:48 -08001046 }
1047 }
1048 } catch (Exception e) {
1049 a[0] += 1000;
1050 }
1051 return a;
1052 }
1053
Aart Bik4a342772015-11-30 10:17:46 -08001054 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001055 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1056 /// CHECK-DAG: NullCheck loop:<<Loop>>
1057 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1058 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001059 //
Aart Bik4a342772015-11-30 10:17:46 -08001060 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001061 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1062 /// CHECK-DAG: Deoptimize loop:none
1063 //
1064 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
1065 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1066 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1067 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001068 private static int linearDynamicBCE1(int[] x, int lo, int hi) {
1069 int result = 0;
1070 for (int i = lo; i < hi; i++) {
1071 sResult += x[i];
1072 }
1073 return result;
1074 }
1075
1076 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001077 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1078 /// CHECK-DAG: NullCheck loop:<<Loop>>
1079 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1080 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001081 //
Aart Bik4a342772015-11-30 10:17:46 -08001082 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001083 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1084 /// CHECK-DAG: Deoptimize loop:none
1085 //
1086 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
1087 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1088 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1089 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001090 private static int linearDynamicBCE2(int[] x, int lo, int hi, int offset) {
1091 int result = 0;
1092 for (int i = lo; i < hi; i++) {
1093 sResult += x[offset + i];
1094 }
1095 return result;
1096 }
1097
1098 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001099 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1100 /// CHECK-DAG: NullCheck loop:<<Loop>>
1101 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1102 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001103 //
Aart Bik4a342772015-11-30 10:17:46 -08001104 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001105 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1106 /// CHECK-DAG: Deoptimize loop:none
1107 //
1108 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
1109 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1110 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1111 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001112 private static int wrapAroundDynamicBCE(int[] x) {
1113 int w = 9;
1114 int result = 0;
1115 for (int i = 0; i < 10; i++) {
1116 result += x[w];
1117 w = i;
1118 }
1119 return result;
1120 }
1121
1122 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001123 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1124 /// CHECK-DAG: NullCheck loop:<<Loop>>
1125 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1126 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001127 //
Aart Bik4a342772015-11-30 10:17:46 -08001128 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001129 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1130 /// CHECK-DAG: Deoptimize loop:none
1131 //
1132 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
1133 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1134 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1135 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001136 private static int periodicDynamicBCE(int[] x) {
1137 int k = 0;
1138 int result = 0;
1139 for (int i = 0; i < 10; i++) {
1140 result += x[k];
1141 k = 1 - k;
1142 }
1143 return result;
1144 }
1145
1146 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001147 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1148 /// CHECK-DAG: NullCheck loop:<<Loop>>
1149 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1150 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001151 //
Aart Bik4a342772015-11-30 10:17:46 -08001152 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001153 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1154 /// CHECK-DAG: Deoptimize loop:none
1155 //
1156 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
1157 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1158 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1159 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001160 static int dynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
1161 // This loop could be infinite for hi = max int. Since i is also used
1162 // as subscript, however, dynamic bce can proceed.
1163 int result = 0;
1164 for (int i = lo; i <= hi; i++) {
1165 result += x[i];
1166 }
1167 return result;
1168 }
1169
1170 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001171 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1172 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001173 //
Aart Bik4a342772015-11-30 10:17:46 -08001174 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001175 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1176 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
1177 //
1178 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -08001179 /// CHECK-NOT: Deoptimize
1180 static int noDynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
1181 // As above, but now the index is not used as subscript,
1182 // and dynamic bce is not applied.
1183 int result = 0;
1184 for (int k = 0, i = lo; i <= hi; i++) {
1185 result += x[k++];
1186 }
1187 return result;
1188 }
1189
1190 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001191 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1192 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001193 //
Aart Bik4a342772015-11-30 10:17:46 -08001194 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001195 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1196 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
1197 //
1198 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -08001199 /// CHECK-NOT: Deoptimize
1200 static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) {
1201 int result = 0;
1202 // Mix of int and long induction.
1203 int k = 0;
1204 for (long i = lo; i < hi; i++) {
1205 result += x[k++];
1206 }
1207 return result;
1208 }
1209
Aart Bik97412c922016-02-19 20:14:38 -08001210 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (before)
1211 /// CHECK-DAG: BoundsCheck loop:<<InnerLoop:B\d+>>
1212 /// CHECK-DAG: ArrayGet loop:<<InnerLoop>>
1213 /// CHECK-DAG: If loop:<<InnerLoop>>
1214 /// CHECK-DAG: If loop:<<OuterLoop:B\d+>>
1215 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
1216 //
1217 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
1218 /// CHECK-DAG: ArrayGet loop:<<InnerLoop:B\d+>>
1219 /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>>
1220 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
1221 //
1222 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
1223 /// CHECK-NOT: BoundsCheck
1224 //
1225 // No additional top tests were introduced.
1226 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
1227 /// CHECK-DAG: If
1228 /// CHECK-DAG: If
1229 /// CHECK-NOT: If
1230 static int dynamicBCEConstantRange(int[] x) {
1231 int result = 0;
1232 for (int i = 2; i <= 6; i++) {
1233 // Range analysis sees that innermost loop is finite and always taken.
1234 for (int j = i - 2; j <= i + 2; j++) {
1235 result += x[j];
1236 }
1237 }
1238 return result;
1239 }
1240
Aart Bik4a342772015-11-30 10:17:46 -08001241 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001242 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop:B\d+>>
1243 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
1244 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001245 //
Aart Bik4a342772015-11-30 10:17:46 -08001246 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001247 // Order matters:
1248 /// CHECK: Deoptimize loop:<<Loop:B\d+>>
1249 // CHECK-NOT: Goto loop:<<Loop>>
1250 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
1251 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
1252 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
1253 /// CHECK: Goto loop:<<Loop>>
1254 //
1255 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
1256 /// CHECK-DAG: Deoptimize loop:none
Aart Bik4a342772015-11-30 10:17:46 -08001257 static int dynamicBCEAndConstantIndices(int[] x, int[][] a, int lo, int hi) {
1258 // Deliberately test array length on a before the loop so that only bounds checks
1259 // on constant subscripts remain, making them a viable candidate for hoisting.
1260 if (a.length == 0) {
1261 return -1;
1262 }
1263 // Loop that allows BCE on x[i].
1264 int result = 0;
1265 for (int i = lo; i < hi; i++) {
1266 result += x[i];
1267 if ((i % 10) != 0) {
1268 // None of the subscripts inside a conditional are removed by dynamic bce,
1269 // making them a candidate for deoptimization based on constant indices.
1270 // Compiler should ensure the array loads are not subsequently hoisted
1271 // "above" the deoptimization "barrier" on the bounds.
1272 a[0][i] = 1;
1273 a[1][i] = 2;
1274 a[99][i] = 3;
1275 }
1276 }
1277 return result;
1278 }
1279
Aart Bik09e8d5f2016-01-22 16:49:55 -08001280 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (before)
1281 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1282 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1283 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1284 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1285 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1286 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1287 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1288 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1289 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1290 // For brevity, just test occurrence of at least one of each in the loop:
1291 /// CHECK-DAG: NullCheck loop:<<Loop>>
1292 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1293 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001294 //
Aart Bik09e8d5f2016-01-22 16:49:55 -08001295 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
1296 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1297 /// CHECK-NOT: ArrayGet loop:<<Loop>>
1298 //
1299 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
1300 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1301 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1302 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
1303 //
1304 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
1305 /// CHECK-DAG: Deoptimize loop:none
1306 static int dynamicBCEAndConstantIndicesAllPrimTypes(int[] q,
1307 boolean[] r,
1308 byte[] s,
1309 char[] t,
1310 short[] u,
1311 int[] v,
1312 long[] w,
1313 float[] x,
1314 double[] y, int lo, int hi) {
Aart Bik4a342772015-11-30 10:17:46 -08001315 int result = 0;
1316 for (int i = lo; i < hi; i++) {
Aart Bik09e8d5f2016-01-22 16:49:55 -08001317 // All constant index array references can be hoisted out of the loop during BCE on q[i].
Aart Bik4a342772015-11-30 10:17:46 -08001318 result += q[i] + (r[0] ? 1 : 0) + (int) s[0] + (int) t[0] + (int) u[0] + (int) v[0] +
Aart Bik09e8d5f2016-01-22 16:49:55 -08001319 (int) w[0] + (int) x[0] + (int) y[0];
1320 }
1321 return result;
1322 }
1323
1324 /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (before)
1325 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1326 /// CHECK-DAG: NullCheck loop:<<Loop>>
1327 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1328 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
1329 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1330 /// CHECK-DAG: NullCheck loop:<<Loop>>
1331 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1332 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
1333 //
1334 /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
1335 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1336 /// CHECK-DAG: Deoptimize loop:none
1337 //
1338 /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
1339 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1340 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
1341 static int dynamicBCEAndConstantIndexRefType(int[] q, Integer[] z, int lo, int hi) {
1342 int result = 0;
1343 for (int i = lo; i < hi; i++) {
1344 // Similar to above, but now implicit call to intValue() may prevent hoisting
1345 // z[0] itself during BCE on q[i]. Therefore, we just check BCE on q[i].
1346 result += q[i] + z[0];
Aart Bik4a342772015-11-30 10:17:46 -08001347 }
1348 return result;
1349 }
1350
Aart Bik22af3be2015-09-10 12:50:58 -07001351 //
1352 // Verifier.
1353 //
1354
1355 public static void main(String[] args) {
Aart Bik6ab903c2016-02-24 15:18:55 -08001356 // Set to run expensive tests for correctness too.
1357 boolean HEAVY = false;
1358
Aart Bik22af3be2015-09-10 12:50:58 -07001359 int[] empty = { };
1360 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1361
1362 // Linear and wrap-around.
1363 expectEquals(0, linear(empty));
1364 expectEquals(55, linear(x));
1365 expectEquals(0, linearDown(empty));
1366 expectEquals(55, linearDown(x));
1367 expectEquals(0, linearObscure(empty));
1368 expectEquals(55, linearObscure(x));
Aart Bikf475bee2015-09-16 12:50:25 -07001369 expectEquals(0, linearVeryObscure(empty));
1370 expectEquals(55, linearVeryObscure(x));
Aart Bik7d57d7f2015-12-09 14:39:48 -08001371 expectEquals(0, hiddenStride(empty));
1372 expectEquals(55, hiddenStride(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001373 expectEquals(0, linearWhile(empty));
1374 expectEquals(55, linearWhile(x));
Aart Bikf475bee2015-09-16 12:50:25 -07001375 expectEquals(0, linearThreeWayPhi(empty));
1376 expectEquals(50, linearThreeWayPhi(x));
1377 expectEquals(0, linearFourWayPhi(empty));
1378 expectEquals(51, linearFourWayPhi(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001379 expectEquals(0, wrapAroundThenLinear(empty));
1380 expectEquals(55, wrapAroundThenLinear(x));
Aart Bikf475bee2015-09-16 12:50:25 -07001381 expectEquals(0, wrapAroundThenLinearThreeWayPhi(empty));
1382 expectEquals(54, wrapAroundThenLinearThreeWayPhi(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001383
1384 // Linear with parameter.
1385 sResult = 0;
1386 try {
1387 linearWithParameter(-1);
1388 } catch (NegativeArraySizeException e) {
1389 sResult = 1;
1390 }
1391 expectEquals(1, sResult);
1392 for (int n = 0; n < 32; n++) {
1393 int[] r = linearWithParameter(n);
1394 expectEquals(n, r.length);
1395 for (int i = 0; i < n; i++) {
1396 expectEquals(i, r[i]);
1397 }
1398 }
1399
Aart Bikf475bee2015-09-16 12:50:25 -07001400 // Linear copy.
1401 expectEquals(0, linearCopy(empty).length);
1402 {
1403 int[] r = linearCopy(x);
1404 expectEquals(x.length, r.length);
1405 for (int i = 0; i < x.length; i++) {
1406 expectEquals(x[i], r[i]);
1407 }
1408 }
1409
Aart Bik22af3be2015-09-10 12:50:58 -07001410 // Linear with non-unit strides.
Aart Bik4a342772015-11-30 10:17:46 -08001411 expectEquals(55, linearByTwo(x));
1412 expectEquals(25, linearByTwoSkip1(x));
1413 expectEquals(25, linearByTwoSkip2(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001414 expectEquals(56, linearWithCompoundStride());
1415 expectEquals(66, linearWithLargePositiveStride());
1416 expectEquals(66, linearWithVeryLargePositiveStride());
1417 expectEquals(66, linearWithLargeNegativeStride());
1418 expectEquals(66, linearWithVeryLargeNegativeStride());
1419
Aart Bikf475bee2015-09-16 12:50:25 -07001420 // Special forms.
Aart Bik9401f532015-09-28 16:25:56 -07001421 expectEquals(55, linearForNEUp());
1422 expectEquals(55, linearForNEDown());
Aart Bik358af832016-02-24 14:17:53 -08001423 expectEquals(55, linearForNEArrayLengthUp(x));
1424 expectEquals(55, linearForNEArrayLengthDown(x));
Aart Bik9401f532015-09-28 16:25:56 -07001425 expectEquals(55, linearDoWhileUp());
1426 expectEquals(55, linearDoWhileDown());
Aart Bikf475bee2015-09-16 12:50:25 -07001427 expectEquals(55, linearShort());
Aart Bik4a342772015-11-30 10:17:46 -08001428 expectEquals(55, invariantFromPreLoop(x, 1));
Aart Bikb738d4f2015-12-03 11:23:35 -08001429 linearTriangularOnTwoArrayLengths(10);
1430 linearTriangularOnOneArrayLength(10);
1431 linearTriangularOnParameter(10);
Aart Bik97412c922016-02-19 20:14:38 -08001432 linearTriangularVariationsInnerStrict(10);
1433 linearTriangularVariationsInnerNonStrict(10);
Aart Bikb738d4f2015-12-03 11:23:35 -08001434
1435 // Sorting.
1436 int[] sort = { 5, 4, 1, 9, 10, 2, 7, 6, 3, 8 };
1437 bubble(sort);
1438 for (int i = 0; i < 10; i++) {
1439 expectEquals(sort[i], x[i]);
1440 }
Aart Bikf475bee2015-09-16 12:50:25 -07001441
Aart Bik22af3be2015-09-10 12:50:58 -07001442 // Periodic adds (1, 3), one at the time.
1443 expectEquals(0, periodicIdiom(-1));
1444 for (int tc = 0; tc < 32; tc++) {
1445 int expected = (tc >> 1) << 2;
1446 if ((tc & 1) != 0)
1447 expected += 1;
1448 expectEquals(expected, periodicIdiom(tc));
1449 }
1450
1451 // Periodic adds (1, 3), one at the time.
1452 expectEquals(0, periodicSequence2(-1));
1453 for (int tc = 0; tc < 32; tc++) {
1454 int expected = (tc >> 1) << 2;
1455 if ((tc & 1) != 0)
1456 expected += 1;
1457 expectEquals(expected, periodicSequence2(tc));
1458 }
1459
1460 // Periodic adds (1, 3, 5, 7), all at once.
1461 expectEquals(0, periodicSequence4(-1));
1462 for (int tc = 0; tc < 32; tc++) {
1463 expectEquals(tc * 16, periodicSequence4(tc));
1464 }
1465
Aart Bikf475bee2015-09-16 12:50:25 -07001466 // Large bounds.
1467 expectEquals(55, justRightUp1());
1468 expectEquals(55, justRightUp2());
1469 expectEquals(55, justRightUp3());
1470 expectEquals(55, justRightDown1());
1471 expectEquals(55, justRightDown2());
1472 expectEquals(55, justRightDown3());
1473 sResult = 0;
1474 try {
1475 justOOBUp();
1476 } catch (ArrayIndexOutOfBoundsException e) {
1477 sResult = 1;
1478 }
1479 expectEquals(1, sResult);
1480 sResult = 0;
1481 try {
1482 justOOBDown();
1483 } catch (ArrayIndexOutOfBoundsException e) {
1484 sResult = 1;
1485 }
1486 expectEquals(1, sResult);
1487
Aart Bik22af3be2015-09-10 12:50:58 -07001488 // Lower bound goes OOB.
1489 sResult = 0;
1490 try {
1491 lowerOOB(x);
1492 } catch (ArrayIndexOutOfBoundsException e) {
1493 sResult += 1000;
1494 }
1495 expectEquals(1000, sResult);
1496
1497 // Upper bound goes OOB.
1498 sResult = 0;
1499 try {
1500 upperOOB(x);
1501 } catch (ArrayIndexOutOfBoundsException e) {
1502 sResult += 1000;
1503 }
1504 expectEquals(1055, sResult);
1505
Aart Bik9401f532015-09-28 16:25:56 -07001506 // Do while up goes OOB.
1507 sResult = 0;
1508 try {
1509 doWhileUpOOB();
1510 } catch (ArrayIndexOutOfBoundsException e) {
1511 sResult += 1000;
1512 }
1513 expectEquals(1055, sResult);
1514
1515 // Do while down goes OOB.
1516 sResult = 0;
1517 try {
1518 doWhileDownOOB();
1519 } catch (ArrayIndexOutOfBoundsException e) {
1520 sResult += 1000;
1521 }
1522 expectEquals(1055, sResult);
Aart Bik4a342772015-11-30 10:17:46 -08001523
Aart Bik97412c922016-02-19 20:14:38 -08001524 // Hidden OOB.
1525 sResult = 0;
1526 try {
1527 hiddenOOB1(10); // no OOB
1528 } catch (ArrayIndexOutOfBoundsException e) {
1529 sResult += 1000;
1530 }
1531 expectEquals(1, sResult);
1532 sResult = 0;
1533 try {
1534 hiddenOOB1(-2147483648); // OOB
1535 } catch (ArrayIndexOutOfBoundsException e) {
1536 sResult += 1000;
1537 }
1538 expectEquals(1001, sResult);
1539 sResult = 0;
1540 try {
1541 hiddenOOB2(1); // no OOB
1542 } catch (ArrayIndexOutOfBoundsException e) {
1543 sResult += 1000;
1544 }
1545 expectEquals(1, sResult);
Aart Bik6ab903c2016-02-24 15:18:55 -08001546 if (HEAVY) {
1547 sResult = 0;
1548 try {
1549 hiddenOOB2(2147483647); // OOB
1550 } catch (ArrayIndexOutOfBoundsException e) {
1551 sResult += 1000;
1552 }
1553 expectEquals(1002, sResult);
Aart Bik97412c922016-02-19 20:14:38 -08001554 }
Aart Bik97412c922016-02-19 20:14:38 -08001555 sResult = 0;
1556 try {
1557 hiddenInfiniteOOB();
1558 } catch (ArrayIndexOutOfBoundsException e) {
1559 sResult += 1000;
1560 }
1561 expectEquals(1011, sResult);
1562 sResult = 0;
1563 try {
1564 hiddenFiniteOOB();
1565 } catch (ArrayIndexOutOfBoundsException e) {
1566 sResult += 1000;
1567 }
1568 expectEquals(1111, sResult);
1569
1570 // Addition.
1571 {
1572 int[] e1 ={ 1, 2, 3, 4, 4, 4, 4, 3, 2, 1 };
1573 int[] a1 = add();
1574 for (int i = 0; i < 10; i++) {
1575 expectEquals(a1[i], e1[i]);
1576 }
1577 }
1578
Aart Bik7d57d7f2015-12-09 14:39:48 -08001579 // Multiplication.
1580 {
1581 int[] e1 = { 7, 1, 2, 2, 1, 0, 2, 0, 0, 1 };
1582 int[] a1 = multiply1();
1583 for (int i = 0; i < 10; i++) {
1584 expectEquals(a1[i], e1[i]);
1585 }
1586 int[] e2 = { 1001, 0, 0, 1, 0, 0, 1, 0, 0, 1 };
1587 int[] a2 = multiply2();
1588 for (int i = 0; i < 10; i++) {
1589 expectEquals(a2[i], e2[i]);
1590 }
1591 }
1592
Aart Bik4a342772015-11-30 10:17:46 -08001593 // Dynamic BCE.
1594 sResult = 0;
1595 try {
1596 linearDynamicBCE1(x, -1, x.length);
1597 } catch (ArrayIndexOutOfBoundsException e) {
1598 sResult += 1000;
1599 }
1600 expectEquals(1000, sResult);
1601 sResult = 0;
1602 linearDynamicBCE1(x, 0, x.length);
1603 expectEquals(55, sResult);
1604 sResult = 0;
1605 try {
1606 linearDynamicBCE1(x, 0, x.length + 1);
1607 } catch (ArrayIndexOutOfBoundsException e) {
1608 sResult += 1000;
1609 }
1610 expectEquals(1055, sResult);
1611
1612 // Dynamic BCE with offset.
1613 sResult = 0;
1614 try {
1615 linearDynamicBCE2(x, 0, x.length, -1);
1616 } catch (ArrayIndexOutOfBoundsException e) {
1617 sResult += 1000;
1618 }
1619 expectEquals(1000, sResult);
1620 sResult = 0;
1621 linearDynamicBCE2(x, 0, x.length, 0);
1622 expectEquals(55, sResult);
1623 sResult = 0;
1624 try {
1625 linearDynamicBCE2(x, 0, x.length, 1);
1626 } catch (ArrayIndexOutOfBoundsException e) {
1627 sResult += 1000;
1628 }
1629 expectEquals(1054, sResult);
1630
1631 // Dynamic BCE candidates.
1632 expectEquals(55, wrapAroundDynamicBCE(x));
1633 expectEquals(15, periodicDynamicBCE(x));
1634 expectEquals(55, dynamicBCEPossiblyInfiniteLoop(x, 0, 9));
1635 expectEquals(55, noDynamicBCEPossiblyInfiniteLoop(x, 0, 9));
1636 expectEquals(55, noDynamicBCEMixedInductionTypes(x, 0, 10));
Aart Bik97412c922016-02-19 20:14:38 -08001637 expectEquals(125, dynamicBCEConstantRange(x));
Aart Bik4a342772015-11-30 10:17:46 -08001638
1639 // Dynamic BCE combined with constant indices.
1640 int[][] a;
1641 a = new int[0][0];
1642 expectEquals(-1, dynamicBCEAndConstantIndices(x, a, 0, 10));
1643 a = new int[100][10];
1644 expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
1645 for (int i = 0; i < 10; i++) {
1646 expectEquals((i % 10) != 0 ? 1 : 0, a[0][i]);
1647 expectEquals((i % 10) != 0 ? 2 : 0, a[1][i]);
1648 expectEquals((i % 10) != 0 ? 3 : 0, a[99][i]);
1649 }
1650 a = new int[2][10];
1651 sResult = 0;
1652 try {
1653 expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
1654 } catch (ArrayIndexOutOfBoundsException e) {
1655 sResult = 1;
1656 }
1657 expectEquals(1, sResult);
1658 expectEquals(a[0][1], 1);
1659 expectEquals(a[1][1], 2);
1660
1661 // Dynamic BCE combined with constant indices of all types.
1662 boolean[] x1 = { true };
1663 byte[] x2 = { 2 };
1664 char[] x3 = { 3 };
1665 short[] x4 = { 4 };
1666 int[] x5 = { 5 };
1667 long[] x6 = { 6 };
1668 float[] x7 = { 7 };
1669 double[] x8 = { 8 };
Aart Bik09e8d5f2016-01-22 16:49:55 -08001670 expectEquals(415,
1671 dynamicBCEAndConstantIndicesAllPrimTypes(x, x1, x2, x3, x4, x5, x6, x7, x8, 0, 10));
Aart Bik4a342772015-11-30 10:17:46 -08001672 Integer[] x9 = { 9 };
Aart Bik09e8d5f2016-01-22 16:49:55 -08001673 expectEquals(145, dynamicBCEAndConstantIndexRefType(x, x9, 0, 10));
Aart Bik22af3be2015-09-10 12:50:58 -07001674 }
1675
1676 private static void expectEquals(int expected, int result) {
1677 if (expected != result) {
1678 throw new Error("Expected: " + expected + ", found: " + result);
1679 }
1680 }
1681}