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 getRadius() {
     22     return radius;
     23   }
     24   public double getArea() {
     25     return radius * radius * Math.PI;
     26   }
     27   private double radius;
     28 }
     29 
     30 class TestClass {
     31   static {
     32     sTestClassObj = new TestClass(-1, -2);
     33   }
     34   TestClass() {
     35   }
     36   TestClass(int i, int j) {
     37     this.i = i;
     38     this.j = j;
     39   }
     40   int i;
     41   int j;
     42   volatile int k;
     43   TestClass next;
     44   String str;
     45   static int si;
     46   static TestClass sTestClassObj;
     47 }
     48 
     49 class SubTestClass extends TestClass {
     50   int k;
     51 }
     52 
     53 class TestClass2 {
     54   int i;
     55   int j;
     56 }
     57 
     58 class TestClass3 {
     59   float floatField = 8.0f;
     60   boolean test1 = true;
     61 }
     62 
     63 class Finalizable {
     64   static boolean sVisited = false;
     65   static final int VALUE = 0xbeef;
     66   int i;
     67 
     68   protected void finalize() {
     69     if (i != VALUE) {
     70       System.out.println("Where is the beef?");
     71     }
     72     sVisited = true;
     73   }
     74 }
     75 
     76 interface Filter {
     77   public boolean isValid(int i);
     78 }
     79 
     80 public class Main {
     81 
     82   /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before)
     83   /// CHECK: NewInstance
     84   /// CHECK: InstanceFieldSet
     85   /// CHECK: InstanceFieldGet
     86 
     87   /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after)
     88   /// CHECK-NOT: NewInstance
     89   /// CHECK-NOT: InstanceFieldSet
     90   /// CHECK-NOT: InstanceFieldGet
     91 
     92   static double calcCircleArea(double radius) {
     93     return new Circle(radius).getArea();
     94   }
     95 
     96   /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (before)
     97   /// CHECK: InstanceFieldSet
     98   /// CHECK: InstanceFieldSet
     99   /// CHECK: InstanceFieldGet
    100   /// CHECK: InstanceFieldGet
    101 
    102   /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (after)
    103   /// CHECK: InstanceFieldSet
    104   /// CHECK: InstanceFieldSet
    105   /// CHECK-NOT: NullCheck
    106   /// CHECK-NOT: InstanceFieldGet
    107 
    108   // Different fields shouldn't alias.
    109   static int test1(TestClass obj1, TestClass obj2) {
    110     obj1.i = 1;
    111     obj2.j = 2;
    112     return obj1.i + obj2.j;
    113   }
    114 
    115   /// CHECK-START: int Main.test2(TestClass) load_store_elimination (before)
    116   /// CHECK: InstanceFieldSet
    117   /// CHECK: InstanceFieldSet
    118   /// CHECK: InstanceFieldGet
    119 
    120   /// CHECK-START: int Main.test2(TestClass) load_store_elimination (after)
    121   /// CHECK: InstanceFieldSet
    122   /// CHECK-NOT: NullCheck
    123   /// CHECK-NOT: InstanceFieldSet
    124   /// CHECK-NOT: InstanceFieldGet
    125 
    126   // Redundant store of the same value.
    127   static int test2(TestClass obj) {
    128     obj.j = 1;
    129     obj.j = 1;
    130     return obj.j;
    131   }
    132 
    133   /// CHECK-START: int Main.test3(TestClass) load_store_elimination (before)
    134   /// CHECK: StaticFieldGet
    135   /// CHECK: NewInstance
    136   /// CHECK: InstanceFieldSet
    137   /// CHECK: InstanceFieldSet
    138   /// CHECK: InstanceFieldSet
    139   /// CHECK: InstanceFieldSet
    140   /// CHECK: InstanceFieldGet
    141   /// CHECK: InstanceFieldGet
    142   /// CHECK: InstanceFieldGet
    143   /// CHECK: InstanceFieldGet
    144 
    145   /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after)
    146   /// CHECK: StaticFieldGet
    147   /// CHECK: NewInstance
    148   /// CHECK: InstanceFieldSet
    149   /// CHECK: InstanceFieldSet
    150   /// CHECK: InstanceFieldSet
    151   /// CHECK: InstanceFieldSet
    152   /// CHECK-NOT: InstanceFieldGet
    153   /// CHECK-NOT: StaticFieldGet
    154 
    155   // A new allocation (even non-singleton) shouldn't alias with pre-existing values.
    156   static int test3(TestClass obj) {
    157     TestClass obj1 = TestClass.sTestClassObj;
    158     TestClass obj2 = new TestClass();  // Cannot alias with obj or obj1 which pre-exist.
    159     obj.next = obj2;  // Make obj2 a non-singleton.
    160     // All stores below need to stay since obj/obj1/obj2 are not singletons.
    161     obj.i = 1;
    162     obj1.j = 2;
    163     // Following stores won't kill values of obj.i and obj1.j.
    164     obj2.i = 3;
    165     obj2.j = 4;
    166     return obj.i + obj1.j + obj2.i + obj2.j;
    167   }
    168 
    169   /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before)
    170   /// CHECK: InstanceFieldSet
    171   /// CHECK: InstanceFieldGet
    172   /// CHECK: Return
    173   /// CHECK: InstanceFieldSet
    174 
    175   /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
    176   /// CHECK: InstanceFieldSet
    177   /// CHECK-NOT: NullCheck
    178   /// CHECK-NOT: InstanceFieldGet
    179   /// CHECK: Return
    180   /// CHECK: InstanceFieldSet
    181 
    182   // Set and merge the same value in two branches.
    183   static int test4(TestClass obj, boolean b) {
    184     if (b) {
    185       obj.i = 1;
    186     } else {
    187       obj.i = 1;
    188     }
    189     return obj.i;
    190   }
    191 
    192   /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before)
    193   /// CHECK: InstanceFieldSet
    194   /// CHECK: InstanceFieldGet
    195   /// CHECK: Return
    196   /// CHECK: InstanceFieldSet
    197 
    198   /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after)
    199   /// CHECK: InstanceFieldSet
    200   /// CHECK: InstanceFieldGet
    201   /// CHECK: Return
    202   /// CHECK: InstanceFieldSet
    203 
    204   // Set and merge different values in two branches.
    205   static int test5(TestClass obj, boolean b) {
    206     if (b) {
    207       obj.i = 1;
    208     } else {
    209       obj.i = 2;
    210     }
    211     return obj.i;
    212   }
    213 
    214   /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before)
    215   /// CHECK: InstanceFieldSet
    216   /// CHECK: InstanceFieldSet
    217   /// CHECK: InstanceFieldSet
    218   /// CHECK: InstanceFieldGet
    219   /// CHECK: InstanceFieldGet
    220 
    221   /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after)
    222   /// CHECK: InstanceFieldSet
    223   /// CHECK: InstanceFieldSet
    224   /// CHECK: InstanceFieldSet
    225   /// CHECK: InstanceFieldGet
    226   /// CHECK-NOT: NullCheck
    227   /// CHECK-NOT: InstanceFieldGet
    228 
    229   // Setting the same value doesn't clear the value for aliased locations.
    230   static int test6(TestClass obj1, TestClass obj2, boolean b) {
    231     obj1.i = 1;
    232     obj1.j = 2;
    233     if (b) {
    234       obj2.j = 2;
    235     }
    236     return obj1.j + obj2.j;
    237   }
    238 
    239   /// CHECK-START: int Main.test7(TestClass) load_store_elimination (before)
    240   /// CHECK: InstanceFieldSet
    241   /// CHECK: InstanceFieldGet
    242 
    243   /// CHECK-START: int Main.test7(TestClass) load_store_elimination (after)
    244   /// CHECK: InstanceFieldSet
    245   /// CHECK: InstanceFieldGet
    246 
    247   // Invocation should kill values in non-singleton heap locations.
    248   static int test7(TestClass obj) {
    249     obj.i = 1;
    250     System.out.print("");
    251     return obj.i;
    252   }
    253 
    254   /// CHECK-START: int Main.test8() load_store_elimination (before)
    255   /// CHECK: NewInstance
    256   /// CHECK: InstanceFieldSet
    257   /// CHECK: InvokeVirtual
    258   /// CHECK: InstanceFieldGet
    259 
    260   /// CHECK-START: int Main.test8() load_store_elimination (after)
    261   /// CHECK-NOT: NewInstance
    262   /// CHECK-NOT: InstanceFieldSet
    263   /// CHECK: InvokeVirtual
    264   /// CHECK-NOT: NullCheck
    265   /// CHECK-NOT: InstanceFieldGet
    266 
    267   // Invocation should not kill values in singleton heap locations.
    268   static int test8() {
    269     TestClass obj = new TestClass();
    270     obj.i = 1;
    271     System.out.print("");
    272     return obj.i;
    273   }
    274 
    275   /// CHECK-START: int Main.test9(TestClass) load_store_elimination (before)
    276   /// CHECK: NewInstance
    277   /// CHECK: InstanceFieldSet
    278   /// CHECK: InstanceFieldSet
    279   /// CHECK: InstanceFieldGet
    280 
    281   /// CHECK-START: int Main.test9(TestClass) load_store_elimination (after)
    282   /// CHECK: NewInstance
    283   /// CHECK: InstanceFieldSet
    284   /// CHECK: InstanceFieldSet
    285   /// CHECK: InstanceFieldGet
    286 
    287   // Invocation should kill values in non-singleton heap locations.
    288   static int test9(TestClass obj) {
    289     TestClass obj2 = new TestClass();
    290     obj2.i = 1;
    291     obj.next = obj2;
    292     System.out.print("");
    293     return obj2.i;
    294   }
    295 
    296   /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before)
    297   /// CHECK: StaticFieldGet
    298   /// CHECK: InstanceFieldGet
    299   /// CHECK: StaticFieldSet
    300   /// CHECK: InstanceFieldGet
    301 
    302   /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
    303   /// CHECK: StaticFieldGet
    304   /// CHECK: InstanceFieldGet
    305   /// CHECK: StaticFieldSet
    306   /// CHECK-NOT: NullCheck
    307   /// CHECK-NOT: InstanceFieldGet
    308 
    309   // Static fields shouldn't alias with instance fields.
    310   static int test10(TestClass obj) {
    311     TestClass.si += obj.i;
    312     return obj.i;
    313   }
    314 
    315   /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before)
    316   /// CHECK: InstanceFieldSet
    317   /// CHECK: InstanceFieldGet
    318 
    319   /// CHECK-START: int Main.test11(TestClass) load_store_elimination (after)
    320   /// CHECK: InstanceFieldSet
    321   /// CHECK-NOT: NullCheck
    322   /// CHECK-NOT: InstanceFieldGet
    323 
    324   // Loop without heap writes.
    325   // obj.i is actually hoisted to the loop pre-header by licm already.
    326   static int test11(TestClass obj) {
    327     obj.i = 1;
    328     int sum = 0;
    329     for (int i = 0; i < 10; i++) {
    330       sum += obj.i;
    331     }
    332     return sum;
    333   }
    334 
    335   /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (before)
    336   /// CHECK: InstanceFieldSet
    337   /// CHECK: InstanceFieldGet
    338   /// CHECK: InstanceFieldSet
    339 
    340   /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (after)
    341   /// CHECK: InstanceFieldSet
    342   /// CHECK: InstanceFieldGet
    343   /// CHECK: InstanceFieldSet
    344 
    345   // Loop with heap writes.
    346   static int test12(TestClass obj1, TestClass obj2) {
    347     obj1.i = 1;
    348     int sum = 0;
    349     for (int i = 0; i < 10; i++) {
    350       sum += obj1.i;
    351       obj2.i = sum;
    352     }
    353     return sum;
    354   }
    355 
    356   /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (before)
    357   /// CHECK: InstanceFieldSet
    358   /// CHECK: InstanceFieldSet
    359   /// CHECK: InstanceFieldGet
    360   /// CHECK: InstanceFieldGet
    361 
    362   /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (after)
    363   /// CHECK: InstanceFieldSet
    364   /// CHECK: InstanceFieldSet
    365   /// CHECK-NOT: NullCheck
    366   /// CHECK-NOT: InstanceFieldGet
    367 
    368   // Different classes shouldn't alias.
    369   static int test13(TestClass obj1, TestClass2 obj2) {
    370     obj1.i = 1;
    371     obj2.i = 2;
    372     return obj1.i + obj2.i;
    373   }
    374 
    375   /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (before)
    376   /// CHECK: InstanceFieldSet
    377   /// CHECK: InstanceFieldSet
    378   /// CHECK: InstanceFieldGet
    379 
    380   /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (after)
    381   /// CHECK: InstanceFieldSet
    382   /// CHECK: InstanceFieldSet
    383   /// CHECK: InstanceFieldGet
    384 
    385   // Subclass may alias with super class.
    386   static int test14(TestClass obj1, SubTestClass obj2) {
    387     obj1.i = 1;
    388     obj2.i = 2;
    389     return obj1.i;
    390   }
    391 
    392   /// CHECK-START: int Main.test15() load_store_elimination (before)
    393   /// CHECK: StaticFieldSet
    394   /// CHECK: StaticFieldSet
    395   /// CHECK: StaticFieldGet
    396 
    397   /// CHECK-START: int Main.test15() load_store_elimination (after)
    398   /// CHECK: <<Const2:i\d+>> IntConstant 2
    399   /// CHECK: StaticFieldSet
    400   /// CHECK: StaticFieldSet
    401   /// CHECK-NOT: StaticFieldGet
    402   /// CHECK: Return [<<Const2>>]
    403 
    404   // Static field access from subclass's name.
    405   static int test15() {
    406     TestClass.si = 1;
    407     SubTestClass.si = 2;
    408     return TestClass.si;
    409   }
    410 
    411   /// CHECK-START: int Main.test16() load_store_elimination (before)
    412   /// CHECK: NewInstance
    413   /// CHECK: InstanceFieldSet
    414   /// CHECK: InstanceFieldSet
    415   /// CHECK: InstanceFieldGet
    416   /// CHECK: InstanceFieldGet
    417 
    418   /// CHECK-START: int Main.test16() load_store_elimination (after)
    419   /// CHECK-NOT: NewInstance
    420   /// CHECK-NOT: InstanceFieldSet
    421   /// CHECK-NOT: InstanceFieldGet
    422 
    423   // Test inlined constructor.
    424   static int test16() {
    425     TestClass obj = new TestClass(1, 2);
    426     return obj.i + obj.j;
    427   }
    428 
    429   /// CHECK-START: int Main.test17() load_store_elimination (before)
    430   /// CHECK: NewInstance
    431   /// CHECK: InstanceFieldSet
    432   /// CHECK: InstanceFieldGet
    433 
    434   /// CHECK-START: int Main.test17() load_store_elimination (after)
    435   /// CHECK: <<Const0:i\d+>> IntConstant 0
    436   /// CHECK-NOT: NewInstance
    437   /// CHECK-NOT: InstanceFieldSet
    438   /// CHECK-NOT: InstanceFieldGet
    439   /// CHECK: Return [<<Const0>>]
    440 
    441   // Test getting default value.
    442   static int test17() {
    443     TestClass obj = new TestClass();
    444     obj.j = 1;
    445     return obj.i;
    446   }
    447 
    448   /// CHECK-START: int Main.test18(TestClass) load_store_elimination (before)
    449   /// CHECK: InstanceFieldSet
    450   /// CHECK: InstanceFieldGet
    451 
    452   /// CHECK-START: int Main.test18(TestClass) load_store_elimination (after)
    453   /// CHECK: InstanceFieldSet
    454   /// CHECK: InstanceFieldGet
    455 
    456   // Volatile field load/store shouldn't be eliminated.
    457   static int test18(TestClass obj) {
    458     obj.k = 1;
    459     return obj.k;
    460   }
    461 
    462   /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (before)
    463   /// CHECK:     {{f\d+}} ArrayGet
    464   /// CHECK:     {{f\d+}} ArrayGet
    465 
    466   /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (after)
    467   /// CHECK:     {{f\d+}} ArrayGet
    468   /// CHECK-NOT: {{f\d+}} ArrayGet
    469 
    470   // I/F, J/D aliasing should not happen any more and LSE should eliminate the load.
    471   static float test19(float[] fa1, float[] fa2) {
    472     fa1[0] = fa2[0];
    473     return fa1[0];
    474   }
    475 
    476   /// CHECK-START: TestClass Main.test20() load_store_elimination (before)
    477   /// CHECK: NewInstance
    478   /// CHECK: InstanceFieldSet
    479 
    480   /// CHECK-START: TestClass Main.test20() load_store_elimination (after)
    481   /// CHECK: NewInstance
    482   /// CHECK-NOT: InstanceFieldSet
    483 
    484   // Storing default heap value is redundant if the heap location has the
    485   // default heap value.
    486   static TestClass test20() {
    487     TestClass obj = new TestClass();
    488     obj.i = 0;
    489     return obj;
    490   }
    491 
    492   /// CHECK-START: void Main.test21(TestClass) load_store_elimination (before)
    493   /// CHECK: NewInstance
    494   /// CHECK: InstanceFieldSet
    495   /// CHECK: InstanceFieldSet
    496   /// CHECK: InstanceFieldSet
    497   /// CHECK: InstanceFieldGet
    498   /// CHECK: InstanceFieldGet
    499 
    500   /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after)
    501   /// CHECK: NewInstance
    502   /// CHECK: InstanceFieldSet
    503   /// CHECK: InstanceFieldSet
    504   /// CHECK: InstanceFieldSet
    505   /// CHECK: InstanceFieldGet
    506   /// CHECK: InstanceFieldGet
    507 
    508   // Loop side effects can kill heap values, stores need to be kept in that case.
    509   static void test21(TestClass obj0) {
    510     TestClass obj = new TestClass();
    511     obj0.str = "abc";
    512     obj.str = "abc";
    513     for (int i = 0; i < 2; i++) {
    514       // Generate some loop side effect that writes into obj.
    515       obj.str = "def";
    516     }
    517     System.out.print(obj0.str.substring(0, 0) + obj.str.substring(0, 0));
    518   }
    519 
    520   /// CHECK-START: int Main.test22() load_store_elimination (before)
    521   /// CHECK: NewInstance
    522   /// CHECK: InstanceFieldSet
    523   /// CHECK: NewInstance
    524   /// CHECK: InstanceFieldSet
    525   /// CHECK: InstanceFieldGet
    526   /// CHECK: NewInstance
    527   /// CHECK: InstanceFieldSet
    528   /// CHECK: InstanceFieldGet
    529   /// CHECK: InstanceFieldGet
    530 
    531   /// CHECK-START: int Main.test22() load_store_elimination (after)
    532   /// CHECK-NOT: NewInstance
    533   /// CHECK-NOT: InstanceFieldSet
    534   /// CHECK-NOT: NewInstance
    535   /// CHECK-NOT: InstanceFieldSet
    536   /// CHECK-NOT: InstanceFieldGet
    537   /// CHECK-NOT: NewInstance
    538   /// CHECK-NOT: InstanceFieldSet
    539   /// CHECK-NOT: InstanceFieldGet
    540   /// CHECK-NOT: InstanceFieldGet
    541 
    542   // For a singleton, loop side effects can kill its field values only if:
    543   // (1) it dominiates the loop header, and
    544   // (2) its fields are stored into inside a loop.
    545   static int test22() {
    546     int sum = 0;
    547     TestClass obj1 = new TestClass();
    548     obj1.i = 2;    // This store can be eliminated since obj1 is never stored into inside a loop.
    549     for (int i = 0; i < 2; i++) {
    550       TestClass obj2 = new TestClass();
    551       obj2.i = 3;  // This store can be eliminated since the singleton is inside the loop.
    552       sum += obj2.i;
    553     }
    554     TestClass obj3 = new TestClass();
    555     obj3.i = 5;    // This store can be eliminated since the singleton is created after the loop.
    556     sum += obj1.i + obj3.i;
    557     return sum;
    558   }
    559 
    560   /// CHECK-START: int Main.test23(boolean) load_store_elimination (before)
    561   /// CHECK: NewInstance
    562   /// CHECK: InstanceFieldSet
    563   /// CHECK: InstanceFieldGet
    564   /// CHECK: InstanceFieldSet
    565   /// CHECK: InstanceFieldGet
    566   /// CHECK: Return
    567   /// CHECK: InstanceFieldGet
    568   /// CHECK: InstanceFieldSet
    569 
    570   /// CHECK-START: int Main.test23(boolean) load_store_elimination (after)
    571   /// CHECK: NewInstance
    572   /// CHECK-NOT: InstanceFieldSet
    573   /// CHECK-NOT: InstanceFieldGet
    574   /// CHECK: InstanceFieldSet
    575   /// CHECK: InstanceFieldGet
    576   /// CHECK: Return
    577   /// CHECK-NOT: InstanceFieldGet
    578   /// CHECK: InstanceFieldSet
    579 
    580   // Test store elimination on merging.
    581   static int test23(boolean b) {
    582     TestClass obj = new TestClass();
    583     obj.i = 3;      // This store can be eliminated since the value flows into each branch.
    584     if (b) {
    585       obj.i += 1;   // This store cannot be eliminated due to the merge later.
    586     } else {
    587       obj.i += 2;   // This store cannot be eliminated due to the merge later.
    588     }
    589     return obj.i;
    590   }
    591 
    592   /// CHECK-START: float Main.test24() load_store_elimination (before)
    593   /// CHECK-DAG:     <<True:i\d+>>     IntConstant 1
    594   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
    595   /// CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
    596   /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
    597   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<True>>]
    598   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float8>>]
    599   /// CHECK-DAG:     <<GetTest:z\d+>>  InstanceFieldGet [<<Obj>>]
    600   /// CHECK-DAG:     <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
    601   /// CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<GetField>>,<<GetTest>>]
    602   /// CHECK-DAG:                       Return [<<Select>>]
    603 
    604   /// CHECK-START: float Main.test24() load_store_elimination (after)
    605   /// CHECK-DAG:     <<True:i\d+>>     IntConstant 1
    606   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
    607   /// CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
    608   /// CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<Float8>>,<<True>>]
    609   /// CHECK-DAG:                       Return [<<Select>>]
    610 
    611   static float test24() {
    612     float a = 42.0f;
    613     TestClass3 obj = new TestClass3();
    614     if (obj.test1) {
    615       a = obj.floatField;
    616     }
    617     return a;
    618   }
    619 
    620   /// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
    621   /// CHECK: NewInstance
    622   /// CHECK: InstanceFieldSet
    623 
    624   /// CHECK-START: void Main.testFinalizable() load_store_elimination (after)
    625   /// CHECK: NewInstance
    626   /// CHECK: InstanceFieldSet
    627 
    628   // Allocations and stores into finalizable objects cannot be eliminated.
    629   static void testFinalizable() {
    630     Finalizable finalizable = new Finalizable();
    631     finalizable.i = Finalizable.VALUE;
    632   }
    633 
    634   static java.lang.ref.WeakReference<Object> getWeakReference() {
    635     return new java.lang.ref.WeakReference<>(new Object());
    636   }
    637 
    638   static void testFinalizableByForcingGc() {
    639     testFinalizable();
    640     java.lang.ref.WeakReference<Object> reference = getWeakReference();
    641 
    642     Runtime runtime = Runtime.getRuntime();
    643     for (int i = 0; i < 20; ++i) {
    644       runtime.gc();
    645       System.runFinalization();
    646       try {
    647         Thread.sleep(1);
    648       } catch (InterruptedException e) {
    649         throw new AssertionError(e);
    650       }
    651 
    652       // Check to see if the weak reference has been garbage collected.
    653       if (reference.get() == null) {
    654         // A little bit more sleep time to make sure.
    655         try {
    656           Thread.sleep(100);
    657         } catch (InterruptedException e) {
    658           throw new AssertionError(e);
    659         }
    660         if (!Finalizable.sVisited) {
    661           System.out.println("finalize() not called.");
    662         }
    663         return;
    664       }
    665     }
    666     System.out.println("testFinalizableByForcingGc() failed to force gc.");
    667   }
    668 
    669   /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (before)
    670   /// CHECK: InstanceFieldSet
    671   /// CHECK: Select
    672 
    673   /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (after)
    674   /// CHECK: InstanceFieldSet
    675   /// CHECK: Select
    676 
    677   // Test that HSelect creates alias.
    678   static int $noinline$testHSelect(boolean b) {
    679     if (sFlag) {
    680       throw new Error();
    681     }
    682     TestClass obj = new TestClass();
    683     TestClass obj2 = null;
    684     obj.i = 0xdead;
    685     if (b) {
    686       obj2 = obj;
    687     }
    688     return obj2.i;
    689   }
    690 
    691   static int sumWithFilter(int[] array, Filter f) {
    692     int sum = 0;
    693     for (int i = 0; i < array.length; i++) {
    694       if (f.isValid(array[i])) {
    695         sum += array[i];
    696       }
    697     }
    698     return sum;
    699   }
    700 
    701   /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (before)
    702   /// CHECK: NewInstance
    703   /// CHECK: InstanceFieldSet
    704   /// CHECK: InstanceFieldSet
    705   /// CHECK: InstanceFieldGet
    706   /// CHECK: InstanceFieldGet
    707 
    708   /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (after)
    709   /// CHECK-NOT: NewInstance
    710   /// CHECK-NOT: InstanceFieldSet
    711   /// CHECK-NOT: InstanceFieldGet
    712 
    713   // A lambda-style allocation can be eliminated after inlining.
    714   static int sumWithinRange(int[] array, final int low, final int high) {
    715     Filter filter = new Filter() {
    716       public boolean isValid(int i) {
    717         return (i >= low) && (i <= high);
    718       }
    719     };
    720     return sumWithFilter(array, filter);
    721   }
    722 
    723   private static int mI = 0;
    724   private static float mF = 0f;
    725 
    726   /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (before)
    727   /// CHECK: NewInstance
    728   /// CHECK: NewInstance
    729   /// CHECK: NewInstance
    730 
    731   /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (after)
    732   /// CHECK-NOT: NewInstance
    733 
    734   private static float testAllocationEliminationWithLoops() {
    735     for (int i0 = 0; i0 < 5; i0++) {
    736       for (int i1 = 0; i1 < 5; i1++) {
    737         for (int i2 = 0; i2 < 5; i2++) {
    738           int lI0 = ((int) new Integer(((int) new Integer(mI))));
    739           if (((boolean) new Boolean(false))) {
    740             for (int i3 = 576 - 1; i3 >= 0; i3--) {
    741               mF -= 976981405.0f;
    742             }
    743           }
    744         }
    745       }
    746     }
    747     return 1.0f;
    748   }
    749 
    750   /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (before)
    751   /// CHECK: NewInstance
    752   /// CHECK: InstanceFieldSet
    753   /// CHECK: InstanceFieldSet
    754   /// CHECK: InstanceFieldSet
    755   /// CHECK: InstanceFieldSet
    756 
    757   /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (after)
    758   /// CHECK: NewInstance
    759   /// CHECK: InstanceFieldSet
    760   /// CHECK: InstanceFieldSet
    761   /// CHECK-NOT: InstanceFieldSet
    762 
    763   private static TestClass2 testStoreStore() {
    764     TestClass2 obj = new TestClass2();
    765     obj.i = 41;
    766     obj.j = 42;
    767     obj.i = 41;
    768     obj.j = 43;
    769     return obj;
    770   }
    771 
    772   /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (before)
    773   /// CHECK: NewInstance
    774   /// CHECK: InstanceFieldSet
    775   /// CHECK: InstanceFieldSet
    776   /// CHECK: InstanceFieldSet
    777   /// CHECK: InstanceFieldSet
    778   /// CHECK: Deoptimize
    779   /// CHECK: ArraySet
    780   /// CHECK: ArraySet
    781   /// CHECK: ArraySet
    782   /// CHECK: ArraySet
    783   /// CHECK: ArrayGet
    784   /// CHECK: ArrayGet
    785   /// CHECK: ArrayGet
    786   /// CHECK: ArrayGet
    787 
    788   /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (after)
    789   /// CHECK: NewInstance
    790   /// CHECK: InstanceFieldSet
    791   /// CHECK: InstanceFieldSet
    792   /// CHECK-NOT: InstanceFieldSet
    793   /// CHECK: Deoptimize
    794   /// CHECK: ArraySet
    795   /// CHECK: ArraySet
    796   /// CHECK: ArraySet
    797   /// CHECK: ArraySet
    798   /// CHECK-NOT: ArrayGet
    799 
    800   private static int testStoreStoreWithDeoptimize(int[] arr) {
    801     TestClass2 obj = new TestClass2();
    802     obj.i = 41;
    803     obj.j = 42;
    804     obj.i = 41;
    805     obj.j = 43;
    806     arr[0] = 1;  // One HDeoptimize here.
    807     arr[1] = 1;
    808     arr[2] = 1;
    809     arr[3] = 1;
    810     return arr[0] + arr[1] + arr[2] + arr[3];
    811   }
    812 
    813   /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (before)
    814   /// CHECK: NewInstance
    815 
    816   /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (after)
    817   /// CHECK-NOT: NewInstance
    818 
    819   private static double getCircleArea(double radius, boolean b) {
    820     double area = 0d;
    821     if (b) {
    822       area = new Circle(radius).getArea();
    823     }
    824     return area;
    825   }
    826 
    827   /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (before)
    828   /// CHECK: Deoptimize
    829   /// CHECK: NewInstance
    830   /// CHECK: Deoptimize
    831   /// CHECK: NewInstance
    832 
    833   /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (after)
    834   /// CHECK: Deoptimize
    835   /// CHECK: NewInstance
    836   /// CHECK: Deoptimize
    837   /// CHECK-NOT: NewInstance
    838 
    839   private static double testDeoptimize(int[] iarr, double[] darr, double radius) {
    840     iarr[0] = 1;  // One HDeoptimize here. Not triggered.
    841     iarr[1] = 1;
    842     Circle circle1 = new Circle(radius);
    843     iarr[2] = 1;
    844     darr[0] = circle1.getRadius();  // One HDeoptimize here, which holds circle1 live. Triggered.
    845     darr[1] = circle1.getRadius();
    846     darr[2] = circle1.getRadius();
    847     darr[3] = circle1.getRadius();
    848     return new Circle(Math.PI).getArea();
    849   }
    850 
    851   /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (before)
    852   /// CHECK: NewArray
    853   /// CHECK: ArraySet
    854   /// CHECK: ArraySet
    855   /// CHECK: ArrayGet
    856   /// CHECK: ArrayGet
    857   /// CHECK: ArrayGet
    858   /// CHECK: ArrayGet
    859 
    860   /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (after)
    861   /// CHECK-NOT: NewArray
    862   /// CHECK-NOT: ArraySet
    863   /// CHECK-NOT: ArrayGet
    864   private static int testAllocationEliminationOfArray1() {
    865     int[] array = new int[4];
    866     array[2] = 4;
    867     array[3] = 7;
    868     return array[0] + array[1] + array[2] + array[3];
    869   }
    870 
    871   /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (before)
    872   /// CHECK: NewArray
    873   /// CHECK: ArraySet
    874   /// CHECK: ArraySet
    875   /// CHECK: ArrayGet
    876 
    877   /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (after)
    878   /// CHECK: NewArray
    879   /// CHECK: ArraySet
    880   /// CHECK: ArraySet
    881   /// CHECK: ArrayGet
    882   private static int testAllocationEliminationOfArray2() {
    883     // Cannot eliminate array allocation since array is accessed with non-constant
    884     // index.
    885     int[] array = new int[4];
    886     array[2] = 4;
    887     array[3] = 7;
    888     int sum = 0;
    889     for (int e : array) {
    890       sum += e;
    891     }
    892     return sum;
    893   }
    894 
    895   /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (before)
    896   /// CHECK: NewArray
    897   /// CHECK: ArraySet
    898   /// CHECK: ArrayGet
    899 
    900   /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (after)
    901   /// CHECK-NOT: NewArray
    902   /// CHECK-NOT: ArraySet
    903   /// CHECK-NOT: ArrayGet
    904   private static int testAllocationEliminationOfArray3(int i) {
    905     int[] array = new int[4];
    906     array[i] = 4;
    907     return array[i];
    908   }
    909 
    910   /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (before)
    911   /// CHECK: NewArray
    912   /// CHECK: ArraySet
    913   /// CHECK: ArraySet
    914   /// CHECK: ArrayGet
    915   /// CHECK: ArrayGet
    916 
    917   /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (after)
    918   /// CHECK: NewArray
    919   /// CHECK: ArraySet
    920   /// CHECK: ArraySet
    921   /// CHECK: ArrayGet
    922   /// CHECK-NOT: ArrayGet
    923   private static int testAllocationEliminationOfArray4(int i) {
    924     // Cannot eliminate array allocation due to index aliasing between 1 and i.
    925     int[] array = new int[4];
    926     array[1] = 2;
    927     array[i] = 4;
    928     return array[1] + array[i];
    929   }
    930 
    931   static void assertIntEquals(int result, int expected) {
    932     if (expected != result) {
    933       throw new Error("Expected: " + expected + ", found: " + result);
    934     }
    935   }
    936 
    937   static void assertFloatEquals(float result, float expected) {
    938     if (expected != result) {
    939       throw new Error("Expected: " + expected + ", found: " + result);
    940     }
    941   }
    942 
    943   static void assertDoubleEquals(double result, double expected) {
    944     if (expected != result) {
    945       throw new Error("Expected: " + expected + ", found: " + result);
    946     }
    947   }
    948 
    949   public static void main(String[] args) {
    950     assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
    951     assertIntEquals(test1(new TestClass(), new TestClass()), 3);
    952     assertIntEquals(test2(new TestClass()), 1);
    953     TestClass obj1 = new TestClass();
    954     TestClass obj2 = new TestClass();
    955     obj1.next = obj2;
    956     assertIntEquals(test3(obj1), 10);
    957     assertIntEquals(test4(new TestClass(), true), 1);
    958     assertIntEquals(test4(new TestClass(), false), 1);
    959     assertIntEquals(test5(new TestClass(), true), 1);
    960     assertIntEquals(test5(new TestClass(), false), 2);
    961     assertIntEquals(test6(new TestClass(), new TestClass(), true), 4);
    962     assertIntEquals(test6(new TestClass(), new TestClass(), false), 2);
    963     assertIntEquals(test7(new TestClass()), 1);
    964     assertIntEquals(test8(), 1);
    965     obj1 = new TestClass();
    966     obj2 = new TestClass();
    967     obj1.next = obj2;
    968     assertIntEquals(test9(new TestClass()), 1);
    969     assertIntEquals(test10(new TestClass(3, 4)), 3);
    970     assertIntEquals(TestClass.si, 3);
    971     assertIntEquals(test11(new TestClass()), 10);
    972     assertIntEquals(test12(new TestClass(), new TestClass()), 10);
    973     assertIntEquals(test13(new TestClass(), new TestClass2()), 3);
    974     SubTestClass obj3 = new SubTestClass();
    975     assertIntEquals(test14(obj3, obj3), 2);
    976     assertIntEquals(test15(), 2);
    977     assertIntEquals(test16(), 3);
    978     assertIntEquals(test17(), 0);
    979     assertIntEquals(test18(new TestClass()), 1);
    980     float[] fa1 = { 0.8f };
    981     float[] fa2 = { 1.8f };
    982     assertFloatEquals(test19(fa1, fa2), 1.8f);
    983     assertFloatEquals(test20().i, 0);
    984     test21(new TestClass());
    985     assertIntEquals(test22(), 13);
    986     assertIntEquals(test23(true), 4);
    987     assertIntEquals(test23(false), 5);
    988     assertFloatEquals(test24(), 8.0f);
    989     testFinalizableByForcingGc();
    990     assertIntEquals($noinline$testHSelect(true), 0xdead);
    991     int[] array = {2, 5, 9, -1, -3, 10, 8, 4};
    992     assertIntEquals(sumWithinRange(array, 1, 5), 11);
    993     assertFloatEquals(testAllocationEliminationWithLoops(), 1.0f);
    994     assertFloatEquals(mF, 0f);
    995     assertDoubleEquals(Math.PI * Math.PI * Math.PI, getCircleArea(Math.PI, true));
    996     assertDoubleEquals(0d, getCircleArea(Math.PI, false));
    997 
    998     int[] iarray = {0, 0, 0};
    999     double[] darray = {0d, 0d, 0d};
   1000     try {
   1001       assertDoubleEquals(Math.PI * Math.PI * Math.PI, testDeoptimize(iarray, darray, Math.PI));
   1002     } catch (Exception e) {
   1003       System.out.println(e);
   1004     }
   1005     assertIntEquals(iarray[0], 1);
   1006     assertIntEquals(iarray[1], 1);
   1007     assertIntEquals(iarray[2], 1);
   1008     assertDoubleEquals(darray[0], Math.PI);
   1009     assertDoubleEquals(darray[1], Math.PI);
   1010     assertDoubleEquals(darray[2], Math.PI);
   1011 
   1012     assertIntEquals(testAllocationEliminationOfArray1(), 11);
   1013     assertIntEquals(testAllocationEliminationOfArray2(), 11);
   1014     assertIntEquals(testAllocationEliminationOfArray3(2), 4);
   1015     assertIntEquals(testAllocationEliminationOfArray4(2), 6);
   1016 
   1017     assertIntEquals(testStoreStore().i, 41);
   1018     assertIntEquals(testStoreStore().j, 43);
   1019     assertIntEquals(testStoreStoreWithDeoptimize(new int[4]), 4);
   1020   }
   1021 
   1022   static boolean sFlag;
   1023 }
   1024