blob: 0c32491e4e1fb85c49edaaff0a5684062f2b6029 [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
397 /// CHECK-START: int Main.linearDoWhileUp() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800398 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800399 //
Aart Bik9401f532015-09-28 16:25:56 -0700400 /// CHECK-START: int Main.linearDoWhileUp() BCE (after)
401 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800402 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700403 private static int linearDoWhileUp() {
Aart Bikf475bee2015-09-16 12:50:25 -0700404 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
405 int result = 0;
406 int i = 0;
Aart Bikf475bee2015-09-16 12:50:25 -0700407 do {
408 result += x[i++];
409 } while (i < 10);
410 return result;
411 }
412
Aart Bik9401f532015-09-28 16:25:56 -0700413 /// CHECK-START: int Main.linearDoWhileDown() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800414 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800415 //
Aart Bik9401f532015-09-28 16:25:56 -0700416 /// CHECK-START: int Main.linearDoWhileDown() BCE (after)
417 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800418 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700419 private static int linearDoWhileDown() {
420 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
421 int result = 0;
422 int i = 9;
423 do {
424 result += x[i--];
425 } while (0 <= i);
426 return result;
427 }
428
Aart Bikf475bee2015-09-16 12:50:25 -0700429 /// CHECK-START: int Main.linearShort() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800430 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800431 //
Aart Bikf475bee2015-09-16 12:50:25 -0700432 /// CHECK-START: int Main.linearShort() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800433 /// CHECK-DAG: BoundsCheck
434 //
435 /// CHECK-START: int Main.linearShort() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800436 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700437 private static int linearShort() {
438 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
439 int result = 0;
440 // TODO: make this work
441 for (short i = 0; i < 10; i++) {
442 result += x[i];
443 }
444 return result;
445 }
446
Aart Bik4a342772015-11-30 10:17:46 -0800447 /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800448 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800449 //
Aart Bik4a342772015-11-30 10:17:46 -0800450 /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (after)
451 /// CHECK-NOT: BoundsCheck
452 /// CHECK-NOT: Deoptimize
453 private static int invariantFromPreLoop(int[] x, int y) {
454 int result = 0;
455 // Strange pre-loop that sets upper bound.
456 int hi;
457 while (true) {
458 y = y % 3;
459 hi = x.length;
460 if (y != 123) break;
461 }
462 for (int i = 0; i < hi; i++) {
463 result += x[i];
464 }
465 return result;
466 }
467
Aart Bikb738d4f2015-12-03 11:23:35 -0800468 /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800469 /// CHECK-DAG: BoundsCheck
470 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800471 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800472 /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (after)
473 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800474 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
Aart Bikb738d4f2015-12-03 11:23:35 -0800475 private static void linearTriangularOnTwoArrayLengths(int n) {
476 int[] a = new int[n];
477 for (int i = 0; i < a.length; i++) {
478 int[] b = new int[i];
479 for (int j = 0; j < b.length; j++) {
480 // Need to know j < b.length < a.length for static bce.
481 a[j] += 1;
482 // Need to know just j < b.length for static bce.
483 b[j] += 1;
484 }
485 verifyTriangular(a, b, i, n);
486 }
487 }
488
489 /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800490 /// CHECK-DAG: BoundsCheck
491 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800492 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800493 /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (after)
494 /// CHECK-NOT: BoundsCheck
Aart Bikb738d4f2015-12-03 11:23:35 -0800495 /// CHECK-NOT: Deoptimize
496 private static void linearTriangularOnOneArrayLength(int n) {
497 int[] a = new int[n];
498 for (int i = 0; i < a.length; i++) {
499 int[] b = new int[i];
500 for (int j = 0; j < i; j++) {
501 // Need to know j < i < a.length for static bce.
502 a[j] += 1;
503 // Need to know just j < i for static bce.
504 b[j] += 1;
505 }
506 verifyTriangular(a, b, i, n);
507 }
508 }
509
510 /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800511 /// CHECK-DAG: BoundsCheck
512 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800513 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800514 /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (after)
515 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800516 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
Aart Bikb738d4f2015-12-03 11:23:35 -0800517 private static void linearTriangularOnParameter(int n) {
518 int[] a = new int[n];
519 for (int i = 0; i < n; i++) {
520 int[] b = new int[i];
521 for (int j = 0; j < i; j++) {
522 // Need to know j < i < n for static bce.
523 a[j] += 1;
524 // Need to know just j < i for static bce.
525 b[j] += 1;
526 }
527 verifyTriangular(a, b, i, n);
528 }
529 }
530
Aart Bik97412c922016-02-19 20:14:38 -0800531 /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800532 /// CHECK-DAG: BoundsCheck
533 /// CHECK-DAG: BoundsCheck
534 /// CHECK-DAG: BoundsCheck
535 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800536 //
Aart Bik97412c922016-02-19 20:14:38 -0800537 /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (after)
Aart Bik7d57d7f2015-12-09 14:39:48 -0800538 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800539 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
540 private static void linearTriangularVariationsInnerStrict(int n) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800541 int[] a = new int[n];
542 for (int i = 0; i < n; i++) {
543 for (int j = 0; j < i; j++) {
544 a[j] += 1;
545 }
Aart Bik97412c922016-02-19 20:14:38 -0800546 for (int j = i - 1; j > -1; j--) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800547 a[j] += 1;
548 }
549 for (int j = i; j < n; j++) {
550 a[j] += 1;
551 }
552 for (int j = n - 1; j > i - 1; j--) {
553 a[j] += 1;
554 }
555 }
556 verifyTriangular(a);
557 }
558
Aart Bik97412c922016-02-19 20:14:38 -0800559 /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (before)
560 /// CHECK-DAG: BoundsCheck
561 /// CHECK-DAG: BoundsCheck
562 /// CHECK-DAG: BoundsCheck
563 /// CHECK-DAG: BoundsCheck
564 //
565 /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (after)
566 /// CHECK-NOT: BoundsCheck
567 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
568 private static void linearTriangularVariationsInnerNonStrict(int n) {
569 int[] a = new int[n];
570 for (int i = 0; i < n; i++) {
571 for (int j = 0; j <= i - 1; j++) {
572 a[j] += 1;
573 }
574 for (int j = i - 1; j >= 0; j--) {
575 a[j] += 1;
576 }
577 for (int j = i; j <= n - 1; j++) {
578 a[j] += 1;
579 }
580 for (int j = n - 1; j >= i; j--) {
581 a[j] += 1;
582 }
583 }
584 verifyTriangular(a);
585 }
586
Aart Bik7d57d7f2015-12-09 14:39:48 -0800587 // Verifier for triangular loops.
Aart Bikb738d4f2015-12-03 11:23:35 -0800588 private static void verifyTriangular(int[] a, int[] b, int m, int n) {
589 expectEquals(n, a.length);
590 for (int i = 0, k = m; i < n; i++) {
591 expectEquals(a[i], k);
592 if (k > 0) k--;
593 }
594 expectEquals(m, b.length);
595 for (int i = 0; i < m; i++) {
596 expectEquals(b[i], 1);
597 }
598 }
599
Aart Bik7d57d7f2015-12-09 14:39:48 -0800600 // Verifier for triangular loops.
601 private static void verifyTriangular(int[] a) {
602 int n = a.length;
603 for (int i = 0; i < n; i++) {
604 expectEquals(a[i], n + n);
605 }
606 }
607
Aart Bikb738d4f2015-12-03 11:23:35 -0800608 /// CHECK-START: void Main.bubble(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800609 /// CHECK-DAG: BoundsCheck
610 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800611 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800612 /// CHECK-START: void Main.bubble(int[]) BCE (after)
613 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800614 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
Aart Bikb738d4f2015-12-03 11:23:35 -0800615 private static void bubble(int[] a) {
616 for (int i = a.length; --i >= 0;) {
617 for (int j = 0; j < i; j++) {
618 if (a[j] > a[j+1]) {
619 int tmp = a[j];
620 a[j] = a[j+1];
621 a[j+1] = tmp;
622 }
623 }
624 }
625 }
626
Aart Bik22af3be2015-09-10 12:50:58 -0700627 /// CHECK-START: int Main.periodicIdiom(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800628 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800629 //
Aart Bik22af3be2015-09-10 12:50:58 -0700630 /// CHECK-START: int Main.periodicIdiom(int) BCE (after)
631 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800632 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700633 private static int periodicIdiom(int tc) {
634 int[] x = { 1, 3 };
635 // Loop with periodic sequence (0, 1).
636 int k = 0;
637 int result = 0;
638 for (int i = 0; i < tc; i++) {
639 result += x[k];
640 k = 1 - k;
641 }
642 return result;
643 }
644
645 /// CHECK-START: int Main.periodicSequence2(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800646 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800647 //
Aart Bik22af3be2015-09-10 12:50:58 -0700648 /// CHECK-START: int Main.periodicSequence2(int) BCE (after)
649 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800650 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700651 private static int periodicSequence2(int tc) {
652 int[] x = { 1, 3 };
653 // Loop with periodic sequence (0, 1).
654 int k = 0;
655 int l = 1;
656 int result = 0;
657 for (int i = 0; i < tc; i++) {
658 result += x[k];
659 int t = l;
660 l = k;
661 k = t;
662 }
663 return result;
664 }
665
666 /// CHECK-START: int Main.periodicSequence4(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800667 /// CHECK-DAG: BoundsCheck
668 /// CHECK-DAG: BoundsCheck
669 /// CHECK-DAG: BoundsCheck
670 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800671 //
Aart Bik22af3be2015-09-10 12:50:58 -0700672 /// CHECK-START: int Main.periodicSequence4(int) BCE (after)
673 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800674 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700675 private static int periodicSequence4(int tc) {
676 int[] x = { 1, 3, 5, 7 };
677 // Loop with periodic sequence (0, 1, 2, 3).
678 int k = 0;
679 int l = 1;
680 int m = 2;
681 int n = 3;
682 int result = 0;
683 for (int i = 0; i < tc; i++) {
684 result += x[k] + x[l] + x[m] + x[n]; // all used at once
685 int t = n;
686 n = k;
687 k = l;
688 l = m;
689 m = t;
690 }
691 return result;
692 }
693
Aart Bikf475bee2015-09-16 12:50:25 -0700694 /// CHECK-START: int Main.justRightUp1() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800695 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800696 //
Aart Bikf475bee2015-09-16 12:50:25 -0700697 /// CHECK-START: int Main.justRightUp1() BCE (after)
698 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800699 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700700 private static int justRightUp1() {
701 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
702 int result = 0;
703 for (int i = Integer.MAX_VALUE - 10, k = 0; i < Integer.MAX_VALUE; i++) {
704 result += x[k++];
705 }
706 return result;
707 }
708
709 /// CHECK-START: int Main.justRightUp2() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800710 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800711 //
Aart Bikf475bee2015-09-16 12:50:25 -0700712 /// CHECK-START: int Main.justRightUp2() BCE (after)
713 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800714 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700715 private static int justRightUp2() {
716 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
717 int result = 0;
718 for (int i = Integer.MAX_VALUE - 10; i < Integer.MAX_VALUE; i++) {
719 result += x[i - Integer.MAX_VALUE + 10];
720 }
721 return result;
722 }
723
724 /// CHECK-START: int Main.justRightUp3() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800725 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800726 //
Aart Bikf475bee2015-09-16 12:50:25 -0700727 /// CHECK-START: int Main.justRightUp3() BCE (after)
728 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800729 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700730 private static int justRightUp3() {
731 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
732 int result = 0;
733 for (int i = Integer.MAX_VALUE - 10, k = 0; i <= Integer.MAX_VALUE - 1; i++) {
734 result += x[k++];
735 }
736 return result;
737 }
738
739 /// CHECK-START: int Main.justOOBUp() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800740 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800741 //
Aart Bikf475bee2015-09-16 12:50:25 -0700742 /// CHECK-START: int Main.justOOBUp() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800743 /// CHECK-DAG: BoundsCheck
744 //
745 /// CHECK-START: int Main.justOOBUp() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800746 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700747 private static int justOOBUp() {
748 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
749 int result = 0;
750 // Infinite loop!
751 for (int i = Integer.MAX_VALUE - 9, k = 0; i <= Integer.MAX_VALUE; i++) {
752 result += x[k++];
753 }
754 return result;
755 }
756
757 /// CHECK-START: int Main.justRightDown1() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800758 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800759 //
Aart Bikf475bee2015-09-16 12:50:25 -0700760 /// CHECK-START: int Main.justRightDown1() BCE (after)
761 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800762 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700763 private static int justRightDown1() {
764 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
765 int result = 0;
766 for (int i = Integer.MIN_VALUE + 10, k = 0; i > Integer.MIN_VALUE; i--) {
767 result += x[k++];
768 }
769 return result;
770 }
771
772 /// CHECK-START: int Main.justRightDown2() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800773 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800774 //
Aart Bikf475bee2015-09-16 12:50:25 -0700775 /// CHECK-START: int Main.justRightDown2() BCE (after)
776 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800777 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700778 private static int justRightDown2() {
779 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
780 int result = 0;
781 for (int i = Integer.MIN_VALUE + 10; i > Integer.MIN_VALUE; i--) {
782 result += x[Integer.MAX_VALUE + i];
783 }
784 return result;
785 }
786
787 /// CHECK-START: int Main.justRightDown3() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800788 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800789 //
Aart Bikf475bee2015-09-16 12:50:25 -0700790 /// CHECK-START: int Main.justRightDown3() BCE (after)
791 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800792 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700793 private static int justRightDown3() {
794 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
795 int result = 0;
796 for (int i = Integer.MIN_VALUE + 10, k = 0; i >= Integer.MIN_VALUE + 1; i--) {
797 result += x[k++];
798 }
799 return result;
800 }
801
802 /// CHECK-START: int Main.justOOBDown() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800803 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800804 //
Aart Bikf475bee2015-09-16 12:50:25 -0700805 /// CHECK-START: int Main.justOOBDown() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800806 /// CHECK-DAG: BoundsCheck
807 //
808 /// CHECK-START: int Main.justOOBDown() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800809 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700810 private static int justOOBDown() {
811 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
812 int result = 0;
813 // Infinite loop!
814 for (int i = Integer.MIN_VALUE + 9, k = 0; i >= Integer.MIN_VALUE; i--) {
815 result += x[k++];
816 }
817 return result;
818 }
819
Aart Bik9401f532015-09-28 16:25:56 -0700820 /// CHECK-START: void Main.lowerOOB(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800821 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800822 //
Aart Bik9401f532015-09-28 16:25:56 -0700823 /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800824 /// CHECK-DAG: BoundsCheck
825 //
826 /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800827 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700828 private static void lowerOOB(int[] x) {
Aart Bik09e8d5f2016-01-22 16:49:55 -0800829 // OOB!
Aart Bik22af3be2015-09-10 12:50:58 -0700830 for (int i = -1; i < x.length; i++) {
831 sResult += x[i];
832 }
833 }
834
Aart Bik9401f532015-09-28 16:25:56 -0700835 /// CHECK-START: void Main.upperOOB(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800836 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800837 //
Aart Bik9401f532015-09-28 16:25:56 -0700838 /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800839 /// CHECK-DAG: BoundsCheck
840 //
841 /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800842 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700843 private static void upperOOB(int[] x) {
Aart Bik09e8d5f2016-01-22 16:49:55 -0800844 // OOB!
Aart Bik22af3be2015-09-10 12:50:58 -0700845 for (int i = 0; i <= x.length; i++) {
846 sResult += x[i];
847 }
848 }
849
Aart Bik9401f532015-09-28 16:25:56 -0700850 /// CHECK-START: void Main.doWhileUpOOB() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800851 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800852 //
Aart Bik9401f532015-09-28 16:25:56 -0700853 /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800854 /// CHECK-DAG: BoundsCheck
855 //
856 /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800857 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700858 private static void doWhileUpOOB() {
859 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
860 int i = 0;
Aart Bik09e8d5f2016-01-22 16:49:55 -0800861 // OOB!
Aart Bik9401f532015-09-28 16:25:56 -0700862 do {
863 sResult += x[i++];
864 } while (i <= x.length);
865 }
866
867 /// CHECK-START: void Main.doWhileDownOOB() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800868 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800869 //
Aart Bik9401f532015-09-28 16:25:56 -0700870 /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800871 /// CHECK-DAG: BoundsCheck
872 //
873 /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800874 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700875 private static void doWhileDownOOB() {
876 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
877 int i = x.length - 1;
Aart Bik09e8d5f2016-01-22 16:49:55 -0800878 // OOB!
Aart Bik9401f532015-09-28 16:25:56 -0700879 do {
880 sResult += x[i--];
881 } while (-1 <= i);
882 }
883
Aart Bik97412c922016-02-19 20:14:38 -0800884 /// CHECK-START: void Main.hiddenOOB1(int) BCE (before)
885 /// CHECK-DAG: BoundsCheck
886 //
887 /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
888 /// CHECK-DAG: Deoptimize
889 //
890 /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
891 /// CHECK-NOT: BoundsCheck
892 private static void hiddenOOB1(int lo) {
893 int[] a = { 1 } ;
894 for (int i = lo; i <= 10; i++) {
895 // Dangerous loop where careless static range analysis would yield strict upper bound
896 // on index j of 5. When, for instance, lo and thus i = -2147483648, the upper bound
897 // becomes really positive due to arithmetic wrap-around, causing OOB.
898 // Dynamic BCE is feasible though, since it checks the range.
899 for (int j = 4; j < i - 5; j++) {
900 sResult += a[j - 4];
901 }
902 }
903 }
904
905 /// CHECK-START: void Main.hiddenOOB2(int) BCE (before)
906 /// CHECK-DAG: BoundsCheck
907 //
908 /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
909 /// CHECK-DAG: Deoptimize
910 //
911 /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
912 /// CHECK-NOT: BoundsCheck
913 private static void hiddenOOB2(int hi) {
914 int[] a = { 1 } ;
915 for (int i = 0; i < hi; i++) {
916 // Dangerous loop where careless static range analysis would yield strict lower bound
Aart Bik6ab903c2016-02-24 15:18:55 -0800917 // on index j of 5. When, for instance, hi and thus i = 2147483647, the upper bound
Aart Bik97412c922016-02-19 20:14:38 -0800918 // becomes really negative due to arithmetic wrap-around, causing OOB.
919 // Dynamic BCE is feasible though, since it checks the range.
920 for (int j = 6; j > i + 5; j--) {
921 sResult += a[j - 6];
922 }
923 }
924 }
925
926 /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (before)
927 /// CHECK-DAG: BoundsCheck
928 //
929 /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
930 /// CHECK-DAG: BoundsCheck
931 //
932 /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
933 /// CHECK-NOT: Deoptimize
934 private static void hiddenInfiniteOOB() {
935 int[] a = { 11 } ;
936 for (int i = -1; i <= 0; i++) {
937 // Dangerous loop where careless static range analysis would yield a safe upper bound
938 // of -3. In reality, due to arithmetic wrap-around (when i = -1, j <= 2147483647;
939 // whereas when i = 0, j <= -3), this is an infinite loop that goes OOB.
940 for (int j = -3; j <= 2147483646 * i - 3; j++) {
941 sResult += a[j + 3];
942 }
943 }
944 }
945
946 /// CHECK-START: void Main.hiddenFiniteOOB() BCE (before)
947 /// CHECK-DAG: BoundsCheck
948 //
949 /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
950 /// CHECK-DAG: Deoptimize
951 //
952 /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
953 /// CHECK-NOT: BoundsCheck
954 private static void hiddenFiniteOOB() {
955 int[] a = { 111 } ;
956 for (int i = -1; i <= 0; i++) {
957 // Dangerous loop similar as above where the loop is now finite, but the
958 // loop still goes out of bounds for i = -1 due to the large upper bound.
959 // Dynamic BCE is feasible though, since it checks the range.
960 for (int j = -4; j < 2147483646 * i - 3; j++) {
961 sResult += a[j + 4];
962 }
963 }
964 }
965
966 /// CHECK-START: int[] Main.add() BCE (before)
967 /// CHECK-DAG: BoundsCheck
968 //
969 /// CHECK-START: int[] Main.add() BCE (after)
970 /// CHECK-NOT: BoundsCheck
971 /// CHECK-NOT: Deoptimize
972 private static int[] add() {
973 int[] a = new int[10];
974 for (int i = 0; i <= 3; i++) {
975 for (int j = 0; j <= 6; j++) {
976 a[i + j] += 1;
977 }
978 }
979 return a;
980 }
981
Aart Bik7d57d7f2015-12-09 14:39:48 -0800982 /// CHECK-START: int[] Main.multiply1() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800983 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800984 //
985 /// CHECK-START: int[] Main.multiply1() BCE (after)
986 /// CHECK-NOT: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800987 /// CHECK-NOT: Deoptimize
988 private static int[] multiply1() {
989 int[] a = new int[10];
990 try {
991 for (int i = 0; i <= 3; i++) {
992 for (int j = 0; j <= 3; j++) {
993 // Range [0,9]: safe.
994 a[i * j] += 1;
995 }
996 }
997 } catch (Exception e) {
998 a[0] += 1000;
999 }
1000 return a;
1001 }
1002
1003 /// CHECK-START: int[] Main.multiply2() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001004 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -08001005 //
1006 /// CHECK-START: int[] Main.multiply2() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001007 /// CHECK-DAG: BoundsCheck
1008 //
1009 /// CHECK-START: int[] Main.multiply2() BCE (after)
1010 /// CHECK-NOT: Deoptimize
Aart Bik7d57d7f2015-12-09 14:39:48 -08001011 static int[] multiply2() {
1012 int[] a = new int[10];
1013 try {
1014 for (int i = -3; i <= 3; i++) {
1015 for (int j = -3; j <= 3; j++) {
1016 // Range [-9,9]: unsafe.
Aart Bik09e8d5f2016-01-22 16:49:55 -08001017 a[i * j] += 1;
Aart Bik7d57d7f2015-12-09 14:39:48 -08001018 }
1019 }
1020 } catch (Exception e) {
1021 a[0] += 1000;
1022 }
1023 return a;
1024 }
1025
Aart Bik4a342772015-11-30 10:17:46 -08001026 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001027 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1028 /// CHECK-DAG: NullCheck loop:<<Loop>>
1029 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1030 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001031 //
Aart Bik4a342772015-11-30 10:17:46 -08001032 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001033 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1034 /// CHECK-DAG: Deoptimize loop:none
1035 //
1036 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
1037 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1038 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1039 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001040 private static int linearDynamicBCE1(int[] x, int lo, int hi) {
1041 int result = 0;
1042 for (int i = lo; i < hi; i++) {
1043 sResult += x[i];
1044 }
1045 return result;
1046 }
1047
1048 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001049 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1050 /// CHECK-DAG: NullCheck loop:<<Loop>>
1051 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1052 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001053 //
Aart Bik4a342772015-11-30 10:17:46 -08001054 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001055 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1056 /// CHECK-DAG: Deoptimize loop:none
1057 //
1058 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
1059 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1060 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1061 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001062 private static int linearDynamicBCE2(int[] x, int lo, int hi, int offset) {
1063 int result = 0;
1064 for (int i = lo; i < hi; i++) {
1065 sResult += x[offset + i];
1066 }
1067 return result;
1068 }
1069
1070 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001071 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1072 /// CHECK-DAG: NullCheck loop:<<Loop>>
1073 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1074 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001075 //
Aart Bik4a342772015-11-30 10:17:46 -08001076 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001077 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1078 /// CHECK-DAG: Deoptimize loop:none
1079 //
1080 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
1081 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1082 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1083 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001084 private static int wrapAroundDynamicBCE(int[] x) {
1085 int w = 9;
1086 int result = 0;
1087 for (int i = 0; i < 10; i++) {
1088 result += x[w];
1089 w = i;
1090 }
1091 return result;
1092 }
1093
1094 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001095 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1096 /// CHECK-DAG: NullCheck loop:<<Loop>>
1097 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1098 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001099 //
Aart Bik4a342772015-11-30 10:17:46 -08001100 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001101 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1102 /// CHECK-DAG: Deoptimize loop:none
1103 //
1104 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
1105 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1106 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1107 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001108 private static int periodicDynamicBCE(int[] x) {
1109 int k = 0;
1110 int result = 0;
1111 for (int i = 0; i < 10; i++) {
1112 result += x[k];
1113 k = 1 - k;
1114 }
1115 return result;
1116 }
1117
1118 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001119 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1120 /// CHECK-DAG: NullCheck loop:<<Loop>>
1121 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1122 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001123 //
Aart Bik4a342772015-11-30 10:17:46 -08001124 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001125 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
1126 /// CHECK-DAG: Deoptimize loop:none
1127 //
1128 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
1129 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1130 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1131 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
Aart Bik4a342772015-11-30 10:17:46 -08001132 static int dynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
1133 // This loop could be infinite for hi = max int. Since i is also used
1134 // as subscript, however, dynamic bce can proceed.
1135 int result = 0;
1136 for (int i = lo; i <= hi; i++) {
1137 result += x[i];
1138 }
1139 return result;
1140 }
1141
1142 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001143 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1144 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001145 //
Aart Bik4a342772015-11-30 10:17:46 -08001146 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001147 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1148 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
1149 //
1150 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -08001151 /// CHECK-NOT: Deoptimize
1152 static int noDynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
1153 // As above, but now the index is not used as subscript,
1154 // and dynamic bce is not applied.
1155 int result = 0;
1156 for (int k = 0, i = lo; i <= hi; i++) {
1157 result += x[k++];
1158 }
1159 return result;
1160 }
1161
1162 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001163 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1164 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001165 //
Aart Bik4a342772015-11-30 10:17:46 -08001166 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001167 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1168 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
1169 //
1170 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -08001171 /// CHECK-NOT: Deoptimize
1172 static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) {
1173 int result = 0;
1174 // Mix of int and long induction.
1175 int k = 0;
1176 for (long i = lo; i < hi; i++) {
1177 result += x[k++];
1178 }
1179 return result;
1180 }
1181
Aart Bik97412c922016-02-19 20:14:38 -08001182 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (before)
1183 /// CHECK-DAG: BoundsCheck loop:<<InnerLoop:B\d+>>
1184 /// CHECK-DAG: ArrayGet loop:<<InnerLoop>>
1185 /// CHECK-DAG: If loop:<<InnerLoop>>
1186 /// CHECK-DAG: If loop:<<OuterLoop:B\d+>>
1187 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
1188 //
1189 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
1190 /// CHECK-DAG: ArrayGet loop:<<InnerLoop:B\d+>>
1191 /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>>
1192 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
1193 //
1194 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
1195 /// CHECK-NOT: BoundsCheck
1196 //
1197 // No additional top tests were introduced.
1198 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
1199 /// CHECK-DAG: If
1200 /// CHECK-DAG: If
1201 /// CHECK-NOT: If
1202 static int dynamicBCEConstantRange(int[] x) {
1203 int result = 0;
1204 for (int i = 2; i <= 6; i++) {
1205 // Range analysis sees that innermost loop is finite and always taken.
1206 for (int j = i - 2; j <= i + 2; j++) {
1207 result += x[j];
1208 }
1209 }
1210 return result;
1211 }
1212
Aart Bik4a342772015-11-30 10:17:46 -08001213 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001214 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop:B\d+>>
1215 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
1216 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001217 //
Aart Bik4a342772015-11-30 10:17:46 -08001218 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -08001219 // Order matters:
1220 /// CHECK: Deoptimize loop:<<Loop:B\d+>>
1221 // CHECK-NOT: Goto loop:<<Loop>>
1222 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
1223 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
1224 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
1225 /// CHECK: Goto loop:<<Loop>>
1226 //
1227 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
1228 /// CHECK-DAG: Deoptimize loop:none
Aart Bik4a342772015-11-30 10:17:46 -08001229 static int dynamicBCEAndConstantIndices(int[] x, int[][] a, int lo, int hi) {
1230 // Deliberately test array length on a before the loop so that only bounds checks
1231 // on constant subscripts remain, making them a viable candidate for hoisting.
1232 if (a.length == 0) {
1233 return -1;
1234 }
1235 // Loop that allows BCE on x[i].
1236 int result = 0;
1237 for (int i = lo; i < hi; i++) {
1238 result += x[i];
1239 if ((i % 10) != 0) {
1240 // None of the subscripts inside a conditional are removed by dynamic bce,
1241 // making them a candidate for deoptimization based on constant indices.
1242 // Compiler should ensure the array loads are not subsequently hoisted
1243 // "above" the deoptimization "barrier" on the bounds.
1244 a[0][i] = 1;
1245 a[1][i] = 2;
1246 a[99][i] = 3;
1247 }
1248 }
1249 return result;
1250 }
1251
Aart Bik09e8d5f2016-01-22 16:49:55 -08001252 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (before)
1253 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1254 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1255 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1256 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1257 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1258 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1259 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1260 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1261 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1262 // For brevity, just test occurrence of at least one of each in the loop:
1263 /// CHECK-DAG: NullCheck loop:<<Loop>>
1264 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1265 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
Aart Bik7d57d7f2015-12-09 14:39:48 -08001266 //
Aart Bik09e8d5f2016-01-22 16:49:55 -08001267 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
1268 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1269 /// CHECK-NOT: ArrayGet loop:<<Loop>>
1270 //
1271 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
1272 /// CHECK-NOT: NullCheck loop:{{B\d+}}
1273 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1274 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
1275 //
1276 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
1277 /// CHECK-DAG: Deoptimize loop:none
1278 static int dynamicBCEAndConstantIndicesAllPrimTypes(int[] q,
1279 boolean[] r,
1280 byte[] s,
1281 char[] t,
1282 short[] u,
1283 int[] v,
1284 long[] w,
1285 float[] x,
1286 double[] y, int lo, int hi) {
Aart Bik4a342772015-11-30 10:17:46 -08001287 int result = 0;
1288 for (int i = lo; i < hi; i++) {
Aart Bik09e8d5f2016-01-22 16:49:55 -08001289 // All constant index array references can be hoisted out of the loop during BCE on q[i].
Aart Bik4a342772015-11-30 10:17:46 -08001290 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 -08001291 (int) w[0] + (int) x[0] + (int) y[0];
1292 }
1293 return result;
1294 }
1295
1296 /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (before)
1297 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1298 /// CHECK-DAG: NullCheck loop:<<Loop>>
1299 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1300 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
1301 /// CHECK-DAG: ArrayGet loop:<<Loop>>
1302 /// CHECK-DAG: NullCheck loop:<<Loop>>
1303 /// CHECK-DAG: ArrayLength loop:<<Loop>>
1304 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
1305 //
1306 /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
1307 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
1308 /// CHECK-DAG: Deoptimize loop:none
1309 //
1310 /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
1311 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
1312 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
1313 static int dynamicBCEAndConstantIndexRefType(int[] q, Integer[] z, int lo, int hi) {
1314 int result = 0;
1315 for (int i = lo; i < hi; i++) {
1316 // Similar to above, but now implicit call to intValue() may prevent hoisting
1317 // z[0] itself during BCE on q[i]. Therefore, we just check BCE on q[i].
1318 result += q[i] + z[0];
Aart Bik4a342772015-11-30 10:17:46 -08001319 }
1320 return result;
1321 }
1322
Aart Bik22af3be2015-09-10 12:50:58 -07001323 //
1324 // Verifier.
1325 //
1326
1327 public static void main(String[] args) {
Aart Bik6ab903c2016-02-24 15:18:55 -08001328 // Set to run expensive tests for correctness too.
1329 boolean HEAVY = false;
1330
Aart Bik22af3be2015-09-10 12:50:58 -07001331 int[] empty = { };
1332 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1333
1334 // Linear and wrap-around.
1335 expectEquals(0, linear(empty));
1336 expectEquals(55, linear(x));
1337 expectEquals(0, linearDown(empty));
1338 expectEquals(55, linearDown(x));
1339 expectEquals(0, linearObscure(empty));
1340 expectEquals(55, linearObscure(x));
Aart Bikf475bee2015-09-16 12:50:25 -07001341 expectEquals(0, linearVeryObscure(empty));
1342 expectEquals(55, linearVeryObscure(x));
Aart Bik7d57d7f2015-12-09 14:39:48 -08001343 expectEquals(0, hiddenStride(empty));
1344 expectEquals(55, hiddenStride(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001345 expectEquals(0, linearWhile(empty));
1346 expectEquals(55, linearWhile(x));
Aart Bikf475bee2015-09-16 12:50:25 -07001347 expectEquals(0, linearThreeWayPhi(empty));
1348 expectEquals(50, linearThreeWayPhi(x));
1349 expectEquals(0, linearFourWayPhi(empty));
1350 expectEquals(51, linearFourWayPhi(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001351 expectEquals(0, wrapAroundThenLinear(empty));
1352 expectEquals(55, wrapAroundThenLinear(x));
Aart Bikf475bee2015-09-16 12:50:25 -07001353 expectEquals(0, wrapAroundThenLinearThreeWayPhi(empty));
1354 expectEquals(54, wrapAroundThenLinearThreeWayPhi(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001355
1356 // Linear with parameter.
1357 sResult = 0;
1358 try {
1359 linearWithParameter(-1);
1360 } catch (NegativeArraySizeException e) {
1361 sResult = 1;
1362 }
1363 expectEquals(1, sResult);
1364 for (int n = 0; n < 32; n++) {
1365 int[] r = linearWithParameter(n);
1366 expectEquals(n, r.length);
1367 for (int i = 0; i < n; i++) {
1368 expectEquals(i, r[i]);
1369 }
1370 }
1371
Aart Bikf475bee2015-09-16 12:50:25 -07001372 // Linear copy.
1373 expectEquals(0, linearCopy(empty).length);
1374 {
1375 int[] r = linearCopy(x);
1376 expectEquals(x.length, r.length);
1377 for (int i = 0; i < x.length; i++) {
1378 expectEquals(x[i], r[i]);
1379 }
1380 }
1381
Aart Bik22af3be2015-09-10 12:50:58 -07001382 // Linear with non-unit strides.
Aart Bik4a342772015-11-30 10:17:46 -08001383 expectEquals(55, linearByTwo(x));
1384 expectEquals(25, linearByTwoSkip1(x));
1385 expectEquals(25, linearByTwoSkip2(x));
Aart Bik22af3be2015-09-10 12:50:58 -07001386 expectEquals(56, linearWithCompoundStride());
1387 expectEquals(66, linearWithLargePositiveStride());
1388 expectEquals(66, linearWithVeryLargePositiveStride());
1389 expectEquals(66, linearWithLargeNegativeStride());
1390 expectEquals(66, linearWithVeryLargeNegativeStride());
1391
Aart Bikf475bee2015-09-16 12:50:25 -07001392 // Special forms.
Aart Bik9401f532015-09-28 16:25:56 -07001393 expectEquals(55, linearForNEUp());
1394 expectEquals(55, linearForNEDown());
1395 expectEquals(55, linearDoWhileUp());
1396 expectEquals(55, linearDoWhileDown());
Aart Bikf475bee2015-09-16 12:50:25 -07001397 expectEquals(55, linearShort());
Aart Bik4a342772015-11-30 10:17:46 -08001398 expectEquals(55, invariantFromPreLoop(x, 1));
Aart Bikb738d4f2015-12-03 11:23:35 -08001399 linearTriangularOnTwoArrayLengths(10);
1400 linearTriangularOnOneArrayLength(10);
1401 linearTriangularOnParameter(10);
Aart Bik97412c922016-02-19 20:14:38 -08001402 linearTriangularVariationsInnerStrict(10);
1403 linearTriangularVariationsInnerNonStrict(10);
Aart Bikb738d4f2015-12-03 11:23:35 -08001404
1405 // Sorting.
1406 int[] sort = { 5, 4, 1, 9, 10, 2, 7, 6, 3, 8 };
1407 bubble(sort);
1408 for (int i = 0; i < 10; i++) {
1409 expectEquals(sort[i], x[i]);
1410 }
Aart Bikf475bee2015-09-16 12:50:25 -07001411
Aart Bik22af3be2015-09-10 12:50:58 -07001412 // Periodic adds (1, 3), one at the time.
1413 expectEquals(0, periodicIdiom(-1));
1414 for (int tc = 0; tc < 32; tc++) {
1415 int expected = (tc >> 1) << 2;
1416 if ((tc & 1) != 0)
1417 expected += 1;
1418 expectEquals(expected, periodicIdiom(tc));
1419 }
1420
1421 // Periodic adds (1, 3), one at the time.
1422 expectEquals(0, periodicSequence2(-1));
1423 for (int tc = 0; tc < 32; tc++) {
1424 int expected = (tc >> 1) << 2;
1425 if ((tc & 1) != 0)
1426 expected += 1;
1427 expectEquals(expected, periodicSequence2(tc));
1428 }
1429
1430 // Periodic adds (1, 3, 5, 7), all at once.
1431 expectEquals(0, periodicSequence4(-1));
1432 for (int tc = 0; tc < 32; tc++) {
1433 expectEquals(tc * 16, periodicSequence4(tc));
1434 }
1435
Aart Bikf475bee2015-09-16 12:50:25 -07001436 // Large bounds.
1437 expectEquals(55, justRightUp1());
1438 expectEquals(55, justRightUp2());
1439 expectEquals(55, justRightUp3());
1440 expectEquals(55, justRightDown1());
1441 expectEquals(55, justRightDown2());
1442 expectEquals(55, justRightDown3());
1443 sResult = 0;
1444 try {
1445 justOOBUp();
1446 } catch (ArrayIndexOutOfBoundsException e) {
1447 sResult = 1;
1448 }
1449 expectEquals(1, sResult);
1450 sResult = 0;
1451 try {
1452 justOOBDown();
1453 } catch (ArrayIndexOutOfBoundsException e) {
1454 sResult = 1;
1455 }
1456 expectEquals(1, sResult);
1457
Aart Bik22af3be2015-09-10 12:50:58 -07001458 // Lower bound goes OOB.
1459 sResult = 0;
1460 try {
1461 lowerOOB(x);
1462 } catch (ArrayIndexOutOfBoundsException e) {
1463 sResult += 1000;
1464 }
1465 expectEquals(1000, sResult);
1466
1467 // Upper bound goes OOB.
1468 sResult = 0;
1469 try {
1470 upperOOB(x);
1471 } catch (ArrayIndexOutOfBoundsException e) {
1472 sResult += 1000;
1473 }
1474 expectEquals(1055, sResult);
1475
Aart Bik9401f532015-09-28 16:25:56 -07001476 // Do while up goes OOB.
1477 sResult = 0;
1478 try {
1479 doWhileUpOOB();
1480 } catch (ArrayIndexOutOfBoundsException e) {
1481 sResult += 1000;
1482 }
1483 expectEquals(1055, sResult);
1484
1485 // Do while down goes OOB.
1486 sResult = 0;
1487 try {
1488 doWhileDownOOB();
1489 } catch (ArrayIndexOutOfBoundsException e) {
1490 sResult += 1000;
1491 }
1492 expectEquals(1055, sResult);
Aart Bik4a342772015-11-30 10:17:46 -08001493
Aart Bik97412c922016-02-19 20:14:38 -08001494 // Hidden OOB.
1495 sResult = 0;
1496 try {
1497 hiddenOOB1(10); // no OOB
1498 } catch (ArrayIndexOutOfBoundsException e) {
1499 sResult += 1000;
1500 }
1501 expectEquals(1, sResult);
1502 sResult = 0;
1503 try {
1504 hiddenOOB1(-2147483648); // OOB
1505 } catch (ArrayIndexOutOfBoundsException e) {
1506 sResult += 1000;
1507 }
1508 expectEquals(1001, sResult);
1509 sResult = 0;
1510 try {
1511 hiddenOOB2(1); // no OOB
1512 } catch (ArrayIndexOutOfBoundsException e) {
1513 sResult += 1000;
1514 }
1515 expectEquals(1, sResult);
Aart Bik6ab903c2016-02-24 15:18:55 -08001516 if (HEAVY) {
1517 sResult = 0;
1518 try {
1519 hiddenOOB2(2147483647); // OOB
1520 } catch (ArrayIndexOutOfBoundsException e) {
1521 sResult += 1000;
1522 }
1523 expectEquals(1002, sResult);
Aart Bik97412c922016-02-19 20:14:38 -08001524 }
Aart Bik97412c922016-02-19 20:14:38 -08001525 sResult = 0;
1526 try {
1527 hiddenInfiniteOOB();
1528 } catch (ArrayIndexOutOfBoundsException e) {
1529 sResult += 1000;
1530 }
1531 expectEquals(1011, sResult);
1532 sResult = 0;
1533 try {
1534 hiddenFiniteOOB();
1535 } catch (ArrayIndexOutOfBoundsException e) {
1536 sResult += 1000;
1537 }
1538 expectEquals(1111, sResult);
1539
1540 // Addition.
1541 {
1542 int[] e1 ={ 1, 2, 3, 4, 4, 4, 4, 3, 2, 1 };
1543 int[] a1 = add();
1544 for (int i = 0; i < 10; i++) {
1545 expectEquals(a1[i], e1[i]);
1546 }
1547 }
1548
Aart Bik7d57d7f2015-12-09 14:39:48 -08001549 // Multiplication.
1550 {
1551 int[] e1 = { 7, 1, 2, 2, 1, 0, 2, 0, 0, 1 };
1552 int[] a1 = multiply1();
1553 for (int i = 0; i < 10; i++) {
1554 expectEquals(a1[i], e1[i]);
1555 }
1556 int[] e2 = { 1001, 0, 0, 1, 0, 0, 1, 0, 0, 1 };
1557 int[] a2 = multiply2();
1558 for (int i = 0; i < 10; i++) {
1559 expectEquals(a2[i], e2[i]);
1560 }
1561 }
1562
Aart Bik4a342772015-11-30 10:17:46 -08001563 // Dynamic BCE.
1564 sResult = 0;
1565 try {
1566 linearDynamicBCE1(x, -1, x.length);
1567 } catch (ArrayIndexOutOfBoundsException e) {
1568 sResult += 1000;
1569 }
1570 expectEquals(1000, sResult);
1571 sResult = 0;
1572 linearDynamicBCE1(x, 0, x.length);
1573 expectEquals(55, sResult);
1574 sResult = 0;
1575 try {
1576 linearDynamicBCE1(x, 0, x.length + 1);
1577 } catch (ArrayIndexOutOfBoundsException e) {
1578 sResult += 1000;
1579 }
1580 expectEquals(1055, sResult);
1581
1582 // Dynamic BCE with offset.
1583 sResult = 0;
1584 try {
1585 linearDynamicBCE2(x, 0, x.length, -1);
1586 } catch (ArrayIndexOutOfBoundsException e) {
1587 sResult += 1000;
1588 }
1589 expectEquals(1000, sResult);
1590 sResult = 0;
1591 linearDynamicBCE2(x, 0, x.length, 0);
1592 expectEquals(55, sResult);
1593 sResult = 0;
1594 try {
1595 linearDynamicBCE2(x, 0, x.length, 1);
1596 } catch (ArrayIndexOutOfBoundsException e) {
1597 sResult += 1000;
1598 }
1599 expectEquals(1054, sResult);
1600
1601 // Dynamic BCE candidates.
1602 expectEquals(55, wrapAroundDynamicBCE(x));
1603 expectEquals(15, periodicDynamicBCE(x));
1604 expectEquals(55, dynamicBCEPossiblyInfiniteLoop(x, 0, 9));
1605 expectEquals(55, noDynamicBCEPossiblyInfiniteLoop(x, 0, 9));
1606 expectEquals(55, noDynamicBCEMixedInductionTypes(x, 0, 10));
Aart Bik97412c922016-02-19 20:14:38 -08001607 expectEquals(125, dynamicBCEConstantRange(x));
Aart Bik4a342772015-11-30 10:17:46 -08001608
1609 // Dynamic BCE combined with constant indices.
1610 int[][] a;
1611 a = new int[0][0];
1612 expectEquals(-1, dynamicBCEAndConstantIndices(x, a, 0, 10));
1613 a = new int[100][10];
1614 expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
1615 for (int i = 0; i < 10; i++) {
1616 expectEquals((i % 10) != 0 ? 1 : 0, a[0][i]);
1617 expectEquals((i % 10) != 0 ? 2 : 0, a[1][i]);
1618 expectEquals((i % 10) != 0 ? 3 : 0, a[99][i]);
1619 }
1620 a = new int[2][10];
1621 sResult = 0;
1622 try {
1623 expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
1624 } catch (ArrayIndexOutOfBoundsException e) {
1625 sResult = 1;
1626 }
1627 expectEquals(1, sResult);
1628 expectEquals(a[0][1], 1);
1629 expectEquals(a[1][1], 2);
1630
1631 // Dynamic BCE combined with constant indices of all types.
1632 boolean[] x1 = { true };
1633 byte[] x2 = { 2 };
1634 char[] x3 = { 3 };
1635 short[] x4 = { 4 };
1636 int[] x5 = { 5 };
1637 long[] x6 = { 6 };
1638 float[] x7 = { 7 };
1639 double[] x8 = { 8 };
Aart Bik09e8d5f2016-01-22 16:49:55 -08001640 expectEquals(415,
1641 dynamicBCEAndConstantIndicesAllPrimTypes(x, x1, x2, x3, x4, x5, x6, x7, x8, 0, 10));
Aart Bik4a342772015-11-30 10:17:46 -08001642 Integer[] x9 = { 9 };
Aart Bik09e8d5f2016-01-22 16:49:55 -08001643 expectEquals(145, dynamicBCEAndConstantIndexRefType(x, x9, 0, 10));
Aart Bik22af3be2015-09-10 12:50:58 -07001644 }
1645
1646 private static void expectEquals(int expected, int result) {
1647 if (expected != result) {
1648 throw new Error("Expected: " + expected + ", found: " + result);
1649 }
1650 }
1651}