blob: e518a61f8825ce625a4222c865132389acca9da0 [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 //
25 // Various sequence variables where bound checks can be removed from loop.
26 //
27
28 /// CHECK-START: int Main.linear(int[]) BCE (before)
29 /// CHECK-DAG: BoundsCheck
30 /// CHECK-START: int Main.linear(int[]) BCE (after)
31 /// CHECK-NOT: BoundsCheck
32 private static int linear(int[] x) {
33 int result = 0;
34 for (int i = 0; i < x.length; i++) {
35 result += x[i];
36 }
37 return result;
38 }
39
40 /// CHECK-START: int Main.linearDown(int[]) BCE (before)
41 /// CHECK-DAG: BoundsCheck
42 /// CHECK-START: int Main.linearDown(int[]) BCE (after)
43 /// CHECK-NOT: BoundsCheck
44 private static int linearDown(int[] x) {
45 int result = 0;
46 for (int i = x.length - 1; i >= 0; i--) {
47 result += x[i];
48 }
49 return result;
50 }
51
52 /// CHECK-START: int Main.linearObscure(int[]) BCE (before)
53 /// CHECK-DAG: BoundsCheck
54 /// CHECK-START: int Main.linearObscure(int[]) BCE (after)
55 /// CHECK-NOT: BoundsCheck
56 private static int linearObscure(int[] x) {
57 int result = 0;
58 for (int i = x.length - 1; i >= 0; i--) {
59 int k = i + 5;
60 result += x[k - 5];
61 }
62 return result;
63 }
64
65 /// CHECK-START: int Main.linearWhile(int[]) BCE (before)
66 /// CHECK-DAG: BoundsCheck
67 /// CHECK-START: int Main.linearWhile(int[]) BCE (after)
68 /// CHECK-NOT: BoundsCheck
69 private static int linearWhile(int[] x) {
70 int i = 0;
71 int result = 0;
72 while (i < x.length) {
73 result += x[i++];
74 }
75 return result;
76 }
77
78 /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (before)
79 /// CHECK-DAG: BoundsCheck
80 /// CHECK-START: int Main.wrapAroundThenLinear(int[]) BCE (after)
81 /// CHECK-NOT: BoundsCheck
82 private static int wrapAroundThenLinear(int[] x) {
83 // Loop with wrap around (length - 1, 0, 1, 2, ..).
84 int w = x.length - 1;
85 int result = 0;
86 for (int i = 0; i < x.length; i++) {
87 result += x[w];
88 w = i;
89 }
90 return result;
91 }
92
93 /// CHECK-START: int[] Main.linearWithParameter(int) BCE (before)
94 /// CHECK-DAG: BoundsCheck
95 /// CHECK-START: int[] Main.linearWithParameter(int) BCE (after)
96 /// CHECK-NOT: BoundsCheck
97 private static int[] linearWithParameter(int n) {
98 int[] x = new int[n];
99 for (int i = 0; i < n; i++) {
100 x[i] = i;
101 }
102 return x;
103 }
104
105 /// CHECK-START: int Main.linearWithCompoundStride() BCE (before)
106 /// CHECK-DAG: BoundsCheck
107 /// CHECK-START: int Main.linearWithCompoundStride() BCE (after)
108 /// CHECK-NOT: BoundsCheck
109 private static int linearWithCompoundStride() {
110 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };
111 int result = 0;
112 for (int i = 0; i <= 12; ) {
113 i++;
114 result += x[i];
115 i++;
116 }
117 return result;
118 }
119
120 /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (before)
121 /// CHECK-DAG: BoundsCheck
122 /// CHECK-START: int Main.linearWithLargePositiveStride() BCE (after)
123 /// CHECK-NOT: BoundsCheck
124 private static int linearWithLargePositiveStride() {
125 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
126 int result = 0;
127 int k = 0;
128 // Range analysis has no problem with a trip-count defined by a
129 // reasonably large positive stride.
130 for (int i = 1; i <= 10 * 10000000 + 1; i += 10000000) {
131 result += x[k++];
132 }
133 return result;
134 }
135
136 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (before)
137 /// CHECK-DAG: BoundsCheck
138 /// CHECK-START: int Main.linearWithVeryLargePositiveStride() BCE (after)
139 /// CHECK-DAG: BoundsCheck
140 private static int linearWithVeryLargePositiveStride() {
141 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
142 int result = 0;
143 int k = 0;
144 // Range analysis conservatively bails due to potential of wrap-around
145 // arithmetic while computing the trip-count for this very large stride.
146 for (int i = 1; i < 2147483647; i += 195225786) {
147 result += x[k++];
148 }
149 return result;
150 }
151
152 /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (before)
153 /// CHECK-DAG: BoundsCheck
154 /// CHECK-START: int Main.linearWithLargeNegativeStride() BCE (after)
155 /// CHECK-NOT: BoundsCheck
156 private static int linearWithLargeNegativeStride() {
157 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
158 int result = 0;
159 int k = 0;
160 // Range analysis has no problem with a trip-count defined by a
161 // reasonably large negative stride.
162 for (int i = -1; i >= -10 * 10000000 - 1; i -= 10000000) {
163 result += x[k++];
164 }
165 return result;
166 }
167
168 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (before)
169 /// CHECK-DAG: BoundsCheck
170 /// CHECK-START: int Main.linearWithVeryLargeNegativeStride() BCE (after)
171 /// CHECK-DAG: BoundsCheck
172 private static int linearWithVeryLargeNegativeStride() {
173 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
174 int result = 0;
175 int k = 0;
176 // Range analysis conservatively bails due to potential of wrap-around
177 // arithmetic while computing the trip-count for this very large stride.
178 for (int i = -2; i > -2147483648; i -= 195225786) {
179 result += x[k++];
180 }
181 return result;
182 }
183
184 /// CHECK-START: int Main.periodicIdiom(int) BCE (before)
185 /// CHECK-DAG: BoundsCheck
186 /// CHECK-START: int Main.periodicIdiom(int) BCE (after)
187 /// CHECK-NOT: BoundsCheck
188 private static int periodicIdiom(int tc) {
189 int[] x = { 1, 3 };
190 // Loop with periodic sequence (0, 1).
191 int k = 0;
192 int result = 0;
193 for (int i = 0; i < tc; i++) {
194 result += x[k];
195 k = 1 - k;
196 }
197 return result;
198 }
199
200 /// CHECK-START: int Main.periodicSequence2(int) BCE (before)
201 /// CHECK-DAG: BoundsCheck
202 /// CHECK-START: int Main.periodicSequence2(int) BCE (after)
203 /// CHECK-NOT: BoundsCheck
204 private static int periodicSequence2(int tc) {
205 int[] x = { 1, 3 };
206 // Loop with periodic sequence (0, 1).
207 int k = 0;
208 int l = 1;
209 int result = 0;
210 for (int i = 0; i < tc; i++) {
211 result += x[k];
212 int t = l;
213 l = k;
214 k = t;
215 }
216 return result;
217 }
218
219 /// CHECK-START: int Main.periodicSequence4(int) BCE (before)
220 /// CHECK-DAG: BoundsCheck
221 /// CHECK-DAG: BoundsCheck
222 /// CHECK-DAG: BoundsCheck
223 /// CHECK-DAG: BoundsCheck
224 /// CHECK-START: int Main.periodicSequence4(int) BCE (after)
225 /// CHECK-NOT: BoundsCheck
226 private static int periodicSequence4(int tc) {
227 int[] x = { 1, 3, 5, 7 };
228 // Loop with periodic sequence (0, 1, 2, 3).
229 int k = 0;
230 int l = 1;
231 int m = 2;
232 int n = 3;
233 int result = 0;
234 for (int i = 0; i < tc; i++) {
235 result += x[k] + x[l] + x[m] + x[n]; // all used at once
236 int t = n;
237 n = k;
238 k = l;
239 l = m;
240 m = t;
241 }
242 return result;
243 }
244
245 //
246 // Cases that actually go out of bounds. These test cases
247 // ensure the exceptions are thrown at the right places.
248 //
249
250 private static void lowerOOB(int[] x) {
251 for (int i = -1; i < x.length; i++) {
252 sResult += x[i];
253 }
254 }
255
256 private static void upperOOB(int[] x) {
257 for (int i = 0; i <= x.length; i++) {
258 sResult += x[i];
259 }
260 }
261
262 //
263 // Verifier.
264 //
265
266 public static void main(String[] args) {
267 int[] empty = { };
268 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
269
270 // Linear and wrap-around.
271 expectEquals(0, linear(empty));
272 expectEquals(55, linear(x));
273 expectEquals(0, linearDown(empty));
274 expectEquals(55, linearDown(x));
275 expectEquals(0, linearObscure(empty));
276 expectEquals(55, linearObscure(x));
277 expectEquals(0, linearWhile(empty));
278 expectEquals(55, linearWhile(x));
279 expectEquals(0, wrapAroundThenLinear(empty));
280 expectEquals(55, wrapAroundThenLinear(x));
281
282 // Linear with parameter.
283 sResult = 0;
284 try {
285 linearWithParameter(-1);
286 } catch (NegativeArraySizeException e) {
287 sResult = 1;
288 }
289 expectEquals(1, sResult);
290 for (int n = 0; n < 32; n++) {
291 int[] r = linearWithParameter(n);
292 expectEquals(n, r.length);
293 for (int i = 0; i < n; i++) {
294 expectEquals(i, r[i]);
295 }
296 }
297
298 // Linear with non-unit strides.
299 expectEquals(56, linearWithCompoundStride());
300 expectEquals(66, linearWithLargePositiveStride());
301 expectEquals(66, linearWithVeryLargePositiveStride());
302 expectEquals(66, linearWithLargeNegativeStride());
303 expectEquals(66, linearWithVeryLargeNegativeStride());
304
305 // Periodic adds (1, 3), one at the time.
306 expectEquals(0, periodicIdiom(-1));
307 for (int tc = 0; tc < 32; tc++) {
308 int expected = (tc >> 1) << 2;
309 if ((tc & 1) != 0)
310 expected += 1;
311 expectEquals(expected, periodicIdiom(tc));
312 }
313
314 // Periodic adds (1, 3), one at the time.
315 expectEquals(0, periodicSequence2(-1));
316 for (int tc = 0; tc < 32; tc++) {
317 int expected = (tc >> 1) << 2;
318 if ((tc & 1) != 0)
319 expected += 1;
320 expectEquals(expected, periodicSequence2(tc));
321 }
322
323 // Periodic adds (1, 3, 5, 7), all at once.
324 expectEquals(0, periodicSequence4(-1));
325 for (int tc = 0; tc < 32; tc++) {
326 expectEquals(tc * 16, periodicSequence4(tc));
327 }
328
329 // Lower bound goes OOB.
330 sResult = 0;
331 try {
332 lowerOOB(x);
333 } catch (ArrayIndexOutOfBoundsException e) {
334 sResult += 1000;
335 }
336 expectEquals(1000, sResult);
337
338 // Upper bound goes OOB.
339 sResult = 0;
340 try {
341 upperOOB(x);
342 } catch (ArrayIndexOutOfBoundsException e) {
343 sResult += 1000;
344 }
345 expectEquals(1055, sResult);
346
347 }
348
349 private static void expectEquals(int expected, int result) {
350 if (expected != result) {
351 throw new Error("Expected: " + expected + ", found: " + result);
352 }
353 }
354}