1 /*
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 
17 class Circle {
Circle(double radius)18   Circle(double radius) {
19     this.radius = radius;
20   }
getArea()21   public double getArea() {
22     return radius * radius * Math.PI;
23   }
24   private double radius;
25 }
26 
27 class TestClass {
28   static {
29     sTestClassObj = new TestClass(-1, -2);
30   }
TestClass()31   TestClass() {
32   }
TestClass(int i, int j)33   TestClass(int i, int j) {
34     this.i = i;
35     this.j = j;
36   }
37   int i;
38   int j;
39   volatile int k;
40   TestClass next;
41   String str;
42   static int si;
43   static TestClass sTestClassObj;
44 }
45 
46 class SubTestClass extends TestClass {
47   int k;
48 }
49 
50 class TestClass2 {
51   int i;
52   int j;
53 }
54 
55 class TestClass3 {
56   float floatField = 8.0f;
57   boolean test1 = true;
58 }
59 
60 class Finalizable {
61   static boolean sVisited = false;
62   static final int VALUE = 0xbeef;
63   int i;
64 
finalize()65   protected void finalize() {
66     if (i != VALUE) {
67       System.out.println("Where is the beef?");
68     }
69     sVisited = true;
70   }
71 }
72 
73 public class Main {
74 
75   /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before)
76   /// CHECK: NewInstance
77   /// CHECK: InstanceFieldSet
78   /// CHECK: InstanceFieldGet
79 
80   /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after)
81   /// CHECK: NewInstance
82   /// CHECK-NOT: InstanceFieldSet
83   /// CHECK-NOT: InstanceFieldGet
84 
calcCircleArea(double radius)85   static double calcCircleArea(double radius) {
86     return new Circle(radius).getArea();
87   }
88 
89   /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (before)
90   /// CHECK: InstanceFieldSet
91   /// CHECK: InstanceFieldSet
92   /// CHECK: InstanceFieldGet
93   /// CHECK: InstanceFieldGet
94 
95   /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (after)
96   /// CHECK: InstanceFieldSet
97   /// CHECK: InstanceFieldSet
98   /// CHECK-NOT: NullCheck
99   /// CHECK-NOT: InstanceFieldGet
100 
101   // Different fields shouldn't alias.
test1(TestClass obj1, TestClass obj2)102   static int test1(TestClass obj1, TestClass obj2) {
103     obj1.i = 1;
104     obj2.j = 2;
105     return obj1.i + obj2.j;
106   }
107 
108   /// CHECK-START: int Main.test2(TestClass) load_store_elimination (before)
109   /// CHECK: InstanceFieldSet
110   /// CHECK: InstanceFieldSet
111   /// CHECK: InstanceFieldGet
112 
113   /// CHECK-START: int Main.test2(TestClass) load_store_elimination (after)
114   /// CHECK: InstanceFieldSet
115   /// CHECK-NOT: NullCheck
116   /// CHECK-NOT: InstanceFieldSet
117   /// CHECK-NOT: InstanceFieldGet
118 
119   // Redundant store of the same value.
test2(TestClass obj)120   static int test2(TestClass obj) {
121     obj.j = 1;
122     obj.j = 1;
123     return obj.j;
124   }
125 
126   /// CHECK-START: int Main.test3(TestClass) load_store_elimination (before)
127   /// CHECK: NewInstance
128   /// CHECK: StaticFieldGet
129   /// CHECK: NewInstance
130   /// CHECK: InstanceFieldSet
131   /// CHECK: InstanceFieldSet
132   /// CHECK: InstanceFieldSet
133   /// CHECK: InstanceFieldSet
134   /// CHECK: InstanceFieldGet
135   /// CHECK: InstanceFieldGet
136   /// CHECK: InstanceFieldGet
137   /// CHECK: InstanceFieldGet
138 
139   /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after)
140   /// CHECK: NewInstance
141   /// CHECK: StaticFieldGet
142   /// CHECK: NewInstance
143   /// CHECK: InstanceFieldSet
144   /// CHECK: InstanceFieldSet
145   /// CHECK: InstanceFieldSet
146   /// CHECK: InstanceFieldSet
147   /// CHECK-NOT: InstanceFieldGet
148   /// CHECK-NOT: StaticFieldGet
149 
150   // A new allocation (even non-singleton) shouldn't alias with pre-existing values.
test3(TestClass obj)151   static int test3(TestClass obj) {
152     // Do an allocation here to avoid the HLoadClass and HClinitCheck
153     // at the second allocation.
154     new TestClass();
155     TestClass obj1 = TestClass.sTestClassObj;
156     TestClass obj2 = new TestClass();  // Cannot alias with obj or obj1 which pre-exist.
157     obj.next = obj2;  // Make obj2 a non-singleton.
158     // All stores below need to stay since obj/obj1/obj2 are not singletons.
159     obj.i = 1;
160     obj1.j = 2;
161     // Following stores won't kill values of obj.i and obj1.j.
162     obj2.i = 3;
163     obj2.j = 4;
164     return obj.i + obj1.j + obj2.i + obj2.j;
165   }
166 
167   /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before)
168   /// CHECK: InstanceFieldSet
169   /// CHECK: InstanceFieldGet
170   /// CHECK: Return
171   /// CHECK: InstanceFieldSet
172 
173   /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
174   /// CHECK: InstanceFieldSet
175   /// CHECK-NOT: NullCheck
176   /// CHECK-NOT: InstanceFieldGet
177   /// CHECK: Return
178   /// CHECK: InstanceFieldSet
179 
180   // Set and merge the same value in two branches.
test4(TestClass obj, boolean b)181   static int test4(TestClass obj, boolean b) {
182     if (b) {
183       obj.i = 1;
184     } else {
185       obj.i = 1;
186     }
187     return obj.i;
188   }
189 
190   /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before)
191   /// CHECK: InstanceFieldSet
192   /// CHECK: InstanceFieldGet
193   /// CHECK: Return
194   /// CHECK: InstanceFieldSet
195 
196   /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after)
197   /// CHECK: InstanceFieldSet
198   /// CHECK: InstanceFieldGet
199   /// CHECK: Return
200   /// CHECK: InstanceFieldSet
201 
202   // Set and merge different values in two branches.
test5(TestClass obj, boolean b)203   static int test5(TestClass obj, boolean b) {
204     if (b) {
205       obj.i = 1;
206     } else {
207       obj.i = 2;
208     }
209     return obj.i;
210   }
211 
212   /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before)
213   /// CHECK: InstanceFieldSet
214   /// CHECK: InstanceFieldSet
215   /// CHECK: InstanceFieldSet
216   /// CHECK: InstanceFieldGet
217   /// CHECK: InstanceFieldGet
218 
219   /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after)
220   /// CHECK: InstanceFieldSet
221   /// CHECK: InstanceFieldSet
222   /// CHECK: InstanceFieldSet
223   /// CHECK: InstanceFieldGet
224   /// CHECK-NOT: NullCheck
225   /// CHECK-NOT: InstanceFieldGet
226 
227   // Setting the same value doesn't clear the value for aliased locations.
test6(TestClass obj1, TestClass obj2, boolean b)228   static int test6(TestClass obj1, TestClass obj2, boolean b) {
229     obj1.i = 1;
230     obj1.j = 2;
231     if (b) {
232       obj2.j = 2;
233     }
234     return obj1.j + obj2.j;
235   }
236 
237   /// CHECK-START: int Main.test7(TestClass) load_store_elimination (before)
238   /// CHECK: InstanceFieldSet
239   /// CHECK: InstanceFieldGet
240 
241   /// CHECK-START: int Main.test7(TestClass) load_store_elimination (after)
242   /// CHECK: InstanceFieldSet
243   /// CHECK: InstanceFieldGet
244 
245   // Invocation should kill values in non-singleton heap locations.
test7(TestClass obj)246   static int test7(TestClass obj) {
247     obj.i = 1;
248     System.out.print("");
249     return obj.i;
250   }
251 
252   /// CHECK-START: int Main.test8() load_store_elimination (before)
253   /// CHECK: NewInstance
254   /// CHECK: InstanceFieldSet
255   /// CHECK: InvokeVirtual
256   /// CHECK: InstanceFieldGet
257 
258   /// CHECK-START: int Main.test8() load_store_elimination (after)
259   /// CHECK: NewInstance
260   /// CHECK-NOT: InstanceFieldSet
261   /// CHECK: InvokeVirtual
262   /// CHECK-NOT: NullCheck
263   /// CHECK-NOT: InstanceFieldGet
264 
265   // Invocation should not kill values in singleton heap locations.
test8()266   static int test8() {
267     TestClass obj = new TestClass();
268     obj.i = 1;
269     System.out.print("");
270     return obj.i;
271   }
272 
273   /// CHECK-START: int Main.test9(TestClass) load_store_elimination (before)
274   /// CHECK: NewInstance
275   /// CHECK: InstanceFieldSet
276   /// CHECK: InstanceFieldSet
277   /// CHECK: InstanceFieldGet
278 
279   /// CHECK-START: int Main.test9(TestClass) load_store_elimination (after)
280   /// CHECK: NewInstance
281   /// CHECK: InstanceFieldSet
282   /// CHECK: InstanceFieldSet
283   /// CHECK: InstanceFieldGet
284 
285   // Invocation should kill values in non-singleton heap locations.
test9(TestClass obj)286   static int test9(TestClass obj) {
287     TestClass obj2 = new TestClass();
288     obj2.i = 1;
289     obj.next = obj2;
290     System.out.print("");
291     return obj2.i;
292   }
293 
294   /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before)
295   /// CHECK: StaticFieldGet
296   /// CHECK: InstanceFieldGet
297   /// CHECK: StaticFieldSet
298   /// CHECK: InstanceFieldGet
299 
300   /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
301   /// CHECK: StaticFieldGet
302   /// CHECK: InstanceFieldGet
303   /// CHECK: StaticFieldSet
304   /// CHECK-NOT: NullCheck
305   /// CHECK-NOT: InstanceFieldGet
306 
307   // Static fields shouldn't alias with instance fields.
test10(TestClass obj)308   static int test10(TestClass obj) {
309     TestClass.si += obj.i;
310     return obj.i;
311   }
312 
313   /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before)
314   /// CHECK: InstanceFieldSet
315   /// CHECK: InstanceFieldGet
316 
317   /// CHECK-START: int Main.test11(TestClass) load_store_elimination (after)
318   /// CHECK: InstanceFieldSet
319   /// CHECK-NOT: NullCheck
320   /// CHECK-NOT: InstanceFieldGet
321 
322   // Loop without heap writes.
323   // obj.i is actually hoisted to the loop pre-header by licm already.
test11(TestClass obj)324   static int test11(TestClass obj) {
325     obj.i = 1;
326     int sum = 0;
327     for (int i = 0; i < 10; i++) {
328       sum += obj.i;
329     }
330     return sum;
331   }
332 
333   /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (before)
334   /// CHECK: InstanceFieldSet
335   /// CHECK: InstanceFieldGet
336   /// CHECK: InstanceFieldSet
337 
338   /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (after)
339   /// CHECK: InstanceFieldSet
340   /// CHECK: InstanceFieldGet
341   /// CHECK: InstanceFieldSet
342 
343   // Loop with heap writes.
test12(TestClass obj1, TestClass obj2)344   static int test12(TestClass obj1, TestClass obj2) {
345     obj1.i = 1;
346     int sum = 0;
347     for (int i = 0; i < 10; i++) {
348       sum += obj1.i;
349       obj2.i = sum;
350     }
351     return sum;
352   }
353 
354   /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (before)
355   /// CHECK: InstanceFieldSet
356   /// CHECK: InstanceFieldSet
357   /// CHECK: InstanceFieldGet
358   /// CHECK: InstanceFieldGet
359 
360   /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (after)
361   /// CHECK: InstanceFieldSet
362   /// CHECK: InstanceFieldSet
363   /// CHECK-NOT: NullCheck
364   /// CHECK-NOT: InstanceFieldGet
365 
366   // Different classes shouldn't alias.
test13(TestClass obj1, TestClass2 obj2)367   static int test13(TestClass obj1, TestClass2 obj2) {
368     obj1.i = 1;
369     obj2.i = 2;
370     return obj1.i + obj2.i;
371   }
372 
373   /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (before)
374   /// CHECK: InstanceFieldSet
375   /// CHECK: InstanceFieldSet
376   /// CHECK: InstanceFieldGet
377 
378   /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (after)
379   /// CHECK: InstanceFieldSet
380   /// CHECK: InstanceFieldSet
381   /// CHECK: InstanceFieldGet
382 
383   // Subclass may alias with super class.
test14(TestClass obj1, SubTestClass obj2)384   static int test14(TestClass obj1, SubTestClass obj2) {
385     obj1.i = 1;
386     obj2.i = 2;
387     return obj1.i;
388   }
389 
390   /// CHECK-START: int Main.test15() load_store_elimination (before)
391   /// CHECK: StaticFieldSet
392   /// CHECK: StaticFieldSet
393   /// CHECK: StaticFieldGet
394 
395   /// CHECK-START: int Main.test15() load_store_elimination (after)
396   /// CHECK: <<Const2:i\d+>> IntConstant 2
397   /// CHECK: StaticFieldSet
398   /// CHECK: StaticFieldSet
399   /// CHECK-NOT: StaticFieldGet
400   /// CHECK: Return [<<Const2>>]
401 
402   // Static field access from subclass's name.
test15()403   static int test15() {
404     TestClass.si = 1;
405     SubTestClass.si = 2;
406     return TestClass.si;
407   }
408 
409   /// CHECK-START: int Main.test16() load_store_elimination (before)
410   /// CHECK: NewInstance
411   /// CHECK: InstanceFieldSet
412   /// CHECK: InstanceFieldSet
413   /// CHECK: InstanceFieldGet
414   /// CHECK: InstanceFieldGet
415 
416   /// CHECK-START: int Main.test16() load_store_elimination (after)
417   /// CHECK: NewInstance
418   /// CHECK-NOT: InstanceFieldSet
419   /// CHECK-NOT: InstanceFieldGet
420 
421   // Test inlined constructor.
test16()422   static int test16() {
423     TestClass obj = new TestClass(1, 2);
424     return obj.i + obj.j;
425   }
426 
427   /// CHECK-START: int Main.test17() load_store_elimination (before)
428   /// CHECK: NewInstance
429   /// CHECK: InstanceFieldSet
430   /// CHECK: InstanceFieldGet
431 
432   /// CHECK-START: int Main.test17() load_store_elimination (after)
433   /// CHECK: <<Const0:i\d+>> IntConstant 0
434   /// CHECK: NewInstance
435   /// CHECK-NOT: InstanceFieldSet
436   /// CHECK-NOT: InstanceFieldGet
437   /// CHECK: Return [<<Const0>>]
438 
439   // Test getting default value.
test17()440   static int test17() {
441     TestClass obj = new TestClass();
442     obj.j = 1;
443     return obj.i;
444   }
445 
446   /// CHECK-START: int Main.test18(TestClass) load_store_elimination (before)
447   /// CHECK: InstanceFieldSet
448   /// CHECK: InstanceFieldGet
449 
450   /// CHECK-START: int Main.test18(TestClass) load_store_elimination (after)
451   /// CHECK: InstanceFieldSet
452   /// CHECK: InstanceFieldGet
453 
454   // Volatile field load/store shouldn't be eliminated.
test18(TestClass obj)455   static int test18(TestClass obj) {
456     obj.k = 1;
457     return obj.k;
458   }
459 
460   /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (before)
461   /// CHECK:     {{f\d+}} ArrayGet
462   /// CHECK:     {{f\d+}} ArrayGet
463 
464   /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (after)
465   /// CHECK:     {{f\d+}} ArrayGet
466   /// CHECK-NOT: {{f\d+}} ArrayGet
467 
468   // I/F, J/D aliasing should not happen any more and LSE should eliminate the load.
test19(float[] fa1, float[] fa2)469   static float test19(float[] fa1, float[] fa2) {
470     fa1[0] = fa2[0];
471     return fa1[0];
472   }
473 
474   /// CHECK-START: TestClass Main.test20() load_store_elimination (before)
475   /// CHECK: NewInstance
476   /// CHECK: InstanceFieldSet
477 
478   /// CHECK-START: TestClass Main.test20() load_store_elimination (after)
479   /// CHECK: NewInstance
480   /// CHECK-NOT: InstanceFieldSet
481 
482   // Storing default heap value is redundant if the heap location has the
483   // default heap value.
test20()484   static TestClass test20() {
485     TestClass obj = new TestClass();
486     obj.i = 0;
487     return obj;
488   }
489 
490   /// CHECK-START: void Main.test21(TestClass) load_store_elimination (before)
491   /// CHECK: NewInstance
492   /// CHECK: InstanceFieldSet
493   /// CHECK: InstanceFieldSet
494   /// CHECK: InstanceFieldSet
495   /// CHECK: InstanceFieldGet
496   /// CHECK: InstanceFieldGet
497 
498   /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after)
499   /// CHECK: NewInstance
500   /// CHECK: InstanceFieldSet
501   /// CHECK: InstanceFieldSet
502   /// CHECK: InstanceFieldSet
503   /// CHECK: InstanceFieldGet
504   /// CHECK: InstanceFieldGet
505 
506   // Loop side effects can kill heap values, stores need to be kept in that case.
test21(TestClass obj0)507   static void test21(TestClass obj0) {
508     TestClass obj = new TestClass();
509     obj0.str = "abc";
510     obj.str = "abc";
511     for (int i = 0; i < 2; i++) {
512       // Generate some loop side effect that writes into obj.
513       obj.str = "def";
514     }
515     System.out.print(obj0.str.substring(0, 0) + obj.str.substring(0, 0));
516   }
517 
518   /// CHECK-START: int Main.test22() load_store_elimination (before)
519   /// CHECK: NewInstance
520   /// CHECK: InstanceFieldSet
521   /// CHECK: NewInstance
522   /// CHECK: InstanceFieldSet
523   /// CHECK: InstanceFieldGet
524   /// CHECK: NewInstance
525   /// CHECK: InstanceFieldSet
526   /// CHECK: InstanceFieldGet
527   /// CHECK: InstanceFieldGet
528 
529   /// CHECK-START: int Main.test22() load_store_elimination (after)
530   /// CHECK: NewInstance
531   /// CHECK-NOT: InstanceFieldSet
532   /// CHECK: NewInstance
533   /// CHECK-NOT: InstanceFieldSet
534   /// CHECK-NOT: InstanceFieldGet
535   /// CHECK: NewInstance
536   /// CHECK-NOT: InstanceFieldSet
537   /// CHECK-NOT: InstanceFieldGet
538   /// CHECK-NOT: InstanceFieldGet
539 
540   // For a singleton, loop side effects can kill its field values only if:
541   // (1) it dominiates the loop header, and
542   // (2) its fields are stored into inside a loop.
test22()543   static int test22() {
544     int sum = 0;
545     TestClass obj1 = new TestClass();
546     obj1.i = 2;    // This store can be eliminated since obj1 is never stored into inside a loop.
547     for (int i = 0; i < 2; i++) {
548       TestClass obj2 = new TestClass();
549       obj2.i = 3;  // This store can be eliminated since the singleton is inside the loop.
550       sum += obj2.i;
551     }
552     TestClass obj3 = new TestClass();
553     obj3.i = 5;    // This store can be eliminated since the singleton is created after the loop.
554     sum += obj1.i + obj3.i;
555     return sum;
556   }
557 
558   /// CHECK-START: int Main.test23(boolean) load_store_elimination (before)
559   /// CHECK: NewInstance
560   /// CHECK: InstanceFieldSet
561   /// CHECK: InstanceFieldGet
562   /// CHECK: InstanceFieldSet
563   /// CHECK: InstanceFieldGet
564   /// CHECK: Return
565   /// CHECK: InstanceFieldGet
566   /// CHECK: InstanceFieldSet
567 
568   /// CHECK-START: int Main.test23(boolean) load_store_elimination (after)
569   /// CHECK: NewInstance
570   /// CHECK-NOT: InstanceFieldSet
571   /// CHECK-NOT: InstanceFieldGet
572   /// CHECK: InstanceFieldSet
573   /// CHECK: InstanceFieldGet
574   /// CHECK: Return
575   /// CHECK-NOT: InstanceFieldGet
576   /// CHECK: InstanceFieldSet
577 
578   // Test store elimination on merging.
test23(boolean b)579   static int test23(boolean b) {
580     TestClass obj = new TestClass();
581     obj.i = 3;      // This store can be eliminated since the value flows into each branch.
582     if (b) {
583       obj.i += 1;   // This store cannot be eliminated due to the merge later.
584     } else {
585       obj.i += 2;   // This store cannot be eliminated due to the merge later.
586     }
587     return obj.i;
588   }
589 
590   /// CHECK-START: float Main.test24() load_store_elimination (before)
591   /// CHECK-DAG:     <<True:i\d+>>     IntConstant 1
592   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
593   /// CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
594   /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
595   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<True>>]
596   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float8>>]
597   /// CHECK-DAG:     <<GetTest:z\d+>>  InstanceFieldGet [<<Obj>>]
598   /// CHECK-DAG:     <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
599   /// CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<GetField>>,<<GetTest>>]
600   /// CHECK-DAG:                       Return [<<Select>>]
601 
602   /// CHECK-START: float Main.test24() load_store_elimination (after)
603   /// CHECK-DAG:     <<True:i\d+>>     IntConstant 1
604   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
605   /// CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
606   /// CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<Float8>>,<<True>>]
607   /// CHECK-DAG:                       Return [<<Select>>]
608 
test24()609   static float test24() {
610     float a = 42.0f;
611     TestClass3 obj = new TestClass3();
612     if (obj.test1) {
613       a = obj.floatField;
614     }
615     return a;
616   }
617 
618   /// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
619   /// CHECK: NewInstance
620   /// CHECK: InstanceFieldSet
621 
622   /// CHECK-START: void Main.testFinalizable() load_store_elimination (after)
623   /// CHECK: NewInstance
624   /// CHECK: InstanceFieldSet
625 
626   // Allocations and stores into finalizable objects cannot be eliminated.
testFinalizable()627   static void testFinalizable() {
628     Finalizable finalizable = new Finalizable();
629     finalizable.i = Finalizable.VALUE;
630   }
631 
getWeakReference()632   static java.lang.ref.WeakReference<Object> getWeakReference() {
633     return new java.lang.ref.WeakReference<>(new Object());
634   }
635 
testFinalizableByForcingGc()636   static void testFinalizableByForcingGc() {
637     testFinalizable();
638     java.lang.ref.WeakReference<Object> reference = getWeakReference();
639 
640     Runtime runtime = Runtime.getRuntime();
641     for (int i = 0; i < 20; ++i) {
642       runtime.gc();
643       System.runFinalization();
644       try {
645         Thread.sleep(1);
646       } catch (InterruptedException e) {
647         throw new AssertionError(e);
648       }
649 
650       // Check to see if the weak reference has been garbage collected.
651       if (reference.get() == null) {
652         // A little bit more sleep time to make sure.
653         try {
654           Thread.sleep(100);
655         } catch (InterruptedException e) {
656           throw new AssertionError(e);
657         }
658         if (!Finalizable.sVisited) {
659           System.out.println("finalize() not called.");
660         }
661         return;
662       }
663     }
664     System.out.println("testFinalizableByForcingGc() failed to force gc.");
665   }
666 
667   /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (before)
668   /// CHECK: InstanceFieldSet
669   /// CHECK: Select
670 
671   /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (after)
672   /// CHECK: InstanceFieldSet
673   /// CHECK: Select
674 
675   // Test that HSelect creates alias.
$noinline$testHSelect(boolean b)676   public static int $noinline$testHSelect(boolean b) {
677     if (sFlag) {
678       throw new Error();
679     }
680     TestClass obj = new TestClass();
681     TestClass obj2 = null;
682     obj.i = 0xdead;
683     if (b) {
684       obj2 = obj;
685     }
686     return obj2.i;
687   }
688 
assertIntEquals(int result, int expected)689   public static void assertIntEquals(int result, int expected) {
690     if (expected != result) {
691       throw new Error("Expected: " + expected + ", found: " + result);
692     }
693   }
694 
assertFloatEquals(float result, float expected)695   public static void assertFloatEquals(float result, float expected) {
696     if (expected != result) {
697       throw new Error("Expected: " + expected + ", found: " + result);
698     }
699   }
700 
assertDoubleEquals(double result, double expected)701   public static void assertDoubleEquals(double result, double expected) {
702     if (expected != result) {
703       throw new Error("Expected: " + expected + ", found: " + result);
704     }
705   }
706 
main(String[] args)707   public static void main(String[] args) {
708     assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
709     assertIntEquals(test1(new TestClass(), new TestClass()), 3);
710     assertIntEquals(test2(new TestClass()), 1);
711     TestClass obj1 = new TestClass();
712     TestClass obj2 = new TestClass();
713     obj1.next = obj2;
714     assertIntEquals(test3(obj1), 10);
715     assertIntEquals(test4(new TestClass(), true), 1);
716     assertIntEquals(test4(new TestClass(), false), 1);
717     assertIntEquals(test5(new TestClass(), true), 1);
718     assertIntEquals(test5(new TestClass(), false), 2);
719     assertIntEquals(test6(new TestClass(), new TestClass(), true), 4);
720     assertIntEquals(test6(new TestClass(), new TestClass(), false), 2);
721     assertIntEquals(test7(new TestClass()), 1);
722     assertIntEquals(test8(), 1);
723     obj1 = new TestClass();
724     obj2 = new TestClass();
725     obj1.next = obj2;
726     assertIntEquals(test9(new TestClass()), 1);
727     assertIntEquals(test10(new TestClass(3, 4)), 3);
728     assertIntEquals(TestClass.si, 3);
729     assertIntEquals(test11(new TestClass()), 10);
730     assertIntEquals(test12(new TestClass(), new TestClass()), 10);
731     assertIntEquals(test13(new TestClass(), new TestClass2()), 3);
732     SubTestClass obj3 = new SubTestClass();
733     assertIntEquals(test14(obj3, obj3), 2);
734     assertIntEquals(test15(), 2);
735     assertIntEquals(test16(), 3);
736     assertIntEquals(test17(), 0);
737     assertIntEquals(test18(new TestClass()), 1);
738     float[] fa1 = { 0.8f };
739     float[] fa2 = { 1.8f };
740     assertFloatEquals(test19(fa1, fa2), 1.8f);
741     assertFloatEquals(test20().i, 0);
742     test21(new TestClass());
743     assertIntEquals(test22(), 13);
744     assertIntEquals(test23(true), 4);
745     assertIntEquals(test23(false), 5);
746     assertFloatEquals(test24(), 8.0f);
747     testFinalizableByForcingGc();
748     assertIntEquals($noinline$testHSelect(true), 0xdead);
749   }
750 
751   static boolean sFlag;
752 }
753