blob: 3f6e48bbaec94487e84fa13f8c6270b2494e8935 [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)
29 /// CHECK-DAG: BoundsCheck
30 /// CHECK-START: int Main.linear(int[]) BCE (after)
31 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080032 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070033 private static int linear(int[] x) {
34 int result = 0;
35 for (int i = 0; i < x.length; i++) {
36 result += x[i];
37 }
38 return result;
39 }
40
41 /// CHECK-START: int Main.linearDown(int[]) BCE (before)
42 /// CHECK-DAG: BoundsCheck
43 /// CHECK-START: int Main.linearDown(int[]) BCE (after)
44 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080045 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070046 private static int linearDown(int[] x) {
47 int result = 0;
48 for (int i = x.length - 1; i >= 0; i--) {
49 result += x[i];
50 }
51 return result;
52 }
53
54 /// CHECK-START: int Main.linearObscure(int[]) BCE (before)
55 /// CHECK-DAG: BoundsCheck
56 /// CHECK-START: int Main.linearObscure(int[]) BCE (after)
57 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080058 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070059 private static int linearObscure(int[] x) {
60 int result = 0;
61 for (int i = x.length - 1; i >= 0; i--) {
62 int k = i + 5;
63 result += x[k - 5];
64 }
65 return result;
66 }
67
Aart Bikf475bee2015-09-16 12:50:25 -070068 /// CHECK-START: int Main.linearVeryObscure(int[]) BCE (before)
69 /// CHECK-DAG: BoundsCheck
70 /// CHECK-START: int Main.linearVeryObscure(int[]) BCE (after)
71 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080072 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -070073 private static int linearVeryObscure(int[] x) {
74 int result = 0;
75 for (int i = 0; i < x.length; i++) {
76 int k = (-i) + (i << 5) + i - (32 * i) + 5 + (int) i;
77 result += x[k - 5];
78 }
79 return result;
80 }
81
Aart Bik22af3be2015-09-10 12:50:58 -070082 /// CHECK-START: int Main.linearWhile(int[]) BCE (before)
83 /// CHECK-DAG: BoundsCheck
84 /// CHECK-START: int Main.linearWhile(int[]) BCE (after)
85 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080086 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070087 private static int linearWhile(int[] x) {
88 int i = 0;
89 int result = 0;
90 while (i < x.length) {
91 result += x[i++];
92 }
93 return result;
94 }
95
Aart Bikf475bee2015-09-16 12:50:25 -070096 /// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (before)
97 /// CHECK-DAG: BoundsCheck
98 /// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (after)
99 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800100 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700101 private static int linearThreeWayPhi(int[] x) {
102 int result = 0;
103 for (int i = 0; i < x.length; ) {
104 if (x[i] == 5) {
105 i++;
106 continue;
107 }
108 result += x[i++];
109 }
110 return result;
111 }
112
113 /// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (before)
114 /// CHECK-DAG: BoundsCheck
115 /// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (after)
116 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800117 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700118 private static int linearFourWayPhi(int[] x) {
119 int result = 0;
120 for (int i = 0; i < x.length; ) {
121 if (x[i] == 5) {
122 i++;
123 continue;
124 } else if (x[i] == 6) {
125 i++;
126 result += 7;
127 continue;
128 }
129 result += x[i++];
130 }
131 return result;
132 }
133
Aart Bik22af3be2015-09-10 12:50:58 -0700134 /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (before)
135 /// CHECK-DAG: BoundsCheck
136 /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (after)
137 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800138 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700139 private static int wrapAroundThenLinear(int[] x) {
140 // Loop with wrap around (length - 1, 0, 1, 2, ..).
141 int w = x.length - 1;
142 int result = 0;
143 for (int i = 0; i < x.length; i++) {
144 result += x[w];
145 w = i;
146 }
147 return result;
148 }
149
Aart Bikf475bee2015-09-16 12:50:25 -0700150 /// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (before)
151 /// CHECK-DAG: BoundsCheck
152 /// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (after)
153 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800154 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700155 private static int wrapAroundThenLinearThreeWayPhi(int[] x) {
156 // Loop with wrap around (length - 1, 0, 1, 2, ..).
157 int w = x.length - 1;
158 int result = 0;
159 for (int i = 0; i < x.length; ) {
160 if (x[w] == 1) {
161 w = i++;
162 continue;
163 }
164 result += x[w];
165 w = i++;
166 }
167 return result;
168 }
169
Aart Bik22af3be2015-09-10 12:50:58 -0700170 /// CHECK-START: int[] Main.linearWithParameter(int) BCE (before)
171 /// CHECK-DAG: BoundsCheck
172 /// CHECK-START: int[] Main.linearWithParameter(int) BCE (after)
173 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800174 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700175 private static int[] linearWithParameter(int n) {
176 int[] x = new int[n];
177 for (int i = 0; i < n; i++) {
178 x[i] = i;
179 }
180 return x;
181 }
182
Aart Bikf475bee2015-09-16 12:50:25 -0700183 /// CHECK-START: int[] Main.linearCopy(int[]) BCE (before)
184 /// CHECK-DAG: BoundsCheck
185 /// CHECK-START: int[] Main.linearCopy(int[]) BCE (after)
186 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800187 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700188 private static int[] linearCopy(int x[]) {
189 int n = x.length;
190 int y[] = new int[n];
191 for (int i = 0; i < n; i++) {
192 y[i] = x[i];
193 }
194 return y;
195 }
196
Aart Bik4a342772015-11-30 10:17:46 -0800197 /// CHECK-START: int Main.linearByTwo(int[]) BCE (before)
198 /// CHECK-DAG: BoundsCheck
199 /// CHECK-DAG: BoundsCheck
200 /// CHECK-START: int Main.linearByTwo(int[]) BCE (after)
201 /// CHECK-NOT: BoundsCheck
202 /// CHECK-NOT: Deoptimize
203 private static int linearByTwo(int x[]) {
204 int n = x.length / 2;
205 int result = 0;
206 for (int i = 0; i < n; i++) {
207 int ii = i << 1;
208 result += x[ii];
209 result += x[ii + 1];
210 }
211 return result;
212 }
213
214 /// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (before)
215 /// CHECK-DAG: BoundsCheck
216 /// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (after)
217 /// CHECK-NOT: BoundsCheck
218 /// CHECK-NOT: Deoptimize
219 private static int linearByTwoSkip1(int x[]) {
220 int result = 0;
221 for (int i = 0; i < x.length / 2; i++) {
222 result += x[2 * i];
223 }
224 return result;
225 }
226
227 /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (before)
228 /// CHECK-DAG: BoundsCheck
229 /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after)
230 /// CHECK-DAG: BoundsCheck
231 /// CHECK-NOT: Deoptimize
232 private static int linearByTwoSkip2(int x[]) {
233 int result = 0;
234 // This case is not optimized.
235 for (int i = 0; i < x.length; i+=2) {
236 result += x[i];
237 }
238 return result;
239 }
240
Aart Bik22af3be2015-09-10 12:50:58 -0700241 /// CHECK-START: int Main.linearWithCompoundStride() BCE (before)
242 /// CHECK-DAG: BoundsCheck
243 /// CHECK-START: int Main.linearWithCompoundStride() BCE (after)
244 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800245 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700246 private static int linearWithCompoundStride() {
247 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
248 int result = 0;
249 for (int i = 0; i <= 12; ) {
250 i++;
251 result += x[i];
252 i++;
253 }
254 return result;
255 }
256
257 /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (before)
258 /// CHECK-DAG: BoundsCheck
259 /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (after)
260 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800261 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700262 private static int linearWithLargePositiveStride() {
263 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
264 int result = 0;
265 int k = 0;
266 // Range analysis has no problem with a trip-count defined by a
Aart Bikf475bee2015-09-16 12:50:25 -0700267 // reasonably large positive stride far away from upper bound.
Aart Bik22af3be2015-09-10 12:50:58 -0700268 for (int i = 1; i <= 10 * 10000000 + 1; i += 10000000) {
269 result += x[k++];
270 }
271 return result;
272 }
273
274 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (before)
275 /// CHECK-DAG: BoundsCheck
276 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
277 /// CHECK-DAG: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800278 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700279 private static int linearWithVeryLargePositiveStride() {
280 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
281 int result = 0;
282 int k = 0;
283 // Range analysis conservatively bails due to potential of wrap-around
284 // arithmetic while computing the trip-count for this very large stride.
Aart Bikf475bee2015-09-16 12:50:25 -0700285 for (int i = 1; i < Integer.MAX_VALUE; i += 195225786) {
Aart Bik22af3be2015-09-10 12:50:58 -0700286 result += x[k++];
287 }
288 return result;
289 }
290
291 /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (before)
292 /// CHECK-DAG: BoundsCheck
293 /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (after)
294 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800295 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700296 private static int linearWithLargeNegativeStride() {
297 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
298 int result = 0;
299 int k = 0;
300 // Range analysis has no problem with a trip-count defined by a
Aart Bikf475bee2015-09-16 12:50:25 -0700301 // reasonably large negative stride far away from lower bound.
Aart Bik22af3be2015-09-10 12:50:58 -0700302 for (int i = -1; i >= -10 * 10000000 - 1; i -= 10000000) {
303 result += x[k++];
304 }
305 return result;
306 }
307
308 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (before)
309 /// CHECK-DAG: BoundsCheck
310 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
311 /// CHECK-DAG: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800312 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700313 private static int linearWithVeryLargeNegativeStride() {
314 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
315 int result = 0;
316 int k = 0;
317 // Range analysis conservatively bails due to potential of wrap-around
318 // arithmetic while computing the trip-count for this very large stride.
Aart Bikf475bee2015-09-16 12:50:25 -0700319 for (int i = -2; i > Integer.MIN_VALUE; i -= 195225786) {
Aart Bik22af3be2015-09-10 12:50:58 -0700320 result += x[k++];
321 }
322 return result;
323 }
324
Aart Bik9401f532015-09-28 16:25:56 -0700325 /// CHECK-START: int Main.linearForNEUp() BCE (before)
Aart Bikf475bee2015-09-16 12:50:25 -0700326 /// CHECK-DAG: BoundsCheck
Aart Bik9401f532015-09-28 16:25:56 -0700327 /// CHECK-START: int Main.linearForNEUp() BCE (after)
Aart Bikf475bee2015-09-16 12:50:25 -0700328 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800329 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700330 private static int linearForNEUp() {
Aart Bikf475bee2015-09-16 12:50:25 -0700331 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
332 int result = 0;
333 for (int i = 0; i != 10; i++) {
334 result += x[i];
335 }
336 return result;
337 }
338
Aart Bik9401f532015-09-28 16:25:56 -0700339 /// CHECK-START: int Main.linearForNEDown() BCE (before)
Aart Bikf475bee2015-09-16 12:50:25 -0700340 /// CHECK-DAG: BoundsCheck
Aart Bik9401f532015-09-28 16:25:56 -0700341 /// CHECK-START: int Main.linearForNEDown() BCE (after)
342 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800343 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700344 private static int linearForNEDown() {
345 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
346 int result = 0;
347 for (int i = 9; i != -1; i--) {
348 result += x[i];
349 }
350 return result;
351 }
352
353 /// CHECK-START: int Main.linearDoWhileUp() BCE (before)
Aart Bikf475bee2015-09-16 12:50:25 -0700354 /// CHECK-DAG: BoundsCheck
Aart Bik9401f532015-09-28 16:25:56 -0700355 /// CHECK-START: int Main.linearDoWhileUp() BCE (after)
356 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800357 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700358 private static int linearDoWhileUp() {
Aart Bikf475bee2015-09-16 12:50:25 -0700359 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
360 int result = 0;
361 int i = 0;
Aart Bikf475bee2015-09-16 12:50:25 -0700362 do {
363 result += x[i++];
364 } while (i < 10);
365 return result;
366 }
367
Aart Bik9401f532015-09-28 16:25:56 -0700368 /// CHECK-START: int Main.linearDoWhileDown() BCE (before)
369 /// CHECK-DAG: BoundsCheck
370 /// CHECK-START: int Main.linearDoWhileDown() BCE (after)
371 /// 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 linearDoWhileDown() {
374 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
375 int result = 0;
376 int i = 9;
377 do {
378 result += x[i--];
379 } while (0 <= i);
380 return result;
381 }
382
Aart Bikf475bee2015-09-16 12:50:25 -0700383 /// CHECK-START: int Main.linearShort() BCE (before)
384 /// CHECK-DAG: BoundsCheck
385 /// CHECK-START: int Main.linearShort() BCE (after)
386 /// CHECK-DAG: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800387 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700388 private static int linearShort() {
389 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
390 int result = 0;
391 // TODO: make this work
392 for (short i = 0; i < 10; i++) {
393 result += x[i];
394 }
395 return result;
396 }
397
Aart Bik4a342772015-11-30 10:17:46 -0800398 /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (before)
399 /// CHECK-DAG: BoundsCheck
400 /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (after)
401 /// CHECK-NOT: BoundsCheck
402 /// CHECK-NOT: Deoptimize
403 private static int invariantFromPreLoop(int[] x, int y) {
404 int result = 0;
405 // Strange pre-loop that sets upper bound.
406 int hi;
407 while (true) {
408 y = y % 3;
409 hi = x.length;
410 if (y != 123) break;
411 }
412 for (int i = 0; i < hi; i++) {
413 result += x[i];
414 }
415 return result;
416 }
417
Aart Bikb738d4f2015-12-03 11:23:35 -0800418 /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (before)
419 /// CHECK-DAG: BoundsCheck
420 /// CHECK-DAG: ArrayGet
421 /// CHECK-DAG: ArraySet
422 /// CHECK-DAG: BoundsCheck
423 /// CHECK-DAG: ArrayGet
424 /// CHECK-DAG: ArraySet
425 /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (after)
426 /// CHECK-NOT: BoundsCheck
427 /// CHECK-DAG: ArrayGet
428 /// CHECK-DAG: ArraySet
429 /// CHECK-NOT: BoundsCheck
430 /// CHECK-DAG: ArrayGet
431 /// CHECK-DAG: ArraySet
432 /// CHECK-NOT: Deoptimize
433 private static void linearTriangularOnTwoArrayLengths(int n) {
434 int[] a = new int[n];
435 for (int i = 0; i < a.length; i++) {
436 int[] b = new int[i];
437 for (int j = 0; j < b.length; j++) {
438 // Need to know j < b.length < a.length for static bce.
439 a[j] += 1;
440 // Need to know just j < b.length for static bce.
441 b[j] += 1;
442 }
443 verifyTriangular(a, b, i, n);
444 }
445 }
446
447 /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (before)
448 /// CHECK-DAG: BoundsCheck
449 /// CHECK-DAG: ArrayGet
450 /// CHECK-DAG: ArraySet
451 /// CHECK-DAG: BoundsCheck
452 /// CHECK-DAG: ArrayGet
453 /// CHECK-DAG: ArraySet
454 /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (after)
455 /// CHECK-NOT: BoundsCheck
456 /// CHECK-DAG: ArrayGet
457 /// CHECK-DAG: ArraySet
458 /// CHECK-NOT: BoundsCheck
459 /// CHECK-DAG: ArrayGet
460 /// CHECK-DAG: ArraySet
461 /// CHECK-NOT: Deoptimize
462 private static void linearTriangularOnOneArrayLength(int n) {
463 int[] a = new int[n];
464 for (int i = 0; i < a.length; i++) {
465 int[] b = new int[i];
466 for (int j = 0; j < i; j++) {
467 // Need to know j < i < a.length for static bce.
468 a[j] += 1;
469 // Need to know just j < i for static bce.
470 b[j] += 1;
471 }
472 verifyTriangular(a, b, i, n);
473 }
474 }
475
476 /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (before)
477 /// CHECK-DAG: BoundsCheck
478 /// CHECK-DAG: ArrayGet
479 /// CHECK-DAG: ArraySet
480 /// CHECK-DAG: BoundsCheck
481 /// CHECK-DAG: ArrayGet
482 /// CHECK-DAG: ArraySet
483 /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (after)
484 /// CHECK-NOT: BoundsCheck
485 /// CHECK-DAG: ArrayGet
486 /// CHECK-DAG: ArraySet
487 /// CHECK-NOT: BoundsCheck
488 /// CHECK-DAG: ArrayGet
489 /// CHECK-DAG: ArraySet
490 /// CHECK-NOT: Deoptimize
491 private static void linearTriangularOnParameter(int n) {
492 int[] a = new int[n];
493 for (int i = 0; i < n; i++) {
494 int[] b = new int[i];
495 for (int j = 0; j < i; j++) {
496 // Need to know j < i < n for static bce.
497 a[j] += 1;
498 // Need to know just j < i for static bce.
499 b[j] += 1;
500 }
501 verifyTriangular(a, b, i, n);
502 }
503 }
504
505 // Verifier for triangular methods.
506 private static void verifyTriangular(int[] a, int[] b, int m, int n) {
507 expectEquals(n, a.length);
508 for (int i = 0, k = m; i < n; i++) {
509 expectEquals(a[i], k);
510 if (k > 0) k--;
511 }
512 expectEquals(m, b.length);
513 for (int i = 0; i < m; i++) {
514 expectEquals(b[i], 1);
515 }
516 }
517
518 /// CHECK-START: void Main.bubble(int[]) BCE (before)
519 /// CHECK-DAG: BoundsCheck
520 /// CHECK-DAG: ArrayGet
521 /// CHECK-DAG: BoundsCheck
522 /// CHECK-DAG: ArrayGet
523 /// CHECK-DAG: If
524 /// CHECK-DAG: ArraySet
525 /// CHECK-DAG: ArraySet
526 /// CHECK-START: void Main.bubble(int[]) BCE (after)
527 /// CHECK-NOT: BoundsCheck
528 /// CHECK-DAG: ArrayGet
529 /// CHECK-NOT: BoundsCheck
530 /// CHECK-DAG: ArrayGet
531 /// CHECK-DAG: If
532 /// CHECK-DAG: ArraySet
533 /// CHECK-DAG: ArraySet
534 /// CHECK-NOT: Deoptimize
535 private static void bubble(int[] a) {
536 for (int i = a.length; --i >= 0;) {
537 for (int j = 0; j < i; j++) {
538 if (a[j] > a[j+1]) {
539 int tmp = a[j];
540 a[j] = a[j+1];
541 a[j+1] = tmp;
542 }
543 }
544 }
545 }
546
Aart Bik22af3be2015-09-10 12:50:58 -0700547 /// CHECK-START: int Main.periodicIdiom(int) BCE (before)
548 /// CHECK-DAG: BoundsCheck
549 /// CHECK-START: int Main.periodicIdiom(int) BCE (after)
550 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800551 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700552 private static int periodicIdiom(int tc) {
553 int[] x = { 1, 3 };
554 // Loop with periodic sequence (0, 1).
555 int k = 0;
556 int result = 0;
557 for (int i = 0; i < tc; i++) {
558 result += x[k];
559 k = 1 - k;
560 }
561 return result;
562 }
563
564 /// CHECK-START: int Main.periodicSequence2(int) BCE (before)
565 /// CHECK-DAG: BoundsCheck
566 /// CHECK-START: int Main.periodicSequence2(int) BCE (after)
567 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800568 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700569 private static int periodicSequence2(int tc) {
570 int[] x = { 1, 3 };
571 // Loop with periodic sequence (0, 1).
572 int k = 0;
573 int l = 1;
574 int result = 0;
575 for (int i = 0; i < tc; i++) {
576 result += x[k];
577 int t = l;
578 l = k;
579 k = t;
580 }
581 return result;
582 }
583
584 /// CHECK-START: int Main.periodicSequence4(int) BCE (before)
585 /// CHECK-DAG: BoundsCheck
586 /// CHECK-DAG: BoundsCheck
587 /// CHECK-DAG: BoundsCheck
588 /// CHECK-DAG: BoundsCheck
589 /// CHECK-START: int Main.periodicSequence4(int) BCE (after)
590 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800591 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700592 private static int periodicSequence4(int tc) {
593 int[] x = { 1, 3, 5, 7 };
594 // Loop with periodic sequence (0, 1, 2, 3).
595 int k = 0;
596 int l = 1;
597 int m = 2;
598 int n = 3;
599 int result = 0;
600 for (int i = 0; i < tc; i++) {
601 result += x[k] + x[l] + x[m] + x[n]; // all used at once
602 int t = n;
603 n = k;
604 k = l;
605 l = m;
606 m = t;
607 }
608 return result;
609 }
610
Aart Bikf475bee2015-09-16 12:50:25 -0700611 /// CHECK-START: int Main.justRightUp1() BCE (before)
612 /// CHECK-DAG: BoundsCheck
613 /// CHECK-START: int Main.justRightUp1() BCE (after)
614 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800615 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700616 private static int justRightUp1() {
617 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
618 int result = 0;
619 for (int i = Integer.MAX_VALUE - 10, k = 0; i < Integer.MAX_VALUE; i++) {
620 result += x[k++];
621 }
622 return result;
623 }
624
625 /// CHECK-START: int Main.justRightUp2() BCE (before)
626 /// CHECK-DAG: BoundsCheck
627 /// CHECK-START: int Main.justRightUp2() BCE (after)
628 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800629 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700630 private static int justRightUp2() {
631 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
632 int result = 0;
633 for (int i = Integer.MAX_VALUE - 10; i < Integer.MAX_VALUE; i++) {
634 result += x[i - Integer.MAX_VALUE + 10];
635 }
636 return result;
637 }
638
639 /// CHECK-START: int Main.justRightUp3() BCE (before)
640 /// CHECK-DAG: BoundsCheck
641 /// CHECK-START: int Main.justRightUp3() BCE (after)
642 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800643 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700644 private static int justRightUp3() {
645 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
646 int result = 0;
647 for (int i = Integer.MAX_VALUE - 10, k = 0; i <= Integer.MAX_VALUE - 1; i++) {
648 result += x[k++];
649 }
650 return result;
651 }
652
653 /// CHECK-START: int Main.justOOBUp() BCE (before)
654 /// CHECK-DAG: BoundsCheck
655 /// CHECK-START: int Main.justOOBUp() BCE (after)
656 /// CHECK-DAG: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800657 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700658 private static int justOOBUp() {
659 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
660 int result = 0;
661 // Infinite loop!
662 for (int i = Integer.MAX_VALUE - 9, k = 0; i <= Integer.MAX_VALUE; i++) {
663 result += x[k++];
664 }
665 return result;
666 }
667
668 /// CHECK-START: int Main.justRightDown1() BCE (before)
669 /// CHECK-DAG: BoundsCheck
670 /// CHECK-START: int Main.justRightDown1() BCE (after)
671 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800672 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700673 private static int justRightDown1() {
674 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
675 int result = 0;
676 for (int i = Integer.MIN_VALUE + 10, k = 0; i > Integer.MIN_VALUE; i--) {
677 result += x[k++];
678 }
679 return result;
680 }
681
682 /// CHECK-START: int Main.justRightDown2() BCE (before)
683 /// CHECK-DAG: BoundsCheck
684 /// CHECK-START: int Main.justRightDown2() BCE (after)
685 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800686 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700687 private static int justRightDown2() {
688 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
689 int result = 0;
690 for (int i = Integer.MIN_VALUE + 10; i > Integer.MIN_VALUE; i--) {
691 result += x[Integer.MAX_VALUE + i];
692 }
693 return result;
694 }
695
696 /// CHECK-START: int Main.justRightDown3() BCE (before)
697 /// CHECK-DAG: BoundsCheck
698 /// CHECK-START: int Main.justRightDown3() BCE (after)
699 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800700 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700701 private static int justRightDown3() {
702 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
703 int result = 0;
704 for (int i = Integer.MIN_VALUE + 10, k = 0; i >= Integer.MIN_VALUE + 1; i--) {
705 result += x[k++];
706 }
707 return result;
708 }
709
710 /// CHECK-START: int Main.justOOBDown() BCE (before)
711 /// CHECK-DAG: BoundsCheck
712 /// CHECK-START: int Main.justOOBDown() BCE (after)
713 /// CHECK-DAG: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800714 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700715 private static int justOOBDown() {
716 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
717 int result = 0;
718 // Infinite loop!
719 for (int i = Integer.MIN_VALUE + 9, k = 0; i >= Integer.MIN_VALUE; i--) {
720 result += x[k++];
721 }
722 return result;
723 }
724
Aart Bik9401f532015-09-28 16:25:56 -0700725 /// CHECK-START: void Main.lowerOOB(int[]) BCE (before)
726 /// CHECK-DAG: BoundsCheck
727 /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
728 /// CHECK-DAG: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800729 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700730 private static void lowerOOB(int[] x) {
731 for (int i = -1; i < x.length; i++) {
732 sResult += x[i];
733 }
734 }
735
Aart Bik9401f532015-09-28 16:25:56 -0700736 /// CHECK-START: void Main.upperOOB(int[]) BCE (before)
737 /// CHECK-DAG: BoundsCheck
738 /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
739 /// CHECK-DAG: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800740 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700741 private static void upperOOB(int[] x) {
742 for (int i = 0; i <= x.length; i++) {
743 sResult += x[i];
744 }
745 }
746
Aart Bik9401f532015-09-28 16:25:56 -0700747 /// CHECK-START: void Main.doWhileUpOOB() BCE (before)
748 /// CHECK-DAG: BoundsCheck
749 /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
750 /// CHECK-DAG: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800751 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700752 private static void doWhileUpOOB() {
753 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
754 int i = 0;
755 do {
756 sResult += x[i++];
757 } while (i <= x.length);
758 }
759
760 /// CHECK-START: void Main.doWhileDownOOB() BCE (before)
761 /// CHECK-DAG: BoundsCheck
762 /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
763 /// CHECK-DAG: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800764 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700765 private static void doWhileDownOOB() {
766 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
767 int i = x.length - 1;
768 do {
769 sResult += x[i--];
770 } while (-1 <= i);
771 }
772
Aart Bik4a342772015-11-30 10:17:46 -0800773 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (before)
774 /// CHECK-DAG: StaticFieldGet
775 /// CHECK-DAG: NullCheck
776 /// CHECK-DAG: ArrayLength
777 /// CHECK-DAG: BoundsCheck
778 /// CHECK-DAG: ArrayGet
779 /// CHECK-DAG: StaticFieldSet
780 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
781 /// CHECK-DAG: StaticFieldGet
782 /// CHECK-NOT: NullCheck
783 /// CHECK-NOT: ArrayLength
784 /// CHECK-NOT: BoundsCheck
785 /// CHECK-DAG: ArrayGet
786 /// CHECK-DAG: StaticFieldSet
787 /// CHECK-DAG: Exit
788 /// CHECK-DAG: Deoptimize
789 /// CHECK-DAG: Deoptimize
790 /// CHECK-DAG: Deoptimize
791 private static int linearDynamicBCE1(int[] x, int lo, int hi) {
792 int result = 0;
793 for (int i = lo; i < hi; i++) {
794 sResult += x[i];
795 }
796 return result;
797 }
798
799 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (before)
800 /// CHECK-DAG: StaticFieldGet
801 /// CHECK-DAG: NullCheck
802 /// CHECK-DAG: ArrayLength
803 /// CHECK-DAG: BoundsCheck
804 /// CHECK-DAG: ArrayGet
805 /// CHECK-DAG: StaticFieldSet
806 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
807 /// CHECK-DAG: StaticFieldGet
808 /// CHECK-NOT: NullCheck
809 /// CHECK-NOT: ArrayLength
810 /// CHECK-NOT: BoundsCheck
811 /// CHECK-DAG: ArrayGet
812 /// CHECK-DAG: StaticFieldSet
813 /// CHECK-DAG: Exit
814 /// CHECK-DAG: Deoptimize
815 /// CHECK-DAG: Deoptimize
816 /// CHECK-DAG: Deoptimize
817 private static int linearDynamicBCE2(int[] x, int lo, int hi, int offset) {
818 int result = 0;
819 for (int i = lo; i < hi; i++) {
820 sResult += x[offset + i];
821 }
822 return result;
823 }
824
825 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (before)
826 /// CHECK-DAG: NullCheck
827 /// CHECK-DAG: ArrayLength
828 /// CHECK-DAG: BoundsCheck
829 /// CHECK-DAG: ArrayGet
830 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
831 /// CHECK-DAG: Deoptimize
832 /// CHECK-DAG: Deoptimize
833 /// CHECK-DAG: Deoptimize
834 /// CHECK-NOT: NullCheck
835 /// CHECK-NOT: ArrayLength
836 /// CHECK-NOT: BoundsCheck
837 /// CHECK-DAG: ArrayGet
838 private static int wrapAroundDynamicBCE(int[] x) {
839 int w = 9;
840 int result = 0;
841 for (int i = 0; i < 10; i++) {
842 result += x[w];
843 w = i;
844 }
845 return result;
846 }
847
848 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (before)
849 /// CHECK-DAG: NullCheck
850 /// CHECK-DAG: ArrayLength
851 /// CHECK-DAG: BoundsCheck
852 /// CHECK-DAG: ArrayGet
853 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
854 /// CHECK-DAG: Deoptimize
855 /// CHECK-DAG: Deoptimize
856 /// CHECK-DAG: Deoptimize
857 /// CHECK-NOT: NullCheck
858 /// CHECK-NOT: ArrayLength
859 /// CHECK-NOT: BoundsCheck
860 /// CHECK-DAG: ArrayGet
861 private static int periodicDynamicBCE(int[] x) {
862 int k = 0;
863 int result = 0;
864 for (int i = 0; i < 10; i++) {
865 result += x[k];
866 k = 1 - k;
867 }
868 return result;
869 }
870
871 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
872 /// CHECK-DAG: NullCheck
873 /// CHECK-DAG: ArrayLength
874 /// CHECK-DAG: BoundsCheck
875 /// CHECK-DAG: ArrayGet
876 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
877 /// CHECK-NOT: NullCheck
878 /// CHECK-NOT: ArrayLength
879 /// CHECK-NOT: BoundsCheck
880 /// CHECK-DAG: ArrayGet
881 /// CHECK-DAG: Exit
882 /// CHECK-DAG: Deoptimize
883 /// CHECK-DAG: Deoptimize
884 /// CHECK-DAG: Deoptimize
885 static int dynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
886 // This loop could be infinite for hi = max int. Since i is also used
887 // as subscript, however, dynamic bce can proceed.
888 int result = 0;
889 for (int i = lo; i <= hi; i++) {
890 result += x[i];
891 }
892 return result;
893 }
894
895 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
896 /// CHECK-DAG: NullCheck
897 /// CHECK-DAG: ArrayLength
898 /// CHECK-DAG: BoundsCheck
899 /// CHECK-DAG: ArrayGet
900 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
901 /// CHECK-DAG: NullCheck
902 /// CHECK-DAG: ArrayLength
903 /// CHECK-DAG: BoundsCheck
904 /// CHECK-DAG: ArrayGet
905 /// CHECK-NOT: Deoptimize
906 static int noDynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
907 // As above, but now the index is not used as subscript,
908 // and dynamic bce is not applied.
909 int result = 0;
910 for (int k = 0, i = lo; i <= hi; i++) {
911 result += x[k++];
912 }
913 return result;
914 }
915
916 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (before)
917 /// CHECK-DAG: NullCheck
918 /// CHECK-DAG: ArrayLength
919 /// CHECK-DAG: BoundsCheck
920 /// CHECK-DAG: ArrayGet
921 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
922 /// CHECK-DAG: NullCheck
923 /// CHECK-DAG: ArrayLength
924 /// CHECK-DAG: BoundsCheck
925 /// CHECK-DAG: ArrayGet
926 /// CHECK-NOT: Deoptimize
927 static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) {
928 int result = 0;
929 // Mix of int and long induction.
930 int k = 0;
931 for (long i = lo; i < hi; i++) {
932 result += x[k++];
933 }
934 return result;
935 }
936
937 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (before)
938 /// CHECK-DAG: NullCheck
939 /// CHECK-DAG: ArrayLength
940 /// CHECK-DAG: NotEqual
941 /// CHECK-DAG: If
942 /// CHECK-DAG: If
943 /// CHECK-DAG: NullCheck
944 /// CHECK-DAG: ArrayLength
945 /// CHECK-DAG: BoundsCheck
946 /// CHECK-DAG: ArrayGet
947 /// CHECK-DAG: If
948 /// CHECK-DAG: BoundsCheck
949 /// CHECK-DAG: BoundsCheck
950 /// CHECK-DAG: BoundsCheck
951 /// CHECK-DAG: BoundsCheck
952 /// CHECK-DAG: BoundsCheck
953 /// CHECK-DAG: BoundsCheck
954 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
955 /// CHECK-DAG: NullCheck
956 /// CHECK-DAG: ArrayLength
957 /// CHECK-DAG: NotEqual
958 /// CHECK-DAG: If
959 /// CHECK-DAG: If
960 /// CHECK-NOT: BoundsCheck
961 /// CHECK-DAG: ArrayGet
962 /// CHECK-DAG: If
963 /// CHECK-DAG: Deoptimize
964 /// CHECK-DAG: BoundsCheck
965 /// CHECK-DAG: BoundsCheck
966 /// CHECK-DAG: BoundsCheck
967 /// CHECK-NOT: BoundsCheck
968 /// CHECK-DAG: Exit
969 /// CHECK-DAG: Deoptimize
970 /// CHECK-DAG: Deoptimize
971 /// CHECK-DAG: Deoptimize
972 /// CHECK-NOT: ArrayGet
973 static int dynamicBCEAndConstantIndices(int[] x, int[][] a, int lo, int hi) {
974 // Deliberately test array length on a before the loop so that only bounds checks
975 // on constant subscripts remain, making them a viable candidate for hoisting.
976 if (a.length == 0) {
977 return -1;
978 }
979 // Loop that allows BCE on x[i].
980 int result = 0;
981 for (int i = lo; i < hi; i++) {
982 result += x[i];
983 if ((i % 10) != 0) {
984 // None of the subscripts inside a conditional are removed by dynamic bce,
985 // making them a candidate for deoptimization based on constant indices.
986 // Compiler should ensure the array loads are not subsequently hoisted
987 // "above" the deoptimization "barrier" on the bounds.
988 a[0][i] = 1;
989 a[1][i] = 2;
990 a[99][i] = 3;
991 }
992 }
993 return result;
994 }
995
996 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], java.lang.Integer[], int, int) BCE (before)
997 /// CHECK-DAG: If
998 /// CHECK-DAG: BoundsCheck
999 /// CHECK-DAG: ArrayGet
1000 /// CHECK-DAG: BoundsCheck
1001 /// CHECK-DAG: ArrayGet
1002 /// CHECK-DAG: BoundsCheck
1003 /// CHECK-DAG: ArrayGet
1004 /// CHECK-DAG: BoundsCheck
1005 /// CHECK-DAG: ArrayGet
1006 /// CHECK-DAG: BoundsCheck
1007 /// CHECK-DAG: ArrayGet
1008 /// CHECK-DAG: BoundsCheck
1009 /// CHECK-DAG: ArrayGet
1010 /// CHECK-DAG: BoundsCheck
1011 /// CHECK-DAG: ArrayGet
1012 /// CHECK-DAG: BoundsCheck
1013 /// CHECK-DAG: ArrayGet
1014 /// CHECK-DAG: BoundsCheck
1015 /// CHECK-DAG: ArrayGet
1016 /// CHECK-DAG: BoundsCheck
1017 /// CHECK-DAG: ArrayGet
1018 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], java.lang.Integer[], int, int) BCE (after)
1019 /// CHECK-DAG: If
1020 /// CHECK-NOT: BoundsCheck
1021 /// CHECK-DAG: ArrayGet
1022 /// CHECK-NOT: BoundsCheck
1023 /// CHECK-NOT: ArrayGet
1024 /// CHECK-DAG: Exit
1025 /// CHECK-DAG: Deoptimize
1026 /// CHECK-DAG: Deoptimize
1027 /// CHECK-DAG: Deoptimize
1028 /// CHECK-DAG: Deoptimize
1029 /// CHECK-DAG: Deoptimize
1030 /// CHECK-DAG: ArrayGet
1031 /// CHECK-DAG: Deoptimize
1032 /// CHECK-DAG: Deoptimize
1033 /// CHECK-DAG: ArrayGet
1034 /// CHECK-DAG: Deoptimize
1035 /// CHECK-DAG: Deoptimize
1036 /// CHECK-DAG: ArrayGet
1037 /// CHECK-DAG: Deoptimize
1038 /// CHECK-DAG: Deoptimize
1039 /// CHECK-DAG: ArrayGet
1040 /// CHECK-DAG: Deoptimize
1041 /// CHECK-DAG: Deoptimize
1042 /// CHECK-DAG: ArrayGet
1043 /// CHECK-DAG: Deoptimize
1044 /// CHECK-DAG: Deoptimize
1045 /// CHECK-DAG: ArrayGet
1046 /// CHECK-DAG: Deoptimize
1047 /// CHECK-DAG: Deoptimize
1048 /// CHECK-DAG: ArrayGet
1049 /// CHECK-DAG: Deoptimize
1050 /// CHECK-DAG: Deoptimize
1051 /// CHECK-DAG: ArrayGet
1052 /// CHECK-DAG: Deoptimize
1053 /// CHECK-DAG: Deoptimize
1054 /// CHECK-DAG: ArrayGet
1055 static int dynamicBCEAndConstantIndicesAllTypes(int[] q,
1056 boolean[] r,
1057 byte[] s,
1058 char[] t,
1059 short[] u,
1060 int[] v,
1061 long[] w,
1062 float[] x,
1063 double[] y,
1064 Integer[] z, int lo, int hi) {
1065 int result = 0;
1066 for (int i = lo; i < hi; i++) {
1067 result += q[i] + (r[0] ? 1 : 0) + (int) s[0] + (int) t[0] + (int) u[0] + (int) v[0] +
1068 (int) w[0] + (int) x[0] + (int) y[0] + (int) z[0];
1069 }
1070 return result;
1071 }
1072
Aart Bik22af3be2015-09-10 12:50:58 -07001073 //
1074 // Verifier.
1075 //
1076
1077 public static void main(String[] args) {
1078 int[] empty = { };
1079 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1080
1081 // Linear and wrap-around.
1082 expectEquals(0, linear(empty));
1083 expectEquals(55, linear(x));
1084 expectEquals(0, linearDown(empty));
1085 expectEquals(55, linearDown(x));
1086 expectEquals(0, linearObscure(empty));
1087 expectEquals(55, linearObscure(x));
Aart Bikf475bee2015-09-16 12:50:25 -07001088 expectEquals(0, linearVeryObscure(empty));
1089 expectEquals(55, linearVeryObscure(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001090 expectEquals(0, linearWhile(empty));
1091 expectEquals(55, linearWhile(x));
Aart Bikf475bee2015-09-16 12:50:25 -07001092 expectEquals(0, linearThreeWayPhi(empty));
1093 expectEquals(50, linearThreeWayPhi(x));
1094 expectEquals(0, linearFourWayPhi(empty));
1095 expectEquals(51, linearFourWayPhi(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001096 expectEquals(0, wrapAroundThenLinear(empty));
1097 expectEquals(55, wrapAroundThenLinear(x));
Aart Bikf475bee2015-09-16 12:50:25 -07001098 expectEquals(0, wrapAroundThenLinearThreeWayPhi(empty));
1099 expectEquals(54, wrapAroundThenLinearThreeWayPhi(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001100
1101 // Linear with parameter.
1102 sResult = 0;
1103 try {
1104 linearWithParameter(-1);
1105 } catch (NegativeArraySizeException e) {
1106 sResult = 1;
1107 }
1108 expectEquals(1, sResult);
1109 for (int n = 0; n < 32; n++) {
1110 int[] r = linearWithParameter(n);
1111 expectEquals(n, r.length);
1112 for (int i = 0; i < n; i++) {
1113 expectEquals(i, r[i]);
1114 }
1115 }
1116
Aart Bikf475bee2015-09-16 12:50:25 -07001117 // Linear copy.
1118 expectEquals(0, linearCopy(empty).length);
1119 {
1120 int[] r = linearCopy(x);
1121 expectEquals(x.length, r.length);
1122 for (int i = 0; i < x.length; i++) {
1123 expectEquals(x[i], r[i]);
1124 }
1125 }
1126
Aart Bik22af3be2015-09-10 12:50:58 -07001127 // Linear with non-unit strides.
Aart Bik4a342772015-11-30 10:17:46 -08001128 expectEquals(55, linearByTwo(x));
1129 expectEquals(25, linearByTwoSkip1(x));
1130 expectEquals(25, linearByTwoSkip2(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001131 expectEquals(56, linearWithCompoundStride());
1132 expectEquals(66, linearWithLargePositiveStride());
1133 expectEquals(66, linearWithVeryLargePositiveStride());
1134 expectEquals(66, linearWithLargeNegativeStride());
1135 expectEquals(66, linearWithVeryLargeNegativeStride());
1136
Aart Bikf475bee2015-09-16 12:50:25 -07001137 // Special forms.
Aart Bik9401f532015-09-28 16:25:56 -07001138 expectEquals(55, linearForNEUp());
1139 expectEquals(55, linearForNEDown());
1140 expectEquals(55, linearDoWhileUp());
1141 expectEquals(55, linearDoWhileDown());
Aart Bikf475bee2015-09-16 12:50:25 -07001142 expectEquals(55, linearShort());
Aart Bik4a342772015-11-30 10:17:46 -08001143 expectEquals(55, invariantFromPreLoop(x, 1));
Aart Bikb738d4f2015-12-03 11:23:35 -08001144 linearTriangularOnTwoArrayLengths(10);
1145 linearTriangularOnOneArrayLength(10);
1146 linearTriangularOnParameter(10);
1147
1148 // Sorting.
1149 int[] sort = { 5, 4, 1, 9, 10, 2, 7, 6, 3, 8 };
1150 bubble(sort);
1151 for (int i = 0; i < 10; i++) {
1152 expectEquals(sort[i], x[i]);
1153 }
Aart Bikf475bee2015-09-16 12:50:25 -07001154
Aart Bik22af3be2015-09-10 12:50:58 -07001155 // Periodic adds (1, 3), one at the time.
1156 expectEquals(0, periodicIdiom(-1));
1157 for (int tc = 0; tc < 32; tc++) {
1158 int expected = (tc >> 1) << 2;
1159 if ((tc & 1) != 0)
1160 expected += 1;
1161 expectEquals(expected, periodicIdiom(tc));
1162 }
1163
1164 // Periodic adds (1, 3), one at the time.
1165 expectEquals(0, periodicSequence2(-1));
1166 for (int tc = 0; tc < 32; tc++) {
1167 int expected = (tc >> 1) << 2;
1168 if ((tc & 1) != 0)
1169 expected += 1;
1170 expectEquals(expected, periodicSequence2(tc));
1171 }
1172
1173 // Periodic adds (1, 3, 5, 7), all at once.
1174 expectEquals(0, periodicSequence4(-1));
1175 for (int tc = 0; tc < 32; tc++) {
1176 expectEquals(tc * 16, periodicSequence4(tc));
1177 }
1178
Aart Bikf475bee2015-09-16 12:50:25 -07001179 // Large bounds.
1180 expectEquals(55, justRightUp1());
1181 expectEquals(55, justRightUp2());
1182 expectEquals(55, justRightUp3());
1183 expectEquals(55, justRightDown1());
1184 expectEquals(55, justRightDown2());
1185 expectEquals(55, justRightDown3());
1186 sResult = 0;
1187 try {
1188 justOOBUp();
1189 } catch (ArrayIndexOutOfBoundsException e) {
1190 sResult = 1;
1191 }
1192 expectEquals(1, sResult);
1193 sResult = 0;
1194 try {
1195 justOOBDown();
1196 } catch (ArrayIndexOutOfBoundsException e) {
1197 sResult = 1;
1198 }
1199 expectEquals(1, sResult);
1200
Aart Bik22af3be2015-09-10 12:50:58 -07001201 // Lower bound goes OOB.
1202 sResult = 0;
1203 try {
1204 lowerOOB(x);
1205 } catch (ArrayIndexOutOfBoundsException e) {
1206 sResult += 1000;
1207 }
1208 expectEquals(1000, sResult);
1209
1210 // Upper bound goes OOB.
1211 sResult = 0;
1212 try {
1213 upperOOB(x);
1214 } catch (ArrayIndexOutOfBoundsException e) {
1215 sResult += 1000;
1216 }
1217 expectEquals(1055, sResult);
1218
Aart Bik9401f532015-09-28 16:25:56 -07001219 // Do while up goes OOB.
1220 sResult = 0;
1221 try {
1222 doWhileUpOOB();
1223 } catch (ArrayIndexOutOfBoundsException e) {
1224 sResult += 1000;
1225 }
1226 expectEquals(1055, sResult);
1227
1228 // Do while down goes OOB.
1229 sResult = 0;
1230 try {
1231 doWhileDownOOB();
1232 } catch (ArrayIndexOutOfBoundsException e) {
1233 sResult += 1000;
1234 }
1235 expectEquals(1055, sResult);
Aart Bik4a342772015-11-30 10:17:46 -08001236
1237 // Dynamic BCE.
1238 sResult = 0;
1239 try {
1240 linearDynamicBCE1(x, -1, x.length);
1241 } catch (ArrayIndexOutOfBoundsException e) {
1242 sResult += 1000;
1243 }
1244 expectEquals(1000, sResult);
1245 sResult = 0;
1246 linearDynamicBCE1(x, 0, x.length);
1247 expectEquals(55, sResult);
1248 sResult = 0;
1249 try {
1250 linearDynamicBCE1(x, 0, x.length + 1);
1251 } catch (ArrayIndexOutOfBoundsException e) {
1252 sResult += 1000;
1253 }
1254 expectEquals(1055, sResult);
1255
1256 // Dynamic BCE with offset.
1257 sResult = 0;
1258 try {
1259 linearDynamicBCE2(x, 0, x.length, -1);
1260 } catch (ArrayIndexOutOfBoundsException e) {
1261 sResult += 1000;
1262 }
1263 expectEquals(1000, sResult);
1264 sResult = 0;
1265 linearDynamicBCE2(x, 0, x.length, 0);
1266 expectEquals(55, sResult);
1267 sResult = 0;
1268 try {
1269 linearDynamicBCE2(x, 0, x.length, 1);
1270 } catch (ArrayIndexOutOfBoundsException e) {
1271 sResult += 1000;
1272 }
1273 expectEquals(1054, sResult);
1274
1275 // Dynamic BCE candidates.
1276 expectEquals(55, wrapAroundDynamicBCE(x));
1277 expectEquals(15, periodicDynamicBCE(x));
1278 expectEquals(55, dynamicBCEPossiblyInfiniteLoop(x, 0, 9));
1279 expectEquals(55, noDynamicBCEPossiblyInfiniteLoop(x, 0, 9));
1280 expectEquals(55, noDynamicBCEMixedInductionTypes(x, 0, 10));
1281
1282 // Dynamic BCE combined with constant indices.
1283 int[][] a;
1284 a = new int[0][0];
1285 expectEquals(-1, dynamicBCEAndConstantIndices(x, a, 0, 10));
1286 a = new int[100][10];
1287 expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
1288 for (int i = 0; i < 10; i++) {
1289 expectEquals((i % 10) != 0 ? 1 : 0, a[0][i]);
1290 expectEquals((i % 10) != 0 ? 2 : 0, a[1][i]);
1291 expectEquals((i % 10) != 0 ? 3 : 0, a[99][i]);
1292 }
1293 a = new int[2][10];
1294 sResult = 0;
1295 try {
1296 expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
1297 } catch (ArrayIndexOutOfBoundsException e) {
1298 sResult = 1;
1299 }
1300 expectEquals(1, sResult);
1301 expectEquals(a[0][1], 1);
1302 expectEquals(a[1][1], 2);
1303
1304 // Dynamic BCE combined with constant indices of all types.
1305 boolean[] x1 = { true };
1306 byte[] x2 = { 2 };
1307 char[] x3 = { 3 };
1308 short[] x4 = { 4 };
1309 int[] x5 = { 5 };
1310 long[] x6 = { 6 };
1311 float[] x7 = { 7 };
1312 double[] x8 = { 8 };
1313 Integer[] x9 = { 9 };
1314 expectEquals(505,
1315 dynamicBCEAndConstantIndicesAllTypes(x, x1, x2, x3, x4, x5, x6, x7, x8, x9, 0, 10));
Aart Bik22af3be2015-09-10 12:50:58 -07001316 }
1317
1318 private static void expectEquals(int expected, int result) {
1319 if (expected != result) {
1320 throw new Error("Expected: " + expected + ", found: " + result);
1321 }
1322 }
1323}