blob: 0ea85da5ce0eda7814a50eba15be665d54cc3ad6 [file] [log] [blame]
Aart Bik281c6812016-08-26 11:31:48 -07001/*
2 * Copyright (C) 2016 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 * Tests on loop optimizations related to induction.
19 */
20public class Main {
21
22 static int[] a = new int[10];
23
24 /// CHECK-START: void Main.deadSingleLoop() loop_optimization (before)
25 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none
26 //
27 /// CHECK-START: void Main.deadSingleLoop() loop_optimization (after)
28 /// CHECK-NOT: Phi loop:{{B\d+}} outer_loop:none
29 static void deadSingleLoop() {
30 for (int i = 0; i < 4; i++) {
31 }
32 }
33
34 /// CHECK-START: void Main.deadNestedLoops() loop_optimization (before)
35 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
36 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:<<Loop>>
37 //
38 /// CHECK-START: void Main.deadNestedLoops() loop_optimization (after)
39 /// CHECK-NOT: Phi loop:{{B\d+}}
40 static void deadNestedLoops() {
41 for (int i = 0; i < 4; i++) {
42 for (int j = 0; j < 4; j++) {
43 }
44 }
45 }
46
47 /// CHECK-START: void Main.deadNestedAndFollowingLoops() loop_optimization (before)
48 /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none
49 /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
50 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:<<Loop2>>
51 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:<<Loop2>>
52 /// CHECK-DAG: Phi loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
53 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:<<Loop3>>
54 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none
55 //
56 /// CHECK-START: void Main.deadNestedAndFollowingLoops() loop_optimization (after)
57 /// CHECK-NOT: Phi loop:{{B\d+}}
58 static void deadNestedAndFollowingLoops() {
59 for (int i = 0; i < 4; i++) {
60 for (int j = 0; j < 4; j++) {
61 for (int k = 0; k < 4; k++) {
62 }
63 for (int k = 0; k < 4; k++) {
64 }
65 }
66 for (int j = 0; j < 4; j++) {
67 for (int k = 0; k < 4; k++) {
68 }
69 }
70 }
71 for (int i = 0; i < 4; i++) {
72 }
73 }
74
75 /// CHECK-START: void Main.deadInduction() loop_optimization (before)
76 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
77 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
78 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
79 //
80 /// CHECK-START: void Main.deadInduction() loop_optimization (after)
81 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
82 /// CHECK-NOT: Phi loop:<<Loop>> outer_loop:none
83 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
84 static void deadInduction() {
85 int dead = 0;
86 for (int i = 0; i < a.length; i++) {
87 a[i] = 1;
88 dead += 5;
89 }
90 }
91
92 /// CHECK-START: void Main.deadManyInduction() loop_optimization (before)
93 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
94 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
95 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
96 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
97 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
98 //
99 /// CHECK-START: void Main.deadManyInduction() loop_optimization (after)
100 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
101 /// CHECK-NOT: Phi loop:<<Loop>> outer_loop:none
102 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
103 static void deadManyInduction() {
104 int dead1 = 0, dead2 = 1, dead3 = 3;
105 for (int i = 0; i < a.length; i++) {
106 dead1 += 5;
107 a[i] = 2;
108 dead2 += 10;
109 dead3 += 100;
110 }
111 }
112
113 /// CHECK-START: void Main.deadSequence() loop_optimization (before)
114 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
115 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
116 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
117 //
118 /// CHECK-START: void Main.deadSequence() loop_optimization (after)
119 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
120 /// CHECK-NOT: Phi loop:<<Loop>> outer_loop:none
121 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
122 static void deadSequence() {
123 int dead = 0;
124 for (int i = 0; i < a.length; i++) {
125 a[i] = 3;
126 // Increment value defined inside loop,
127 // but sequence itself not used anywhere.
128 dead += i;
129 }
130 }
131
132 /// CHECK-START: void Main.deadCycleWithException(int) loop_optimization (before)
133 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
134 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
135 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
136 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
137 //
138 /// CHECK-START: void Main.deadCycleWithException(int) loop_optimization (after)
139 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
140 /// CHECK-NOT: Phi loop:<<Loop>> outer_loop:none
141 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
142 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
143 static void deadCycleWithException(int k) {
144 int dead = 0;
145 for (int i = 0; i < a.length; i++) {
146 a[i] = 4;
147 // Increment value of dead cycle may throw exception.
148 dead += a[k];
149 }
150 }
151
152 /// CHECK-START: int Main.closedFormInductionUp() loop_optimization (before)
153 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
154 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none
155 /// CHECK-DAG: Return [<<Phi1>>] loop:none
156 //
157 /// CHECK-START: int Main.closedFormInductionUp() loop_optimization (after)
Aart Bik8c4a8542016-10-06 11:36:57 -0700158 /// CHECK-NOT: Phi loop:{{B\d+}} outer_loop:none
Aart Bik281c6812016-08-26 11:31:48 -0700159 /// CHECK-DAG: Return loop:none
160 static int closedFormInductionUp() {
161 int closed = 12345;
162 for (int i = 0; i < 10; i++) {
163 closed += 5;
164 }
165 return closed; // only needs last value
166 }
167
168 /// CHECK-START: int Main.closedFormInductionInAndDown(int) loop_optimization (before)
169 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
170 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none
171 /// CHECK-DAG: Return [<<Phi2>>] loop:none
172 //
173 /// CHECK-START: int Main.closedFormInductionInAndDown(int) loop_optimization (after)
Aart Bik8c4a8542016-10-06 11:36:57 -0700174 /// CHECK-NOT: Phi loop:{{B\d+}} outer_loop:none
Aart Bik281c6812016-08-26 11:31:48 -0700175 /// CHECK-DAG: Return loop:none
176 static int closedFormInductionInAndDown(int closed) {
177 for (int i = 0; i < 10; i++) {
178 closed -= 5;
179 }
180 return closed; // only needs last value
181 }
182
Aart Bik8c4a8542016-10-06 11:36:57 -0700183 // TODO: move closed form even further out?
184 static int closedFormNested() {
185 int closed = 0;
186 for (int i = 0; i < 10; i++) {
187 for (int j = 0; j < 10; j++) {
188 closed++;
189 }
190 }
191 return closed; // only needs last-value
192 }
193
Aart Bik281c6812016-08-26 11:31:48 -0700194 // TODO: taken test around closed form?
195 static int closedFormInductionUpN(int n) {
196 int closed = 12345;
197 for (int i = 0; i < n; i++) {
198 closed += 5;
199 }
200 return closed; // only needs last value
201 }
202
203 // TODO: taken test around closed form?
204 static int closedFormInductionInAndDownN(int closed, int n) {
205 for (int i = 0; i < n; i++) {
206 closed -= 5;
207 }
208 return closed; // only needs last value
209 }
210
211 // TODO: move closed form even further out?
Aart Bik8c4a8542016-10-06 11:36:57 -0700212 static int closedFormNestedN(int n) {
Aart Bik281c6812016-08-26 11:31:48 -0700213 int closed = 0;
214 for (int i = 0; i < n; i++) {
215 for (int j = 0; j < 10; j++) {
216 closed++;
217 }
218 }
219 return closed; // only needs last-value
220 }
221
Aart Bik8c4a8542016-10-06 11:36:57 -0700222 // TODO: move closed form even further out?
223 static int closedFormNestedNN(int n) {
224 int closed = 0;
225 for (int i = 0; i < n; i++) {
226 for (int j = 0; j < n; j++) {
227 closed++;
228 }
229 }
230 return closed; // only needs last-value
231 }
232
233 /// CHECK-START: int Main.mainIndexReturned() loop_optimization (before)
234 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:{{B\d+}} outer_loop:none
235 /// CHECK-DAG: Return [<<Phi>>] loop:none
236 //
237 /// CHECK-START: int Main.mainIndexReturned() loop_optimization (after)
238 /// CHECK-NOT: Phi loop:{{B\d+}} outer_loop:none
239 /// CHECK-DAG: Return loop:none
240 static int mainIndexReturned() {
Aart Bik281c6812016-08-26 11:31:48 -0700241 int i;
Aart Bik8c4a8542016-10-06 11:36:57 -0700242 for (i = 0; i < 10; i++);
Aart Bik281c6812016-08-26 11:31:48 -0700243 return i;
244 }
245
246 // If ever replaced by closed form, last value should be correct!
Aart Bik8c4a8542016-10-06 11:36:57 -0700247 static int periodicReturned() {
Aart Bik281c6812016-08-26 11:31:48 -0700248 int k = 0;
Aart Bik8c4a8542016-10-06 11:36:57 -0700249 for (int i = 0; i < 9; i++) {
Aart Bik281c6812016-08-26 11:31:48 -0700250 k = 1 - k;
251 }
252 return k;
253 }
254
Aart Bik8c4a8542016-10-06 11:36:57 -0700255 // If ever replaced by closed form, last value should be correct!
Aart Bik281c6812016-08-26 11:31:48 -0700256 private static int getSum21() {
257 int k = 0;
258 int sum = 0;
259 for (int i = 0; i < 6; i++) {
260 k++;
261 sum += k;
262 }
263 return sum;
264 }
265
Aart Bik8c4a8542016-10-06 11:36:57 -0700266 // TODO: handle as closed/empty eventually?
267 static int mainIndexReturnedN(int n) {
268 int i;
269 for (i = 0; i < n; i++);
270 return i;
271 }
272
273 // If ever replaced by closed form, last value should be correct!
274 static int periodicReturnedN(int n) {
275 int k = 0;
276 for (int i = 0; i < n; i++) {
277 k = 1 - k;
278 }
279 return k;
280 }
281
282 // If ever replaced by closed form, last value should be correct!
283 private static int getSumN(int n) {
284 int k = 0;
285 int sum = 0;
286 for (int i = 0; i < n; i++) {
287 k++;
288 sum += k;
289 }
290 return sum;
291 }
292
293 // If ever replaced by closed form, last value should be correct!
Aart Bik281c6812016-08-26 11:31:48 -0700294 private static int closedTwice() {
295 int closed = 0;
296 for (int i = 0; i < 10; i++) {
297 closed++;
298 }
299 // Closed form of first loop defines trip count of second loop.
300 int other_closed = 0;
301 for (int i = 0; i < closed; i++) {
302 other_closed++;
303 }
304 return other_closed;
305 }
306
307 /// CHECK-START: int Main.closedFeed() loop_optimization (before)
308 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop1:B\d+>> outer_loop:none
309 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop1>> outer_loop:none
310 /// CHECK-DAG: <<Phi3:i\d+>> Phi loop:<<Loop2:B\d+>> outer_loop:none
311 /// CHECK-DAG: <<Phi4:i\d+>> Phi loop:<<Loop2>> outer_loop:none
312 /// CHECK-DAG: Return [<<Phi3>>] loop:none
313 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
314 //
315 /// CHECK-START: int Main.closedFeed() loop_optimization (after)
Aart Bik8c4a8542016-10-06 11:36:57 -0700316 /// CHECK-NOT: Phi loop:{{B\d+}} outer_loop:none
Aart Bik281c6812016-08-26 11:31:48 -0700317 /// CHECK-DAG: Return loop:none
318 private static int closedFeed() {
319 int closed = 0;
320 for (int i = 0; i < 10; i++) {
321 closed++;
322 }
323 // Closed form of first loop feeds into initial value of second loop,
324 // used when generating closed form for the latter.
325 for (int i = 0; i < 10; i++) {
326 closed++;
327 }
328 return closed;
329 }
330
331 /// CHECK-START: int Main.closedLargeUp() loop_optimization (before)
332 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
333 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none
334 /// CHECK-DAG: Return [<<Phi1>>] loop:none
335 //
336 /// CHECK-START: int Main.closedLargeUp() loop_optimization (after)
337 /// CHECK-NOT: Phi loop:B\d+ outer_loop:none
338 /// CHECK-DAG: Return loop:none
339 private static int closedLargeUp() {
340 int closed = 0;
341 for (int i = 0; i < 10; i++) {
342 closed += 0x7fffffff;
343 }
344 return closed;
345 }
346
347 /// CHECK-START: int Main.closedLargeDown() loop_optimization (before)
348 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
349 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none
350 /// CHECK-DAG: Return [<<Phi1>>] loop:none
351 //
352 /// CHECK-START: int Main.closedLargeDown() loop_optimization (after)
353 /// CHECK-NOT: Phi loop:B\d+ outer_loop:none
354 /// CHECK-DAG: Return loop:none
355 private static int closedLargeDown() {
356 int closed = 0;
357 for (int i = 0; i < 10; i++) {
358 closed -= 0x7fffffff;
359 }
360 return closed;
361 }
362
Aart Bik8c4a8542016-10-06 11:36:57 -0700363 /// CHECK-START: int Main.waterFall() loop_optimization (before)
364 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop1:B\d+>> outer_loop:none
365 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop2:B\d+>> outer_loop:none
366 /// CHECK-DAG: <<Phi3:i\d+>> Phi loop:<<Loop3:B\d+>> outer_loop:none
367 /// CHECK-DAG: <<Phi4:i\d+>> Phi loop:<<Loop4:B\d+>> outer_loop:none
368 /// CHECK-DAG: <<Phi5:i\d+>> Phi loop:<<Loop5:B\d+>> outer_loop:none
369 /// CHECK-DAG: Return [<<Phi5>>] loop:none
370 //
371 /// CHECK-START: int Main.waterFall() loop_optimization (after)
372 /// CHECK-NOT: Phi loop:B\d+ outer_loop:none
373 /// CHECK-DAG: Return loop:none
374 private static int waterFall() {
375 int i = 0;
376 for (; i < 10; i++);
377 for (; i < 20; i++);
378 for (; i < 30; i++);
379 for (; i < 40; i++);
380 for (; i < 50; i++);
381 return i; // this should become just 50
382 }
383
Aart Bik281c6812016-08-26 11:31:48 -0700384 private static int exceptionExitBeforeAdd() {
385 int k = 0;
386 try {
387 for (int i = 0; i < 10; i++) {
388 a[i] = 0;
389 k += 10; // increment last
390 }
391 } catch(Exception e) {
392 // Flag error by returning current
393 // value of k negated.
394 return -k-1;
395 }
396 return k;
397 }
398
399 private static int exceptionExitAfterAdd() {
400 int k = 0;
401 try {
402 for (int i = 0; i < 10; i++) {
403 k += 10; // increment first
404 a[i] = 0;
405 }
406 } catch(Exception e) {
407 // Flag error by returning current
408 // value of k negated.
409 return -k-1;
410 }
411 return k;
412 }
413
414 public static void main(String[] args) {
415 deadSingleLoop();
416 deadNestedLoops();
417 deadNestedAndFollowingLoops();
418
419 deadInduction();
420 for (int i = 0; i < a.length; i++) {
421 expectEquals(1, a[i]);
422 }
423 deadManyInduction();
424 for (int i = 0; i < a.length; i++) {
425 expectEquals(2, a[i]);
426 }
427 deadSequence();
428 for (int i = 0; i < a.length; i++) {
429 expectEquals(3, a[i]);
430 }
431 try {
432 deadCycleWithException(-1);
433 throw new Error("Expected: IOOB exception");
434 } catch (IndexOutOfBoundsException e) {
435 }
436 for (int i = 0; i < a.length; i++) {
437 expectEquals(i == 0 ? 4 : 3, a[i]);
438 }
439 deadCycleWithException(0);
440 for (int i = 0; i < a.length; i++) {
441 expectEquals(4, a[i]);
442 }
443
Aart Bik8c4a8542016-10-06 11:36:57 -0700444 expectEquals(12395, closedFormInductionUp());
445 expectEquals(12295, closedFormInductionInAndDown(12345));
446 expectEquals(10 * 10, closedFormNested());
Aart Bik281c6812016-08-26 11:31:48 -0700447 for (int n = -4; n < 10; n++) {
448 int tc = (n <= 0) ? 0 : n;
Aart Bik8c4a8542016-10-06 11:36:57 -0700449 expectEquals(12345 + tc * 5, closedFormInductionUpN(n));
450 expectEquals(12345 - tc * 5, closedFormInductionInAndDownN(12345, n));
451 expectEquals(tc * 10, closedFormNestedN(n));
452 expectEquals(tc * tc, closedFormNestedNN(n));
Aart Bik281c6812016-08-26 11:31:48 -0700453 }
454
Aart Bik8c4a8542016-10-06 11:36:57 -0700455 expectEquals(10, mainIndexReturned());
456 expectEquals(1, periodicReturned());
457 expectEquals(21, getSum21());
Aart Bik281c6812016-08-26 11:31:48 -0700458 for (int n = -4; n < 4; n++) {
459 int tc = (n <= 0) ? 0 : n;
Aart Bik8c4a8542016-10-06 11:36:57 -0700460 expectEquals(tc, mainIndexReturnedN(n));
461 expectEquals(tc & 1, periodicReturnedN(n));
462 expectEquals((tc * (tc + 1)) / 2, getSumN(n));
Aart Bik281c6812016-08-26 11:31:48 -0700463 }
Aart Bik8c4a8542016-10-06 11:36:57 -0700464
Aart Bik281c6812016-08-26 11:31:48 -0700465 expectEquals(10, closedTwice());
466 expectEquals(20, closedFeed());
467 expectEquals(-10, closedLargeUp());
468 expectEquals(10, closedLargeDown());
Aart Bik8c4a8542016-10-06 11:36:57 -0700469 expectEquals(50, waterFall());
Aart Bik281c6812016-08-26 11:31:48 -0700470
471 expectEquals(100, exceptionExitBeforeAdd());
472 expectEquals(100, exceptionExitAfterAdd());
473 a = null;
474 expectEquals(-1, exceptionExitBeforeAdd());
475 expectEquals(-11, exceptionExitAfterAdd());
476 a = new int[4];
477 expectEquals(-41, exceptionExitBeforeAdd());
478 expectEquals(-51, exceptionExitAfterAdd());
479
480 System.out.println("passed");
481 }
482
483 private static void expectEquals(int expected, int result) {
484 if (expected != result) {
485 throw new Error("Expected: " + expected + ", found: " + result);
486 }
487 }
488}