Home | History | Annotate | Download | only in src
      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 {
     18   Circle(double radius) {
     19     this.radius = radius;
     20   }
     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   }
     31   TestClass() {
     32   }
     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 
     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 
     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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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.
    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 
    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.
    627   static void testFinalizable() {
    628     Finalizable finalizable = new Finalizable();
    629     finalizable.i = Finalizable.VALUE;
    630   }
    631 
    632   static java.lang.ref.WeakReference<Object> getWeakReference() {
    633     return new java.lang.ref.WeakReference<>(new Object());
    634   }
    635 
    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.
    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 
    689   public static void assertIntEquals(int result, int expected) {
    690     if (expected != result) {
    691       throw new Error("Expected: " + expected + ", found: " + result);
    692     }
    693   }
    694 
    695   public static void assertFloatEquals(float result, float expected) {
    696     if (expected != result) {
    697       throw new Error("Expected: " + expected + ", found: " + result);
    698     }
    699   }
    700 
    701   public static void assertDoubleEquals(double result, double expected) {
    702     if (expected != result) {
    703       throw new Error("Expected: " + expected + ", found: " + result);
    704     }
    705   }
    706 
    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