blob: 924ff6773f9049e7e2b674794b6533755c66eca3 [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;
Mingyao Yang7f43a3d2015-10-27 16:38:33 -070025}
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;
Mingyao Yang7f43a3d2015-10-27 16:38:33 -070039}
Mingyao Yang8df69d42015-10-22 15:40:58 -070040
41class SubTestClass extends TestClass {
42 int k;
Mingyao Yang7f43a3d2015-10-27 16:38:33 -070043}
Mingyao Yang8df69d42015-10-22 15:40:58 -070044
45class TestClass2 {
46 int i;
47 int j;
Mingyao Yang7f43a3d2015-10-27 16:38:33 -070048}
49
50class Finalizable {
51 static boolean sVisited = false;
52 static final int VALUE = 0xbeef;
53 int i;
54
55 protected void finalize() {
56 if (i != VALUE) {
57 System.out.println("Where is the beef?");
58 }
59 sVisited = true;
60 }
61}
Mingyao Yang8df69d42015-10-22 15:40:58 -070062
63public class Main {
64
65 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before)
66 /// CHECK: NewInstance
67 /// CHECK: InstanceFieldSet
68 /// CHECK: InstanceFieldGet
69
70 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after)
71 /// CHECK: NewInstance
Mingyao Yang7f43a3d2015-10-27 16:38:33 -070072 /// CHECK-NOT: InstanceFieldSet
Mingyao Yang8df69d42015-10-22 15:40:58 -070073 /// CHECK-NOT: InstanceFieldGet
74
75 static double calcCircleArea(double radius) {
76 return new Circle(radius).getArea();
77 }
78
79 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (before)
80 /// CHECK: InstanceFieldSet
81 /// CHECK: InstanceFieldSet
82 /// CHECK: InstanceFieldGet
83 /// CHECK: InstanceFieldGet
84
85 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (after)
86 /// CHECK: InstanceFieldSet
87 /// CHECK: InstanceFieldSet
88 /// CHECK-NOT: NullCheck
89 /// CHECK-NOT: InstanceFieldGet
90
91 // Different fields shouldn't alias.
92 static int test1(TestClass obj1, TestClass obj2) {
93 obj1.i = 1;
94 obj2.j = 2;
95 return obj1.i + obj2.j;
96 }
97
98 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (before)
99 /// CHECK: InstanceFieldSet
100 /// CHECK: InstanceFieldSet
101 /// CHECK: InstanceFieldGet
102
103 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (after)
104 /// CHECK: InstanceFieldSet
105 /// CHECK-NOT: NullCheck
106 /// CHECK-NOT: InstanceFieldSet
107 /// CHECK-NOT: InstanceFieldGet
108
109 // Redundant store of the same value.
110 static int test2(TestClass obj) {
111 obj.j = 1;
112 obj.j = 1;
113 return obj.j;
114 }
115
116 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (before)
117 /// CHECK: InstanceFieldSet
118 /// CHECK: InstanceFieldGet
119 /// CHECK: InstanceFieldSet
120 /// CHECK: NewInstance
121 /// CHECK: InstanceFieldSet
122 /// CHECK: InstanceFieldSet
123 /// CHECK: InstanceFieldGet
124 /// CHECK: InstanceFieldGet
125 /// CHECK: InstanceFieldGet
126 /// CHECK: InstanceFieldGet
127
128 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after)
129 /// CHECK: InstanceFieldSet
130 /// CHECK: InstanceFieldGet
131 /// CHECK: InstanceFieldSet
132 /// CHECK: NewInstance
Mingyao Yang7f43a3d2015-10-27 16:38:33 -0700133 /// CHECK-NOT: InstanceFieldSet
Mingyao Yang8df69d42015-10-22 15:40:58 -0700134 /// CHECK-NOT: InstanceFieldGet
135
136 // A new allocation shouldn't alias with pre-existing values.
137 static int test3(TestClass obj) {
138 obj.i = 1;
139 obj.next.j = 2;
140 TestClass obj2 = new TestClass();
141 obj2.i = 3;
142 obj2.j = 4;
143 return obj.i + obj.next.j + obj2.i + obj2.j;
144 }
145
146 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before)
147 /// CHECK: InstanceFieldSet
148 /// CHECK: InstanceFieldGet
149 /// CHECK: Return
150 /// CHECK: InstanceFieldSet
151
152 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
153 /// CHECK: InstanceFieldSet
154 /// CHECK-NOT: NullCheck
155 /// CHECK-NOT: InstanceFieldGet
156 /// CHECK: Return
157 /// CHECK: InstanceFieldSet
158
159 // Set and merge the same value in two branches.
160 static int test4(TestClass obj, boolean b) {
161 if (b) {
162 obj.i = 1;
163 } else {
164 obj.i = 1;
165 }
166 return obj.i;
167 }
168
169 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before)
170 /// CHECK: InstanceFieldSet
171 /// CHECK: InstanceFieldGet
172 /// CHECK: Return
173 /// CHECK: InstanceFieldSet
174
175 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after)
176 /// CHECK: InstanceFieldSet
177 /// CHECK: InstanceFieldGet
178 /// CHECK: Return
179 /// CHECK: InstanceFieldSet
180
181 // Set and merge different values in two branches.
182 static int test5(TestClass obj, boolean b) {
183 if (b) {
184 obj.i = 1;
185 } else {
186 obj.i = 2;
187 }
188 return obj.i;
189 }
190
191 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before)
192 /// CHECK: InstanceFieldSet
193 /// CHECK: InstanceFieldSet
194 /// CHECK: InstanceFieldSet
195 /// CHECK: InstanceFieldGet
196 /// CHECK: InstanceFieldGet
197
198 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after)
199 /// CHECK: InstanceFieldSet
200 /// CHECK: InstanceFieldSet
201 /// CHECK: InstanceFieldSet
202 /// CHECK: InstanceFieldGet
203 /// CHECK-NOT: NullCheck
204 /// CHECK-NOT: InstanceFieldGet
205
206 // Setting the same value doesn't clear the value for aliased locations.
207 static int test6(TestClass obj1, TestClass obj2, boolean b) {
208 obj1.i = 1;
209 obj1.j = 2;
210 if (b) {
211 obj2.j = 2;
212 }
213 return obj1.j + obj2.j;
214 }
215
216 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (before)
217 /// CHECK: InstanceFieldSet
218 /// CHECK: InstanceFieldGet
219
220 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (after)
221 /// CHECK: InstanceFieldSet
222 /// CHECK: InstanceFieldGet
223
224 // Invocation should kill values in non-singleton heap locations.
225 static int test7(TestClass obj) {
226 obj.i = 1;
227 System.out.print("");
228 return obj.i;
229 }
230
231 /// CHECK-START: int Main.test8() load_store_elimination (before)
232 /// CHECK: NewInstance
233 /// CHECK: InstanceFieldSet
234 /// CHECK: InvokeVirtual
235 /// CHECK: InstanceFieldGet
236
237 /// CHECK-START: int Main.test8() load_store_elimination (after)
238 /// CHECK: NewInstance
Mingyao Yang7f43a3d2015-10-27 16:38:33 -0700239 /// CHECK-NOT: InstanceFieldSet
Mingyao Yang8df69d42015-10-22 15:40:58 -0700240 /// CHECK: InvokeVirtual
241 /// CHECK-NOT: NullCheck
242 /// CHECK-NOT: InstanceFieldGet
243
244 // Invocation should not kill values in singleton heap locations.
245 static int test8() {
246 TestClass obj = new TestClass();
247 obj.i = 1;
248 System.out.print("");
249 return obj.i;
250 }
251
252 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (before)
253 /// CHECK: NewInstance
254 /// CHECK: InstanceFieldSet
255 /// CHECK: InstanceFieldSet
256 /// CHECK: InstanceFieldGet
257
258 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (after)
259 /// CHECK: NewInstance
260 /// CHECK: InstanceFieldSet
261 /// CHECK: InstanceFieldSet
262 /// CHECK: InstanceFieldGet
263
264 // Invocation should kill values in non-singleton heap locations.
265 static int test9(TestClass obj) {
266 TestClass obj2 = new TestClass();
267 obj2.i = 1;
268 obj.next = obj2;
269 System.out.print("");
270 return obj2.i;
271 }
272
273 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before)
274 /// CHECK: StaticFieldGet
275 /// CHECK: InstanceFieldGet
276 /// CHECK: StaticFieldSet
277 /// CHECK: InstanceFieldGet
278
279 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
280 /// CHECK: StaticFieldGet
281 /// CHECK: InstanceFieldGet
282 /// CHECK: StaticFieldSet
283 /// CHECK-NOT: NullCheck
284 /// CHECK-NOT: InstanceFieldGet
285
286 // Static fields shouldn't alias with instance fields.
287 static int test10(TestClass obj) {
288 TestClass.si += obj.i;
289 return obj.i;
290 }
291
292 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before)
293 /// CHECK: InstanceFieldSet
294 /// CHECK: InstanceFieldGet
295
296 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (after)
297 /// CHECK: InstanceFieldSet
298 /// CHECK-NOT: NullCheck
299 /// CHECK-NOT: InstanceFieldGet
300
301 // Loop without heap writes.
302 // obj.i is actually hoisted to the loop pre-header by licm already.
303 static int test11(TestClass obj) {
304 obj.i = 1;
305 int sum = 0;
306 for (int i = 0; i < 10; i++) {
307 sum += obj.i;
308 }
309 return sum;
310 }
311
312 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (before)
313 /// CHECK: InstanceFieldSet
314 /// CHECK: InstanceFieldGet
315 /// CHECK: InstanceFieldSet
316
317 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (after)
318 /// CHECK: InstanceFieldSet
319 /// CHECK: InstanceFieldGet
320 /// CHECK: InstanceFieldSet
321
322 // Loop with heap writes.
323 static int test12(TestClass obj1, TestClass obj2) {
324 obj1.i = 1;
325 int sum = 0;
326 for (int i = 0; i < 10; i++) {
327 sum += obj1.i;
328 obj2.i = sum;
329 }
330 return sum;
331 }
332
333 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (before)
334 /// CHECK: InstanceFieldSet
335 /// CHECK: InstanceFieldSet
336 /// CHECK: InstanceFieldGet
337 /// CHECK: InstanceFieldGet
338
339 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (after)
340 /// CHECK: InstanceFieldSet
341 /// CHECK: InstanceFieldSet
342 /// CHECK-NOT: NullCheck
343 /// CHECK-NOT: InstanceFieldGet
344
345 // Different classes shouldn't alias.
346 static int test13(TestClass obj1, TestClass2 obj2) {
347 obj1.i = 1;
348 obj2.i = 2;
349 return obj1.i + obj2.i;
350 }
351
352 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (before)
353 /// CHECK: InstanceFieldSet
354 /// CHECK: InstanceFieldSet
355 /// CHECK: InstanceFieldGet
356
357 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (after)
358 /// CHECK: InstanceFieldSet
359 /// CHECK: InstanceFieldSet
360 /// CHECK: InstanceFieldGet
361
362 // Subclass may alias with super class.
363 static int test14(TestClass obj1, SubTestClass obj2) {
364 obj1.i = 1;
365 obj2.i = 2;
366 return obj1.i;
367 }
368
369 /// CHECK-START: int Main.test15() load_store_elimination (before)
370 /// CHECK: StaticFieldSet
371 /// CHECK: StaticFieldSet
372 /// CHECK: StaticFieldGet
373
374 /// CHECK-START: int Main.test15() load_store_elimination (after)
375 /// CHECK: <<Const2:i\d+>> IntConstant 2
376 /// CHECK: StaticFieldSet
377 /// CHECK: StaticFieldSet
378 /// CHECK-NOT: StaticFieldGet
379 /// CHECK: Return [<<Const2>>]
380
381 // Static field access from subclass's name.
382 static int test15() {
383 TestClass.si = 1;
384 SubTestClass.si = 2;
385 return TestClass.si;
386 }
387
388 /// CHECK-START: int Main.test16() load_store_elimination (before)
389 /// CHECK: NewInstance
390 /// CHECK: InstanceFieldSet
391 /// CHECK: InstanceFieldSet
392 /// CHECK: InstanceFieldGet
393 /// CHECK: InstanceFieldGet
394
395 /// CHECK-START: int Main.test16() load_store_elimination (after)
396 /// CHECK: NewInstance
Mingyao Yang7f43a3d2015-10-27 16:38:33 -0700397 /// CHECK-NOT: InstanceFieldSet
398 /// CHECK-NOT: InstanceFieldGet
Mingyao Yang8df69d42015-10-22 15:40:58 -0700399
400 // Test inlined constructor.
401 static int test16() {
402 TestClass obj = new TestClass(1, 2);
403 return obj.i + obj.j;
404 }
405
406 /// CHECK-START: int Main.test17() load_store_elimination (before)
407 /// CHECK: NewInstance
408 /// CHECK: InstanceFieldSet
409 /// CHECK: InstanceFieldGet
410
411 /// CHECK-START: int Main.test17() load_store_elimination (after)
412 /// CHECK: <<Const0:i\d+>> IntConstant 0
413 /// CHECK: NewInstance
Mingyao Yang7f43a3d2015-10-27 16:38:33 -0700414 /// CHECK-NOT: InstanceFieldSet
415 /// CHECK-NOT: InstanceFieldGet
Mingyao Yang8df69d42015-10-22 15:40:58 -0700416 /// CHECK: Return [<<Const0>>]
417
418 // Test getting default value.
419 static int test17() {
420 TestClass obj = new TestClass();
421 obj.j = 1;
422 return obj.i;
423 }
424
425 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (before)
426 /// CHECK: InstanceFieldSet
427 /// CHECK: InstanceFieldGet
428
429 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (after)
430 /// CHECK: InstanceFieldSet
431 /// CHECK: InstanceFieldGet
432
433 // Volatile field load/store shouldn't be eliminated.
434 static int test18(TestClass obj) {
435 obj.k = 1;
436 return obj.k;
437 }
438
439 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (before)
440 /// CHECK: <<IntTypeValue:i\d+>> ArrayGet
441 /// CHECK: ArraySet
442 /// CHECK: <<FloatTypeValue:f\d+>> ArrayGet
443
444 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (after)
445 /// CHECK: <<IntTypeValue:i\d+>> ArrayGet
446 /// CHECK: ArraySet
447 /// CHECK: <<FloatTypeValue:f\d+>> ArrayGet
448
449 // I/F, J/D aliasing should keep the load/store.
450 static float test19(float[] fa1, float[] fa2) {
451 fa1[0] = fa2[0];
452 return fa1[0];
453 }
454
455 /// CHECK-START: TestClass Main.test20() load_store_elimination (before)
456 /// CHECK: NewInstance
457 /// CHECK: InstanceFieldSet
458
459 /// CHECK-START: TestClass Main.test20() load_store_elimination (after)
460 /// CHECK: NewInstance
461 /// CHECK-NOT: InstanceFieldSet
462
463 // Storing default heap value is redundant if the heap location has the
464 // default heap value.
465 static TestClass test20() {
466 TestClass obj = new TestClass();
467 obj.i = 0;
468 return obj;
469 }
470
Mingyao Yang7f43a3d2015-10-27 16:38:33 -0700471 /// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
472 /// CHECK: NewInstance
473 /// CHECK: InstanceFieldSet
474
475 /// CHECK-START: void Main.testFinalizable() load_store_elimination (after)
476 /// CHECK: NewInstance
477 /// CHECK: InstanceFieldSet
478
479 // Allocations and stores into finalizable objects cannot be eliminated.
480 static void testFinalizable() {
481 Finalizable finalizable = new Finalizable();
482 finalizable.i = Finalizable.VALUE;
483 }
484
485 static java.lang.ref.WeakReference<Object> getWeakReference() {
486 return new java.lang.ref.WeakReference<>(new Object());
487 }
488
489 static void testFinalizableByForcingGc() {
490 testFinalizable();
491 java.lang.ref.WeakReference<Object> reference = getWeakReference();
492
493 Runtime runtime = Runtime.getRuntime();
494 for (int i = 0; i < 20; ++i) {
495 runtime.gc();
496 System.runFinalization();
497 try {
498 Thread.sleep(1);
499 } catch (InterruptedException e) {
500 throw new AssertionError(e);
501 }
502
503 // Check to see if the weak reference has been garbage collected.
504 if (reference.get() == null) {
505 // A little bit more sleep time to make sure.
506 try {
507 Thread.sleep(100);
508 } catch (InterruptedException e) {
509 throw new AssertionError(e);
510 }
511 if (!Finalizable.sVisited) {
512 System.out.println("finalize() not called.");
513 }
514 return;
515 }
516 }
517 System.out.println("testFinalizableByForcingGc() failed to force gc.");
518 }
519
Mingyao Yang8df69d42015-10-22 15:40:58 -0700520 public static void assertIntEquals(int expected, int result) {
521 if (expected != result) {
522 throw new Error("Expected: " + expected + ", found: " + result);
523 }
524 }
525
526 public static void assertFloatEquals(float expected, float result) {
527 if (expected != result) {
528 throw new Error("Expected: " + expected + ", found: " + result);
529 }
530 }
531
532 public static void assertDoubleEquals(double expected, double result) {
533 if (expected != result) {
534 throw new Error("Expected: " + expected + ", found: " + result);
535 }
536 }
537
538 public static void main(String[] args) {
539 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
540 assertIntEquals(test1(new TestClass(), new TestClass()), 3);
541 assertIntEquals(test2(new TestClass()), 1);
542 TestClass obj1 = new TestClass();
543 TestClass obj2 = new TestClass();
544 obj1.next = obj2;
545 assertIntEquals(test3(obj1), 10);
546 assertIntEquals(test4(new TestClass(), true), 1);
547 assertIntEquals(test4(new TestClass(), false), 1);
548 assertIntEquals(test5(new TestClass(), true), 1);
549 assertIntEquals(test5(new TestClass(), false), 2);
550 assertIntEquals(test6(new TestClass(), new TestClass(), true), 4);
551 assertIntEquals(test6(new TestClass(), new TestClass(), false), 2);
552 assertIntEquals(test7(new TestClass()), 1);
553 assertIntEquals(test8(), 1);
554 obj1 = new TestClass();
555 obj2 = new TestClass();
556 obj1.next = obj2;
557 assertIntEquals(test9(new TestClass()), 1);
558 assertIntEquals(test10(new TestClass(3, 4)), 3);
559 assertIntEquals(TestClass.si, 3);
560 assertIntEquals(test11(new TestClass()), 10);
561 assertIntEquals(test12(new TestClass(), new TestClass()), 10);
562 assertIntEquals(test13(new TestClass(), new TestClass2()), 3);
563 SubTestClass obj3 = new SubTestClass();
564 assertIntEquals(test14(obj3, obj3), 2);
565 assertIntEquals(test15(), 2);
566 assertIntEquals(test16(), 3);
567 assertIntEquals(test17(), 0);
568 assertIntEquals(test18(new TestClass()), 1);
569 float[] fa1 = { 0.8f };
570 float[] fa2 = { 1.8f };
571 assertFloatEquals(test19(fa1, fa2), 1.8f);
572 assertFloatEquals(test20().i, 0);
Mingyao Yang7f43a3d2015-10-27 16:38:33 -0700573 testFinalizableByForcingGc();
Mingyao Yang8df69d42015-10-22 15:40:58 -0700574 }
575}