blob: 2e19c88ff55275f263201a36ea8a33d1d8b2dbc9 [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
91 /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0 loop:none
92 /// CHECK-DAG: <<Int:i\d+>> IntConstant 7 loop:none
93 /// CHECK-DAG: <<Rem:i\d+>> Rem [<<Par>>,<<Int>>] loop:none
94 /// CHECK-DAG: <<Add:i\d+>> Add [<<Rem>>,<<Zer>>] loop:none
95 /// CHECK-DAG: Return [<<Add>>] loop:none
96 //
97 /// CHECK-START: int Main.geo4(int) loop_optimization (after)
98 /// CHECK-NOT: Phi
99 public static int geo4(int a) {
100 for (int i = 0; i < 10; i++) {
101 a %= 7;
102 }
103 return a;
104 }
105
106 // TODO: someday?
107 public static int geo1BCE() {
108 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
109 11, 12, 13, 14, 15, 16, 17, 19, 19, 20,
110 21, 22, 23, 24, 25, 26 };
111 int a = 1;
112 int r = 0;
113 for (int i = 0; i < 3; i++) {
114 r += x[a];
115 a *= 5;
116 }
117 return r;
118 }
119
120 // TODO: someday?
121 public static int geo2BCE() {
122 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
123 11, 12, 13, 14, 15, 16, 17, 19, 19, 20,
124 21, 22, 23, 24, 25, 26 };
125 int a = 1;
126 int r = 0;
127 for (int i = 0; i < 5; i++) {
128 r += x[a];
129 a <<= 1;
130 }
131 return r;
132 }
133
134 /// CHECK-START: int Main.geo3BCE() BCE (before)
135 /// CHECK-DAG: BoundsCheck loop:none
136 /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
137 //
138 /// CHECK-START: int Main.geo3BCE() BCE (after)
139 /// CHECK-NOT: BoundsCheck
140 /// CHECK-NOT: Deoptimize
141 public static int geo3BCE() {
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 = 25;
146 int r = 0;
147 for (int i = 0; i < 100; i++) { // a converges to 0
148 r += x[a];
149 a /= 5;
150 }
151 return r;
152 }
153
154 /// CHECK-START: int Main.geo4BCE() BCE (before)
155 /// CHECK-DAG: BoundsCheck loop:none
156 /// CHECK-DAG: BoundsCheck loop:{{B\d+}}
157 //
158 /// CHECK-START: int Main.geo4BCE() BCE (after)
159 /// CHECK-NOT: BoundsCheck
160 /// CHECK-NOT: Deoptimize
161 public static int geo4BCE() {
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.geoMulBlackHole(int) loop_optimization (before)
175 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
176 /// CHECK-DAG: Mul loop:<<Loop>>
177 //
178 /// CHECK-START: int Main.geoMulBlackHole(int) loop_optimization (after)
179 /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
180 /// CHECK-DAG: Return [<<Zero>>]
181 //
182 /// CHECK-START: int Main.geoMulBlackHole(int) loop_optimization (after)
183 /// CHECK-NOT: Phi
184 /// CHECK-NOT: Mul
185 public static int geoMulBlackHole(int a) {
186 for (int i = 0; i < 100; i++) {
187 a *= 10;
188 }
189 return a;
190 }
191
192 /// CHECK-START: int Main.geoShlBlackHole(int) loop_optimization (before)
193 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
194 /// CHECK-DAG: Shl loop:<<Loop>>
195 //
196 /// CHECK-START: int Main.geoShlBlackHole(int) loop_optimization (after)
197 /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
198 /// CHECK-DAG: Return [<<Zero>>]
199 //
200 /// CHECK-START: int Main.geoShlBlackHole(int) loop_optimization (after)
201 /// CHECK-NOT: Phi
202 /// CHECK-NOT: Shl
203 public static int geoShlBlackHole(int a) {
204 for (int i = 0; i < 100; i++) {
205 a <<= 1;
206 }
207 return a;
208 }
209
210 /// CHECK-START: int Main.geoDivBlackHole(int) loop_optimization (before)
211 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
212 /// CHECK-DAG: Div loop:<<Loop>>
213 //
214 /// CHECK-START: int Main.geoDivBlackHole(int) loop_optimization (after)
215 /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0
216 /// CHECK-DAG: Return [<<Zero>>]
217 //
218 /// CHECK-START: int Main.geoDivBlackHole(int) loop_optimization (after)
219 /// CHECK-NOT: Phi
220 /// CHECK-NOT: Div
221 public static int geoDivBlackHole(int a) {
222 for (int i = 0; i < 100; i++) {
223 a /= 10;
224 }
225 return a;
226 }
227
228 // TODO: Rem is already optimized away by the time the loop optimizer runs;
229 // we could still optimize this case with last value on wrap-around!
230 //
231 /// CHECK-START: int Main.geoRemBlackHole(int) loop_optimization (before)
232 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
233 /// CHECK-DAG: Phi loop:<<Loop>>
234 //
235 /// CHECK-START: int Main.geoRemBlackHole(int) loop_optimization (after)
236 /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
237 /// CHECK-DAG: Phi loop:<<Loop>>
238 public static int geoRemBlackHole(int a) {
239 for (int i = 0; i < 100; i++) {
240 a %= 1;
241 }
242 return a;
243 }
244
245 //
246 // Verifier.
247 //
248
249 public static void main(String[] args) {
250 int m = 1410065408;
251 for (int i = -100; i <= 100; i++) {
252 expectEquals(m * i, geo1(i));
253 }
254 for (int i = 1; i <= 1000000000; i *= 10) {
255 expectEquals( m * i, geo1( i));
256 expectEquals(-m * i, geo1(-i));
257 }
258
259 for (int i = -100; i <= 100; i++) {
260 expectEquals(i << 10, geo2(i));
261 }
262 for (int i = 0; i < 22; i++) {
263 expectEquals(1 << (i + 10), geo2(1 << i));
264 }
265 expectEquals(0x80000400, geo2(0x00200001));
266 expectEquals(0x00000000, geo2(0x00400000));
267 expectEquals(0x00000400, geo2(0x00400001));
268
269 int d = 59049;
270 for (int i = -100; i <= 100; i++) {
271 expectEquals(0, geo3(i));
272 }
273 for (int i = 1; i <= 100; i++) {
274 expectEquals( i, geo3( i * d));
275 expectEquals( i, geo3( i * d + 1));
276 expectEquals(-i, geo3(-i * d));
277 expectEquals(-i, geo3(-i * d - 1));
278 }
279
280 for (int i = -100; i <= 100; i++) {
281 expectEquals(i % 7, geo4(i));
282 }
283
284 expectEquals(34, geo1BCE());
285 expectEquals(36, geo2BCE());
286 expectEquals(131, geo3BCE());
287 expectEquals(125, geo4BCE());
288
289 // Nothing escapes!
290 expectEquals(0, geoMulBlackHole(0));
291 expectEquals(0, geoShlBlackHole(0));
292 expectEquals(0, geoDivBlackHole(0));
293 expectEquals(0, geoRemBlackHole(0));
294 for (int i = -100; i <= 100; i++) {
295 expectEquals(0, geoMulBlackHole(i));
296 expectEquals(0, geoShlBlackHole(i));
297 expectEquals(0, geoDivBlackHole(i));
298 expectEquals(0, geoRemBlackHole(i));
299 }
300 for (int i = 0; i < 31; i++) {
301 expectEquals(0, geoMulBlackHole(1 << i));
302 expectEquals(0, geoShlBlackHole(1 << i));
303 expectEquals(0, geoDivBlackHole(1 << i));
304 expectEquals(0, geoRemBlackHole(1 << i));
305 }
306 expectEquals(0, geoMulBlackHole(0x7fffffff));
307 expectEquals(0, geoShlBlackHole(0x7fffffff));
308 expectEquals(0, geoDivBlackHole(0x7fffffff));
309 expectEquals(0, geoRemBlackHole(0x7fffffff));
310 expectEquals(0, geoMulBlackHole(0x80000000));
311 expectEquals(0, geoShlBlackHole(0x80000000));
312 expectEquals(0, geoDivBlackHole(0x80000000));
313 expectEquals(0, geoRemBlackHole(0x80000000));
314
315 System.out.println("passed");
316 }
317
318 private static void expectEquals(int expected, int result) {
319 if (expected != result) {
320 throw new Error("Expected: " + expected + ", found: " + result);
321 }
322 }
323}