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
17class Circle {
18  Circle(double radius) {
19    this.radius = radius;
20  }
21  public double getArea() {
22    return radius * radius * Math.PI;
23  }
24  private double radius;
25}
26
27class 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
46class SubTestClass extends TestClass {
47  int k;
48}
49
50class TestClass2 {
51  int i;
52  int j;
53}
54
55class TestClass3 {
56  float floatField = 8.0f;
57  boolean test1 = true;
58}
59
60class 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
73public 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