blob: 948a7b7dcc868a70f5139d9cb1039a3dc5db7428 [file] [log] [blame]
Aart Bik22af3be2015-09-10 12:50:58 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//
18// Test on loop optimizations.
19//
20public class Main {
21
22 static int sResult;
23
24 //
Aart Bik9401f532015-09-28 16:25:56 -070025 // Various sequence variables used in bound checks.
Aart Bik22af3be2015-09-10 12:50:58 -070026 //
27
28 /// CHECK-START: int Main.linear(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080029 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080030 //
Aart Bik22af3be2015-09-10 12:50:58 -070031 /// CHECK-START: int Main.linear(int[]) BCE (after)
32 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080033 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070034 private static int linear(int[] x) {
35 int result = 0;
36 for (int i = 0; i < x.length; i++) {
37 result += x[i];
38 }
39 return result;
40 }
41
42 /// CHECK-START: int Main.linearDown(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080043 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080044 //
Aart Bik22af3be2015-09-10 12:50:58 -070045 /// CHECK-START: int Main.linearDown(int[]) BCE (after)
46 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080047 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070048 private static int linearDown(int[] x) {
49 int result = 0;
50 for (int i = x.length - 1; i >= 0; i--) {
51 result += x[i];
52 }
53 return result;
54 }
55
56 /// CHECK-START: int Main.linearObscure(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080057 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080058 //
Aart Bik22af3be2015-09-10 12:50:58 -070059 /// CHECK-START: int Main.linearObscure(int[]) BCE (after)
60 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080061 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -070062 private static int linearObscure(int[] x) {
63 int result = 0;
64 for (int i = x.length - 1; i >= 0; i--) {
65 int k = i + 5;
66 result += x[k - 5];
67 }
68 return result;
69 }
70
Aart Bikf475bee2015-09-16 12:50:25 -070071 /// CHECK-START: int Main.linearVeryObscure(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080072 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080073 //
Aart Bikf475bee2015-09-16 12:50:25 -070074 /// CHECK-START: int Main.linearVeryObscure(int[]) BCE (after)
75 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -080076 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -070077 private static int linearVeryObscure(int[] x) {
78 int result = 0;
79 for (int i = 0; i < x.length; i++) {
80 int k = (-i) + (i << 5) + i - (32 * i) + 5 + (int) i;
81 result += x[k - 5];
82 }
83 return result;
84 }
85
Aart Bik7d57d7f2015-12-09 14:39:48 -080086 /// CHECK-START: int Main.hiddenStride(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -080087 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -080088 //
89 /// CHECK-START: int Main.hiddenStride(int[]) BCE (after)
90 /// CHECK-NOT: BoundsCheck
91 /// CHECK-NOT: Deoptimize
92 static int hiddenStride(int[] a) {
93 int result = 0;
94 for (int i = 1; i <= 1; i++) {
95 // Obscured unit stride.
96 for (int j = 0; j < a.length; j += i) {
97 result += a[j];
98 }
99 }
100 return result;
101 }
102
Aart Bik22af3be2015-09-10 12:50:58 -0700103 /// CHECK-START: int Main.linearWhile(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800104 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800105 //
Aart Bik22af3be2015-09-10 12:50:58 -0700106 /// CHECK-START: int Main.linearWhile(int[]) BCE (after)
107 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800108 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700109 private static int linearWhile(int[] x) {
110 int i = 0;
111 int result = 0;
112 while (i < x.length) {
113 result += x[i++];
114 }
115 return result;
116 }
117
Aart Bikf475bee2015-09-16 12:50:25 -0700118 /// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800119 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800120 //
Aart Bikf475bee2015-09-16 12:50:25 -0700121 /// CHECK-START: int Main.linearThreeWayPhi(int[]) BCE (after)
122 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800123 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700124 private static int linearThreeWayPhi(int[] x) {
125 int result = 0;
126 for (int i = 0; i < x.length; ) {
127 if (x[i] == 5) {
128 i++;
129 continue;
130 }
131 result += x[i++];
132 }
133 return result;
134 }
135
136 /// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800137 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800138 //
Aart Bikf475bee2015-09-16 12:50:25 -0700139 /// CHECK-START: int Main.linearFourWayPhi(int[]) BCE (after)
140 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800141 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700142 private static int linearFourWayPhi(int[] x) {
143 int result = 0;
144 for (int i = 0; i < x.length; ) {
145 if (x[i] == 5) {
146 i++;
147 continue;
148 } else if (x[i] == 6) {
149 i++;
150 result += 7;
151 continue;
152 }
153 result += x[i++];
154 }
155 return result;
156 }
157
Aart Bik22af3be2015-09-10 12:50:58 -0700158 /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800159 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800160 //
Aart Bik22af3be2015-09-10 12:50:58 -0700161 /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (after)
162 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800163 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700164 private static int wrapAroundThenLinear(int[] x) {
165 // Loop with wrap around (length - 1, 0, 1, 2, ..).
166 int w = x.length - 1;
167 int result = 0;
168 for (int i = 0; i < x.length; i++) {
169 result += x[w];
170 w = i;
171 }
172 return result;
173 }
174
Aart Bikf475bee2015-09-16 12:50:25 -0700175 /// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800176 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800177 //
Aart Bikf475bee2015-09-16 12:50:25 -0700178 /// CHECK-START: int Main.wrapAroundThenLinearThreeWayPhi(int[]) BCE (after)
179 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800180 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700181 private static int wrapAroundThenLinearThreeWayPhi(int[] x) {
182 // Loop with wrap around (length - 1, 0, 1, 2, ..).
183 int w = x.length - 1;
184 int result = 0;
185 for (int i = 0; i < x.length; ) {
186 if (x[w] == 1) {
187 w = i++;
188 continue;
189 }
190 result += x[w];
191 w = i++;
192 }
193 return result;
194 }
195
Aart Bik22af3be2015-09-10 12:50:58 -0700196 /// CHECK-START: int[] Main.linearWithParameter(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800197 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800198 //
Aart Bik22af3be2015-09-10 12:50:58 -0700199 /// CHECK-START: int[] Main.linearWithParameter(int) BCE (after)
200 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800201 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700202 private static int[] linearWithParameter(int n) {
203 int[] x = new int[n];
204 for (int i = 0; i < n; i++) {
205 x[i] = i;
206 }
207 return x;
208 }
209
Aart Bikf475bee2015-09-16 12:50:25 -0700210 /// CHECK-START: int[] Main.linearCopy(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800211 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800212 //
Aart Bikf475bee2015-09-16 12:50:25 -0700213 /// CHECK-START: int[] Main.linearCopy(int[]) BCE (after)
214 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800215 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700216 private static int[] linearCopy(int x[]) {
217 int n = x.length;
218 int y[] = new int[n];
219 for (int i = 0; i < n; i++) {
220 y[i] = x[i];
221 }
222 return y;
223 }
224
Aart Bik4a342772015-11-30 10:17:46 -0800225 /// CHECK-START: int Main.linearByTwo(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800226 /// CHECK-DAG: BoundsCheck
227 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800228 //
Aart Bik4a342772015-11-30 10:17:46 -0800229 /// CHECK-START: int Main.linearByTwo(int[]) BCE (after)
230 /// CHECK-NOT: BoundsCheck
231 /// CHECK-NOT: Deoptimize
232 private static int linearByTwo(int x[]) {
233 int n = x.length / 2;
234 int result = 0;
235 for (int i = 0; i < n; i++) {
236 int ii = i << 1;
237 result += x[ii];
238 result += x[ii + 1];
239 }
240 return result;
241 }
242
243 /// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800244 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800245 //
Aart Bik4a342772015-11-30 10:17:46 -0800246 /// CHECK-START: int Main.linearByTwoSkip1(int[]) BCE (after)
247 /// CHECK-NOT: BoundsCheck
248 /// CHECK-NOT: Deoptimize
249 private static int linearByTwoSkip1(int x[]) {
250 int result = 0;
251 for (int i = 0; i < x.length / 2; i++) {
252 result += x[2 * i];
253 }
254 return result;
255 }
256
257 /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800258 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800259 //
Aart Bik4a342772015-11-30 10:17:46 -0800260 /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800261 /// CHECK-DAG: BoundsCheck
262 //
263 /// CHECK-START: int Main.linearByTwoSkip2(int[]) BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800264 /// CHECK-NOT: Deoptimize
265 private static int linearByTwoSkip2(int x[]) {
266 int result = 0;
267 // This case is not optimized.
268 for (int i = 0; i < x.length; i+=2) {
269 result += x[i];
270 }
271 return result;
272 }
273
Aart Bik22af3be2015-09-10 12:50:58 -0700274 /// CHECK-START: int Main.linearWithCompoundStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800275 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800276 //
Aart Bik22af3be2015-09-10 12:50:58 -0700277 /// CHECK-START: int Main.linearWithCompoundStride() BCE (after)
278 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800279 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700280 private static int linearWithCompoundStride() {
281 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
282 int result = 0;
283 for (int i = 0; i <= 12; ) {
284 i++;
285 result += x[i];
286 i++;
287 }
288 return result;
289 }
290
291 /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800292 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800293 //
Aart Bik22af3be2015-09-10 12:50:58 -0700294 /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (after)
295 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800296 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700297 private static int linearWithLargePositiveStride() {
298 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
299 int result = 0;
300 int k = 0;
301 // Range analysis has no problem with a trip-count defined by a
Aart Bikf475bee2015-09-16 12:50:25 -0700302 // reasonably large positive stride far away from upper bound.
Aart Bik22af3be2015-09-10 12:50:58 -0700303 for (int i = 1; i <= 10 * 10000000 + 1; i += 10000000) {
304 result += x[k++];
305 }
306 return result;
307 }
308
309 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800310 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800311 //
Aart Bik22af3be2015-09-10 12:50:58 -0700312 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800313 /// CHECK-DAG: BoundsCheck
314 //
315 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800316 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700317 private static int linearWithVeryLargePositiveStride() {
318 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
319 int result = 0;
320 int k = 0;
321 // Range analysis conservatively bails due to potential of wrap-around
322 // arithmetic while computing the trip-count for this very large stride.
Aart Bikf475bee2015-09-16 12:50:25 -0700323 for (int i = 1; i < Integer.MAX_VALUE; i += 195225786) {
Aart Bik22af3be2015-09-10 12:50:58 -0700324 result += x[k++];
325 }
326 return result;
327 }
328
329 /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800330 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800331 //
Aart Bik22af3be2015-09-10 12:50:58 -0700332 /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (after)
333 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800334 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700335 private static int linearWithLargeNegativeStride() {
336 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
337 int result = 0;
338 int k = 0;
339 // Range analysis has no problem with a trip-count defined by a
Aart Bikf475bee2015-09-16 12:50:25 -0700340 // reasonably large negative stride far away from lower bound.
Aart Bik22af3be2015-09-10 12:50:58 -0700341 for (int i = -1; i >= -10 * 10000000 - 1; i -= 10000000) {
342 result += x[k++];
343 }
344 return result;
345 }
346
347 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800348 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800349 //
Aart Bik22af3be2015-09-10 12:50:58 -0700350 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800351 /// CHECK-DAG: BoundsCheck
352 //
353 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
Aart Bik4a342772015-11-30 10:17:46 -0800354 /// CHECK-NOT: Deoptimize
Aart Bik22af3be2015-09-10 12:50:58 -0700355 private static int linearWithVeryLargeNegativeStride() {
356 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
357 int result = 0;
358 int k = 0;
359 // Range analysis conservatively bails due to potential of wrap-around
360 // arithmetic while computing the trip-count for this very large stride.
Aart Bikf475bee2015-09-16 12:50:25 -0700361 for (int i = -2; i > Integer.MIN_VALUE; i -= 195225786) {
Aart Bik22af3be2015-09-10 12:50:58 -0700362 result += x[k++];
363 }
364 return result;
365 }
366
Aart Bik9401f532015-09-28 16:25:56 -0700367 /// CHECK-START: int Main.linearForNEUp() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800368 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800369 //
Aart Bik9401f532015-09-28 16:25:56 -0700370 /// CHECK-START: int Main.linearForNEUp() BCE (after)
Aart Bikf475bee2015-09-16 12:50:25 -0700371 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800372 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700373 private static int linearForNEUp() {
Aart Bikf475bee2015-09-16 12:50:25 -0700374 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
375 int result = 0;
376 for (int i = 0; i != 10; i++) {
377 result += x[i];
378 }
379 return result;
380 }
381
Aart Bik9401f532015-09-28 16:25:56 -0700382 /// CHECK-START: int Main.linearForNEDown() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800383 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800384 //
Aart Bik9401f532015-09-28 16:25:56 -0700385 /// CHECK-START: int Main.linearForNEDown() BCE (after)
386 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800387 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700388 private static int linearForNEDown() {
389 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
390 int result = 0;
391 for (int i = 9; i != -1; i--) {
392 result += x[i];
393 }
394 return result;
395 }
396
Aart Bik358af832016-02-24 14:17:53 -0800397 /// CHECK-START: int Main.linearForNEArrayLengthUp(int[]) BCE (before)
398 /// CHECK-DAG: BoundsCheck
399 //
400 /// CHECK-START: int Main.linearForNEArrayLengthUp(int[]) BCE (after)
401 /// CHECK-NOT: BoundsCheck
402 /// CHECK-NOT: Deoptimize
403 private static int linearForNEArrayLengthUp(int[] x) {
404 int result = 0;
405 for (int i = 0; i != x.length; i++) {
406 result += x[i];
407 }
408 return result;
409 }
410
411 /// CHECK-START: int Main.linearForNEArrayLengthDown(int[]) BCE (before)
412 /// CHECK-DAG: BoundsCheck
413 //
414 /// CHECK-START: int Main.linearForNEArrayLengthDown(int[]) BCE (after)
415 /// CHECK-NOT: BoundsCheck
416 /// CHECK-NOT: Deoptimize
417 private static int linearForNEArrayLengthDown(int[] x) {
418 int result = 0;
419 for (int i = x.length - 1; i != -1; i--) {
420 result += x[i];
421 }
422 return result;
423 }
424
Aart Bik9401f532015-09-28 16:25:56 -0700425 /// CHECK-START: int Main.linearDoWhileUp() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800426 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800427 //
Aart Bik9401f532015-09-28 16:25:56 -0700428 /// CHECK-START: int Main.linearDoWhileUp() BCE (after)
429 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800430 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700431 private static int linearDoWhileUp() {
Aart Bikf475bee2015-09-16 12:50:25 -0700432 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
433 int result = 0;
434 int i = 0;
Aart Bikf475bee2015-09-16 12:50:25 -0700435 do {
436 result += x[i++];
437 } while (i < 10);
438 return result;
439 }
440
Aart Bik9401f532015-09-28 16:25:56 -0700441 /// CHECK-START: int Main.linearDoWhileDown() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800442 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800443 //
Aart Bik9401f532015-09-28 16:25:56 -0700444 /// CHECK-START: int Main.linearDoWhileDown() BCE (after)
445 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800446 /// CHECK-NOT: Deoptimize
Aart Bik9401f532015-09-28 16:25:56 -0700447 private static int linearDoWhileDown() {
448 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
449 int result = 0;
450 int i = 9;
451 do {
452 result += x[i--];
453 } while (0 <= i);
454 return result;
455 }
456
Aart Bik0d345cf2016-03-16 10:49:38 -0700457 /// CHECK-START: int Main.linearLong() BCE (before)
458 /// CHECK-DAG: BoundsCheck
459 //
460 /// CHECK-START: int Main.linearLong() BCE (after)
461 /// CHECK-NOT: BoundsCheck
462 /// CHECK-NOT: Deoptimize
463 private static int linearLong() {
464 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
465 int result = 0;
466 // Induction on constant interval is done in higher precision than necessary,
467 // but truncated at the use as subscript.
468 for (long i = 0; i < 10; i++) {
469 result += x[(int)i];
470 }
471 return result;
472 }
473
474 /// CHECK-START: int Main.linearLongAlt(int[]) BCE (before)
475 /// CHECK-DAG: BoundsCheck
476 //
477 /// CHECK-START: int Main.linearLongAlt(int[]) BCE (after)
478 /// CHECK-NOT: BoundsCheck
479 /// CHECK-NOT: Deoptimize
480 private static int linearLongAlt(int[] x) {
481 int result = 0;
482 // Induction on array length is done in higher precision than necessary,
483 // but truncated at the use as subscript.
484 for (long i = 0; i < x.length; i++) {
485 result += x[(int)i];
486 }
487 return result;
488 }
489
Aart Bikf475bee2015-09-16 12:50:25 -0700490 /// CHECK-START: int Main.linearShort() BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800491 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800492 //
Aart Bikf475bee2015-09-16 12:50:25 -0700493 /// CHECK-START: int Main.linearShort() BCE (after)
Aart Bik0d345cf2016-03-16 10:49:38 -0700494 /// CHECK-NOT: BoundsCheck
Aart Bik4a342772015-11-30 10:17:46 -0800495 /// CHECK-NOT: Deoptimize
Aart Bikf475bee2015-09-16 12:50:25 -0700496 private static int linearShort() {
497 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
498 int result = 0;
Aart Bik0d345cf2016-03-16 10:49:38 -0700499 // Induction is done in short precision, but fits.
Aart Bikf475bee2015-09-16 12:50:25 -0700500 for (short i = 0; i < 10; i++) {
501 result += x[i];
502 }
503 return result;
504 }
505
Aart Bik0d345cf2016-03-16 10:49:38 -0700506 /// CHECK-START: int Main.linearChar() BCE (before)
507 /// CHECK-DAG: BoundsCheck
508 //
509 /// CHECK-START: int Main.linearChar() BCE (after)
510 /// CHECK-NOT: BoundsCheck
511 /// CHECK-NOT: Deoptimize
512 private static int linearChar() {
513 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
514 int result = 0;
515 // Induction is done in char precision, but fits.
516 for (char i = 0; i < 10; i++) {
517 result += x[i];
518 }
519 return result;
520 }
521
522 /// CHECK-START: int Main.linearByte() BCE (before)
523 /// CHECK-DAG: BoundsCheck
524 //
525 /// CHECK-START: int Main.linearByte() BCE (after)
526 /// CHECK-NOT: BoundsCheck
527 /// CHECK-NOT: Deoptimize
528 private static int linearByte() {
529 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
530 int result = 0;
531 // Induction is done in byte precision, but fits.
532 for (byte i = 0; i < 10; i++) {
533 result += x[i];
534 }
535 return result;
536 }
537
Aart Bik4a342772015-11-30 10:17:46 -0800538 /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800539 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800540 //
Aart Bik4a342772015-11-30 10:17:46 -0800541 /// CHECK-START: int Main.invariantFromPreLoop(int[], int) BCE (after)
542 /// CHECK-NOT: BoundsCheck
543 /// CHECK-NOT: Deoptimize
544 private static int invariantFromPreLoop(int[] x, int y) {
545 int result = 0;
546 // Strange pre-loop that sets upper bound.
547 int hi;
548 while (true) {
549 y = y % 3;
550 hi = x.length;
551 if (y != 123) break;
552 }
553 for (int i = 0; i < hi; i++) {
554 result += x[i];
555 }
556 return result;
557 }
558
Aart Bikb738d4f2015-12-03 11:23:35 -0800559 /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800560 /// CHECK-DAG: BoundsCheck
561 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800562 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800563 /// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (after)
564 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800565 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
Aart Bikb738d4f2015-12-03 11:23:35 -0800566 private static void linearTriangularOnTwoArrayLengths(int n) {
567 int[] a = new int[n];
568 for (int i = 0; i < a.length; i++) {
569 int[] b = new int[i];
570 for (int j = 0; j < b.length; j++) {
571 // Need to know j < b.length < a.length for static bce.
572 a[j] += 1;
573 // Need to know just j < b.length for static bce.
574 b[j] += 1;
575 }
576 verifyTriangular(a, b, i, n);
577 }
578 }
579
580 /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800581 /// CHECK-DAG: BoundsCheck
582 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800583 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800584 /// CHECK-START: void Main.linearTriangularOnOneArrayLength(int) BCE (after)
585 /// CHECK-NOT: BoundsCheck
Aart Bikb738d4f2015-12-03 11:23:35 -0800586 /// CHECK-NOT: Deoptimize
587 private static void linearTriangularOnOneArrayLength(int n) {
588 int[] a = new int[n];
589 for (int i = 0; i < a.length; i++) {
590 int[] b = new int[i];
591 for (int j = 0; j < i; j++) {
592 // Need to know j < i < a.length for static bce.
593 a[j] += 1;
594 // Need to know just j < i for static bce.
595 b[j] += 1;
596 }
597 verifyTriangular(a, b, i, n);
598 }
599 }
600
601 /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800602 /// CHECK-DAG: BoundsCheck
603 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800604 //
Aart Bikb738d4f2015-12-03 11:23:35 -0800605 /// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (after)
606 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800607 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
Aart Bikb738d4f2015-12-03 11:23:35 -0800608 private static void linearTriangularOnParameter(int n) {
609 int[] a = new int[n];
610 for (int i = 0; i < n; i++) {
611 int[] b = new int[i];
612 for (int j = 0; j < i; j++) {
613 // Need to know j < i < n for static bce.
614 a[j] += 1;
615 // Need to know just j < i for static bce.
616 b[j] += 1;
617 }
618 verifyTriangular(a, b, i, n);
619 }
620 }
621
Aart Bik97412c922016-02-19 20:14:38 -0800622 /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800623 /// CHECK-DAG: BoundsCheck
624 /// CHECK-DAG: BoundsCheck
625 /// CHECK-DAG: BoundsCheck
626 /// CHECK-DAG: BoundsCheck
Aart Bik7d57d7f2015-12-09 14:39:48 -0800627 //
Aart Bik97412c922016-02-19 20:14:38 -0800628 /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (after)
Aart Bik7d57d7f2015-12-09 14:39:48 -0800629 /// CHECK-NOT: BoundsCheck
Aart Bik97412c922016-02-19 20:14:38 -0800630 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
631 private static void linearTriangularVariationsInnerStrict(int n) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800632 int[] a = new int[n];
633 for (int i = 0; i < n; i++) {
634 for (int j = 0; j < i; j++) {
635 a[j] += 1;
636 }
Aart Bik97412c922016-02-19 20:14:38 -0800637 for (int j = i - 1; j > -1; j--) {
Aart Bik7d57d7f2015-12-09 14:39:48 -0800638 a[j] += 1;
639 }
640 for (int j = i; j < n; j++) {
641 a[j] += 1;
642 }
643 for (int j = n - 1; j > i - 1; j--) {
644 a[j] += 1;
645 }
646 }
647 verifyTriangular(a);
648 }
649
Aart Bik97412c922016-02-19 20:14:38 -0800650 /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (before)
651 /// CHECK-DAG: BoundsCheck
652 /// CHECK-DAG: BoundsCheck
653 /// CHECK-DAG: BoundsCheck
654 /// CHECK-DAG: BoundsCheck
655 //
656 /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (after)
657 /// CHECK-NOT: BoundsCheck
658 // TODO: also CHECK-NOT: Deoptimize, see b/27151190
659 private static void linearTriangularVariationsInnerNonStrict(int n) {
660 int[] a = new int[n];
661 for (int i = 0; i < n; i++) {
662 for (int j = 0; j <= i - 1; j++) {
663 a[j] += 1;
664 }
665 for (int j = i - 1; j >= 0; j--) {
666 a[j] += 1;
667 }
668 for (int j = i; j <= n - 1; j++) {
669 a[j] += 1;
670 }
671 for (int j = n - 1; j >= i; j--) {
672 a[j] += 1;
673 }
674 }
675 verifyTriangular(a);
676 }
677
Aart Bik7d57d7f2015-12-09 14:39:48 -0800678 // Verifier for triangular loops.
Aart Bikb738d4f2015-12-03 11:23:35 -0800679 private static void verifyTriangular(int[] a, int[] b, int m, int n) {
680 expectEquals(n, a.length);
681 for (int i = 0, k = m; i < n; i++) {
682 expectEquals(a[i], k);
683 if (k > 0) k--;
684 }
685 expectEquals(m, b.length);
686 for (int i = 0; i < m; i++) {
687 expectEquals(b[i], 1);
688 }
689 }
690
Aart Bik7d57d7f2015-12-09 14:39:48 -0800691 // Verifier for triangular loops.
692 private static void verifyTriangular(int[] a) {
693 int n = a.length;
694 for (int i = 0; i < n; i++) {
695 expectEquals(a[i], n + n);
696 }
697 }
698
Aart Bik0d345cf2016-03-16 10:49:38 -0700699 /// CHECK-START: int[] Main.linearTriangularOOB() BCE (before)
700 /// CHECK-DAG: BoundsCheck
701 //
702 /// CHECK-START: int[] Main.linearTriangularOOB() BCE (after)
703 /// CHECK-DAG: BoundsCheck
704 //
705 /// CHECK-START: int[] Main.linearTriangularOOB() BCE (after)
706 /// CHECK-NOT: Deoptimize
707 private static int[] linearTriangularOOB() {
708 int[] a = new int[200];
709 try {
710 for (int i = 0; i < 200; i++) {
711 // Lower bound must be recognized as lower precision induction with arithmetic
712 // wrap-around to -128 when i exceeds 127.
713 for (int j = (byte) i; j < 200; j++) {
714 a[j] += 1;
715 }
716 }
717 } catch (ArrayIndexOutOfBoundsException e) {
718 return a;
719 }
720 return null; // failure if this is reached
721 }
722
Aart Bikb6347b72016-02-29 13:56:44 -0800723 //
724 // Verifier.
725 //
726
Aart Bik22af3be2015-09-10 12:50:58 -0700727 public static void main(String[] args) {
728 int[] empty = { };
729 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
730
731 // Linear and wrap-around.
732 expectEquals(0, linear(empty));
733 expectEquals(55, linear(x));
734 expectEquals(0, linearDown(empty));
735 expectEquals(55, linearDown(x));
736 expectEquals(0, linearObscure(empty));
737 expectEquals(55, linearObscure(x));
Aart Bikf475bee2015-09-16 12:50:25 -0700738 expectEquals(0, linearVeryObscure(empty));
739 expectEquals(55, linearVeryObscure(x));
Aart Bik7d57d7f2015-12-09 14:39:48 -0800740 expectEquals(0, hiddenStride(empty));
741 expectEquals(55, hiddenStride(x));
Aart Bik22af3be2015-09-10 12:50:58 -0700742 expectEquals(0, linearWhile(empty));
743 expectEquals(55, linearWhile(x));
Aart Bikf475bee2015-09-16 12:50:25 -0700744 expectEquals(0, linearThreeWayPhi(empty));
745 expectEquals(50, linearThreeWayPhi(x));
746 expectEquals(0, linearFourWayPhi(empty));
747 expectEquals(51, linearFourWayPhi(x));
Aart Bik22af3be2015-09-10 12:50:58 -0700748 expectEquals(0, wrapAroundThenLinear(empty));
749 expectEquals(55, wrapAroundThenLinear(x));
Aart Bikf475bee2015-09-16 12:50:25 -0700750 expectEquals(0, wrapAroundThenLinearThreeWayPhi(empty));
751 expectEquals(54, wrapAroundThenLinearThreeWayPhi(x));
Aart Bik22af3be2015-09-10 12:50:58 -0700752
753 // Linear with parameter.
754 sResult = 0;
755 try {
756 linearWithParameter(-1);
757 } catch (NegativeArraySizeException e) {
758 sResult = 1;
759 }
760 expectEquals(1, sResult);
761 for (int n = 0; n < 32; n++) {
762 int[] r = linearWithParameter(n);
763 expectEquals(n, r.length);
764 for (int i = 0; i < n; i++) {
765 expectEquals(i, r[i]);
766 }
767 }
768
Aart Bikf475bee2015-09-16 12:50:25 -0700769 // Linear copy.
770 expectEquals(0, linearCopy(empty).length);
771 {
772 int[] r = linearCopy(x);
773 expectEquals(x.length, r.length);
774 for (int i = 0; i < x.length; i++) {
775 expectEquals(x[i], r[i]);
776 }
777 }
778
Aart Bik22af3be2015-09-10 12:50:58 -0700779 // Linear with non-unit strides.
Aart Bik4a342772015-11-30 10:17:46 -0800780 expectEquals(55, linearByTwo(x));
781 expectEquals(25, linearByTwoSkip1(x));
782 expectEquals(25, linearByTwoSkip2(x));
Aart Bik22af3be2015-09-10 12:50:58 -0700783 expectEquals(56, linearWithCompoundStride());
784 expectEquals(66, linearWithLargePositiveStride());
785 expectEquals(66, linearWithVeryLargePositiveStride());
786 expectEquals(66, linearWithLargeNegativeStride());
787 expectEquals(66, linearWithVeryLargeNegativeStride());
788
Aart Bikf475bee2015-09-16 12:50:25 -0700789 // Special forms.
Aart Bik9401f532015-09-28 16:25:56 -0700790 expectEquals(55, linearForNEUp());
791 expectEquals(55, linearForNEDown());
Aart Bik358af832016-02-24 14:17:53 -0800792 expectEquals(55, linearForNEArrayLengthUp(x));
793 expectEquals(55, linearForNEArrayLengthDown(x));
Aart Bik9401f532015-09-28 16:25:56 -0700794 expectEquals(55, linearDoWhileUp());
795 expectEquals(55, linearDoWhileDown());
Aart Bik0d345cf2016-03-16 10:49:38 -0700796 expectEquals(55, linearLong());
797 expectEquals(55, linearLongAlt(x));
Aart Bikf475bee2015-09-16 12:50:25 -0700798 expectEquals(55, linearShort());
Aart Bik0d345cf2016-03-16 10:49:38 -0700799 expectEquals(55, linearChar());
800 expectEquals(55, linearByte());
Aart Bik4a342772015-11-30 10:17:46 -0800801 expectEquals(55, invariantFromPreLoop(x, 1));
Aart Bikb738d4f2015-12-03 11:23:35 -0800802 linearTriangularOnTwoArrayLengths(10);
803 linearTriangularOnOneArrayLength(10);
804 linearTriangularOnParameter(10);
Aart Bik97412c922016-02-19 20:14:38 -0800805 linearTriangularVariationsInnerStrict(10);
806 linearTriangularVariationsInnerNonStrict(10);
Aart Bik0d345cf2016-03-16 10:49:38 -0700807 {
808 int[] t = linearTriangularOOB();
809 for (int i = 0; i < 200; i++) {
810 expectEquals(i <= 127 ? i + 1 : 128, t[i]);
811 }
812 }
813
814 System.out.println("passed");
Aart Bik22af3be2015-09-10 12:50:58 -0700815 }
816
817 private static void expectEquals(int expected, int result) {
818 if (expected != result) {
819 throw new Error("Expected: " + expected + ", found: " + result);
820 }
821 }
822}