blob: c766aaa6c9a6485e68933ba842939c614d602fc3 [file] [log] [blame]
Mingyao Yang8df69d42015-10-22 15:40: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
17class Circle {
18 Circle(double radius) {
19 this.radius = radius;
20 }
21 public double getArea() {
22 return radius * radius * Math.PI;
23 }
24 private double radius;
Andreas Gampe55d02cf2015-10-29 02:59:50 +000025};
Mingyao Yang8df69d42015-10-22 15:40:58 -070026
27class TestClass {
28 TestClass() {
29 }
30 TestClass(int i, int j) {
31 this.i = i;
32 this.j = j;
33 }
34 int i;
35 int j;
36 volatile int k;
37 TestClass next;
38 static int si;
Andreas Gampe55d02cf2015-10-29 02:59:50 +000039};
Mingyao Yang8df69d42015-10-22 15:40:58 -070040
41class SubTestClass extends TestClass {
42 int k;
Andreas Gampe55d02cf2015-10-29 02:59:50 +000043};
Mingyao Yang8df69d42015-10-22 15:40:58 -070044
45class TestClass2 {
46 int i;
47 int j;
Andreas Gampe55d02cf2015-10-29 02:59:50 +000048};
Mingyao Yang8df69d42015-10-22 15:40:58 -070049
50public class Main {
51
52 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before)
53 /// CHECK: NewInstance
54 /// CHECK: InstanceFieldSet
55 /// CHECK: InstanceFieldGet
56
57 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after)
58 /// CHECK: NewInstance
Andreas Gampe55d02cf2015-10-29 02:59:50 +000059 /// CHECK: InstanceFieldSet
Mingyao Yang8df69d42015-10-22 15:40:58 -070060 /// CHECK-NOT: InstanceFieldGet
61
62 static double calcCircleArea(double radius) {
63 return new Circle(radius).getArea();
64 }
65
66 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (before)
67 /// CHECK: InstanceFieldSet
68 /// CHECK: InstanceFieldSet
69 /// CHECK: InstanceFieldGet
70 /// CHECK: InstanceFieldGet
71
72 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (after)
73 /// CHECK: InstanceFieldSet
74 /// CHECK: InstanceFieldSet
75 /// CHECK-NOT: NullCheck
76 /// CHECK-NOT: InstanceFieldGet
77
78 // Different fields shouldn't alias.
79 static int test1(TestClass obj1, TestClass obj2) {
80 obj1.i = 1;
81 obj2.j = 2;
82 return obj1.i + obj2.j;
83 }
84
85 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (before)
86 /// CHECK: InstanceFieldSet
87 /// CHECK: InstanceFieldSet
88 /// CHECK: InstanceFieldGet
89
90 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (after)
91 /// CHECK: InstanceFieldSet
92 /// CHECK-NOT: NullCheck
93 /// CHECK-NOT: InstanceFieldSet
94 /// CHECK-NOT: InstanceFieldGet
95
96 // Redundant store of the same value.
97 static int test2(TestClass obj) {
98 obj.j = 1;
99 obj.j = 1;
100 return obj.j;
101 }
102
103 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (before)
104 /// CHECK: InstanceFieldSet
105 /// CHECK: InstanceFieldGet
106 /// CHECK: InstanceFieldSet
107 /// CHECK: NewInstance
108 /// CHECK: InstanceFieldSet
109 /// CHECK: InstanceFieldSet
110 /// CHECK: InstanceFieldGet
111 /// CHECK: InstanceFieldGet
112 /// CHECK: InstanceFieldGet
113 /// CHECK: InstanceFieldGet
114
115 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after)
116 /// CHECK: InstanceFieldSet
117 /// CHECK: InstanceFieldGet
118 /// CHECK: InstanceFieldSet
119 /// CHECK: NewInstance
Andreas Gampe55d02cf2015-10-29 02:59:50 +0000120 /// CHECK: InstanceFieldSet
Mingyao Yang8df69d42015-10-22 15:40:58 -0700121 /// CHECK-NOT: InstanceFieldGet
122
123 // A new allocation shouldn't alias with pre-existing values.
124 static int test3(TestClass obj) {
125 obj.i = 1;
126 obj.next.j = 2;
127 TestClass obj2 = new TestClass();
128 obj2.i = 3;
129 obj2.j = 4;
130 return obj.i + obj.next.j + obj2.i + obj2.j;
131 }
132
133 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before)
134 /// CHECK: InstanceFieldSet
135 /// CHECK: InstanceFieldGet
136 /// CHECK: Return
137 /// CHECK: InstanceFieldSet
138
139 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
140 /// CHECK: InstanceFieldSet
141 /// CHECK-NOT: NullCheck
142 /// CHECK-NOT: InstanceFieldGet
143 /// CHECK: Return
144 /// CHECK: InstanceFieldSet
145
146 // Set and merge the same value in two branches.
147 static int test4(TestClass obj, boolean b) {
148 if (b) {
149 obj.i = 1;
150 } else {
151 obj.i = 1;
152 }
153 return obj.i;
154 }
155
156 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before)
157 /// CHECK: InstanceFieldSet
158 /// CHECK: InstanceFieldGet
159 /// CHECK: Return
160 /// CHECK: InstanceFieldSet
161
162 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after)
163 /// CHECK: InstanceFieldSet
164 /// CHECK: InstanceFieldGet
165 /// CHECK: Return
166 /// CHECK: InstanceFieldSet
167
168 // Set and merge different values in two branches.
169 static int test5(TestClass obj, boolean b) {
170 if (b) {
171 obj.i = 1;
172 } else {
173 obj.i = 2;
174 }
175 return obj.i;
176 }
177
178 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before)
179 /// CHECK: InstanceFieldSet
180 /// CHECK: InstanceFieldSet
181 /// CHECK: InstanceFieldSet
182 /// CHECK: InstanceFieldGet
183 /// CHECK: InstanceFieldGet
184
185 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after)
186 /// CHECK: InstanceFieldSet
187 /// CHECK: InstanceFieldSet
188 /// CHECK: InstanceFieldSet
189 /// CHECK: InstanceFieldGet
190 /// CHECK-NOT: NullCheck
191 /// CHECK-NOT: InstanceFieldGet
192
193 // Setting the same value doesn't clear the value for aliased locations.
194 static int test6(TestClass obj1, TestClass obj2, boolean b) {
195 obj1.i = 1;
196 obj1.j = 2;
197 if (b) {
198 obj2.j = 2;
199 }
200 return obj1.j + obj2.j;
201 }
202
203 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (before)
204 /// CHECK: InstanceFieldSet
205 /// CHECK: InstanceFieldGet
206
207 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (after)
208 /// CHECK: InstanceFieldSet
209 /// CHECK: InstanceFieldGet
210
211 // Invocation should kill values in non-singleton heap locations.
212 static int test7(TestClass obj) {
213 obj.i = 1;
214 System.out.print("");
215 return obj.i;
216 }
217
218 /// CHECK-START: int Main.test8() load_store_elimination (before)
219 /// CHECK: NewInstance
220 /// CHECK: InstanceFieldSet
221 /// CHECK: InvokeVirtual
222 /// CHECK: InstanceFieldGet
223
224 /// CHECK-START: int Main.test8() load_store_elimination (after)
225 /// CHECK: NewInstance
Andreas Gampe55d02cf2015-10-29 02:59:50 +0000226 /// CHECK: InstanceFieldSet
Mingyao Yang8df69d42015-10-22 15:40:58 -0700227 /// CHECK: InvokeVirtual
228 /// CHECK-NOT: NullCheck
229 /// CHECK-NOT: InstanceFieldGet
230
231 // Invocation should not kill values in singleton heap locations.
232 static int test8() {
233 TestClass obj = new TestClass();
234 obj.i = 1;
235 System.out.print("");
236 return obj.i;
237 }
238
239 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (before)
240 /// CHECK: NewInstance
241 /// CHECK: InstanceFieldSet
242 /// CHECK: InstanceFieldSet
243 /// CHECK: InstanceFieldGet
244
245 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (after)
246 /// CHECK: NewInstance
247 /// CHECK: InstanceFieldSet
248 /// CHECK: InstanceFieldSet
249 /// CHECK: InstanceFieldGet
250
251 // Invocation should kill values in non-singleton heap locations.
252 static int test9(TestClass obj) {
253 TestClass obj2 = new TestClass();
254 obj2.i = 1;
255 obj.next = obj2;
256 System.out.print("");
257 return obj2.i;
258 }
259
260 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before)
261 /// CHECK: StaticFieldGet
262 /// CHECK: InstanceFieldGet
263 /// CHECK: StaticFieldSet
264 /// CHECK: InstanceFieldGet
265
266 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
267 /// CHECK: StaticFieldGet
268 /// CHECK: InstanceFieldGet
269 /// CHECK: StaticFieldSet
270 /// CHECK-NOT: NullCheck
271 /// CHECK-NOT: InstanceFieldGet
272
273 // Static fields shouldn't alias with instance fields.
274 static int test10(TestClass obj) {
275 TestClass.si += obj.i;
276 return obj.i;
277 }
278
279 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before)
280 /// CHECK: InstanceFieldSet
281 /// CHECK: InstanceFieldGet
282
283 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (after)
284 /// CHECK: InstanceFieldSet
285 /// CHECK-NOT: NullCheck
286 /// CHECK-NOT: InstanceFieldGet
287
288 // Loop without heap writes.
289 // obj.i is actually hoisted to the loop pre-header by licm already.
290 static int test11(TestClass obj) {
291 obj.i = 1;
292 int sum = 0;
293 for (int i = 0; i < 10; i++) {
294 sum += obj.i;
295 }
296 return sum;
297 }
298
299 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (before)
300 /// CHECK: InstanceFieldSet
301 /// CHECK: InstanceFieldGet
302 /// CHECK: InstanceFieldSet
303
304 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (after)
305 /// CHECK: InstanceFieldSet
306 /// CHECK: InstanceFieldGet
307 /// CHECK: InstanceFieldSet
308
309 // Loop with heap writes.
310 static int test12(TestClass obj1, TestClass obj2) {
311 obj1.i = 1;
312 int sum = 0;
313 for (int i = 0; i < 10; i++) {
314 sum += obj1.i;
315 obj2.i = sum;
316 }
317 return sum;
318 }
319
320 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (before)
321 /// CHECK: InstanceFieldSet
322 /// CHECK: InstanceFieldSet
323 /// CHECK: InstanceFieldGet
324 /// CHECK: InstanceFieldGet
325
326 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (after)
327 /// CHECK: InstanceFieldSet
328 /// CHECK: InstanceFieldSet
329 /// CHECK-NOT: NullCheck
330 /// CHECK-NOT: InstanceFieldGet
331
332 // Different classes shouldn't alias.
333 static int test13(TestClass obj1, TestClass2 obj2) {
334 obj1.i = 1;
335 obj2.i = 2;
336 return obj1.i + obj2.i;
337 }
338
339 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (before)
340 /// CHECK: InstanceFieldSet
341 /// CHECK: InstanceFieldSet
342 /// CHECK: InstanceFieldGet
343
344 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (after)
345 /// CHECK: InstanceFieldSet
346 /// CHECK: InstanceFieldSet
347 /// CHECK: InstanceFieldGet
348
349 // Subclass may alias with super class.
350 static int test14(TestClass obj1, SubTestClass obj2) {
351 obj1.i = 1;
352 obj2.i = 2;
353 return obj1.i;
354 }
355
356 /// CHECK-START: int Main.test15() load_store_elimination (before)
357 /// CHECK: StaticFieldSet
358 /// CHECK: StaticFieldSet
359 /// CHECK: StaticFieldGet
360
361 /// CHECK-START: int Main.test15() load_store_elimination (after)
362 /// CHECK: <<Const2:i\d+>> IntConstant 2
363 /// CHECK: StaticFieldSet
364 /// CHECK: StaticFieldSet
365 /// CHECK-NOT: StaticFieldGet
366 /// CHECK: Return [<<Const2>>]
367
368 // Static field access from subclass's name.
369 static int test15() {
370 TestClass.si = 1;
371 SubTestClass.si = 2;
372 return TestClass.si;
373 }
374
375 /// CHECK-START: int Main.test16() load_store_elimination (before)
376 /// CHECK: NewInstance
377 /// CHECK: InstanceFieldSet
378 /// CHECK: InstanceFieldSet
379 /// CHECK: InstanceFieldGet
380 /// CHECK: InstanceFieldGet
381
382 /// CHECK-START: int Main.test16() load_store_elimination (after)
383 /// CHECK: NewInstance
Andreas Gampe55d02cf2015-10-29 02:59:50 +0000384 /// CHECK-NOT: StaticFieldSet
385 /// CHECK-NOT: StaticFieldGet
Mingyao Yang8df69d42015-10-22 15:40:58 -0700386
387 // Test inlined constructor.
388 static int test16() {
389 TestClass obj = new TestClass(1, 2);
390 return obj.i + obj.j;
391 }
392
393 /// CHECK-START: int Main.test17() load_store_elimination (before)
394 /// CHECK: NewInstance
395 /// CHECK: InstanceFieldSet
396 /// CHECK: InstanceFieldGet
397
398 /// CHECK-START: int Main.test17() load_store_elimination (after)
399 /// CHECK: <<Const0:i\d+>> IntConstant 0
400 /// CHECK: NewInstance
Andreas Gampe55d02cf2015-10-29 02:59:50 +0000401 /// CHECK-NOT: StaticFieldSet
402 /// CHECK-NOT: StaticFieldGet
Mingyao Yang8df69d42015-10-22 15:40:58 -0700403 /// CHECK: Return [<<Const0>>]
404
405 // Test getting default value.
406 static int test17() {
407 TestClass obj = new TestClass();
408 obj.j = 1;
409 return obj.i;
410 }
411
412 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (before)
413 /// CHECK: InstanceFieldSet
414 /// CHECK: InstanceFieldGet
415
416 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (after)
417 /// CHECK: InstanceFieldSet
418 /// CHECK: InstanceFieldGet
419
420 // Volatile field load/store shouldn't be eliminated.
421 static int test18(TestClass obj) {
422 obj.k = 1;
423 return obj.k;
424 }
425
426 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (before)
427 /// CHECK: <<IntTypeValue:i\d+>> ArrayGet
428 /// CHECK: ArraySet
429 /// CHECK: <<FloatTypeValue:f\d+>> ArrayGet
430
431 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (after)
432 /// CHECK: <<IntTypeValue:i\d+>> ArrayGet
433 /// CHECK: ArraySet
434 /// CHECK: <<FloatTypeValue:f\d+>> ArrayGet
435
436 // I/F, J/D aliasing should keep the load/store.
437 static float test19(float[] fa1, float[] fa2) {
438 fa1[0] = fa2[0];
439 return fa1[0];
440 }
441
442 /// CHECK-START: TestClass Main.test20() load_store_elimination (before)
443 /// CHECK: NewInstance
444 /// CHECK: InstanceFieldSet
445
446 /// CHECK-START: TestClass Main.test20() load_store_elimination (after)
447 /// CHECK: NewInstance
448 /// CHECK-NOT: InstanceFieldSet
449
450 // Storing default heap value is redundant if the heap location has the
451 // default heap value.
452 static TestClass test20() {
453 TestClass obj = new TestClass();
454 obj.i = 0;
455 return obj;
456 }
457
458 public static void assertIntEquals(int expected, int result) {
459 if (expected != result) {
460 throw new Error("Expected: " + expected + ", found: " + result);
461 }
462 }
463
464 public static void assertFloatEquals(float expected, float result) {
465 if (expected != result) {
466 throw new Error("Expected: " + expected + ", found: " + result);
467 }
468 }
469
470 public static void assertDoubleEquals(double expected, double result) {
471 if (expected != result) {
472 throw new Error("Expected: " + expected + ", found: " + result);
473 }
474 }
475
476 public static void main(String[] args) {
477 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
478 assertIntEquals(test1(new TestClass(), new TestClass()), 3);
479 assertIntEquals(test2(new TestClass()), 1);
480 TestClass obj1 = new TestClass();
481 TestClass obj2 = new TestClass();
482 obj1.next = obj2;
483 assertIntEquals(test3(obj1), 10);
484 assertIntEquals(test4(new TestClass(), true), 1);
485 assertIntEquals(test4(new TestClass(), false), 1);
486 assertIntEquals(test5(new TestClass(), true), 1);
487 assertIntEquals(test5(new TestClass(), false), 2);
488 assertIntEquals(test6(new TestClass(), new TestClass(), true), 4);
489 assertIntEquals(test6(new TestClass(), new TestClass(), false), 2);
490 assertIntEquals(test7(new TestClass()), 1);
491 assertIntEquals(test8(), 1);
492 obj1 = new TestClass();
493 obj2 = new TestClass();
494 obj1.next = obj2;
495 assertIntEquals(test9(new TestClass()), 1);
496 assertIntEquals(test10(new TestClass(3, 4)), 3);
497 assertIntEquals(TestClass.si, 3);
498 assertIntEquals(test11(new TestClass()), 10);
499 assertIntEquals(test12(new TestClass(), new TestClass()), 10);
500 assertIntEquals(test13(new TestClass(), new TestClass2()), 3);
501 SubTestClass obj3 = new SubTestClass();
502 assertIntEquals(test14(obj3, obj3), 2);
503 assertIntEquals(test15(), 2);
504 assertIntEquals(test16(), 3);
505 assertIntEquals(test17(), 0);
506 assertIntEquals(test18(new TestClass()), 1);
507 float[] fa1 = { 0.8f };
508 float[] fa2 = { 1.8f };
509 assertFloatEquals(test19(fa1, fa2), 1.8f);
510 assertFloatEquals(test20().i, 0);
Mingyao Yang8df69d42015-10-22 15:40:58 -0700511 }
512}