blob: 7d3d7d9bfe306aae72ef8d1ceb03a8e6c24bd8ea [file] [log] [blame]
Aart Bikc071a012016-12-01 10:22:31 -08001/*
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// Test on loop optimizations, in particular around geometric induction.
19//
20public class Main {
21
22 /// CHECK-START: int Main.geo1(int) loop_optimization (before)
23 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
24 /// CHECK-DAG: Mul loop:<<Loop>>
25 //
26 /// CHECK-START: int Main.geo1(int) loop_optimization (after)
27 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
28 /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0 loop:none
29 /// CHECK-DAG: <<Int:i\d+>> IntConstant 1410065408 loop:none
30 /// CHECK-DAG: <<Mul:i\d+>> Mul [<<Par>>,<<Int>>] loop:none
31 /// CHECK-DAG: <<Add:i\d+>> Add [<<Mul>>,<<Zer>>] loop:none
32 /// CHECK-DAG: Return [<<Add>>] loop:none
33 //
34 /// CHECK-START: int Main.geo1(int) loop_optimization (after)
35 /// CHECK-NOT: Phi
36 public static int geo1(int a) {
37 for (int i = 0; i < 10; i++) {
38 a *= 10;
39 }
40 return a;
41 }
42
43 /// CHECK-START: int Main.geo2(int) loop_optimization (before)
44 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
45 /// CHECK-DAG: Shl loop:<<Loop>>
46 //
47 /// CHECK-START: int Main.geo2(int) loop_optimization (after)
48 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
49 /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0 loop:none
50 /// CHECK-DAG: <<Int:i\d+>> IntConstant 1024 loop:none
51 /// CHECK-DAG: <<Mul:i\d+>> Mul [<<Par>>,<<Int>>] loop:none
52 /// CHECK-DAG: <<Add:i\d+>> Add [<<Mul>>,<<Zer>>] loop:none
53 /// CHECK-DAG: Return [<<Add>>] loop:none
54 //
55 /// CHECK-START: int Main.geo2(int) loop_optimization (after)
56 /// CHECK-NOT: Phi
57 public static int geo2(int a) {
58 for (int i = 0; i < 10; i++) {
59 a <<= 1;
60 }
61 return a;
62 }
63
64 /// CHECK-START: int Main.geo3(int) loop_optimization (before)
65 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
66 /// CHECK-DAG: Div loop:<<Loop>>
67 //
68 /// CHECK-START: int Main.geo3(int) loop_optimization (after)
69 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
70 /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0 loop:none
71 /// CHECK-DAG: <<Int:i\d+>> IntConstant 59049 loop:none
72 /// CHECK-DAG: <<Div:i\d+>> Div [<<Par>>,<<Int>>] loop:none
73 /// CHECK-DAG: <<Add:i\d+>> Add [<<Div>>,<<Zer>>] loop:none
74 /// CHECK-DAG: Return [<<Add>>] loop:none
75 //
76 /// CHECK-START: int Main.geo3(int) loop_optimization (after)
77 /// CHECK-NOT: Phi
78 public static int geo3(int a) {
79 for (int i = 0; i < 10; i++) {
80 a /= 3;
81 }
82 return a;
83 }
84
85 /// CHECK-START: int Main.geo4(int) loop_optimization (before)
86 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
87 /// CHECK-DAG: Rem loop:<<Loop>>
88 //
89 /// CHECK-START: int Main.geo4(int) loop_optimization (after)
90 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
Aart Bikc071a012016-12-01 10:22:31 -080091 /// CHECK-DAG: <<Int:i\d+>> IntConstant 7 loop:none
92 /// CHECK-DAG: <<Rem:i\d+>> Rem [<<Par>>,<<Int>>] loop:none
Aart Bikdf7822e2016-12-06 10:05:30 -080093 /// CHECK-DAG: Return [<<Rem>>] loop:none
Aart Bikc071a012016-12-01 10:22:31 -080094 //
95 /// CHECK-START: int Main.geo4(int) loop_optimization (after)
96 /// CHECK-NOT: Phi
97 public static int geo4(int a) {
98 for (int i = 0; i < 10; i++) {
99 a %= 7;
100 }
101 return a;
102 }
103
104 // TODO: someday?
Aart Bikdf7822e2016-12-06 10:05:30 -0800105 //
106 /// CHECK-START: int Main.geo1BCE() BCE (before)
107 /// CHECK-DAG: BoundsCheck loop:none
108 /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
109 //
110 /// CHECK-START: int Main.geo1BCE() BCE (after)
111 /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
112 //
113 /// CHECK-START: int Main.geo1BCE() BCE (after)
114 /// CHECK-NOT: BoundsCheck loop:none
115 /// CHECK-NOT: Deoptimize
Aart Bikc071a012016-12-01 10:22:31 -0800116 public static int geo1BCE() {
117 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
118 11, 12, 13, 14, 15, 16, 17, 19, 19, 20,
119 21, 22, 23, 24, 25, 26 };
120 int a = 1;
121 int r = 0;
122 for (int i = 0; i < 3; i++) {
123 r += x[a];
124 a *= 5;
125 }
126 return r;
127 }
128
129 // TODO: someday?
Aart Bikdf7822e2016-12-06 10:05:30 -0800130 //
131 /// CHECK-START: int Main.geo2BCE() BCE (before)
132 /// CHECK-DAG: BoundsCheck loop:none
133 /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
134 //
135 /// CHECK-START: int Main.geo2BCE() BCE (after)
136 /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
137 //
138 /// CHECK-START: int Main.geo2BCE() BCE (after)
139 /// CHECK-NOT: BoundsCheck loop:none
140 /// CHECK-NOT: Deoptimize
Aart Bikc071a012016-12-01 10:22:31 -0800141 public static int geo2BCE() {
142 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
143 11, 12, 13, 14, 15, 16, 17, 19, 19, 20,
144 21, 22, 23, 24, 25, 26 };
145 int a = 1;
146 int r = 0;
147 for (int i = 0; i < 5; i++) {
148 r += x[a];
149 a <<= 1;
150 }
151 return r;
152 }
153
154 /// CHECK-START: int Main.geo3BCE() BCE (before)
155 /// CHECK-DAG: BoundsCheck loop:none
156 /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
157 //
158 /// CHECK-START: int Main.geo3BCE() BCE (after)
159 /// CHECK-NOT: BoundsCheck
160 /// CHECK-NOT: Deoptimize
161 public static int geo3BCE() {
162 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
163 11, 12, 13, 14, 15, 16, 17, 19, 19, 20,
164 21, 22, 23, 24, 25, 26 };
165 int a = 25;
166 int r = 0;
167 for (int i = 0; i < 100; i++) { // a converges to 0
168 r += x[a];
169 a /= 5;
170 }
171 return r;
172 }
173
174 /// CHECK-START: int Main.geo4BCE() BCE (before)
175 /// CHECK-DAG: BoundsCheck loop:none
176 /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
177 //
178 /// CHECK-START: int Main.geo4BCE() BCE (after)
179 /// CHECK-NOT: BoundsCheck
180 /// CHECK-NOT: Deoptimize
181 public static int geo4BCE() {
182 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
183 11, 12, 13, 14, 15, 16, 17, 19, 19, 20,
184 21, 22, 23, 24, 25, 26 };
185 int a = 25;
186 int r = 0;
187 for (int i = 0; i < 100; i++) { // a converges to 0
188 r += x[a];
189 a %= 5;
190 }
191 return r;
192 }
193
194 /// CHECK-START: int Main.geoMulBlackHole(int) loop_optimization (before)
195 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
196 /// CHECK-DAG: Mul loop:<<Loop>>
197 //
198 /// CHECK-START: int Main.geoMulBlackHole(int) loop_optimization (after)
199 /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
200 /// CHECK-DAG: Return [<<Zero>>]
201 //
202 /// CHECK-START: int Main.geoMulBlackHole(int) loop_optimization (after)
203 /// CHECK-NOT: Phi
204 /// CHECK-NOT: Mul
205 public static int geoMulBlackHole(int a) {
206 for (int i = 0; i < 100; i++) {
207 a *= 10;
208 }
209 return a;
210 }
211
212 /// CHECK-START: int Main.geoShlBlackHole(int) loop_optimization (before)
213 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
214 /// CHECK-DAG: Shl loop:<<Loop>>
215 //
216 /// CHECK-START: int Main.geoShlBlackHole(int) loop_optimization (after)
217 /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
218 /// CHECK-DAG: Return [<<Zero>>]
219 //
220 /// CHECK-START: int Main.geoShlBlackHole(int) loop_optimization (after)
221 /// CHECK-NOT: Phi
222 /// CHECK-NOT: Shl
223 public static int geoShlBlackHole(int a) {
224 for (int i = 0; i < 100; i++) {
225 a <<= 1;
226 }
227 return a;
228 }
229
230 /// CHECK-START: int Main.geoDivBlackHole(int) loop_optimization (before)
231 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
232 /// CHECK-DAG: Div loop:<<Loop>>
233 //
234 /// CHECK-START: int Main.geoDivBlackHole(int) loop_optimization (after)
235 /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
236 /// CHECK-DAG: Return [<<Zero>>]
237 //
238 /// CHECK-START: int Main.geoDivBlackHole(int) loop_optimization (after)
239 /// CHECK-NOT: Phi
240 /// CHECK-NOT: Div
241 public static int geoDivBlackHole(int a) {
242 for (int i = 0; i < 100; i++) {
243 a /= 10;
244 }
245 return a;
246 }
247
Aart Bikdf7822e2016-12-06 10:05:30 -0800248 // Even though Rem is already optimized away by the time induction analysis
249 // and the loop optimizer run, the loop is optimized with a trivial
250 // wrap-around induction just as the wrap-around for REM would.
Aart Bikc071a012016-12-01 10:22:31 -0800251 //
252 /// CHECK-START: int Main.geoRemBlackHole(int) loop_optimization (before)
253 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
254 /// CHECK-DAG: Phi loop:<<Loop>>
255 //
256 /// CHECK-START: int Main.geoRemBlackHole(int) loop_optimization (after)
Aart Bikdf7822e2016-12-06 10:05:30 -0800257 /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
258 /// CHECK-DAG: Return [<<Zero>>]
259 //
260 /// CHECK-START: int Main.geoRemBlackHole(int) loop_optimization (after)
261 /// CHECK-NOT: Phi
Aart Bikc071a012016-12-01 10:22:31 -0800262 public static int geoRemBlackHole(int a) {
263 for (int i = 0; i < 100; i++) {
264 a %= 1;
265 }
266 return a;
267 }
268
269 //
270 // Verifier.
271 //
272
273 public static void main(String[] args) {
274 int m = 1410065408;
275 for (int i = -100; i <= 100; i++) {
276 expectEquals(m * i, geo1(i));
277 }
278 for (int i = 1; i <= 1000000000; i *= 10) {
279 expectEquals( m * i, geo1( i));
280 expectEquals(-m * i, geo1(-i));
281 }
282
283 for (int i = -100; i <= 100; i++) {
284 expectEquals(i << 10, geo2(i));
285 }
286 for (int i = 0; i < 22; i++) {
287 expectEquals(1 << (i + 10), geo2(1 << i));
288 }
289 expectEquals(0x80000400, geo2(0x00200001));
290 expectEquals(0x00000000, geo2(0x00400000));
291 expectEquals(0x00000400, geo2(0x00400001));
292
293 int d = 59049;
294 for (int i = -100; i <= 100; i++) {
295 expectEquals(0, geo3(i));
296 }
297 for (int i = 1; i <= 100; i++) {
298 expectEquals( i, geo3( i * d));
299 expectEquals( i, geo3( i * d + 1));
300 expectEquals(-i, geo3(-i * d));
301 expectEquals(-i, geo3(-i * d - 1));
302 }
303
304 for (int i = -100; i <= 100; i++) {
305 expectEquals(i % 7, geo4(i));
306 }
307
308 expectEquals(34, geo1BCE());
309 expectEquals(36, geo2BCE());
310 expectEquals(131, geo3BCE());
311 expectEquals(125, geo4BCE());
312
313 // Nothing escapes!
314 expectEquals(0, geoMulBlackHole(0));
315 expectEquals(0, geoShlBlackHole(0));
316 expectEquals(0, geoDivBlackHole(0));
317 expectEquals(0, geoRemBlackHole(0));
318 for (int i = -100; i <= 100; i++) {
319 expectEquals(0, geoMulBlackHole(i));
320 expectEquals(0, geoShlBlackHole(i));
321 expectEquals(0, geoDivBlackHole(i));
322 expectEquals(0, geoRemBlackHole(i));
323 }
324 for (int i = 0; i < 31; i++) {
325 expectEquals(0, geoMulBlackHole(1 << i));
326 expectEquals(0, geoShlBlackHole(1 << i));
327 expectEquals(0, geoDivBlackHole(1 << i));
328 expectEquals(0, geoRemBlackHole(1 << i));
329 }
330 expectEquals(0, geoMulBlackHole(0x7fffffff));
331 expectEquals(0, geoShlBlackHole(0x7fffffff));
332 expectEquals(0, geoDivBlackHole(0x7fffffff));
333 expectEquals(0, geoRemBlackHole(0x7fffffff));
334 expectEquals(0, geoMulBlackHole(0x80000000));
335 expectEquals(0, geoShlBlackHole(0x80000000));
336 expectEquals(0, geoDivBlackHole(0x80000000));
337 expectEquals(0, geoRemBlackHole(0x80000000));
338
339 System.out.println("passed");
340 }
341
342 private static void expectEquals(int expected, int result) {
343 if (expected != result) {
344 throw new Error("Expected: " + expected + ", found: " + result);
345 }
346 }
347}