1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 class Circle {
Circle(double radius)18   Circle(double radius) {
19     this.radius = radius;
20   }
getRadius()21   public double getRadius() {
22     return radius;
23   }
getArea()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   }
TestClass()34   TestClass() {
35   }
TestClass(int i, int j)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   byte b;
46   static int si;
47   static TestClass sTestClassObj;
48 }
49 
50 class SubTestClass extends TestClass {
51   int k;
52 }
53 
54 class TestClass2 {
55   int i;
56   int j;
57   int k;
58   int l;
59   int m;
60 }
61 
62 class TestClass3 {
63   float floatField = 8.0f;
64   boolean test1 = true;
65 }
66 
67 // Chosen to have different values with (x + 1) * 10 and (x - 1) * 10. This
68 // means we can easily make sure that different code is in fact executed on
69 // escape and non-escape paths.
70 // Negative so that high-bits will be set for all the 64-bit values allowing us
71 // to easily check for truncation.
72 class TestClass4 {
73   float floatField = -3.0f;
74   double doubleField = -3.0d;
75   short shortField = -3;
76   int intField = -3;
77   byte byteField = -3;
78   long longField = -3l;
79 }
80 
81 class Finalizable {
82   static boolean sVisited = false;
83   static final int VALUE1 = 0xbeef;
84   static final int VALUE2 = 0xcafe;
85   int i;
86 
finalize()87   protected void finalize() {
88     if (i != VALUE1) {
89       System.out.println("Where is the beef?");
90     }
91     sVisited = true;
92   }
93 }
94 
95 interface Filter {
isValid(int i)96   public boolean isValid(int i);
97 }
98 
99 public class Main {
$noinline$Escape4(TestClass4 o)100   static void $noinline$Escape4(TestClass4 o) {
101     o.floatField += 1.0f;
102     o.doubleField += 1.0d;
103     o.byteField += 1;
104     o.shortField += 1;
105     o.intField += 1;
106     o.longField += 1;
107   }
108 
109   static Object ESCAPE = null;
$noinline$Escape(TestClass o)110   static void $noinline$Escape(TestClass o) {
111     if (o == null) {
112       return;
113     }
114     ESCAPE = o;
115     o.next.i++;
116   }
117 
118   /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before)
119   /// CHECK: NewInstance
120   /// CHECK: InstanceFieldSet
121   /// CHECK: InstanceFieldGet
122 
123   /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after)
124   /// CHECK-NOT: NewInstance
125   /// CHECK-NOT: InstanceFieldSet
126   /// CHECK-NOT: InstanceFieldGet
127 
calcCircleArea(double radius)128   static double calcCircleArea(double radius) {
129     return new Circle(radius).getArea();
130   }
131 
132   /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (before)
133   /// CHECK: InstanceFieldSet
134   /// CHECK: InstanceFieldSet
135   /// CHECK: InstanceFieldGet
136   /// CHECK: InstanceFieldGet
137 
138   /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (after)
139   /// CHECK: InstanceFieldSet
140   /// CHECK: InstanceFieldSet
141   /// CHECK-NOT: NullCheck
142   /// CHECK-NOT: InstanceFieldGet
143 
144   // Different fields shouldn't alias.
test1(TestClass obj1, TestClass obj2)145   static int test1(TestClass obj1, TestClass obj2) {
146     obj1.i = 1;
147     obj2.j = 2;
148     return obj1.i + obj2.j;
149   }
150 
151   /// CHECK-START: int Main.test2(TestClass) load_store_elimination (before)
152   /// CHECK: InstanceFieldSet
153   /// CHECK: InstanceFieldSet
154   /// CHECK: InstanceFieldGet
155 
156   /// CHECK-START: int Main.test2(TestClass) load_store_elimination (after)
157   /// CHECK: InstanceFieldSet
158   /// CHECK-NOT: NullCheck
159   /// CHECK-NOT: InstanceFieldSet
160   /// CHECK-NOT: InstanceFieldGet
161 
162   // Redundant store of the same value.
test2(TestClass obj)163   static int test2(TestClass obj) {
164     obj.j = 1;
165     obj.j = 1;
166     return obj.j;
167   }
168 
169   /// CHECK-START: int Main.test3(TestClass) load_store_elimination (before)
170   /// CHECK: StaticFieldGet
171   /// CHECK: NewInstance
172   /// CHECK: InstanceFieldSet
173   /// CHECK: InstanceFieldSet
174   /// CHECK: InstanceFieldSet
175   /// CHECK: InstanceFieldSet
176   /// CHECK: InstanceFieldSet
177   /// CHECK: InstanceFieldGet
178   /// CHECK: InstanceFieldGet
179   /// CHECK: InstanceFieldGet
180   /// CHECK: InstanceFieldGet
181 
182   /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after)
183   /// CHECK: StaticFieldGet
184   /// CHECK: NewInstance
185   /// CHECK: InstanceFieldSet
186   /// CHECK: InstanceFieldSet
187   /// CHECK: InstanceFieldSet
188   /// CHECK: InstanceFieldSet
189   /// CHECK: InstanceFieldSet
190 
191   /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after)
192   /// CHECK-NOT: InstanceFieldGet
193 
194   // A new allocation (even non-singleton) shouldn't alias with pre-existing values.
test3(TestClass obj)195   static int test3(TestClass obj) {
196     TestClass obj1 = TestClass.sTestClassObj;
197     TestClass obj2 = new TestClass();  // Cannot alias with obj or obj1 which pre-exist.
198     obj.next = obj2;  // Make obj2 a non-singleton.
199     // All stores below need to stay since obj/obj1/obj2 are not singletons.
200     obj.i = 1;
201     obj1.j = 2;
202     // Following stores won't kill values of obj.i and obj1.j.
203     obj2.i = 3;
204     obj2.j = 4;
205     return obj.i + obj1.j + obj2.i + obj2.j;
206   }
207 
208   /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before)
209   /// CHECK-DAG: InstanceFieldSet
210   /// CHECK-DAG: InstanceFieldSet
211   /// CHECK-DAG: InstanceFieldGet
212   /// CHECK-DAG: Return
213 
214   /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
215   /// CHECK-DAG: InstanceFieldSet
216   /// CHECK-DAG: InstanceFieldSet
217   /// CHECK-DAG: Return
218 
219   /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
220   /// CHECK:     NullCheck
221   /// CHECK:     NullCheck
222   /// CHECK-NOT: NullCheck
223 
224   /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after)
225   /// CHECK-NOT: InstanceFieldGet
226   /// CHECK-NOT: Phi
227 
228   // Set and merge the same value in two branches.
test4(TestClass obj, boolean b)229   static int test4(TestClass obj, boolean b) {
230     if (b) {
231       obj.i = 1;
232     } else {
233       obj.i = 1;
234     }
235     return obj.i;
236   }
237 
238   /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before)
239   /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
240   /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
241   /// CHECK-DAG:  <<Obj:l\d+>>       ParameterValue
242   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int1>>]
243   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int2>>]
244   /// CHECK-DAG:  <<GetField:i\d+>>  InstanceFieldGet [{{l\d+}}]
245   /// CHECK-DAG:                     Return [<<GetField>>]
246 
247   /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after)
248   /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
249   /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
250   /// CHECK-DAG:  <<Obj:l\d+>>       ParameterValue
251   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int1>>]
252   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int2>>]
253   /// CHECK-DAG:  <<Phi:i\d+>>       Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
254   /// CHECK-DAG:                     Return [<<Phi>>]
255   /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Int1>>","<<Int2>>"])
256 
257   /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after)
258   /// CHECK-NOT: InstanceFieldGet
259 
260   // Set and merge different values in two branches.
test5(TestClass obj, boolean b)261   static int test5(TestClass obj, boolean b) {
262     if (b) {
263       obj.i = 1;
264     } else {
265       obj.i = 2;
266     }
267     return obj.i;
268   }
269 
270   /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before)
271   /// CHECK-DAG: InstanceFieldSet
272   /// CHECK-DAG: InstanceFieldSet
273   /// CHECK-DAG: InstanceFieldSet
274   /// CHECK-DAG: InstanceFieldGet
275   /// CHECK-DAG: InstanceFieldGet
276 
277   /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after)
278   /// CHECK-DAG: InstanceFieldSet
279   /// CHECK-DAG: InstanceFieldSet
280   /// CHECK-DAG: InstanceFieldSet
281   /// CHECK-DAG: InstanceFieldGet
282 
283   /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after)
284   /// CHECK: InstanceFieldGet
285   /// CHECK-NOT: InstanceFieldGet
286 
287   // Setting the same value doesn't clear the value for aliased locations.
test6(TestClass obj1, TestClass obj2, boolean b)288   static int test6(TestClass obj1, TestClass obj2, boolean b) {
289     obj1.i = 1;
290     obj1.j = 2;
291     if (b) {
292       obj2.j = 2;
293     }
294     return obj1.j + obj2.j;
295   }
296 
297   /// CHECK-START: int Main.test7(TestClass) load_store_elimination (before)
298   /// CHECK: InstanceFieldSet
299   /// CHECK: InstanceFieldGet
300 
301   /// CHECK-START: int Main.test7(TestClass) load_store_elimination (after)
302   /// CHECK: InstanceFieldSet
303   /// CHECK: InstanceFieldGet
304 
305   // Invocation should kill values in non-singleton heap locations.
test7(TestClass obj)306   static int test7(TestClass obj) {
307     obj.i = 1;
308     System.out.print("");
309     return obj.i;
310   }
311 
312   /// CHECK-START: int Main.test8() load_store_elimination (before)
313   /// CHECK: NewInstance
314   /// CHECK: InstanceFieldSet
315   /// CHECK: InvokeVirtual
316   /// CHECK: InstanceFieldGet
317 
318   /// CHECK-START: int Main.test8() load_store_elimination (after)
319   /// CHECK-NOT: NewInstance
320   /// CHECK-NOT: InstanceFieldSet
321   /// CHECK: InvokeVirtual
322   /// CHECK-NOT: NullCheck
323   /// CHECK-NOT: InstanceFieldGet
324 
325   // Invocation should not kill values in singleton heap locations.
test8()326   static int test8() {
327     TestClass obj = new TestClass();
328     obj.i = 1;
329     System.out.print("");
330     return obj.i;
331   }
332 
333   /// CHECK-START: int Main.test9(TestClass) load_store_elimination (before)
334   /// CHECK: NewInstance
335   /// CHECK: InstanceFieldSet
336   /// CHECK: InstanceFieldSet
337   /// CHECK: InstanceFieldGet
338 
339   /// CHECK-START: int Main.test9(TestClass) load_store_elimination (after)
340   /// CHECK: NewInstance
341   /// CHECK: InstanceFieldSet
342   /// CHECK: InstanceFieldSet
343   /// CHECK: InstanceFieldGet
344 
345   // Invocation should kill values in non-singleton heap locations.
test9(TestClass obj)346   static int test9(TestClass obj) {
347     TestClass obj2 = new TestClass();
348     obj2.i = 1;
349     obj.next = obj2;
350     System.out.print("");
351     return obj2.i;
352   }
353 
354   /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before)
355   /// CHECK-DAG: StaticFieldGet
356   /// CHECK-DAG: InstanceFieldGet
357   /// CHECK-DAG: StaticFieldSet
358   /// CHECK-DAG: InstanceFieldGet
359 
360   /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
361   /// CHECK-DAG: StaticFieldGet
362   /// CHECK-DAG: InstanceFieldGet
363   /// CHECK-DAG: StaticFieldSet
364 
365   /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
366   /// CHECK:     NullCheck
367   /// CHECK-NOT: NullCheck
368 
369   /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after)
370   /// CHECK:     InstanceFieldGet
371   /// CHECK-NOT: InstanceFieldGet
372 
373   // Static fields shouldn't alias with instance fields.
test10(TestClass obj)374   static int test10(TestClass obj) {
375     TestClass.si += obj.i;
376     return obj.i;
377   }
378 
379   /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before)
380   /// CHECK: InstanceFieldSet
381   /// CHECK: InstanceFieldGet
382 
383   /// CHECK-START: int Main.test11(TestClass) load_store_elimination (after)
384   /// CHECK: InstanceFieldSet
385   /// CHECK-NOT: NullCheck
386   /// CHECK-NOT: InstanceFieldGet
387 
388   // Loop without heap writes.
test11(TestClass obj)389   static int test11(TestClass obj) {
390     obj.i = 1;
391     int sum = 0;
392     for (int i = 0; i < 10; i++) {
393       sum += obj.i;
394     }
395     return sum;
396   }
397 
398   /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (before)
399   /// CHECK: InstanceFieldSet
400   /// CHECK: InstanceFieldGet
401   /// CHECK: InstanceFieldSet
402 
403   /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (after)
404   /// CHECK: InstanceFieldSet
405   /// CHECK: InstanceFieldGet
406   /// CHECK: InstanceFieldSet
407 
408   // Loop with heap writes.
test12(TestClass obj1, TestClass obj2)409   static int test12(TestClass obj1, TestClass obj2) {
410     obj1.i = 1;
411     int sum = 0;
412     for (int i = 0; i < 10; i++) {
413       sum += obj1.i;
414       obj2.i = sum;
415     }
416     return sum;
417   }
418 
419   /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (before)
420   /// CHECK: InstanceFieldSet
421   /// CHECK: InstanceFieldSet
422   /// CHECK: InstanceFieldGet
423   /// CHECK: InstanceFieldGet
424 
425   /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (after)
426   /// CHECK: InstanceFieldSet
427   /// CHECK: InstanceFieldSet
428   /// CHECK-NOT: NullCheck
429   /// CHECK-NOT: InstanceFieldGet
430 
431   // Different classes shouldn't alias.
test13(TestClass obj1, TestClass2 obj2)432   static int test13(TestClass obj1, TestClass2 obj2) {
433     obj1.i = 1;
434     obj2.i = 2;
435     return obj1.i + obj2.i;
436   }
437 
438   /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (before)
439   /// CHECK: InstanceFieldSet
440   /// CHECK: InstanceFieldSet
441   /// CHECK: InstanceFieldGet
442 
443   /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (after)
444   /// CHECK: InstanceFieldSet
445   /// CHECK: InstanceFieldSet
446   /// CHECK: InstanceFieldGet
447 
448   // Subclass may alias with super class.
test14(TestClass obj1, SubTestClass obj2)449   static int test14(TestClass obj1, SubTestClass obj2) {
450     obj1.i = 1;
451     obj2.i = 2;
452     return obj1.i;
453   }
454 
455   /// CHECK-START: int Main.test15() load_store_elimination (before)
456   /// CHECK: StaticFieldSet
457   /// CHECK: StaticFieldSet
458   /// CHECK: StaticFieldGet
459 
460   /// CHECK-START: int Main.test15() load_store_elimination (after)
461   /// CHECK: <<Const2:i\d+>> IntConstant 2
462   /// CHECK: StaticFieldSet
463   /// CHECK: Return [<<Const2>>]
464 
465   /// CHECK-START: int Main.test15() load_store_elimination (after)
466   /// CHECK-NOT: StaticFieldGet
467 
468   // Static field access from subclass's name.
test15()469   static int test15() {
470     TestClass.si = 1;
471     SubTestClass.si = 2;
472     return TestClass.si;
473   }
474 
475   /// CHECK-START: int Main.test16() load_store_elimination (before)
476   /// CHECK: NewInstance
477   /// CHECK: InstanceFieldSet
478   /// CHECK: InstanceFieldSet
479   /// CHECK: InstanceFieldGet
480   /// CHECK: InstanceFieldGet
481 
482   /// CHECK-START: int Main.test16() load_store_elimination (after)
483   /// CHECK-NOT: NewInstance
484   /// CHECK-NOT: InstanceFieldSet
485   /// CHECK-NOT: InstanceFieldGet
486 
487   // Test inlined constructor.
test16()488   static int test16() {
489     TestClass obj = new TestClass(1, 2);
490     return obj.i + obj.j;
491   }
492 
493   /// CHECK-START: int Main.test17() load_store_elimination (before)
494   /// CHECK: NewInstance
495   /// CHECK: InstanceFieldSet
496   /// CHECK: InstanceFieldGet
497 
498   /// CHECK-START: int Main.test17() load_store_elimination (after)
499   /// CHECK: <<Const0:i\d+>> IntConstant 0
500   /// CHECK-NOT: NewInstance
501   /// CHECK-NOT: InstanceFieldSet
502   /// CHECK-NOT: InstanceFieldGet
503   /// CHECK: Return [<<Const0>>]
504 
505   // Test getting default value.
test17()506   static int test17() {
507     TestClass obj = new TestClass();
508     obj.j = 1;
509     return obj.i;
510   }
511 
512   /// CHECK-START: int Main.test18(TestClass) load_store_elimination (before)
513   /// CHECK: InstanceFieldSet
514   /// CHECK: InstanceFieldGet
515 
516   /// CHECK-START: int Main.test18(TestClass) load_store_elimination (after)
517   /// CHECK: InstanceFieldSet
518   /// CHECK: InstanceFieldGet
519 
520   // Volatile field load/store shouldn't be eliminated.
test18(TestClass obj)521   static int test18(TestClass obj) {
522     obj.k = 1;
523     return obj.k;
524   }
525 
526   /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (before)
527   /// CHECK:     {{f\d+}} ArrayGet
528   /// CHECK:     {{f\d+}} ArrayGet
529 
530   /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (after)
531   /// CHECK:     {{f\d+}} ArrayGet
532   /// CHECK-NOT: {{f\d+}} ArrayGet
533 
534   // I/F, J/D aliasing should not happen any more and LSE should eliminate the load.
test19(float[] fa1, float[] fa2)535   static float test19(float[] fa1, float[] fa2) {
536     fa1[0] = fa2[0];
537     return fa1[0];
538   }
539 
540   /// CHECK-START: TestClass Main.test20() load_store_elimination (before)
541   /// CHECK: NewInstance
542   /// CHECK: InstanceFieldSet
543 
544   /// CHECK-START: TestClass Main.test20() load_store_elimination (after)
545   /// CHECK: NewInstance
546   /// CHECK-NOT: InstanceFieldSet
547 
548   // Storing default heap value is redundant if the heap location has the
549   // default heap value.
test20()550   static TestClass test20() {
551     TestClass obj = new TestClass();
552     obj.i = 0;
553     return obj;
554   }
555 
556   /// CHECK-START: void Main.test21(TestClass) load_store_elimination (before)
557   /// CHECK: NewInstance
558   /// CHECK: InstanceFieldSet
559   /// CHECK: InstanceFieldSet
560   /// CHECK: InstanceFieldSet
561   /// CHECK: InstanceFieldGet
562   /// CHECK: InstanceFieldGet
563 
564   /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after)
565   /// CHECK-DAG: InstanceFieldSet
566   /// CHECK-DAG: Phi
567 
568   /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after)
569   /// CHECK-NOT: NewInstance
570   /// CHECK-NOT: InstanceFieldGet
571 
572   // Loop side effects can kill heap values, stores need to be kept in that case.
test21(TestClass obj0)573   static void test21(TestClass obj0) {
574     TestClass obj = new TestClass();
575     obj0.str = "abc";
576     obj.str = "abc";
577     // Note: This loop is transformed by the loop optimization pass, therefore we
578     // are not checking the exact number of InstanceFieldSet and Phi instructions.
579     for (int i = 0; i < 2; i++) {
580       // Generate some loop side effect that writes into obj.
581       obj.str = "def";
582     }
583     $noinline$printSubstrings00(obj0.str, obj.str);
584   }
585 
$noinline$printSubstrings00(String str1, String str2)586   static void $noinline$printSubstrings00(String str1, String str2) {
587     System.out.print(str1.substring(0, 0) + str2.substring(0, 0));
588   }
589 
590   /// CHECK-START: int Main.test22() load_store_elimination (before)
591   /// CHECK: NewInstance
592   /// CHECK: InstanceFieldSet
593   /// CHECK: NewInstance
594   /// CHECK: InstanceFieldSet
595   /// CHECK: InstanceFieldGet
596   /// CHECK: NewInstance
597   /// CHECK: InstanceFieldSet
598   /// CHECK: InstanceFieldGet
599   /// CHECK: InstanceFieldGet
600 
601   /// CHECK-START: int Main.test22() load_store_elimination (after)
602   /// CHECK-NOT: NewInstance
603   /// CHECK-NOT: InstanceFieldSet
604   /// CHECK-NOT: InstanceFieldGet
605 
606   // For a singleton, loop side effects can kill its field values only if:
607   // (1) it dominiates the loop header, and
608   // (2) its fields are stored into inside a loop.
test22()609   static int test22() {
610     int sum = 0;
611     TestClass obj1 = new TestClass();
612     obj1.i = 2;    // This store can be eliminated since obj1 is never stored into inside a loop.
613     for (int i = 0; i < 2; i++) {
614       TestClass obj2 = new TestClass();
615       obj2.i = 3;  // This store can be eliminated since the singleton is inside the loop.
616       sum += obj2.i;
617     }
618     TestClass obj3 = new TestClass();
619     obj3.i = 5;    // This store can be eliminated since the singleton is created after the loop.
620     sum += obj1.i + obj3.i;
621     return sum;
622   }
623 
624   /// CHECK-START: int Main.test23(boolean) load_store_elimination (before)
625   /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
626   /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
627   /// CHECK-DAG:  <<Int3:i\d+>>      IntConstant 3
628   /// CHECK-DAG:  <<Obj:l\d+>>       NewInstance
629   /// CHECK-DAG:                     InstanceFieldSet [<<Obj>>,<<Int3>>]
630   /// CHECK-DAG:  <<Add1:i\d+>>      Add [<<Get1:i\d+>>,<<Int1>>]
631   /// CHECK-DAG:  <<Get1>>           InstanceFieldGet [<<Obj>>]
632   /// CHECK-DAG:                     InstanceFieldSet [<<Obj>>,<<Add1>>]
633   /// CHECK-DAG:  <<Add2:i\d+>>      Add [<<Get2:i\d+>>,<<Int2>>]
634   /// CHECK-DAG:  <<Get2>>           InstanceFieldGet [<<Obj>>]
635   /// CHECK-DAG:                     InstanceFieldSet [<<Obj>>,<<Add2>>]
636   /// CHECK-DAG:                     Return [<<Get3:i\d+>>]
637   /// CHECK-DAG:  <<Get3>>           InstanceFieldGet [<<Obj>>]
638 
639   /// CHECK-START: int Main.test23(boolean) load_store_elimination (after)
640   /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
641   /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
642   /// CHECK-DAG:  <<Int3:i\d+>>      IntConstant 3
643   /// CHECK-DAG:  <<Add1:i\d+>>      Add [<<Int3>>,<<Int1>>]
644   /// CHECK-DAG:  <<Add2:i\d+>>      Add [<<Int3>>,<<Int2>>]
645   /// CHECK-DAG:  <<Phi:i\d+>>       Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
646   /// CHECK-DAG:                     Return [<<Phi>>]
647   /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Add1>>","<<Add2>>"])
648 
649   /// CHECK-START: int Main.test23(boolean) load_store_elimination (after)
650   /// CHECK-NOT: NewInstance
651   /// CHECK-NOT: InstanceFieldSet
652   /// CHECK-NOT: InstanceFieldGet
653 
654   // Test heap value merging from multiple branches.
test23(boolean b)655   static int test23(boolean b) {
656     TestClass obj = new TestClass();
657     obj.i = 3;      // This store can be eliminated since the value flows into each branch.
658     if (b) {
659       obj.i += 1;   // This store can be eliminated after replacing the load below with a Phi.
660     } else {
661       obj.i += 2;   // This store can be eliminated after replacing the load below with a Phi.
662     }
663     return obj.i;   // This load is eliminated by creating a Phi.
664   }
665 
666   /// CHECK-START: float Main.test24() load_store_elimination (before)
667   /// CHECK-DAG:     <<True:i\d+>>     IntConstant 1
668   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
669   /// CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
670   /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
671   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<True>>]
672   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float8>>]
673   /// CHECK-DAG:     <<GetTest:z\d+>>  InstanceFieldGet [<<Obj>>]
674   /// CHECK-DAG:     <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
675   /// CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<GetField>>,<<GetTest>>]
676   /// CHECK-DAG:                       Return [<<Select>>]
677 
678   /// CHECK-START: float Main.test24() load_store_elimination (after)
679   /// CHECK-DAG:     <<True:i\d+>>     IntConstant 1
680   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
681   /// CHECK-DAG:     <<Float42:f\d+>>  FloatConstant 42
682   /// CHECK-DAG:     <<Select:f\d+>>   Select [<<Float42>>,<<Float8>>,<<True>>]
683   /// CHECK-DAG:                       Return [<<Select>>]
684 
685   /// CHECK-START: float Main.test24() load_store_elimination (after)
686   /// CHECK-NOT:                       NewInstance
687   /// CHECK-NOT:                       InstanceFieldGet
test24()688   static float test24() {
689     float a = 42.0f;
690     TestClass3 obj = new TestClass3();
691     if (obj.test1) {
692       a = obj.floatField;
693     }
694     return a;
695   }
696 
697   /// CHECK-START: int Main.test25(boolean, boolean, boolean) load_store_elimination (before)
698   /// CHECK-DAG:     <<Int1:i\d+>>     IntConstant 1
699   /// CHECK-DAG:     <<Int2:i\d+>>     IntConstant 2
700   /// CHECK-DAG:     <<Int3:i\d+>>     IntConstant 3
701   /// CHECK-DAG:     <<Int5:i\d+>>     IntConstant 5
702   /// CHECK-DAG:     <<Int6:i\d+>>     IntConstant 6
703   /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
704   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int1>>]
705   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int2>>]
706   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int3>>]
707   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int5>>]
708   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Int6>>]
709   /// CHECK-DAG:     <<GetField:i\d+>> InstanceFieldGet [<<Obj>>]
710   /// CHECK-DAG:                       Return [<<GetField>>]
711 
712   /// CHECK-START: int Main.test25(boolean, boolean, boolean) load_store_elimination (after)
713   /// CHECK-DAG:     <<Int1:i\d+>>     IntConstant 1
714   /// CHECK-DAG:     <<Int2:i\d+>>     IntConstant 2
715   /// CHECK-DAG:     <<Int3:i\d+>>     IntConstant 3
716   /// CHECK-DAG:     <<Int5:i\d+>>     IntConstant 5
717   /// CHECK-DAG:     <<Int6:i\d+>>     IntConstant 6
718   /// CHECK-DAG:     <<Phi:i\d+>>      Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>,<<Arg4:i\d+>>,<<Arg5:i\d+>>]
719   /// CHECK-DAG:                       Return [<<Phi>>]
720   /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>","<<Arg4>>","<<Arg5>>"]) == set(["<<Int1>>","<<Int2>>","<<Int3>>","<<Int5>>","<<Int6>>"])
721 
722   /// CHECK-START: int Main.test25(boolean, boolean, boolean) load_store_elimination (after)
723   /// CHECK-NOT:                       NewInstance
724   /// CHECK-NOT:                       InstanceFieldSet
725   /// CHECK-NOT:                       InstanceFieldGet
726 
727   // Test heap value merging from nested branches.
test25(boolean b, boolean c, boolean d)728   static int test25(boolean b, boolean c, boolean d) {
729     TestClass obj = new TestClass();
730     if (b) {
731       if (c) {
732         obj.i = 1;
733       } else {
734         if (d) {
735           obj.i = 2;
736         } else {
737           obj.i = 3;
738         }
739       }
740     } else {
741       if (c) {
742         obj.i = 5;
743       } else {
744         obj.i = 6;
745       }
746     }
747     return obj.i;
748   }
749 
750   /// CHECK-START: float Main.test26(int) load_store_elimination (before)
751   /// CHECK-DAG:     <<Float0:f\d+>>   FloatConstant 0
752   /// CHECK-DAG:     <<Float1:f\d+>>   FloatConstant 1
753   /// CHECK-DAG:     <<Float2:f\d+>>   FloatConstant 2
754   /// CHECK-DAG:     <<Float3:f\d+>>   FloatConstant 3
755   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
756   /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
757   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float8>>]
758   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float0>>]
759   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float1>>]
760   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float2>>]
761   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float3>>]
762   /// CHECK-DAG:     <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
763   /// CHECK-DAG:                       Return [<<GetField>>]
764 
765   /// CHECK-START: float Main.test26(int) load_store_elimination (after)
766   /// CHECK-DAG:     <<Float0:f\d+>>   FloatConstant 0
767   /// CHECK-DAG:     <<Float1:f\d+>>   FloatConstant 1
768   /// CHECK-DAG:     <<Float2:f\d+>>   FloatConstant 2
769   /// CHECK-DAG:     <<Float3:f\d+>>   FloatConstant 3
770   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
771   /// CHECK-DAG:     <<Phi:f\d+>>      Phi [<<Arg1:f\d+>>,<<Arg2:f\d+>>,<<Arg3:f\d+>>,<<Arg4:f\d+>>]
772   /// CHECK-DAG:                       Return [<<Phi>>]
773   /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>","<<Arg4>>"]) == set(["<<Float0>>","<<Float1>>","<<Float2>>","<<Float3>>"])
774 
775   /// CHECK-START: float Main.test26(int) load_store_elimination (after)
776   /// CHECK-NOT:                       NewInstance
777   /// CHECK-NOT:                       InstanceFieldSet
778   /// CHECK-NOT:                       InstanceFieldGet
779 
780   // Test heap value merging from switch statement.
test26(int b)781   static float test26(int b) {
782     TestClass3 obj = new TestClass3();
783     switch (b) {
784       case 1:
785         obj.floatField = 3.0f;
786         break;
787       case 2:
788         obj.floatField = 2.0f;
789         break;
790       case 3:
791         obj.floatField = 1.0f;
792         break;
793       default:
794         obj.floatField = 0.0f;
795         break;
796     }
797     return obj.floatField;
798   }
799 
800   /// CHECK-START: int Main.test27(boolean, boolean) load_store_elimination (before)
801   /// CHECK-DAG:   <<Int1:i\d+>>      IntConstant 1
802   /// CHECK-DAG:   <<Obj:l\d+>>       NewInstance
803   /// CHECK-DAG:                      InstanceFieldSet [<<Obj>>,<<Int1>>]
804   /// CHECK-DAG:                      InstanceFieldSet [<<Obj>>,<<Int1>>]
805   /// CHECK-DAG:                      InstanceFieldSet [<<Obj>>,<<Int1>>]
806   /// CHECK-DAG:                      InstanceFieldSet [<<Obj>>,<<Int1>>]
807   /// CHECK-DAG:   <<GetField:i\d+>>  InstanceFieldGet [<<Obj>>]
808   /// CHECK-DAG:                      Return [<<GetField>>]
809 
810   /// CHECK-START: int Main.test27(boolean, boolean) load_store_elimination (after)
811   /// CHECK-DAG:   <<Int1:i\d+>>      IntConstant 1
812   /// CHECK-DAG:                      Return [<<Int1>>]
813 
814   /// CHECK-START: int Main.test27(boolean, boolean) load_store_elimination (after)
815   /// CHECK-NOT:                      NewInstance
816   /// CHECK-NOT:                      InstanceFieldSet
817   /// CHECK-NOT:                      InstanceFieldGet
818   /// CHECK-NOT:                      Phi
819 
820   // Test merging same value from nested branches.
test27(boolean b, boolean c)821   static int test27(boolean b, boolean c) {
822     TestClass obj = new TestClass();
823     if (b) {
824       if (c) {
825         obj.i = 1;
826       } else {
827         obj.i = 1;
828       }
829     } else {
830       if (c) {
831         obj.i = 1;
832       } else {
833         obj.i = 1;
834       }
835     }
836     return obj.i;
837   }
838 
839   /// CHECK-START: int Main.test28(boolean, boolean) load_store_elimination (before)
840   /// CHECK-DAG:   <<Int0:i\d+>>      IntConstant 0
841   /// CHECK-DAG:   <<Int5:i\d+>>      IntConstant 5
842   /// CHECK-DAG:   <<Int6:i\d+>>      IntConstant 6
843   /// CHECK-DAG:   <<Array:l\d+>>     NewArray
844   /// CHECK-DAG:                      ArraySet [<<Array>>,<<Int0>>,<<Int5>>]
845   /// CHECK-DAG:                      ArraySet [<<Array>>,<<Int0>>,<<Int6>>]
846   /// CHECK-DAG:   <<GetIndex:i\d+>>  ArrayGet [<<Array>>,<<Int0>>]
847   /// CHECK-DAG:                      Return [<<GetIndex>>]
848 
849   /// CHECK-START: int Main.test28(boolean, boolean) load_store_elimination (after)
850   /// CHECK-DAG:   <<Int0:i\d+>>      IntConstant 0
851   /// CHECK-DAG:   <<Int5:i\d+>>      IntConstant 5
852   /// CHECK-DAG:   <<Int6:i\d+>>      IntConstant 6
853   /// CHECK-DAG:   <<Phi:i\d+>>       Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>]
854   /// CHECK-DAG:                      Return [<<Phi>>]
855   /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>"]) == set(["<<Int0>>","<<Int5>>","<<Int6>>"])
856 
857   /// CHECK-START: int Main.test28(boolean, boolean) load_store_elimination (after)
858   /// CHECK-NOT:                       NewArray
859   /// CHECK-NOT:                       ArraySet
860   /// CHECK-NOT:                       ArrayGet
861 
862   // Test merging array stores in branches.
test28(boolean b, boolean c)863   static int test28(boolean b, boolean c) {
864     int[] array = new int[1];
865     if (b) {
866       if (c) {
867         array[0] = 5;
868       } else {
869         array[0] = 6;
870       }
871     } else { /* Default value: 0. */ }
872     return array[0];
873   }
874 
875   /// CHECK-START: float Main.test29(boolean) load_store_elimination (before)
876   /// CHECK-DAG:     <<Float2:f\d+>>   FloatConstant 2
877   /// CHECK-DAG:     <<Float5:f\d+>>   FloatConstant 5
878   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
879   /// CHECK-DAG:     <<Obj:l\d+>>      NewInstance
880   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float8>>]
881   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float2>>]
882   /// CHECK-DAG:                       InstanceFieldSet [<<Obj>>,<<Float5>>]
883   /// CHECK-DAG:     <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
884   /// CHECK-DAG:                       Return [<<GetField>>]
885 
886   /// CHECK-START: float Main.test29(boolean) load_store_elimination (after)
887   /// CHECK-DAG:     <<Float2:f\d+>>   FloatConstant 2
888   /// CHECK-DAG:     <<Float5:f\d+>>   FloatConstant 5
889   /// CHECK-DAG:     <<Float8:f\d+>>   FloatConstant 8
890   /// CHECK-DAG:     <<Phi:f\d+>>      Phi [<<Arg1:f\d+>>,<<Arg2:f\d+>>]
891   /// CHECK-DAG:                       Return [<<Phi>>]
892   /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Float5>>","<<Float2>>"])
893 
894   /// CHECK-START: float Main.test29(boolean) load_store_elimination (after)
895   /// CHECK-NOT:                       NewInstance
896   /// CHECK-NOT:                       InstanceFieldSet
897   /// CHECK-NOT:                       InstanceFieldGet
898 
899   // Test implicit type conversion in branches.
test29(boolean b)900   static float test29(boolean b) {
901     TestClass3 obj = new TestClass3();
902     if (b) {
903       obj.floatField = 5; // Int
904     } else {
905       obj.floatField = 2L; // Long
906     }
907     return obj.floatField;
908   }
909 
910   /// CHECK-START: int Main.test30(TestClass, boolean) load_store_elimination (before)
911   /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
912   /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
913   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int1>>]
914   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int2>>]
915   /// CHECK-DAG:  <<GetField:i\d+>>  InstanceFieldGet [{{l\d+}}]
916   /// CHECK-DAG:                     Return [<<GetField>>]
917 
918   /// CHECK-START: int Main.test30(TestClass, boolean) load_store_elimination (after)
919   /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
920   /// CHECK-DAG:  <<Int2:i\d+>>      IntConstant 2
921   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int1>>]
922   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Int2>>]
923   /// CHECK-DAG:  <<GetField:i\d+>>  InstanceFieldGet [{{l\d+}}]
924   /// CHECK-DAG:                     Return [<<GetField>>]
925 
926   /// CHECK-START: int Main.test30(TestClass, boolean) load_store_elimination (after)
927   /// CHECK-NOT: Phi
928 
929   // Don't merge different values in two branches for different variables.
test30(TestClass obj, boolean b)930   static int test30(TestClass obj, boolean b) {
931     if (b) {
932       obj.i = 1;
933     } else {
934       obj.j = 2;
935     }
936     return obj.i;
937   }
938 
939   /// CHECK-START: int Main.test31(boolean, boolean) load_store_elimination (before)
940   /// CHECK-DAG:  <<Int2:i\d+>>  IntConstant 2
941   /// CHECK-DAG:  <<Int5:i\d+>>  IntConstant 5
942   /// CHECK-DAG:  <<Int6:i\d+>>  IntConstant 6
943   /// CHECK-DAG:                 InstanceFieldSet [{{l\d+}},<<Int5>>] field_name:{{.*TestClass.i}}
944   /// CHECK-DAG:                 InstanceFieldSet [{{l\d+}},<<Int6>>] field_name:{{.*TestClass.i}}
945   /// CHECK-DAG:  <<Get1:i\d+>>  InstanceFieldGet [{{l\d+}}] field_name:{{.*TestClass.i}}
946   /// CHECK-DAG:                 InstanceFieldSet [{{l\d+}},<<Get1>>] field_name:{{.*TestClass.j}}
947   /// CHECK-DAG:                 InstanceFieldSet [{{l\d+}},<<Int2>>] field_name:{{.*TestClass.i}}
948   /// CHECK-DAG:  <<Get2:i\d+>>  InstanceFieldGet [{{l\d+}}]
949   /// CHECK-DAG:                 Return [<<Get2>>]
950 
951   /// CHECK-START: int Main.test31(boolean, boolean) load_store_elimination (after)
952   /// CHECK-DAG:  <<Int2:i\d+>>  IntConstant 2
953   /// CHECK-DAG:  <<Int5:i\d+>>  IntConstant 5
954   /// CHECK-DAG:  <<Int6:i\d+>>  IntConstant 6
955   /// CHECK-DAG:  <<Phi1:i\d+>>  Phi [<<Int5>>,<<Int6>>]
956   /// CHECK-DAG:  <<Phi2:i\d+>>  Phi [<<Phi1>>,<<Int2>>]
957   /// CHECK-DAG:                 Return [<<Phi2>>]
958 
959   /// CHECK-START: int Main.test31(boolean, boolean) load_store_elimination (after)
960   /// CHECK-NOT:                 NewInstance
961   /// CHECK-NOT:                 InstanceFieldSet
962   /// CHECK-NOT:                 InstanceFieldGet
963 
964   // Test nested branches that can't be flattened.
test31(boolean b, boolean c)965   static int test31(boolean b, boolean c) {
966     TestClass obj = new TestClass();
967     if (b) {
968       if (c) {
969         obj.i = 5;
970       } else {
971         obj.i = 6;
972       }
973       obj.j = obj.i;
974     } else {
975       obj.i = 2;
976     }
977     return obj.i;
978   }
979 
980   /// CHECK-START: int Main.test32(int) load_store_elimination (before)
981   /// CHECK-DAG:  <<Int1:i\d+>>      IntConstant 1
982   /// CHECK-DAG:  <<Int10:i\d+>>     IntConstant 10
983   /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.i}}
984   /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.j}}
985   /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.k}}
986   /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.l}}
987   /// CHECK-DAG:  InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.m}}
988   /// CHECK-DAG:                     Return [<<Int10>>]
989 
990   /// CHECK-START: int Main.test32(int) load_store_elimination (after)
991   /// CHECK-DAG:  <<Int10:i\d+>>     IntConstant 10
992   /// CHECK-DAG:                     Return [<<Int10>>]
993 
994   /// CHECK-START: int Main.test32(int) load_store_elimination (after)
995   /// CHECK-NOT:                     NewInstance
996   /// CHECK-NOT:                     InstanceFieldGet
997   /// CHECK-NOT:                     InstanceFieldSet
998   /// CHECK-NOT:                     Phi
999 
1000   // Test no unused Phi instructions are created.
test32(int i)1001   static int test32(int i) {
1002     TestClass2 obj = new TestClass2();
1003     // By default, i/j/k/l/m are initialized to 0.
1004     switch (i) {
1005       case 1: obj.i = 1; break;
1006       case 2: obj.j = 1; break;
1007       case 3: obj.k = 1; break;
1008       case 4: obj.l = 1; break;
1009       case 5: obj.m = 1; break;
1010     }
1011     // So here, each variable has value Phi [0,1,1,1,1,1].
1012     // But since no heap values are used, we should not be creating these Phis.
1013     return 10;
1014   }
1015 
1016   /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (before)
1017   /// CHECK-DAG:                     InstanceFieldSet
1018   /// CHECK-DAG:                     InstanceFieldSet
1019   /// CHECK-DAG: <<Phi:i\d+>>        Phi
1020   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Phi>>]
1021 
1022   /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (after)
1023   /// CHECK-DAG:                     InstanceFieldSet
1024   /// CHECK-DAG:                     Phi
1025 
1026   /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (after)
1027   /// CHECK:                         InstanceFieldSet
1028   /// CHECK-NOT:                     InstanceFieldSet
1029 
1030   // Test eliminating non-observable stores.
test33(TestClass obj, boolean x)1031   static int test33(TestClass obj, boolean x) {
1032     int phi;
1033     if (x) {
1034       obj.i = 1;
1035       phi = 1;
1036     } else {
1037       obj.i = 2;
1038       phi = 2;
1039     }
1040     obj.i = phi;
1041     return phi;
1042   }
1043 
1044   /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (before)
1045   /// CHECK-DAG:                     InstanceFieldSet
1046   /// CHECK-DAG:                     InstanceFieldSet
1047   /// CHECK-DAG: <<Phi:i\d+>>        Phi
1048   /// CHECK-DAG:                     InstanceFieldSet [{{l\d+}},<<Phi>>]
1049 
1050   /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (after)
1051   /// CHECK-DAG:                     InstanceFieldSet
1052   /// CHECK-DAG:                     InstanceFieldSet
1053   /// CHECK-DAG:                     Phi
1054 
1055   /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (after)
1056   /// CHECK:                         InstanceFieldSet
1057   /// CHECK:                         InstanceFieldSet
1058   /// CHECK-NOT:                     InstanceFieldSet
1059 
1060   // Test eliminating a store that writes a Phi equivalent to merged
1061   // heap values of observable stores.
test34(TestClass obj, boolean x, boolean y)1062   static int test34(TestClass obj, boolean x, boolean y) {
1063     int phi;
1064     if (x) {
1065       obj.i = 1;
1066       phi = 1;
1067       if (y) {
1068         return 3;
1069       }
1070     } else {
1071       obj.i = 2;
1072       phi = 2;
1073       if (y) {
1074         return 4;
1075       }
1076     }
1077     obj.i = phi;
1078     return phi;
1079   }
1080 
1081   /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (before)
1082   /// CHECK-DAG:                     InstanceFieldSet
1083   /// CHECK-DAG:                     InstanceFieldSet
1084   /// CHECK-DAG:                     InstanceFieldSet
1085   /// CHECK-DAG:                     InstanceFieldSet
1086   /// CHECK-DAG:                     InstanceFieldGet
1087 
1088   /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (after)
1089   /// CHECK-DAG:                     InstanceFieldSet
1090   /// CHECK-DAG:                     InstanceFieldSet
1091   /// CHECK-DAG:                     InstanceFieldSet
1092   /// CHECK-DAG:                     InstanceFieldSet
1093   /// CHECK-DAG:                     Phi
1094   /// CHECK-DAG:                     Phi
1095   /// CHECK-DAG:                     Phi
1096 
1097   /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (after)
1098   /// CHECK-NOT:                     InstanceFieldGet
1099 
1100   // Test Phi creation for load elimination.
test35(TestClass obj, boolean x, boolean y)1101   static int test35(TestClass obj, boolean x, boolean y) {
1102     if (x) {
1103       obj.i = 1;
1104     } else {
1105       obj.i = 2;
1106     }
1107     if (y) {
1108       if (x) {
1109         obj.i = 3;
1110       }
1111       obj.j = 5;
1112     }
1113     return obj.i;
1114   }
1115 
1116   /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (before)
1117   /// CHECK-DAG:                     InstanceFieldSet
1118   /// CHECK-DAG:                     InstanceFieldSet
1119   /// CHECK-DAG:                     Phi
1120   /// CHECK-DAG:                     InstanceFieldGet
1121 
1122   /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after)
1123   /// CHECK-DAG:                     InstanceFieldSet
1124   /// CHECK-DAG:                     InstanceFieldSet
1125   /// CHECK-DAG:                     Phi
1126 
1127   /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after)
1128   /// CHECK-NOT:                     InstanceFieldGet
1129 
1130   /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after)
1131   /// CHECK:                         Phi
1132   /// CHECK-NOT:                     Phi
1133 
1134   // Test Phi matching for load elimination.
test36(TestClass obj, boolean x)1135   static int test36(TestClass obj, boolean x) {
1136     int phi;
1137     if (x) {
1138       obj.i = 1;
1139       phi = 1;
1140     } else {
1141       obj.i = 2;
1142       phi = 2;
1143     }
1144     // The load is replaced by the existing Phi instead of constructing a new one.
1145     return obj.i + phi;
1146   }
1147 
1148   /// CHECK-START: int Main.test37(TestClass, boolean) load_store_elimination (before)
1149   /// CHECK-DAG:                     InstanceFieldSet
1150   /// CHECK-DAG:                     InstanceFieldGet
1151   /// CHECK-DAG:                     InstanceFieldSet
1152 
1153   /// CHECK-START: int Main.test37(TestClass, boolean) load_store_elimination (after)
1154   /// CHECK-DAG:                     InstanceFieldSet
1155   /// CHECK-DAG:                     InstanceFieldGet
1156   /// CHECK-DAG:                     InstanceFieldSet
1157 
1158   // Test preserving observable stores.
test37(TestClass obj, boolean x)1159   static int test37(TestClass obj, boolean x) {
1160     if (x) {
1161       obj.i = 1;
1162     }
1163     int tmp = obj.i;  // The store above must be kept.
1164     obj.i = 2;
1165     return tmp;
1166   }
1167 
1168   /// CHECK-START: int Main.test38(TestClass, boolean) load_store_elimination (before)
1169   /// CHECK-DAG:                     InstanceFieldSet
1170   /// CHECK-DAG:                     InstanceFieldSet
1171   /// CHECK-DAG:                     InstanceFieldSet
1172   /// CHECK-DAG:                     InstanceFieldSet
1173 
1174   /// CHECK-START: int Main.test38(TestClass, boolean) load_store_elimination (after)
1175   /// CHECK:                         InstanceFieldSet
1176   /// CHECK-NOT:                     InstanceFieldSet
1177 
1178   // Test eliminating store of the same value after eliminating non-observable stores.
test38(TestClass obj, boolean x)1179   static int test38(TestClass obj, boolean x) {
1180     obj.i = 1;
1181     if (x) {
1182       return 1;  // The store above must be kept.
1183     }
1184     obj.i = 2;  // Not observable, shall be eliminated.
1185     obj.i = 3;  // Not observable, shall be eliminated.
1186     obj.i = 1;  // After eliminating the non-observable stores above, this stores the
1187                 // same value that is already stored in `obj.i` and shall be eliminated.
1188     return 2;
1189   }
1190 
1191   /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (before)
1192   /// CHECK-DAG:                     NewInstance
1193   /// CHECK-DAG:                     InstanceFieldSet
1194   /// CHECK-DAG:                     NewInstance
1195   /// CHECK-DAG:                     InstanceFieldSet
1196   /// CHECK-DAG:                     InstanceFieldGet
1197   /// CHECK-DAG:                     InstanceFieldGet
1198 
1199   /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (after)
1200   /// CHECK-DAG:                     NewInstance
1201   /// CHECK-DAG:                     InstanceFieldSet
1202   /// CHECK-DAG:                     NewInstance
1203   /// CHECK-DAG:                     InstanceFieldSet
1204   /// CHECK-DAG:                     Phi
1205   /// CHECK-DAG:                     InstanceFieldGet
1206 
1207   /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (after)
1208   /// CHECK:                         InstanceFieldGet
1209   /// CHECK-NOT:                     InstanceFieldGet
1210 
1211   // Test creating a reference Phi for load elimination.
test39(TestClass obj, boolean x)1212   static int test39(TestClass obj, boolean x) {
1213     obj.next = new TestClass(1, 2);
1214     if (x) {
1215       obj.next = new SubTestClass();
1216     }
1217     return obj.next.i;
1218   }
1219 
1220   /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (before)
1221   /// CHECK-DAG:                     InstanceFieldSet
1222   /// CHECK-DAG:                     InstanceFieldSet
1223   /// CHECK-DAG:                     InstanceFieldGet
1224   /// CHECK-DAG:                     InstanceFieldSet
1225   /// CHECK-DAG:                     InstanceFieldGet
1226 
1227   /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (after)
1228   /// CHECK-DAG:                     InstanceFieldSet
1229   /// CHECK-DAG:                     InstanceFieldSet
1230   /// CHECK-DAG:                     TypeConversion
1231   /// CHECK-DAG:                     InstanceFieldSet
1232   /// CHECK-DAG:                     Phi
1233 
1234   /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (after)
1235   /// CHECK:                         Phi
1236   /// CHECK-NOT:                     Phi
1237 
1238   // Test tracking values containing type conversion.
1239   // Regression test for b/161521389 .
$noinline$testConversion1(TestClass obj, int x)1240   static int $noinline$testConversion1(TestClass obj, int x) {
1241     obj.i = x;
1242     if ((x & 1) != 0) {
1243       obj.b = (byte) x;
1244       obj.i = obj.b;
1245     }
1246     return obj.i;
1247   }
1248 
1249   /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (before)
1250   /// CHECK-DAG:                     InstanceFieldSet
1251   /// CHECK-DAG:                     InstanceFieldSet
1252   /// CHECK-DAG:                     InstanceFieldGet
1253   /// CHECK-DAG:                     InstanceFieldSet
1254   /// CHECK-DAG:                     TypeConversion
1255   /// CHECK-DAG:                     Phi
1256   /// CHECK-DAG:                     InstanceFieldGet
1257 
1258   /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
1259   /// CHECK-DAG:                     InstanceFieldSet
1260   /// CHECK-DAG:                     InstanceFieldSet
1261   /// CHECK-DAG:                     TypeConversion
1262   /// CHECK-DAG:                     InstanceFieldSet
1263   /// CHECK-DAG:                     Phi
1264   /// CHECK-DAG:                     Phi
1265 
1266   /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
1267   /// CHECK:                         Phi
1268   /// CHECK:                         Phi
1269   /// CHECK-NOT:                     Phi
1270 
1271   /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
1272   /// CHECK:                         TypeConversion
1273   /// CHECK-NOT:                     TypeConversion
1274 
1275   /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
1276   /// CHECK-NOT:                     InstanceFieldGet
1277 
1278   // Test moving type conversion when needed.
$noinline$testConversion2(TestClass obj, int x)1279   static int $noinline$testConversion2(TestClass obj, int x) {
1280     int tmp = 0;
1281     obj.i = x;
1282     if ((x & 1) != 0) {
1283       // The instruction simplifier can remove this TypeConversion if there are
1284       // no environment uses. Currently, there is an environment use in NullCheck,
1285       // so this TypeConversion remains and GVN removes the second TypeConversion
1286       // below. Since we really want to test that the TypeConversion from below
1287       // can be moved and used for the load of `obj.b`, we have a similar test
1288       // written in smali in 530-checker-lse3, StoreLoad.test3(int), except that
1289       // it's using static fields (which would not help with the environment use).
1290       obj.b = (byte) x;
1291       obj.i = obj.b;
1292       tmp = (byte) x;
1293     }
1294     return obj.i + tmp;
1295   }
1296 
1297   /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (before)
1298   /// CHECK-DAG:                     InstanceFieldSet
1299   /// CHECK-DAG:                     Phi
1300   /// CHECK-DAG:                     InstanceFieldSet
1301   /// CHECK-DAG:                     InstanceFieldGet
1302   /// CHECK-DAG:                     InstanceFieldSet
1303   /// CHECK-DAG:                     InstanceFieldGet
1304 
1305   /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
1306   /// CHECK-DAG:                     InstanceFieldSet
1307   /// CHECK-DAG:                     Phi
1308   /// CHECK-DAG:                     Phi
1309   /// CHECK-DAG:                     InstanceFieldSet
1310   /// CHECK-DAG:                     TypeConversion
1311   /// CHECK-DAG:                     InstanceFieldSet
1312 
1313   /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
1314   /// CHECK:                         Phi
1315   /// CHECK:                         Phi
1316   /// CHECK-NOT:                     Phi
1317 
1318   /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
1319   /// CHECK:                         TypeConversion
1320   /// CHECK-NOT:                     TypeConversion
1321 
1322   /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
1323   /// CHECK-NOT:                     InstanceFieldGet
1324 
1325   // Test tracking values containing type conversion with loop.
$noinline$testConversion3(TestClass obj, int x)1326   static int $noinline$testConversion3(TestClass obj, int x) {
1327     obj.i = x;
1328     for (int i = 0; i < x; ++i) {
1329       obj.b = (byte) i;
1330       obj.i = obj.b;
1331     }
1332     return obj.i;
1333   }
1334 
1335   /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (before)
1336   /// CHECK-DAG:                     InstanceFieldSet
1337   /// CHECK-DAG:                     Phi
1338   /// CHECK-DAG:                     Phi
1339   /// CHECK-DAG:                     InstanceFieldSet
1340   /// CHECK-DAG:                     InstanceFieldGet
1341   /// CHECK-DAG:                     InstanceFieldSet
1342   /// CHECK-DAG:                     TypeConversion
1343   /// CHECK-DAG:                     InstanceFieldGet
1344 
1345   /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
1346   /// CHECK-DAG:                     InstanceFieldSet
1347   /// CHECK-DAG:                     Phi
1348   /// CHECK-DAG:                     Phi
1349   /// CHECK-DAG:                     InstanceFieldSet
1350   /// CHECK-DAG:                     TypeConversion
1351   /// CHECK-DAG:                     InstanceFieldSet
1352 
1353   /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
1354   /// CHECK:                         Phi
1355   /// CHECK:                         Phi
1356   /// CHECK-NOT:                     Phi
1357 
1358   /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
1359   /// CHECK:                         TypeConversion
1360   /// CHECK-NOT:                     TypeConversion
1361 
1362   /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
1363   /// CHECK-NOT:                     InstanceFieldGet
1364 
1365   // Test moving type conversion when needed with loop.
$noinline$testConversion4(TestClass obj, int x)1366   static int $noinline$testConversion4(TestClass obj, int x) {
1367     int tmp = x;
1368     obj.i = x;
1369     for (int i = 0; i < x; ++i) {
1370       obj.b = (byte) i;
1371       obj.i = obj.b;
1372       tmp = (byte) i;
1373     }
1374     return obj.i + tmp;
1375   }
1376 
1377   /// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
1378   /// CHECK: NewInstance
1379   /// CHECK: InstanceFieldSet
1380   /// CHECK: InstanceFieldSet
1381 
1382   /// CHECK-START: void Main.testFinalizable() load_store_elimination (after)
1383   /// CHECK: NewInstance
1384   /// CHECK: InstanceFieldSet
1385   /// CHECK-NOT: InstanceFieldSet
1386 
1387   // Allocations of finalizable objects cannot be eliminated.
testFinalizable()1388   static void testFinalizable() {
1389     Finalizable finalizable = new Finalizable();
1390     finalizable.i = Finalizable.VALUE2;
1391     finalizable.i = Finalizable.VALUE1;
1392   }
1393 
getWeakReference()1394   static java.lang.ref.WeakReference<Object> getWeakReference() {
1395     return new java.lang.ref.WeakReference<>(new Object());
1396   }
1397 
testFinalizableByForcingGc()1398   static void testFinalizableByForcingGc() {
1399     testFinalizable();
1400     java.lang.ref.WeakReference<Object> reference = getWeakReference();
1401 
1402     Runtime runtime = Runtime.getRuntime();
1403     for (int i = 0; i < 20; ++i) {
1404       runtime.gc();
1405       System.runFinalization();
1406       try {
1407         Thread.sleep(1);
1408       } catch (InterruptedException e) {
1409         throw new AssertionError(e);
1410       }
1411 
1412       // Check to see if the weak reference has been garbage collected.
1413       if (reference.get() == null) {
1414         // A little bit more sleep time to make sure.
1415         try {
1416           Thread.sleep(100);
1417         } catch (InterruptedException e) {
1418           throw new AssertionError(e);
1419         }
1420         if (!Finalizable.sVisited) {
1421           System.out.println("finalize() not called.");
1422         }
1423         return;
1424       }
1425     }
1426     System.out.println("testFinalizableByForcingGc() failed to force gc.");
1427   }
1428 
1429   /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (before)
1430   /// CHECK: InstanceFieldSet
1431   /// CHECK: Select
1432 
1433   /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (after)
1434   /// CHECK: InstanceFieldSet
1435   /// CHECK: Select
1436 
1437   // Test that HSelect creates alias.
$noinline$testHSelect(boolean b)1438   static int $noinline$testHSelect(boolean b) {
1439     TestClass obj = new TestClass();
1440     TestClass obj2 = null;
1441     obj.i = 0xdead;
1442     if (b) {
1443       obj2 = obj;
1444     }
1445     return obj2.i;
1446   }
1447 
sumWithFilter(int[] array, Filter f)1448   static int sumWithFilter(int[] array, Filter f) {
1449     int sum = 0;
1450     for (int i = 0; i < array.length; i++) {
1451       if (f.isValid(array[i])) {
1452         sum += array[i];
1453       }
1454     }
1455     return sum;
1456   }
1457 
1458   /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (before)
1459   /// CHECK-DAG: NewInstance
1460   /// CHECK-DAG: InstanceFieldSet
1461   /// CHECK-DAG: InstanceFieldSet
1462   /// CHECK-DAG: InstanceFieldGet
1463   /// CHECK-DAG: InstanceFieldGet
1464 
1465   /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (after)
1466   /// CHECK-NOT: NewInstance
1467   /// CHECK-NOT: InstanceFieldSet
1468   /// CHECK-NOT: InstanceFieldGet
1469 
1470   // A lambda-style allocation can be eliminated after inlining.
sumWithinRange(int[] array, final int low, final int high)1471   static int sumWithinRange(int[] array, final int low, final int high) {
1472     Filter filter = new Filter() {
1473       public boolean isValid(int i) {
1474         return (i >= low) && (i <= high);
1475       }
1476     };
1477     return sumWithFilter(array, filter);
1478   }
1479 
1480   private static int mI = 0;
1481   private static float mF = 0f;
1482 
1483   /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (before)
1484   /// CHECK: NewInstance
1485   /// CHECK: NewInstance
1486   /// CHECK: NewInstance
1487 
1488   /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (after)
1489   /// CHECK-NOT: NewInstance
1490 
testAllocationEliminationWithLoops()1491   private static float testAllocationEliminationWithLoops() {
1492     for (int i0 = 0; i0 < 5; i0++) {
1493       for (int i1 = 0; i1 < 5; i1++) {
1494         for (int i2 = 0; i2 < 5; i2++) {
1495           int lI0 = ((int) new Integer(((int) new Integer(mI))));
1496           if (((boolean) new Boolean(false))) {
1497             for (int i3 = 576 - 1; i3 >= 0; i3--) {
1498               mF -= 976981405.0f;
1499             }
1500           }
1501         }
1502       }
1503     }
1504     return 1.0f;
1505   }
1506 
1507   /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (before)
1508   /// CHECK: NewInstance
1509   /// CHECK: InstanceFieldSet
1510   /// CHECK: InstanceFieldSet
1511   /// CHECK: InstanceFieldSet
1512   /// CHECK: InstanceFieldSet
1513 
1514   /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (after)
1515   /// CHECK: NewInstance
1516   /// CHECK: InstanceFieldSet
1517   /// CHECK: InstanceFieldSet
1518   /// CHECK-NOT: InstanceFieldSet
1519 
testStoreStore()1520   private static TestClass2 testStoreStore() {
1521     TestClass2 obj = new TestClass2();
1522     obj.i = 41;
1523     obj.j = 42;
1524     obj.i = 41;
1525     obj.j = 43;
1526     return obj;
1527   }
1528 
1529   /// CHECK-START: void Main.testStoreStore2(TestClass2) load_store_elimination (before)
1530   /// CHECK: InstanceFieldSet
1531   /// CHECK: InstanceFieldSet
1532   /// CHECK: InstanceFieldSet
1533   /// CHECK: InstanceFieldSet
1534 
1535   /// CHECK-START: void Main.testStoreStore2(TestClass2) load_store_elimination (after)
1536   /// CHECK: InstanceFieldSet
1537   /// CHECK: InstanceFieldSet
1538   /// CHECK-NOT: InstanceFieldSet
1539 
testStoreStore2(TestClass2 obj)1540   private static void testStoreStore2(TestClass2 obj) {
1541     obj.i = 41;
1542     obj.j = 42;
1543     obj.i = 43;
1544     obj.j = 44;
1545   }
1546 
1547   /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (before)
1548   /// CHECK: InstanceFieldSet
1549   /// CHECK: InstanceFieldSet
1550   /// CHECK: InstanceFieldSet
1551   /// CHECK: InstanceFieldSet
1552 
1553   /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (after)
1554   /// CHECK: InstanceFieldSet
1555   /// CHECK: InstanceFieldSet
1556   /// CHECK: InstanceFieldSet
1557   /// CHECK-NOT: InstanceFieldSet
1558 
1559   /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (after)
1560   /// CHECK-NOT: Phi
1561 
testStoreStore3(TestClass2 obj, boolean flag)1562   private static void testStoreStore3(TestClass2 obj, boolean flag) {
1563     obj.i = 41;
1564     obj.j = 42;    // redundant since it's overwritten in both branches below.
1565     if (flag) {
1566       obj.j = 43;
1567     } else {
1568       obj.j = 44;
1569     }
1570   }
1571 
1572   /// CHECK-START: void Main.testStoreStore4() load_store_elimination (before)
1573   /// CHECK: StaticFieldSet
1574   /// CHECK: StaticFieldSet
1575 
1576   /// CHECK-START: void Main.testStoreStore4() load_store_elimination (after)
1577   /// CHECK: StaticFieldSet
1578   /// CHECK-NOT: StaticFieldSet
1579 
testStoreStore4()1580   private static void testStoreStore4() {
1581     TestClass.si = 61;
1582     TestClass.si = 62;
1583   }
1584 
1585   /// CHECK-START: int Main.testStoreStore5(TestClass2, TestClass2) load_store_elimination (before)
1586   /// CHECK: InstanceFieldSet
1587   /// CHECK: InstanceFieldGet
1588   /// CHECK: InstanceFieldSet
1589 
1590   /// CHECK-START: int Main.testStoreStore5(TestClass2, TestClass2) load_store_elimination (after)
1591   /// CHECK: InstanceFieldSet
1592   /// CHECK: InstanceFieldGet
1593   /// CHECK: InstanceFieldSet
1594 
testStoreStore5(TestClass2 obj1, TestClass2 obj2)1595   private static int testStoreStore5(TestClass2 obj1, TestClass2 obj2) {
1596     obj1.i = 71;      // This store is needed since obj2.i may load from it.
1597     int i = obj2.i;
1598     obj1.i = 72;
1599     return i;
1600   }
1601 
1602   /// CHECK-START: int Main.testStoreStore6(TestClass2, TestClass2) load_store_elimination (before)
1603   /// CHECK: InstanceFieldSet
1604   /// CHECK: InstanceFieldGet
1605   /// CHECK: InstanceFieldSet
1606 
1607   /// CHECK-START: int Main.testStoreStore6(TestClass2, TestClass2) load_store_elimination (after)
1608   /// CHECK-NOT: InstanceFieldSet
1609   /// CHECK: InstanceFieldGet
1610   /// CHECK: InstanceFieldSet
1611 
testStoreStore6(TestClass2 obj1, TestClass2 obj2)1612   private static int testStoreStore6(TestClass2 obj1, TestClass2 obj2) {
1613     obj1.i = 81;      // This store is not needed since obj2.j cannot load from it.
1614     int j = obj2.j;
1615     obj1.i = 82;
1616     return j;
1617   }
1618 
1619   /// CHECK-START: int Main.testNoSideEffects(int[]) load_store_elimination (before)
1620   /// CHECK: ArraySet
1621   /// CHECK: ArraySet
1622   /// CHECK: ArraySet
1623   /// CHECK: ArrayGet
1624 
1625   /// CHECK-START: int Main.testNoSideEffects(int[]) load_store_elimination (after)
1626   /// CHECK: ArraySet
1627   /// CHECK: ArraySet
1628   /// CHECK-NOT: ArraySet
1629   /// CHECK-NOT: ArrayGet
1630 
testNoSideEffects(int[] array)1631   private static int testNoSideEffects(int[] array) {
1632     array[0] = 101;
1633     array[1] = 102;
1634     int bitCount = Integer.bitCount(0x3456);
1635     array[1] = 103;
1636     return array[0] + bitCount;
1637   }
1638 
1639   /// CHECK-START: void Main.testThrow(TestClass2, java.lang.Exception) load_store_elimination (before)
1640   /// CHECK: InstanceFieldSet
1641   /// CHECK: Throw
1642 
1643   /// CHECK-START: void Main.testThrow(TestClass2, java.lang.Exception) load_store_elimination (after)
1644   /// CHECK: InstanceFieldSet
1645   /// CHECK: Throw
1646 
1647   // Make sure throw keeps the store.
testThrow(TestClass2 obj, Exception e)1648   private static void testThrow(TestClass2 obj, Exception e) throws Exception {
1649     obj.i = 55;
1650     throw e;
1651   }
1652 
1653   /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (before)
1654   /// CHECK: NewInstance
1655   /// CHECK: InstanceFieldSet
1656   /// CHECK: InstanceFieldSet
1657   /// CHECK: InstanceFieldSet
1658   /// CHECK: InstanceFieldSet
1659   /// CHECK: Deoptimize
1660   /// CHECK: ArraySet
1661   /// CHECK: ArraySet
1662   /// CHECK: ArraySet
1663   /// CHECK: ArraySet
1664   /// CHECK: ArrayGet
1665   /// CHECK: ArrayGet
1666   /// CHECK: ArrayGet
1667   /// CHECK: ArrayGet
1668 
1669   /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (after)
1670   /// CHECK: NewInstance
1671   /// CHECK: InstanceFieldSet
1672   /// CHECK: InstanceFieldSet
1673   /// CHECK-NOT: InstanceFieldSet
1674   /// CHECK: Deoptimize
1675   /// CHECK: ArraySet
1676   /// CHECK: ArraySet
1677   /// CHECK: ArraySet
1678   /// CHECK: ArraySet
1679   /// CHECK-NOT: ArrayGet
1680 
testStoreStoreWithDeoptimize(int[] arr)1681   private static int testStoreStoreWithDeoptimize(int[] arr) {
1682     TestClass2 obj = new TestClass2();
1683     obj.i = 41;
1684     obj.j = 42;
1685     obj.i = 41;
1686     obj.j = 43;
1687     arr[0] = 1;  // One HDeoptimize here.
1688     arr[1] = 1;
1689     arr[2] = 1;
1690     arr[3] = 1;
1691     return arr[0] + arr[1] + arr[2] + arr[3];
1692   }
1693 
1694   /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (before)
1695   /// CHECK: NewInstance
1696 
1697   /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (after)
1698   /// CHECK-NOT: NewInstance
1699 
getCircleArea(double radius, boolean b)1700   private static double getCircleArea(double radius, boolean b) {
1701     double area = 0d;
1702     if (b) {
1703       area = new Circle(radius).getArea();
1704     }
1705     return area;
1706   }
1707 
1708   /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (before)
1709   /// CHECK: Deoptimize
1710   /// CHECK: NewInstance
1711   /// CHECK: Deoptimize
1712   /// CHECK: NewInstance
1713 
1714   /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (after)
1715   /// CHECK: Deoptimize
1716   /// CHECK: NewInstance
1717   /// CHECK: Deoptimize
1718   /// CHECK-NOT: NewInstance
1719 
testDeoptimize(int[] iarr, double[] darr, double radius)1720   private static double testDeoptimize(int[] iarr, double[] darr, double radius) {
1721     iarr[0] = 1;  // One HDeoptimize here. Not triggered.
1722     iarr[1] = 1;
1723     Circle circle1 = new Circle(radius);
1724     iarr[2] = 1;
1725     darr[0] = circle1.getRadius();  // One HDeoptimize here, which holds circle1 live. Triggered.
1726     darr[1] = circle1.getRadius();
1727     darr[2] = circle1.getRadius();
1728     darr[3] = circle1.getRadius();
1729     return new Circle(Math.PI).getArea();
1730   }
1731 
1732   /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (before)
1733   /// CHECK: NewArray
1734   /// CHECK: ArraySet
1735   /// CHECK: ArraySet
1736   /// CHECK: ArrayGet
1737   /// CHECK: ArrayGet
1738   /// CHECK: ArrayGet
1739   /// CHECK: ArrayGet
1740 
1741   /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (after)
1742   /// CHECK-NOT: NewArray
1743   /// CHECK-NOT: ArraySet
1744   /// CHECK-NOT: ArrayGet
testAllocationEliminationOfArray1()1745   private static int testAllocationEliminationOfArray1() {
1746     int[] array = new int[4];
1747     array[2] = 4;
1748     array[3] = 7;
1749     return array[0] + array[1] + array[2] + array[3];
1750   }
1751 
1752   /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (before)
1753   /// CHECK: NewArray
1754   /// CHECK: ArraySet
1755   /// CHECK: ArraySet
1756   /// CHECK: ArrayGet
1757 
1758   /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (after)
1759   /// CHECK: NewArray
1760   /// CHECK: ArraySet
1761   /// CHECK: ArraySet
1762   /// CHECK: ArrayGet
testAllocationEliminationOfArray2()1763   private static int testAllocationEliminationOfArray2() {
1764     // Cannot eliminate array allocation since array is accessed with non-constant
1765     // index (only 3 elements to prevent vectorization of the reduction).
1766     int[] array = new int[3];
1767     array[1] = 4;
1768     array[2] = 7;
1769     int sum = 0;
1770     for (int e : array) {
1771       sum += e;
1772     }
1773     return sum;
1774   }
1775 
1776   /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (before)
1777   /// CHECK: NewArray
1778   /// CHECK: ArraySet
1779   /// CHECK: ArrayGet
1780 
1781   /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (after)
1782   /// CHECK-NOT: NewArray
1783   /// CHECK-NOT: ArraySet
1784   /// CHECK-NOT: ArrayGet
testAllocationEliminationOfArray3(int i)1785   private static int testAllocationEliminationOfArray3(int i) {
1786     int[] array = new int[4];
1787     array[i] = 4;
1788     return array[i];
1789   }
1790 
1791   /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (before)
1792   /// CHECK: NewArray
1793   /// CHECK: ArraySet
1794   /// CHECK: ArraySet
1795   /// CHECK: ArrayGet
1796   /// CHECK: ArrayGet
1797 
1798   /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (after)
1799   /// CHECK: NewArray
1800   /// CHECK: ArraySet
1801   /// CHECK: ArraySet
1802   /// CHECK: ArrayGet
1803   /// CHECK-NOT: ArrayGet
testAllocationEliminationOfArray4(int i)1804   private static int testAllocationEliminationOfArray4(int i) {
1805     // Cannot eliminate array allocation due to index aliasing between 1 and i.
1806     int[] array = new int[4];
1807     array[1] = 2;
1808     array[i] = 4;
1809     return array[1] + array[i];
1810   }
1811 
1812   /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (before)
1813   /// CHECK: NewArray
1814   /// CHECK: ArraySet
1815   /// CHECK: ArrayGet
1816 
1817   /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (after)
1818   /// CHECK: NewArray
1819   /// CHECK-NOT: ArraySet
1820   /// CHECK-NOT: ArrayGet
testAllocationEliminationOfArray5(int i)1821   private static int testAllocationEliminationOfArray5(int i) {
1822     // Cannot eliminate array allocation due to unknown i that may
1823     // cause NegativeArraySizeException.
1824     int[] array = new int[i];
1825     array[1] = 12;
1826     return array[1];
1827   }
1828 
1829   /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (before)
1830   /// CHECK-DAG: NewInstance
1831   /// CHECK-DAG: InstanceFieldSet
1832   /// CHECK-DAG: InstanceFieldGet
1833   /// CHECK-DAG: Return
1834   /// CHECK-DAG: InstanceFieldSet
1835   /// CHECK-DAG: Throw
1836 
1837   /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after)
1838   /// CHECK-DAG: Return
1839   /// CHECK-DAG: Throw
1840 
1841   /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after)
1842   /// CHECK-NOT: InstanceFieldSet
1843   /// CHECK-NOT: InstanceFieldGet
1844 
1845   /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after)
1846   /// CHECK: NewInstance
1847   /// CHECK-NOT: NewInstance
testExitMerge(boolean cond)1848   private static int testExitMerge(boolean cond) {
1849     TestClass obj = new TestClass();
1850     if (cond) {
1851       obj.i = 1;
1852       return obj.i + 1;
1853     } else {
1854       obj.i = 2;
1855       throw new Error();  // Note: We have a NewInstance here.
1856     }
1857   }
1858 
1859   /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (before)
1860   /// CHECK-DAG: NewInstance
1861   /// CHECK-DAG: InstanceFieldSet
1862   /// CHECK-DAG: InstanceFieldGet
1863   /// CHECK-DAG: InstanceFieldSet
1864   /// CHECK-DAG: InstanceFieldGet
1865 
1866   /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (after)
1867   /// CHECK-NOT: NewInstance
1868   /// CHECK-NOT: InstanceFieldSet
1869   /// CHECK-NOT: InstanceFieldGet
testExitMerge2(boolean cond)1870   private static int testExitMerge2(boolean cond) {
1871     TestClass obj = new TestClass();
1872     int res;
1873     if (cond) {
1874       obj.i = 1;
1875       res = obj.i + 1;
1876     } else {
1877       obj.i = 2;
1878       res = obj.j + 2;
1879     }
1880     return res;
1881   }
1882 
1883   /// CHECK-START: void Main.testStoreSameValue() load_store_elimination (before)
1884   /// CHECK: NewArray
1885   /// CHECK: ArrayGet
1886   /// CHECK: ArraySet
1887 
1888   /// CHECK-START: void Main.testStoreSameValue() load_store_elimination (after)
1889   /// CHECK: NewArray
1890   /// CHECK-NOT: ArrayGet
1891   /// CHECK-NOT: ArraySet
testStoreSameValue()1892   private static void testStoreSameValue() {
1893     Object[] array = new Object[2];
1894     sArray = array;
1895     Object obj = array[0];
1896     array[1] = obj;    // Store the same value as the default value.
1897   }
1898 
1899   /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (before)
1900   /// CHECK-DAG:                 NewArray
1901   /// CHECK-DAG: <<Value:b\d+>>  ArrayGet
1902   /// CHECK-DAG:                 Return [<<Value>>]
1903 
1904   /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after)
1905   /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
1906   /// CHECK-DAG:                 Return [<<Const0>>]
1907 
1908   /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after)
1909   /// CHECK-NOT:                 NewArray
1910   /// CHECK-NOT:                 ArrayGet
1911   /// CHECK-NOT:                 TypeConversion
$noinline$testByteArrayDefaultValue()1912   private static int $noinline$testByteArrayDefaultValue() {
1913     byte[] array = new byte[2];
1914     array[1] = 1;  // FIXME: Without any stores, LSA tells LSE not to run.
1915     return array[0];
1916   }
1917 
1918   static Object[] sArray;
1919 
1920   /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (before)
1921   /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
1922   /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
1923   /// CHECK-DAG: <<A:l\d+>>      NewArray
1924   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const0>>]
1925   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const1>>]
1926   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const1>>]
1927   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [<<A>>,<<Const0>>]
1928   /// CHECK-DAG:                 Return [<<Get>>]
1929   //
1930   /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (after)
1931   /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
1932   /// CHECK-DAG:                 Return [<<Const1>>]
1933   //
1934   /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (after)
1935   /// CHECK-NOT:                 NewArray
1936   /// CHECK-NOT:                 ArraySet
1937   /// CHECK-NOT:                 ArrayGet
testLocalArrayMerge1(boolean x)1938   private static int testLocalArrayMerge1(boolean x) {
1939     // The explicit store can be removed right away
1940     // since it is equivalent to the default.
1941     int[] a = { 0 };
1942     // The diamond pattern stores/load can be replaced
1943     // by the direct value.
1944     if (x) {
1945       a[0] = 1;
1946     } else {
1947       a[0] = 1;
1948     }
1949     return a[0];
1950   }
1951 
1952   /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (before)
1953   /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
1954   /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
1955   /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
1956   /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
1957   /// CHECK-DAG: <<A:l\d+>>      NewArray
1958   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const1>>]
1959   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const2>>]
1960   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const3>>]
1961   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [<<A>>,<<Const0>>]
1962   /// CHECK-DAG:                 Return [<<Get>>]
1963 
1964   /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after)
1965   /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
1966   /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
1967   /// CHECK-DAG: <<Phi:i\d+>>    Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
1968   /// CHECK-DAG:                 Return [<<Phi>>]
1969   /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const2>>","<<Const3>>"])
1970 
1971   /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after)
1972   /// CHECK-NOT:                 NewArray
1973   /// CHECK-NOT:                 ArraySet
1974   /// CHECK-NOT:                 ArrayGet
testLocalArrayMerge2(boolean x)1975   private static int testLocalArrayMerge2(boolean x) {
1976     // The explicit store can be removed eventually even
1977     // though it is not equivalent to the default.
1978     int[] a = { 1 };
1979     // The load after the diamond pattern is eliminated and replaced with a Phi,
1980     // stores are then also eliminated.
1981     if (x) {
1982       a[0] = 2;
1983     } else {
1984       a[0] = 3;
1985     }
1986     return a[0];
1987   }
1988 
1989   /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (before)
1990   /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
1991   /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
1992   /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
1993   /// CHECK-DAG: <<A:l\d+>>      NewArray
1994   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const1>>]
1995   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const2>>]
1996   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [<<A>>,<<Const0>>]
1997   /// CHECK-DAG:                 Return [<<Get>>]
1998 
1999   /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (after)
2000   /// CHECK-NOT:                 NewArray
2001   /// CHECK-NOT:                 ArraySet
2002   /// CHECK-NOT:                 ArrayGet
testLocalArrayMerge3(boolean x)2003   private static int testLocalArrayMerge3(boolean x) {
2004     int[] a = { 1 };
2005     if (x) {
2006       a[0] = 2;
2007     }
2008     return a[0];
2009   }
2010 
2011   /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (before)
2012   /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
2013   /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2014   /// CHECK-DAG: <<A:l\d+>>      NewArray
2015   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const0>>]
2016   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const1>>]
2017   /// CHECK-DAG:                 ArraySet [<<A>>,<<Const0>>,<<Const1>>]
2018   /// CHECK-DAG: <<Get1:b\d+>>   ArrayGet [<<A>>,<<Const0>>]
2019   /// CHECK-DAG: <<Get2:a\d+>>   ArrayGet [<<A>>,<<Const0>>]
2020   /// CHECK-DAG: <<Add:i\d+>>    Add [<<Get1>>,<<Get2>>]
2021   /// CHECK-DAG:                 Return [<<Add>>]
2022   //
2023   /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (after)
2024   /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2025   /// CHECK-DAG: <<Cnv1:b\d+>>   TypeConversion [<<Const1>>]
2026   /// CHECK-DAG: <<Cnv2:a\d+>>   TypeConversion [<<Const1>>]
2027   /// CHECK-DAG: <<Add:i\d+>>    Add [<<Cnv1>>,<<Cnv2>>]
2028   /// CHECK-DAG:                 Return [<<Add>>]
2029   //
2030   /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (after)
2031   /// CHECK-NOT:                 NewArray
2032   /// CHECK-NOT:                 ArraySet
2033   /// CHECK-NOT:                 ArrayGet
testLocalArrayMerge4(boolean x)2034   private static int testLocalArrayMerge4(boolean x) {
2035     byte[] a = { 0 };
2036     if (x) {
2037       a[0] = 1;
2038     } else {
2039       a[0] = 1;
2040     }
2041     // Differently typed (signed vs unsigned),
2042     // but same reference.
2043     return a[0] + (a[0] & 0xff);
2044   }
2045 
2046   /// CHECK-START: int Main.testLocalArrayMerge5(int[], boolean) load_store_elimination (before)
2047   /// CHECK:                     ArraySet
2048   /// CHECK:                     ArraySet
2049   /// CHECK:                     ArraySet
2050 
2051   /// CHECK-START: int Main.testLocalArrayMerge5(int[], boolean) load_store_elimination (after)
2052   /// CHECK-NOT:                 ArraySet
2053 
2054   // Test eliminating store of the same value after eliminating non-observable stores.
testLocalArrayMerge5(int[] a, boolean x)2055   private static int testLocalArrayMerge5(int[] a, boolean x) {
2056     int old = a[0];
2057     if (x) {
2058       a[0] = 1;
2059     } else {
2060       a[0] = 1;
2061     }
2062     // This store makes the stores above dead and they will be eliminated.
2063     // That makes this store unnecessary as we're storing the same value already
2064     // present in this location, so it shall also be eliminated.
2065     a[0] = old;
2066     return old;
2067   }
2068 
2069   /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (before)
2070   /// CHECK-DAG:                 ArraySet
2071   /// CHECK-DAG:                 ArraySet
2072   /// CHECK-DAG:                 ArraySet
2073   /// CHECK-DAG:                 ArrayGet
2074   /// CHECK-DAG:                 ArrayGet
2075 
2076   /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after)
2077   /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2078   /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
2079   /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
2080   /// CHECK-DAG:                 ArraySet
2081   /// CHECK-DAG:                 ArraySet
2082   /// CHECK-DAG: <<Phi:i\d+>>    Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
2083   /// CHECK-DAG:                 Return [<<Phi>>]
2084   /// CHECK-DAG: <<Sub:i\d+>>    Sub [<<Const3>>,<<Phi>>]
2085   /// CHECK-DAG:                 Return [<<Sub>>]
2086   /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const1>>","<<Const2>>"])
2087 
2088   /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after)
2089   /// CHECK:                     Phi
2090   /// CHECK-NOT:                 Phi
2091 
2092   /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after)
2093   /// CHECK-NOT:                 ArrayGet
2094 
2095   // Test that we create a single Phi for eliminating two loads in different blocks.
testLocalArrayMerge6(int[] a, boolean x, boolean y)2096   private static int testLocalArrayMerge6(int[] a, boolean x, boolean y) {
2097     a[0] = 0;
2098     if (x) {
2099       a[0] = 1;
2100     } else {
2101       a[0] = 2;
2102     }
2103     // Phi for load elimination is created here.
2104     if (y) {
2105       return a[0];
2106     } else {
2107       return 3 - a[0];
2108     }
2109   }
2110 
2111   /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (before)
2112   /// CHECK-DAG:                 ArraySet
2113   /// CHECK-DAG:                 ArraySet
2114   /// CHECK-DAG:                 ArraySet
2115   /// CHECK-DAG:                 ArrayGet
2116   /// CHECK-DAG:                 ArraySet
2117   /// CHECK-DAG:                 ArrayGet
2118 
2119   /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (after)
2120   /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
2121   /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2122   /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
2123   /// CHECK-DAG:                 ArraySet
2124   /// CHECK-DAG:                 ArraySet
2125   /// CHECK-DAG:                 ArraySet
2126   /// CHECK-DAG:                 ArraySet
2127   /// CHECK-DAG:                 Return [<<Phi2:i\d+>>]
2128   /// CHECK-DAG: <<Phi2>>        Phi [<<Arg3:i\d+>>,<<Arg4:i\d+>>]
2129   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
2130   /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const1>>","<<Const2>>"])
2131   /// CHECK-EVAL: set(["<<Arg3>>","<<Arg4>>"]) == set(["<<Const0>>","<<Phi1>>"])
2132 
2133   /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (after)
2134   /// CHECK-NOT:                 ArrayGet
2135 
2136   // Test Phi creation for load elimination.
testLocalArrayMerge7(int[] a, boolean x, boolean y)2137   private static int testLocalArrayMerge7(int[] a, boolean x, boolean y) {
2138     a[1] = 0;
2139     if (x) {
2140       if (y) {
2141         a[0] = 1;
2142       } else {
2143         a[0] = 2;
2144       }
2145       a[1] = a[0];
2146     }
2147     return a[1];
2148   }
2149 
2150   /// CHECK-START: int Main.testLocalArrayMerge8(boolean) load_store_elimination (before)
2151   /// CHECK-DAG:                 NewArray
2152   /// CHECK-DAG:                 ArraySet
2153   /// CHECK-DAG:                 ArraySet
2154   /// CHECK-DAG:                 ArraySet
2155   /// CHECK-DAG:                 ArraySet
2156   /// CHECK-DAG:                 ArrayGet
2157   /// CHECK-DAG:                 ArrayGet
2158 
2159   /// CHECK-START: int Main.testLocalArrayMerge8(boolean) load_store_elimination (after)
2160   /// CHECK-NOT:                 NewArray
2161   /// CHECK-NOT:                 ArraySet
2162   /// CHECK-NOT:                 ArrayGet
2163 
2164   // Test Merging default value and an identical value.
testLocalArrayMerge8(boolean x)2165   private static int testLocalArrayMerge8(boolean x) {
2166     int[] a = new int[2];
2167     if (x) {
2168       a[0] = 1;  // Make sure the store below is not eliminated immediately as
2169                  // storing the same value already present in the heap location.
2170       a[0] = 0;  // Store the same value as default value to test merging with
2171                  // the default value from else-block.
2172     } else {
2173       // Do the same as then-block for a different heap location to avoid
2174       // relying on block ordering. (Test both `default+0` and `0+default`.)
2175       a[1] = 1;
2176       a[1] = 0;
2177     }
2178     return a[0] + a[1];
2179   }
2180 
2181   /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (before)
2182   /// CHECK-DAG:                 ArrayGet
2183   /// CHECK-DAG:                 ArraySet
2184   /// CHECK-DAG:                 ArraySet
2185   /// CHECK-DAG:                 ArraySet
2186   /// CHECK-DAG:                 ArraySet
2187 
2188   /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (after)
2189   /// CHECK-DAG:                 ArrayGet
2190   /// CHECK-DAG:                 ArraySet
2191   /// CHECK-DAG:                 ArraySet
2192   /// CHECK-DAG:                 ArraySet
2193   /// CHECK-DAG:                 ArraySet
$noinline$testThrowingArraySet(Object[] a, Object o)2194   private static void $noinline$testThrowingArraySet(Object[] a, Object o) {
2195     Object olda0 = a[0];
2196     a[0] = null;
2197     a[1] = olda0;
2198     a[0] = o;
2199     a[1] = null;
2200   }
2201 
2202   /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (before)
2203   /// CHECK-DAG:                 InstanceFieldSet
2204   /// CHECK-DAG:                 InstanceFieldSet
2205   /// CHECK-DAG:                 InstanceFieldGet
2206   /// CHECK-DAG:                 Phi
2207 
2208   /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (after)
2209   /// CHECK-DAG:                 InstanceFieldSet
2210   /// CHECK-DAG:                 InstanceFieldSet
2211   /// CHECK-DAG:                 Phi
2212   /// CHECK-DAG:                 Phi
2213 
2214   /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (after)
2215   /// CHECK-NOT:                 InstanceFieldGet
2216 
2217   // Test Phi creation for load elimination with loop.
testLoop1(TestClass obj, int n)2218   private static int testLoop1(TestClass obj, int n) {
2219     obj.i = 0;
2220     for (int i = 0; i < n; ++i) {
2221       obj.i = i;
2222     }
2223     return obj.i;
2224   }
2225 
2226   /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (before)
2227   /// CHECK-DAG:                 InstanceFieldSet
2228   /// CHECK-DAG:                 InstanceFieldSet
2229   /// CHECK-DAG:                 InstanceFieldGet
2230   /// CHECK-DAG:                 Phi
2231 
2232   /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after)
2233   /// CHECK-DAG:                 InstanceFieldSet
2234   /// CHECK-DAG:                 InstanceFieldSet
2235 
2236   /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after)
2237   /// CHECK-NOT:                 InstanceFieldGet
2238 
2239   /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after)
2240   /// CHECK:                     Phi
2241   /// CHECK-NOT:                 Phi
2242 
2243   // Test that we do not create any Phis for load elimination when
2244   // the heap value was not modified in the loop.
testLoop2(TestClass obj, int n)2245   private static int testLoop2(TestClass obj, int n) {
2246     obj.i = 1;
2247     for (int i = 0; i < n; ++i) {
2248       obj.j = i;
2249     }
2250     return obj.i;
2251   }
2252 
2253   /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (before)
2254   /// CHECK-DAG:                 InstanceFieldSet
2255   /// CHECK-DAG:                 InstanceFieldSet
2256   /// CHECK-DAG:                 InstanceFieldGet
2257 
2258   /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (after)
2259   /// CHECK:                     InstanceFieldSet
2260   /// CHECK-NOT:                 InstanceFieldSet
2261 
2262   /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (after)
2263   /// CHECK-NOT:                 InstanceFieldGet
2264 
2265   // Test elimination of a store in the loop that stores the same value that was already
2266   // stored before the loop and eliminating the load of that value after the loop.
testLoop3(TestClass obj, int n)2267   private static int testLoop3(TestClass obj, int n) {
2268     obj.i = 1;
2269     for (int i = 0; i < n; ++i) {
2270       obj.i = 1;
2271     }
2272     return obj.i;
2273   }
2274 
2275   /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (before)
2276   /// CHECK-DAG:                 InstanceFieldSet
2277   /// CHECK-DAG:                 InstanceFieldSet
2278 
2279   /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (after)
2280   /// CHECK:                     InstanceFieldSet
2281   /// CHECK-NOT:                 InstanceFieldSet
2282 
2283   /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (after)
2284   /// CHECK-NOT:                 InstanceFieldGet
2285 
2286   // Test store elimination in the loop that stores the same value that was already
2287   // stored before the loop, without any loads of that value.
testLoop4(TestClass obj, int n)2288   private static int testLoop4(TestClass obj, int n) {
2289     obj.i = 1;
2290     for (int i = 0; i < n; ++i) {
2291       obj.i = 1;
2292     }
2293     return n;
2294   }
2295 
2296   /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (before)
2297   /// CHECK-DAG:                 InstanceFieldSet
2298   /// CHECK-DAG:                 InstanceFieldSet
2299   /// CHECK-DAG:                 InstanceFieldGet
2300   /// CHECK-DAG:                 InstanceFieldGet
2301   /// CHECK-DAG:                 InstanceFieldSet
2302   /// CHECK-DAG:                 InstanceFieldSet
2303   /// CHECK-DAG:                 InstanceFieldGet
2304 
2305   /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (after)
2306   /// CHECK:                     InstanceFieldSet
2307   /// CHECK:                     InstanceFieldSet
2308   /// CHECK-NOT:                 InstanceFieldSet
2309 
2310   /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (after)
2311   /// CHECK-NOT:                 InstanceFieldGet
2312 
2313   // Test eliminating loads and stores that just shuffle the same value between
2314   // different heap locations.
testLoop5(TestClass obj, int n)2315   private static int testLoop5(TestClass obj, int n) {
2316     // Initialize both `obj.i` and `obj.j` to the same value and then swap these values
2317     // in the loop. We should be able to determine that the values are always the same.
2318     obj.i = n;
2319     obj.j = n;
2320     for (int i = 0; i < n; ++i) {
2321       if ((i & 1) != 0) {
2322         int tmp = obj.i;
2323         obj.i = obj.j;
2324         obj.j = tmp;
2325       }
2326     }
2327     return obj.i;
2328   }
2329 
2330   /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (before)
2331   /// CHECK-DAG:                 InstanceFieldSet
2332   /// CHECK-DAG:                 InstanceFieldSet
2333   /// CHECK-DAG:                 InstanceFieldGet
2334   /// CHECK-DAG:                 InstanceFieldGet
2335   /// CHECK-DAG:                 InstanceFieldSet
2336   /// CHECK-DAG:                 InstanceFieldSet
2337   /// CHECK-DAG:                 InstanceFieldSet
2338   /// CHECK-DAG:                 InstanceFieldGet
2339 
2340   /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (after)
2341   /// CHECK:                     InstanceFieldSet
2342   /// CHECK:                     InstanceFieldSet
2343   /// CHECK-NOT:                 InstanceFieldSet
2344 
2345   /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (after)
2346   /// CHECK-NOT:                 InstanceFieldGet
2347 
2348   // Test eliminating loads and stores that just shuffle the same value between
2349   // different heap locations, or store the same value.
testLoop6(TestClass obj, int n)2350   private static int testLoop6(TestClass obj, int n) {
2351     // Initialize both `obj.i` and `obj.j` to the same value and then swap these values
2352     // in the loop or set `obj.i` to the same value. We should be able to determine
2353     // that the values are always the same.
2354     obj.i = n;
2355     obj.j = n;
2356     for (int i = 0; i < n; ++i) {
2357       if ((i & 1) != 0) {
2358         int tmp = obj.i;
2359         obj.i = obj.j;
2360         obj.j = tmp;
2361       } else {
2362         obj.i = n;
2363       }
2364     }
2365     return obj.i;
2366   }
2367 
2368   /// CHECK-START: int Main.testLoop7(int) load_store_elimination (before)
2369   /// CHECK-DAG:                 NewInstance
2370   /// CHECK-DAG:                 InstanceFieldGet
2371   /// CHECK-DAG:                 InstanceFieldGet
2372   /// CHECK-DAG:                 InstanceFieldSet
2373   /// CHECK-DAG:                 InstanceFieldSet
2374   /// CHECK-DAG:                 InstanceFieldSet
2375   /// CHECK-DAG:                 InstanceFieldGet
2376 
2377   /// CHECK-START: int Main.testLoop7(int) load_store_elimination (after)
2378   /// CHECK-NOT:                 NewInstance
2379   /// CHECK-NOT:                 InstanceFieldSet
2380   /// CHECK-NOT:                 InstanceFieldGet
2381 
2382   // Test eliminating loads and stores that just shuffle the default value between
2383   // different heap locations, or store the same value.
testLoop7(int n)2384   private static int testLoop7(int n) {
2385     // Leave both `obj.i` and `obj.j` initialized to the default value and then
2386     // swap these values in the loop or set some to the identical value 0.
2387     // We should be able to determine that the values are always the same.
2388     TestClass obj = new TestClass();
2389     for (int i = 0; i < n; ++i) {
2390       if ((i & 1) != 0) {
2391         int tmp = obj.i;
2392         obj.i = obj.j;
2393         obj.j = tmp;
2394       } else {
2395         obj.i = 0;
2396       }
2397     }
2398     return obj.i;
2399   }
2400 
2401   /// CHECK-START: int Main.testLoop8(int) load_store_elimination (before)
2402   /// CHECK-DAG:                 NewInstance
2403   /// CHECK-DAG:                 InstanceFieldGet
2404   /// CHECK-DAG:                 InstanceFieldGet
2405   /// CHECK-DAG:                 InstanceFieldSet
2406   /// CHECK-DAG:                 InstanceFieldSet
2407   /// CHECK-DAG:                 InstanceFieldSet
2408   /// CHECK-DAG:                 InstanceFieldSet
2409   /// CHECK-DAG:                 InstanceFieldGet
2410 
2411   /// CHECK-START: int Main.testLoop8(int) load_store_elimination (after)
2412   /// CHECK-NOT:                 NewInstance
2413   /// CHECK-NOT:                 InstanceFieldSet
2414   /// CHECK-NOT:                 InstanceFieldGet
2415 
2416   /// CHECK-START: int Main.testLoop8(int) load_store_elimination (after)
2417   /// CHECK:                     Phi
2418   /// CHECK:                     Phi
2419   /// CHECK-NOT:                 Phi
2420 
2421   // Test eliminating loads and stores that just shuffle the same value between
2422   // different heap locations, or store the same value. The value is loaded
2423   // after conditionally setting a different value after the loop to test that
2424   // this does not cause creation of excessive Phis.
testLoop8(int n)2425   private static int testLoop8(int n) {
2426     // Leave both `obj.i` and `obj.j` initialized to the default value and then
2427     // swap these values in the loop or set some to the identical value 0.
2428     // We should be able to determine that the values are always the same.
2429     TestClass obj = new TestClass();
2430     for (int i = 0; i < n; ++i) {
2431       if ((i & 1) != 0) {
2432         int tmp = obj.i;
2433         obj.i = obj.j;
2434         obj.j = tmp;
2435       } else {
2436         obj.i = 0;
2437       }
2438     }
2439     // Up to this point, `obj.i` is always 0 but the Phi placeholder below
2440     // must not be included in that determination despite using lazy search
2441     // for Phi placeholders triggered by the `obj.i` load below.
2442     if ((n & 1) == 0) {
2443       obj.i = 1;
2444     }
2445     return obj.i;
2446   }
2447 
2448   /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (before)
2449   /// CHECK-DAG:                 NewInstance
2450   /// CHECK-DAG:                 InstanceFieldSet
2451   /// CHECK-DAG:                 InstanceFieldSet
2452   /// CHECK-DAG:                 Phi
2453   /// CHECK-DAG:                 InstanceFieldGet
2454   /// CHECK-DAG:                 InstanceFieldGet
2455   /// CHECK-DAG:                 InstanceFieldSet
2456   /// CHECK-DAG:                 InstanceFieldSet
2457   /// CHECK-DAG:                 InvokeStaticOrDirect
2458   /// CHECK-DAG:                 InstanceFieldGet
2459 
2460   /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2461   /// CHECK-DAG:                 InstanceFieldSet
2462   /// CHECK-DAG:                 Phi
2463   /// CHECK-DAG:                 Phi
2464   /// CHECK-DAG:                 InstanceFieldGet
2465   /// CHECK-DAG:                 InstanceFieldSet
2466   /// CHECK-DAG:                 Phi
2467 
2468   /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2469   /// CHECK:                     InstanceFieldSet
2470   /// CHECK:                     InstanceFieldSet
2471   /// CHECK-NOT:                 InstanceFieldSet
2472 
2473   /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2474   /// CHECK-NOT:                 NewInstance
2475 
2476   /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2477   /// CHECK:                     InstanceFieldGet
2478   /// CHECK-NOT:                 InstanceFieldGet
2479 
2480   /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2481   /// CHECK:                     Phi
2482   /// CHECK:                     Phi
2483   /// CHECK:                     Phi
2484   /// CHECK-NOT:                 Phi
2485 
2486   // Test that unknown value flowing through a loop back-edge prevents
2487   // elimination of a load but that load can be used as an input to a Phi
2488   // created to eliminate another load.
testLoop9(TestClass obj, int n)2489   private static int testLoop9(TestClass obj, int n) {
2490     TestClass obj0 = new TestClass();
2491     // Initialize both `obj.i` and `obj0.i` to the same value and then swap these values
2492     // in the loop or clobber `obj.i`. We should determine that the `obj.i` load in the
2493     // loop must be kept but the `obj0.i` load can be replaced by a Phi chain.
2494     obj0.i = n;
2495     obj.i = n;
2496     for (int i = 0; i < n; ++i) {
2497       if ((i & 1) != 0) {
2498         int tmp = obj0.i;
2499         obj0.i = obj.i;  // Load cannot be eliminated.
2500         obj.i = tmp;
2501       } else {
2502         $noinline$clobberObservables();  // Makes obj.i unknown.
2503       }
2504     }
2505     return obj0.i;
2506   }
2507 
2508   /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (before)
2509   /// CHECK-DAG:                 InstanceFieldSet
2510   /// CHECK-DAG:                 InstanceFieldGet
2511   /// CHECK-DAG:                 InstanceFieldSet
2512   /// CHECK-DAG:                 InstanceFieldGet
2513 
2514   /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (after)
2515   /// CHECK-DAG:                 InstanceFieldSet
2516   /// CHECK-DAG:                 InstanceFieldGet
2517   /// CHECK-DAG:                 InstanceFieldSet
2518 
2519   /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (after)
2520   /// CHECK:                     InstanceFieldGet
2521   /// CHECK-NOT:                 InstanceFieldGet
2522 
2523   // Test load elimination after finding a non-eliminated load depending
2524   // on loop Phi placeholder.
testLoop10(TestClass obj, int n)2525   private static int testLoop10(TestClass obj, int n) {
2526     obj.i = 1;
2527     for (int i = 0; i < n; ++i) {
2528       $noinline$clobberObservables();
2529     }
2530     int i1 = obj.i;
2531     obj.j = 2;  // Use write side effects to stop GVN from eliminating the load below.
2532     int i2 = obj.i;
2533     return i1 + i2;
2534   }
2535 
2536   /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (before)
2537   /// CHECK-DAG:                 InstanceFieldSet
2538   /// CHECK-DAG:                 Phi
2539   /// CHECK-DAG:                 InstanceFieldSet
2540   /// CHECK-DAG:                 InstanceFieldSet
2541   /// CHECK-DAG:                 InstanceFieldGet
2542 
2543   /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after)
2544   /// CHECK-DAG:                 InstanceFieldSet
2545   /// CHECK-DAG:                 Phi
2546   /// CHECK-DAG:                 Phi
2547   /// CHECK-DAG:                 InstanceFieldSet
2548   /// CHECK-DAG:                 InstanceFieldSet
2549   /// CHECK-DAG:                 Phi
2550 
2551   /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after)
2552   /// CHECK:                     Phi
2553   /// CHECK:                     Phi
2554   /// CHECK:                     Phi
2555   /// CHECK-NOT:                 Phi
2556 
2557   /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after)
2558   /// CHECK-NOT:                 InstanceFieldGet
2559 
2560   // Test load elimination creating two Phis that depend on each other.
testLoop11(TestClass obj, int n)2561   private static int testLoop11(TestClass obj, int n) {
2562     obj.i = 1;
2563     for (int i = 0; i < n; ++i) {
2564       if ((i & 1) != 0) {
2565         obj.i = 2;
2566       } else {
2567         obj.i = 3;
2568       }
2569       // There shall be a Phi created here for `obj.i` before the "++i".
2570       // This Phi and the loop Phi that shall be created for `obj.i` depend on each other.
2571     }
2572     return obj.i;
2573   }
2574 
2575   /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (before)
2576   /// CHECK-DAG:                 InstanceFieldSet
2577   /// CHECK-DAG:                 Phi
2578   /// CHECK-DAG:                 InstanceFieldSet
2579   /// CHECK-DAG:                 InstanceFieldSet
2580   /// CHECK-DAG:                 InstanceFieldGet
2581 
2582   /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after)
2583   /// CHECK-DAG:                 InstanceFieldSet
2584   /// CHECK-DAG:                 Phi
2585   /// CHECK-DAG:                 Phi
2586   /// CHECK-DAG:                 InstanceFieldSet
2587   /// CHECK-DAG:                 InstanceFieldSet
2588 
2589   /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after)
2590   /// CHECK:                     Phi
2591   /// CHECK:                     Phi
2592   /// CHECK-NOT:                 Phi
2593 
2594   /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after)
2595   /// CHECK-NOT:                 InstanceFieldGet
2596 
2597   // Test load elimination creating a single Phi with more than 2 inputs.
testLoop12(TestClass obj, int n)2598   private static int testLoop12(TestClass obj, int n) {
2599     obj.i = 1;
2600     for (int i = 0; i < n; ) {
2601       // Do the loop variable increment first, so that there are back-edges
2602       // directly from the "then" and "else" blocks below.
2603       ++i;
2604       if ((i & 1) != 0) {
2605         obj.i = 2;
2606       } else {
2607         obj.i = 3;
2608       }
2609     }
2610     return obj.i;
2611   }
2612 
2613   /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (before)
2614   /// CHECK-DAG:                 NewArray
2615   /// CHECK-DAG:                 Phi
2616   /// CHECK-DAG:                 ArrayGet
2617   /// CHECK-DAG:                 ArraySet
2618   /// CHECK-DAG:                 ArrayGet
2619   /// CHECK-DAG:                 ArraySet
2620   /// CHECK-DAG:                 InstanceFieldGet
2621   /// CHECK-DAG:                 ArraySet
2622   /// CHECK-DAG:                 ArrayGet
2623 
2624   /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after)
2625   /// CHECK-DAG:                 Phi
2626   /// CHECK-DAG:                 Phi
2627   /// CHECK-DAG:                 Phi
2628   /// CHECK-DAG:                 Phi
2629   /// CHECK-DAG:                 InstanceFieldGet
2630 
2631   /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after)
2632   /// CHECK-NOT:                 NewArray
2633   /// CHECK-NOT:                 ArrayGet
2634   /// CHECK-NOT:                 ArraySet
2635 
2636   /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after)
2637   /// CHECK:                     Phi
2638   /// CHECK:                     Phi
2639   /// CHECK:                     Phi
2640   /// CHECK:                     Phi
2641   /// CHECK-NOT:                 Phi
2642 
2643   // Test eliminating array allocation, loads and stores and creating loop Phis.
testLoop13(TestClass obj, int n)2644   private static int testLoop13(TestClass obj, int n) {
2645     int[] a = new int[3];
2646     for (int i = 0; i < n; ++i) {
2647       a[0] = a[1];
2648       a[1] = a[2];
2649       a[2] = obj.i;
2650     }
2651     return a[0];
2652   }
2653 
2654   /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (before)
2655   /// CHECK-DAG:                 NewArray
2656   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.i
2657   /// CHECK-DAG:                 Phi
2658   /// CHECK-DAG:                 ArrayGet
2659   /// CHECK-DAG:                 ArraySet
2660   /// CHECK-DAG:                 ArrayGet
2661   /// CHECK-DAG:                 ArraySet
2662   /// CHECK-DAG:                 InstanceFieldGet field_name:TestClass2.i
2663   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.j
2664   /// CHECK-DAG:                 InstanceFieldGet field_name:TestClass2.i
2665   /// CHECK-DAG:                 ArraySet
2666   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.k
2667   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.j
2668   /// CHECK-DAG:                 InstanceFieldGet field_name:TestClass2.i
2669   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.k
2670   /// CHECK-DAG:                 ArrayGet
2671 
2672   /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
2673   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.i
2674   /// CHECK-DAG:                 Phi
2675   /// CHECK-DAG:                 Phi
2676   /// CHECK-DAG:                 Phi
2677   /// CHECK-DAG:                 Phi
2678   /// CHECK-DAG:                 InstanceFieldGet field_name:TestClass2.i
2679   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.j
2680   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.k
2681   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.j
2682   /// CHECK-DAG:                 InstanceFieldSet field_name:TestClass2.k
2683 
2684   /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
2685   /// CHECK-NOT:                 NewArray
2686 
2687   /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
2688   /// CHECK:                     InstanceFieldGet field_name:TestClass2.i
2689   /// CHECK-NOT:                 InstanceFieldGet field_name:TestClass2.i
2690 
2691   /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
2692   /// CHECK:                     Phi
2693   /// CHECK:                     Phi
2694   /// CHECK:                     Phi
2695   /// CHECK:                     Phi
2696   /// CHECK-NOT:                 Phi
2697 
2698   // Test load elimination in a loop after determing that the first field load
2699   // (depending on loop Phi placeholder) cannot be eliminated.
testLoop14(TestClass2 obj, int n)2700   private static int testLoop14(TestClass2 obj, int n) {
2701     int[] a = new int[3];
2702     obj.i = 1;
2703     for (int i = 0; i < n; ++i) {
2704       a[0] = a[1];
2705       a[1] = a[2];
2706       int i1 = obj.i;
2707       obj.j = 2;  // Use write side effects to stop GVN from eliminating the load below.
2708       int i2 = obj.i;
2709       a[2] = i1;
2710       if ((i & 2) != 0) {
2711         obj.k = i2;
2712       } else {
2713         obj.j = 3;  // Use write side effects to stop GVN from eliminating the load below.
2714         obj.k = obj.i;
2715         $noinline$clobberObservables();  // Make obj.i unknown.
2716       }
2717     }
2718     return a[0];
2719   }
2720 
2721   /// CHECK-START: int Main.testLoop15(int) load_store_elimination (before)
2722   /// CHECK-DAG:                 NewArray
2723   /// CHECK-IF:     hasIsaFeature("sve")
2724   //
2725   ///     CHECK-DAG:                 VecPredWhile
2726   ///     CHECK-DAG:                 VecStore
2727   //
2728   /// CHECK-ELSE:
2729   //
2730   ///     CHECK-DAG:                 ArraySet
2731   //
2732   /// CHECK-FI:
2733   //
2734   /// CHECK-DAG:                 ArrayGet
2735 
2736   /// CHECK-START: int Main.testLoop15(int) load_store_elimination (after)
2737   /// CHECK-DAG:                 NewArray
2738   /// CHECK-IF:     hasIsaFeature("sve")
2739   //
2740   ///     CHECK-DAG:                 VecPredWhile
2741   ///     CHECK-DAG:                 VecStore
2742   //
2743   /// CHECK-ELSE:
2744   //
2745   ///     CHECK-DAG:                 ArraySet
2746   //
2747   /// CHECK-FI:
2748   //
2749   /// CHECK-DAG:                 ArrayGet
2750   // Test that aliasing array store in the loop is not eliminated
2751   // when a loop Phi placeholder is marked for keeping.
testLoop15(int n)2752   private static int testLoop15(int n) {
2753     int[] a = new int[n + 1];
2754     for (int i = 0; i < n; ++i) {
2755       a[i] = 1;  // Cannot be eliminated due to aliasing.
2756     }
2757     return a[0];
2758   }
2759 
2760   /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (before)
2761   /// CHECK-DAG:                     InstanceFieldSet
2762   /// CHECK-DAG:                     Phi
2763   /// CHECK-DAG:                     InstanceFieldSet
2764   /// CHECK-DAG:                     InstanceFieldGet
2765 
2766   /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
2767   /// CHECK-DAG:                     InstanceFieldSet
2768   /// CHECK-DAG:                     Phi
2769   /// CHECK-DAG:                     InstanceFieldSet
2770 
2771   /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
2772   /// CHECK-NOT:                     InstanceFieldGet
2773 
2774   /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
2775   /// CHECK:                         Phi
2776   /// CHECK-NOT:                     Phi
2777 
2778   // Test that we match an existing loop Phi for eliminating a load.
testLoop16(TestClass obj, int n)2779   static int testLoop16(TestClass obj, int n) {
2780     obj.i = 0;
2781     for (int i = 0; i < n; ) {
2782       ++i;
2783       obj.i = i;
2784     }
2785     // The load is replaced by the existing Phi instead of constructing a new one.
2786     return obj.i;
2787   }
2788 
2789   /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (before)
2790   /// CHECK-DAG:                     InstanceFieldSet
2791   /// CHECK-DAG:                     Phi
2792   /// CHECK-DAG:                     InstanceFieldSet
2793   /// CHECK-DAG:                     InstanceFieldSet
2794   /// CHECK-DAG:                     Phi
2795   /// CHECK-DAG:                     InstanceFieldGet
2796 
2797   /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
2798   /// CHECK-DAG:                     InstanceFieldSet
2799   /// CHECK-DAG:                     Phi
2800   /// CHECK-DAG:                     InstanceFieldSet
2801   /// CHECK-DAG:                     InstanceFieldSet
2802   /// CHECK-DAG:                     Phi
2803 
2804   /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
2805   /// CHECK-NOT:                     InstanceFieldGet
2806 
2807   /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
2808   /// CHECK:                         Phi
2809   /// CHECK:                         Phi
2810   /// CHECK-NOT:                     Phi
2811 
2812   // Test that we match an existing non-loop Phi for eliminating a load,
2813   // one input of the Phi being invariant across a preceding loop.
testLoop17(TestClass obj, int n)2814   static int testLoop17(TestClass obj, int n) {
2815     obj.i = 1;
2816     int phi = 1;
2817     for (int i = 0; i < n; ++i) {
2818       obj.j = 2;  // Unrelated.
2819     }
2820     if ((n & 1) != 0) {
2821       obj.i = 2;
2822       phi = 2;
2823     }
2824     // The load is replaced by the existing Phi instead of constructing a new one.
2825     return obj.i + phi;
2826   }
2827 
2828   /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (before)
2829   /// CHECK-DAG:                     NewArray
2830   /// CHECK-DAG:                     Phi
2831   /// CHECK-DAG:                     ArrayGet
2832   /// CHECK-DAG:                     InstanceFieldSet
2833 
2834   /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after)
2835   /// CHECK-DAG:                     NewArray
2836   /// CHECK-DAG:                     Phi
2837   /// CHECK-DAG:                     InstanceFieldSet
2838 
2839   /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after)
2840   /// CHECK-NOT:                     ArrayGet
2841 
2842   // Test eliminating a load of the default value in a loop
2843   // with the array index being defined inside the loop.
testLoop18(TestClass obj, int n)2844   static int testLoop18(TestClass obj, int n) {
2845     // The NewArray is kept as it may throw for negative n.
2846     // TODO: Eliminate constructor fence even though the NewArray is kept.
2847     int[] a0 = new int[n];
2848     for (int i = 0; i < n; ++i) {
2849       obj.i = a0[i];
2850     }
2851     return n;
2852   }
2853 
2854   /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (before)
2855   /// CHECK-DAG:                     NewArray
2856   /// CHECK-DAG:                     Phi
2857   /// CHECK-DAG:                     ArrayGet
2858   /// CHECK-DAG:                     InstanceFieldSet
2859   /// CHECK-DAG:                     ArraySet
2860 
2861   /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after)
2862   /// CHECK-DAG:                     NewArray
2863   /// CHECK-DAG:                     Phi
2864   /// CHECK-DAG:                     InstanceFieldSet
2865 
2866   /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after)
2867   /// CHECK-NOT:                     ArrayGet
2868   /// CHECK-NOT:                     ArraySet
2869 
2870   // Test eliminating a load of the default value and store of an identical value
2871   // in a loop with the array index being defined inside the loop.
testLoop19(TestClass obj, int n)2872   static int testLoop19(TestClass obj, int n) {
2873     // The NewArray is kept as it may throw for negative n.
2874     // TODO: Eliminate constructor fence even though the NewArray is kept.
2875     int[] a0 = new int[n];
2876     for (int i = 0; i < n; ++i) {
2877       obj.i = a0[i];
2878       a0[i] = 0;  // Store the same value as default.
2879     }
2880     return n;
2881   }
2882 
2883   /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (before)
2884   /// CHECK-DAG:                     NewArray
2885   /// CHECK-DAG:                     Phi
2886   /// CHECK-DAG:                     ArrayGet
2887   /// CHECK-DAG:                     InstanceFieldSet
2888   /// CHECK-DAG:                     ArraySet
2889 
2890   /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after)
2891   /// CHECK-DAG:                     NewArray
2892   /// CHECK-DAG:                     Phi
2893   /// CHECK-DAG:                     InstanceFieldSet
2894 
2895   /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after)
2896   /// CHECK-NOT:                     ArrayGet
2897   /// CHECK-NOT:                     ArraySet
2898 
2899   // Test eliminating a load of the default value and a conditional store of an
2900   // identical value in a loop with the array index being defined inside the loop.
testLoop20(TestClass obj, int n)2901   static int testLoop20(TestClass obj, int n) {
2902     // The NewArray is kept as it may throw for negative n.
2903     // TODO: Eliminate constructor fence even though the NewArray is kept.
2904     int[] a0 = new int[n];
2905     for (int i = 0; i < n; ++i) {
2906       obj.i = a0[i];
2907       if ((i & 1) != 0) {
2908         a0[i] = 0;  // Store the same value as default.
2909       }
2910     }
2911     return n;
2912   }
2913 
2914   /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before)
2915   /// CHECK-DAG:                     InstanceFieldSet
2916   /// CHECK-DAG:                     InstanceFieldGet
2917   /// CHECK-DAG:                     InstanceFieldSet
2918   /// CHECK-DAG:                     InstanceFieldGet
2919   /// CHECK-DAG:                     InstanceFieldSet
2920   /// CHECK-DAG:                     InstanceFieldGet
2921   /// CHECK-DAG:                     InstanceFieldSet
2922 
2923   /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before)
2924   /// CHECK-NOT:                     Phi
2925 
2926   /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
2927   /// CHECK-NOT:                     InstanceFieldGet
2928 
2929   /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
2930   /// CHECK:                         InstanceFieldSet
2931   /// CHECK:                         InstanceFieldSet
2932   /// CHECK:                         InstanceFieldSet
2933   /// CHECK-NOT:                     InstanceFieldSet
2934 
2935   /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
2936   /// CHECK:                         Phi
2937   /// CHECK-NOT:                     Phi
2938 
2939   // Test load elimination when an instance field is used as the loop variable.
testLoop21(TestClass obj, int n)2940   static int testLoop21(TestClass obj, int n) {
2941     for (obj.i = 0; obj.i < n; ++obj.i) {
2942       obj.j = 0;  // Use write side effects to stop GVN from eliminating the load below.
2943       obj.j = obj.i;
2944     }
2945     return n;
2946   }
2947 
2948   /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before)
2949   /// CHECK-DAG:                     InstanceFieldSet
2950   /// CHECK-DAG:                     InstanceFieldGet
2951   /// CHECK-DAG:                     InstanceFieldSet
2952   /// CHECK-DAG:                     InstanceFieldGet
2953   /// CHECK-DAG:                     InstanceFieldSet
2954   /// CHECK-DAG:                     InstanceFieldGet
2955   /// CHECK-DAG:                     InstanceFieldSet
2956   /// CHECK-DAG:                     InstanceFieldSet
2957 
2958   /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before)
2959   /// CHECK-NOT:                     Phi
2960 
2961   /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
2962   /// CHECK-NOT:                     InstanceFieldGet
2963 
2964   /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
2965   /// CHECK:                         InstanceFieldSet
2966   /// CHECK:                         InstanceFieldSet
2967   /// CHECK-NOT:                     InstanceFieldSet
2968 
2969   /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
2970   /// CHECK:                         Phi
2971   /// CHECK-NOT:                     Phi
2972 
2973   // Test load and store elimination when an instance field is used as the loop
2974   // variable and then overwritten after the loop.
testLoop22(TestClass obj, int n)2975   static int testLoop22(TestClass obj, int n) {
2976     for (obj.i = 0; obj.i < n; ++obj.i) {
2977       obj.j = 0;  // Use write side effects to stop GVN from eliminating the load below.
2978       obj.j = obj.i;
2979     }
2980     obj.i = 0;
2981     return n;
2982   }
2983 
2984   /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (before)
2985   /// CHECK-DAG:                     InstanceFieldSet
2986   /// CHECK-DAG:                     Phi
2987   /// CHECK-DAG:                     Phi
2988   /// CHECK-DAG:                     InstanceFieldSet
2989   /// CHECK-DAG:                     InstanceFieldSet
2990   /// CHECK-DAG:                     Phi
2991   /// CHECK-DAG:                     InstanceFieldSet
2992 
2993   /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after)
2994   /// CHECK-DAG:                     Phi
2995   /// CHECK-DAG:                     Phi
2996   /// CHECK-DAG:                     Phi
2997   /// CHECK-DAG:                     InstanceFieldSet
2998 
2999   /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after)
3000   /// CHECK:                         InstanceFieldSet
3001   /// CHECK-NOT:                     InstanceFieldSet
3002 
3003   // Test elimination of non-observable stores.
testLoop23(TestClass obj, int n)3004   static int testLoop23(TestClass obj, int n) {
3005     obj.i = -1;
3006     int phi = -1;
3007     for (int i = 0; i < n; ++i) {
3008       obj.i = i;
3009       phi = i;
3010     }
3011     if ((n & 1) != 0) {
3012       obj.i = 2;
3013       phi = 2;
3014     }
3015     obj.i = phi;  // This store shall be kept, the stores above shall be eliminated.
3016     return phi;
3017   }
3018 
3019   /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (before)
3020   /// CHECK-DAG:                     InstanceFieldSet
3021   /// CHECK-DAG:                     Phi
3022   /// CHECK-DAG:                     Phi
3023   /// CHECK-DAG:                     InstanceFieldSet
3024   /// CHECK-DAG:                     InstanceFieldSet
3025   /// CHECK-DAG:                     Phi
3026   /// CHECK-DAG:                     InstanceFieldSet
3027 
3028   /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after)
3029   /// CHECK-DAG:                     InstanceFieldSet
3030   /// CHECK-DAG:                     Phi
3031   /// CHECK-DAG:                     Phi
3032   /// CHECK-DAG:                     InstanceFieldSet
3033   /// CHECK-DAG:                     InstanceFieldSet
3034   /// CHECK-DAG:                     Phi
3035 
3036   /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after)
3037   /// CHECK:                         InstanceFieldSet
3038   /// CHECK:                         InstanceFieldSet
3039   /// CHECK:                         InstanceFieldSet
3040   /// CHECK-NOT:                     InstanceFieldSet
3041 
3042   // Test matching Phis for store elimination.
testLoop24(TestClass obj, int n)3043   static int testLoop24(TestClass obj, int n) {
3044     obj.i = -1;
3045     int phi = -1;
3046     for (int i = 0; i < n; ++i) {
3047       obj.i = i;
3048       phi = i;
3049     }
3050     if ((n & 1) != 0) {
3051       obj.i = 2;
3052       phi = 2;
3053     }
3054     if (n == 3) {
3055       return -2;  // Make the above stores observable.
3056     }
3057     // As the stores above are observable and kept, we match the merged
3058     // heap value with existing Phis and determine that we're storing
3059     // the same value that's already there, so we eliminate this store.
3060     obj.i = phi;
3061     return phi;
3062   }
3063 
3064   /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (before)
3065   /// CHECK-DAG:                     InstanceFieldSet
3066   /// CHECK-DAG:                     Phi
3067   /// CHECK-DAG:                     Phi
3068   /// CHECK-DAG:                     InstanceFieldSet
3069   /// CHECK-DAG:                     Phi
3070   /// CHECK-DAG:                     InstanceFieldGet
3071   /// CHECK-DAG:                     InstanceFieldSet
3072 
3073   /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after)
3074   /// CHECK-DAG:                     InstanceFieldSet
3075   /// CHECK-DAG:                     Phi
3076   /// CHECK-DAG:                     Phi
3077   /// CHECK-DAG:                     Phi
3078   /// CHECK-DAG:                     InstanceFieldSet
3079   /// CHECK-DAG:                     Phi
3080   /// CHECK-DAG:                     Phi
3081   /// CHECK-DAG:                     InstanceFieldSet
3082 
3083   /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after)
3084   /// CHECK-NOT:                     InstanceFieldGet
3085 
3086   // Test that we do not match multiple dependent Phis for load and store elimination.
testLoop25(TestClass obj, int n)3087   static int testLoop25(TestClass obj, int n) {
3088     obj.i = 1;
3089     int phi = 1;
3090     for (int i = 0; i < n; ++i) {
3091       if ((i & 1) != 0) {
3092         obj.i = 2;
3093         phi = 2;
3094       }
3095       // There is a Phi here for the variable `phi` before the "++i".
3096       // This Phi and the loop Phi for `phi` depend on each other.
3097     }
3098     if (n == 3) {
3099       return -1;  // Make above stores observable.
3100     }
3101     // We're not matching multiple Phi placeholders to existing Phis. Therefore the load
3102     // below requires 2 extra Phis to be created and the store below shall not be eliminated
3103     // even though it stores the same value that's already present in the heap location.
3104     int tmp = obj.i;
3105     obj.i = phi;
3106     return tmp + phi;
3107   }
3108 
3109   /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (before)
3110   /// CHECK-DAG:                     NewInstance
3111   /// CHECK-DAG:                     InstanceFieldSet
3112   /// CHECK-DAG:                     Phi
3113   /// CHECK-DAG:                     NewInstance
3114   /// CHECK-DAG:                     InstanceFieldSet
3115   /// CHECK-DAG:                     InstanceFieldGet
3116   /// CHECK-DAG:                     InstanceFieldGet
3117 
3118   /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after)
3119   /// CHECK-DAG:                     NewInstance
3120   /// CHECK-DAG:                     InstanceFieldSet
3121   /// CHECK-DAG:                     Phi
3122   /// CHECK-DAG:                     Phi
3123   /// CHECK-DAG:                     NewInstance
3124   /// CHECK-DAG:                     InstanceFieldSet
3125   /// CHECK-DAG:                     InstanceFieldGet
3126 
3127   /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after)
3128   /// CHECK:                         InstanceFieldGet
3129   /// CHECK-NOT:                     InstanceFieldGet
3130 
3131   // Test load elimination creating a reference Phi.
testLoop26(TestClass obj, int n)3132   static int testLoop26(TestClass obj, int n) {
3133     obj.next = new TestClass(1, 2);
3134     for (int i = 0; i < n; ++i) {
3135       obj.next = new SubTestClass();
3136     }
3137     return obj.next.i;
3138   }
3139 
3140   /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (before)
3141   /// CHECK-DAG:                     NewInstance
3142   /// CHECK-DAG:                     InstanceFieldSet
3143   /// CHECK-DAG:                     Phi
3144   /// CHECK-DAG:                     NewInstance
3145   /// CHECK-DAG:                     InstanceFieldSet
3146   /// CHECK-DAG:                     InstanceFieldGet
3147   /// CHECK-DAG:                     InstanceFieldGet
3148 
3149   /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after)
3150   /// CHECK-DAG:                     NewInstance
3151   /// CHECK-DAG:                     InstanceFieldSet
3152   /// CHECK-DAG:                     Phi
3153   /// CHECK-DAG:                     Phi
3154   /// CHECK-DAG:                     NewInstance
3155   /// CHECK-DAG:                     InstanceFieldSet
3156   /// CHECK-DAG:                     Phi
3157   /// CHECK-DAG:                     InstanceFieldGet
3158 
3159   /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after)
3160   /// CHECK:                         InstanceFieldGet
3161   /// CHECK-NOT:                     InstanceFieldGet
3162 
3163   // Test load elimination creating two reference Phis that depend on each other.
testLoop27(TestClass obj, int n)3164   static int testLoop27(TestClass obj, int n) {
3165     obj.next = new TestClass(1, 2);
3166     for (int i = 0; i < n; ++i) {
3167       if ((i & 1) != 0) {
3168         obj.next = new SubTestClass();
3169       }
3170       // There shall be a Phi created here for `obj.next` before the "++i".
3171       // This Phi and the loop Phi that shall be created for `obj.next` depend on each other.
3172     }
3173     return obj.next.i;
3174   }
3175 
3176   /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (before)
3177   /// CHECK-DAG:                 InstanceFieldSet
3178   /// CHECK-DAG:                 NewArray
3179   /// CHECK-DAG:                 Phi
3180   /// CHECK-DAG:                 ArrayGet
3181   /// CHECK-DAG:                 ArraySet
3182   /// CHECK-DAG:                 ArrayGet
3183   /// CHECK-DAG:                 ArraySet
3184   /// CHECK-DAG:                 InstanceFieldGet
3185   /// CHECK-DAG:                 ArraySet
3186   /// CHECK-DAG:                 ArrayGet
3187 
3188   /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
3189   /// CHECK-DAG:                 InstanceFieldSet
3190   /// CHECK-DAG:                 Phi
3191   /// CHECK-DAG:                 Phi
3192   /// CHECK-DAG:                 Phi
3193   /// CHECK-DAG:                 Phi
3194   /// CHECK-DAG:                 InstanceFieldGet
3195 
3196   /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
3197   /// CHECK-NOT:                 NewArray
3198   /// CHECK-NOT:                 ArrayGet
3199   /// CHECK-NOT:                 ArraySet
3200 
3201   /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
3202   /// CHECK:                     Phi
3203   /// CHECK:                     Phi
3204   /// CHECK:                     Phi
3205   /// CHECK:                     Phi
3206   /// CHECK-NOT:                 Phi
3207 
3208   // Test eliminating array allocation, loads and stores and creating loop Phis
3209   // after determining that a field load depending on loop Phi placeholder cannot
3210   // be eliminated.
testLoop28(TestClass obj, int n)3211   private static int testLoop28(TestClass obj, int n) {
3212     obj.i = 1;
3213     int[] a = new int[3];
3214     for (int i = 0; i < n; ++i) {
3215       a[0] = a[1];
3216       a[1] = a[2];
3217       a[2] = obj.i;
3218       $noinline$clobberObservables();
3219     }
3220     return a[0];
3221   }
3222 
3223   /// CHECK-START: int Main.testLoop29(int) load_store_elimination (before)
3224   /// CHECK-DAG:                 NewArray
3225   /// CHECK-DAG:                 Phi
3226   /// CHECK-DAG:                 Phi
3227   /// CHECK-DAG:                 ArrayGet
3228   /// CHECK-DAG:                 ArraySet
3229 
3230   /// CHECK-START: int Main.testLoop29(int) load_store_elimination (after)
3231   /// CHECK-DAG:                 NewArray
3232   /// CHECK-DAG:                 Phi
3233   /// CHECK-DAG:                 Phi
3234   /// CHECK-DAG:                 ArrayGet
3235   /// CHECK-DAG:                 ArraySet
3236 
3237   // Test that ArraySet with non-default value prevents matching ArrayGet for
3238   // the same array to default value even when the ArraySet is using an index
3239   // offset by one, making LSA declare that the two heap locations do not alias.
testLoop29(int n)3240   private static int testLoop29(int n) {
3241     int[] a = new int[4];
3242     int sum = 0;
3243     for (int i = 0; i < n; ) {
3244       int value = a[i] + 1;
3245       sum += value;
3246       ++i;
3247       a[i] = value;
3248     }
3249     return sum;
3250   }
3251 
3252   /// CHECK-START: int Main.testLoop30(int) load_store_elimination (before)
3253   /// CHECK-DAG:                 NewArray
3254   /// CHECK-DAG:                 Phi
3255   /// CHECK-DAG:                 Phi
3256   /// CHECK-DAG:                 ArrayGet
3257   /// CHECK-DAG:                 ArraySet
3258 
3259   /// CHECK-START: int Main.testLoop30(int) load_store_elimination (after)
3260   /// CHECK-NOT:                 ArrayGet
3261   /// CHECK-NOT:                 ArraySet
3262 
3263   // Test that ArraySet with default value does not prevent matching ArrayGet
3264   // for the same array to the default value.
testLoop30(int n)3265   private static int testLoop30(int n) {
3266     int[] a = new int[4];  // NewArray is kept due to environment use by Deoptimize.
3267     int sum = 0;
3268     for (int i = 0; i < n; ) {
3269       int value = a[i] + 1;
3270       sum += value;
3271       ++i;
3272       a[i] = 0;
3273     }
3274     return sum;
3275   }
3276 
3277   /// CHECK-START: int Main.testLoop31(int) load_store_elimination (before)
3278   /// CHECK-DAG:                 NewArray
3279   /// CHECK-DAG:                 Phi
3280   /// CHECK-DAG:                 Phi
3281   /// CHECK-DAG:                 ArrayGet
3282   /// CHECK-DAG:                 ArraySet
3283 
3284   /// CHECK-START: int Main.testLoop31(int) load_store_elimination (after)
3285   /// CHECK-NOT:                 ArrayGet
3286   /// CHECK-NOT:                 ArraySet
3287 
3288   // Test that ArraySet with default value read from the array does not
3289   // prevent matching ArrayGet for the same array to the default value.
testLoop31(int n)3290   private static int testLoop31(int n) {
3291     int[] a = new int[4];  // NewArray is kept due to environment use by Deoptimize.
3292     int sum = 0;
3293     for (int i = 0; i < n; ) {
3294       int value = a[i];
3295       sum += value;
3296       ++i;
3297       a[i] = value;
3298     }
3299     return sum;
3300   }
3301 
3302   /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (before)
3303   /// CHECK-DAG:                     InstanceFieldSet
3304   /// CHECK-DAG:                     Phi
3305   /// CHECK-DAG:                     Phi
3306   /// CHECK-DAG:                     InstanceFieldSet
3307   /// CHECK-DAG:                     InstanceFieldSet
3308   /// CHECK-DAG:                     Phi
3309   /// CHECK-DAG:                     InstanceFieldSet
3310 
3311   /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after)
3312   /// CHECK-DAG:                     InstanceFieldSet
3313   /// CHECK-DAG:                     Phi
3314   /// CHECK-DAG:                     Phi
3315   /// CHECK-DAG:                     InstanceFieldSet
3316   /// CHECK-DAG:                     InstanceFieldSet
3317   /// CHECK-DAG:                     Phi
3318 
3319   /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after)
3320   /// CHECK:                         InstanceFieldSet
3321   /// CHECK:                         InstanceFieldSet
3322   /// CHECK:                         InstanceFieldSet
3323   /// CHECK-NOT:                     InstanceFieldSet
3324 
3325   // Test matching Phis for store elimination.
testLoop32(TestClass obj, int n)3326   static int testLoop32(TestClass obj, int n) {
3327     obj.i = -1;
3328     int phi = -1;
3329     for (int i = 0; i < n; ) {
3330       ++i;
3331       if ((i & 1) != 0) {
3332         obj.i = i;
3333         phi = i;
3334       }
3335     }
3336     if ((n & 1) != 0) {
3337       obj.i = 2;
3338       phi = 2;
3339     }
3340     if (n == 3) {
3341       return -2;  // Make the above stores observable.
3342     }
3343     // As the stores above are observable and kept, we match the merged
3344     // heap value with existing Phis and determine that we're storing
3345     // the same value that's already there, so we eliminate this store.
3346     obj.i = phi;
3347     return phi;
3348   }
3349 
3350   // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (before)
3351   // CHECK-DAG:                     InstanceFieldSet
3352   // CHECK-DAG:                     NewArray
3353   // CHECK-DAG:                     Phi
3354   // CHECK-DAG:                     ArrayGet
3355   // CHECK-DAG:                     InstanceFieldSet
3356   // CHECK-DAG:                     Phi
3357   // CHECK-DAG:                     ArrayGet
3358   // CHECK-DAG:                     InstanceFieldGet
3359   // CHECK-DAG:                     InstanceFieldSet
3360   // CHECK-DAG:                     InstanceFieldGet
3361 
3362   // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after)
3363   // CHECK-DAG:                     InstanceFieldSet
3364   // CHECK-DAG:                     Phi
3365   // CHECK-DAG:                     InstanceFieldSet
3366   // CHECK-DAG:                     Phi
3367   // CHECK-DAG:                     InstanceFieldGet
3368   // CHECK-DAG:                     InstanceFieldSet
3369   // CHECK-DAG:                     InstanceFieldGet
3370 
3371   // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after)
3372   // CHECK-NOT:                     ArrayGet
3373 
3374   // Test that when processing Phi placeholder with unknown input, we allow materialized
3375   // default value in pre-header for array location with index defined in the loop.
testLoop33(TestClass obj, int n)3376   static int testLoop33(TestClass obj, int n) {
3377     obj.i = 0;
3378     int[] a0 = new int[n];
3379     for (int i = 0; i < n; ++i) {
3380       obj.i = a0[i];
3381       $noinline$clobberObservables();  // Make `obj.i` unknown.
3382     }
3383     for (int i = 0; i < n; ++i) {
3384       int zero = a0[i];
3385       int unknown = obj.i;
3386       obj.j += zero + unknown;
3387     }
3388     return obj.j;
3389   }
3390 
3391   /// CHECK-START: int Main.testLoop34(int) load_store_elimination (before)
3392   /// CHECK-DAG:                 NewArray
3393   /// CHECK-DAG:                 Phi
3394   /// CHECK-DAG:                 Phi
3395   /// CHECK-DAG:                 ArrayGet
3396   /// CHECK-DAG:                 ArraySet
3397 
3398   /// CHECK-START: int Main.testLoop34(int) load_store_elimination (after)
3399   /// CHECK-DAG:                 NewArray
3400   /// CHECK-DAG:                 Phi
3401   /// CHECK-DAG:                 Phi
3402   /// CHECK-DAG:                 ArrayGet
3403   /// CHECK-DAG:                 ArraySet
3404 
3405   // Test that ArraySet with non-default value prevents matching ArrayGet for
3406   // the same array to default value even when the ArraySet is using an index
3407   // offset by one, making LSA declare that the two heap locations do not alias.
3408   // Also test that the ArraySet is not eliminated.
testLoop34(int n)3409   private static int testLoop34(int n) {
3410     int[] a = new int[n + 1];
3411     int sum = 0;
3412     for (int i = 0; i < n; ) {
3413       int value = a[i] + 1;
3414       sum += value;
3415       ++i;
3416       a[i] = value;
3417     }
3418     return sum;
3419   }
3420 
3421   /// CHECK-START: int Main.testLoop35(int) load_store_elimination (before)
3422   /// CHECK-DAG:                 NewArray
3423   /// CHECK-DAG:                 Phi
3424   /// CHECK-DAG:                 Phi
3425   /// CHECK-DAG:                 ArrayGet
3426   /// CHECK-DAG:                 ArraySet
3427   /// CHECK-DAG:                 ArraySet
3428 
3429   /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after)
3430   /// CHECK-DAG:                 NewArray
3431   /// CHECK-DAG:                 Phi
3432   /// CHECK-DAG:                 Phi
3433   /// CHECK-DAG:                 ArrayGet
3434   /// CHECK-DAG:                 ArraySet
3435 
3436   /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after)
3437   /// CHECK:                     ArraySet
3438   /// CHECK-NOT:                 ArraySet
3439 
3440   // Test that ArraySet with non-default value prevents matching ArrayGet for
3441   // the same array to default value even when the ArraySet is using an index
3442   // offset by one, making LSA declare that the two heap locations do not alias.
3443   // Also test that the ArraySet is not eliminated and that a store after the
3444   // loop is eliminated.
testLoop35(int n)3445   private static int testLoop35(int n) {
3446     int[] a = new int[n + 1];
3447     int sum = 0;
3448     for (int i = 0; i < n; ) {
3449       int value = a[i] + 1;
3450       sum += value;
3451       ++i;
3452       a[i] = value;
3453     }
3454     a[0] = 1;
3455     return sum;
3456   }
3457 
3458   /// CHECK-START: int Main.testLoop36(int) load_store_elimination (before)
3459   /// CHECK-DAG:                 ArraySet
3460   /// CHECK-DAG:                 Deoptimize
3461   /// CHECK-DAG:                 ArrayGet
3462   /// CHECK-DAG:                 ArrayGet
3463   /// CHECK-DAG:                 ArrayGet
3464   /// CHECK-DAG:                 ArrayGet
3465 
3466   /// CHECK-START: int Main.testLoop36(int) load_store_elimination (before)
3467   /// CHECK-NOT:                 BoundsCheck
3468 
3469   /// CHECK-START: int Main.testLoop36(int) load_store_elimination (after)
3470   /// CHECK-DAG:                 ArraySet
3471   /// CHECK-DAG:                 Deoptimize
3472   /// CHECK-DAG:                 ArrayGet
3473   /// CHECK-DAG:                 ArrayGet
3474   /// CHECK-DAG:                 ArrayGet
3475   /// CHECK-DAG:                 ArrayGet
3476 
3477   // Regression test for b/187487955.
3478   // We previously failed a DCHECK() during the search for kept stores when
3479   // we encountered two array locations for the same array and considered
3480   // non-aliasing by LSA when only one of the array locations had index
3481   // defined inside the loop. Note that this situation requires that BCE
3482   // eliminates BoundsCheck instructions, otherwise LSA considers those
3483   // locations aliasing.
testLoop36(int n)3484   private static int testLoop36(int n) {
3485     int[] a = new int[n];
3486     int zero = 0;
3487     int i = 0;
3488     for (; i < n; ++i) {
3489       a[i] = i;
3490       // Extra instructions to avoid loop unrolling.
3491       zero = (((zero ^ 1) + 2) ^ 1) - 2;
3492       zero = (((zero ^ 4) + 8) ^ 4) - 8;
3493     }
3494     // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`.
3495     // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are
3496     // the Phi plus/minus a constant, something that LSA considers non-aliasing
3497     // with the Phi (LSA does not take different loop iterations into account)
3498     // but LSE must consider aliasing across dfferent loop iterations.
3499     return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero;
3500   }
3501 
3502   /// CHECK-START: int Main.testLoop37(int) load_store_elimination (before)
3503   /// CHECK-DAG:                 ArraySet
3504   /// CHECK-DAG:                 Deoptimize
3505   /// CHECK-DAG:                 ArrayGet
3506   /// CHECK-DAG:                 ArrayGet
3507   /// CHECK-DAG:                 ArrayGet
3508   /// CHECK-DAG:                 ArrayGet
3509 
3510   /// CHECK-START: int Main.testLoop37(int) load_store_elimination (before)
3511   /// CHECK-NOT:                 BoundsCheck
3512 
3513   /// CHECK-START: int Main.testLoop37(int) load_store_elimination (after)
3514   /// CHECK-DAG:                 ArraySet
3515   /// CHECK-DAG:                 Deoptimize
3516   /// CHECK-DAG:                 ArrayGet
3517   /// CHECK-DAG:                 ArrayGet
3518   /// CHECK-DAG:                 ArrayGet
3519   /// CHECK-DAG:                 ArrayGet
3520 
3521   // Similar to testLoop36 but the writes are done via a different reference to the same array.
3522   // We previously used a reference comparison for back-edge aliasing analysis but this test
3523   // has different references and therefore needs `HeapLocationCollector::CanReferencesAlias()`.
testLoop37(int n)3524   private static int testLoop37(int n) {
3525     int[] a = new int[n];
3526     int[] b = $noinline$returnArg(a);
3527     int zero = 0;
3528     int i = 0;
3529     for (; i < n; ++i) {
3530       b[i] = i;
3531       // Extra instructions to avoid loop unrolling.
3532       zero = (((zero ^ 1) + 2) ^ 1) - 2;
3533       zero = (((zero ^ 4) + 8) ^ 4) - 8;
3534     }
3535     // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`.
3536     // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are
3537     // the Phi plus/minus a constant, something that LSA considers non-aliasing
3538     // with the Phi (LSA does not take different loop iterations into account)
3539     // but LSE must consider aliasing across dfferent loop iterations.
3540     return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero;
3541   }
3542 
$noinline$returnArg(int[] a)3543   private static int[] $noinline$returnArg(int[] a) {
3544     return a;
3545   }
3546 
3547   /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (before)
3548   /// CHECK-DAG:                 ArraySet
3549   /// CHECK-DAG:                 Deoptimize
3550   /// CHECK-DAG:                 ArrayGet
3551   /// CHECK-DAG:                 ArrayGet
3552   /// CHECK-DAG:                 ArrayGet
3553   /// CHECK-DAG:                 ArrayGet
3554 
3555   /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (before)
3556   /// CHECK-NOT:                 BoundsCheck
3557 
3558   /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (after)
3559   /// CHECK-DAG:                 ArraySet
3560   /// CHECK-DAG:                 Deoptimize
3561 
3562   /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (after)
3563   /// CHECK-NOT:                 ArrayGet
3564 
3565   // Similar to testLoop37 but writing to a different array that exists before allocating `a`,
3566   // so that `HeapLocationCollector::CanReferencesAlias()` returns false and all the ArrayGet
3567   // instructions are actually eliminated.
testLoop38(int n, int[] b)3568   private static int testLoop38(int n, int[] b) {
3569     int[] a = new int[n];
3570     int zero = 0;
3571     int i = 0;
3572     for (; i < n; ++i) {
3573       b[i] = i;
3574       // Extra instructions to avoid loop unrolling.
3575       zero = (((zero ^ 1) + 2) ^ 1) - 2;
3576       zero = (((zero ^ 4) + 8) ^ 4) - 8;
3577     }
3578     // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`.
3579     // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are
3580     // the Phi plus/minus a constant, something that LSA considers non-aliasing
3581     // with the Phi (LSA does not take different loop iterations into account)
3582     // but LSE must consider aliasing across dfferent loop iterations.
3583     return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero;
3584   }
3585 
3586   /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (before)
3587   /// CHECK-DAG:                 InstanceFieldSet
3588   /// CHECK-DAG:                 InstanceFieldGet
3589 
3590   /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (after)
3591   /// CHECK-DAG:                 InstanceFieldSet
3592   /// CHECK-DAG:                 InstanceFieldGet
3593 
3594   // Test heap value clobbering in nested loop.
testNestedLoop1(TestClass obj, int n)3595   private static int testNestedLoop1(TestClass obj, int n) {
3596     obj.i = 1;
3597     for (int i = 0; i < n; ++i) {
3598       for (int j = i + 1; j < n; ++j) {
3599         $noinline$clobberObservables();
3600       }
3601     }
3602     return obj.i;
3603   }
3604 
3605   /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (before)
3606   /// CHECK-DAG:                 InstanceFieldSet
3607   /// CHECK-DAG:                 InstanceFieldSet
3608   /// CHECK-DAG:                 Phi
3609   /// CHECK-DAG:                 InstanceFieldGet
3610   /// CHECK-DAG:                 Phi
3611   /// CHECK-DAG:                 InstanceFieldSet
3612   /// CHECK-DAG:                 InstanceFieldGet
3613 
3614   /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
3615   /// CHECK-DAG:                 InstanceFieldSet
3616   /// CHECK-DAG:                 InstanceFieldSet
3617   /// CHECK-DAG:                 Phi
3618   /// CHECK-DAG:                 Phi
3619   /// CHECK-DAG:                 InstanceFieldGet
3620   /// CHECK-DAG:                 Phi
3621   /// CHECK-DAG:                 InstanceFieldSet
3622 
3623   /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
3624   /// CHECK:                     InstanceFieldGet
3625   /// CHECK-NOT:                 InstanceFieldGet
3626 
3627   /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
3628   /// CHECK:                     Phi
3629   /// CHECK:                     Phi
3630   /// CHECK:                     Phi
3631   /// CHECK-NOT:                 Phi
3632 
3633   // Test heap value clobbering in the nested loop and load elimination for a heap
3634   // location then set to known value before the end of the outer loop.
testNestedLoop2(TestClass obj, int n)3635   private static int testNestedLoop2(TestClass obj, int n) {
3636     obj.i = 1;
3637     obj.j = 2;
3638     for (int i = 0; i < n; ++i) {
3639       int tmp = obj.j;
3640       for (int j = i + 1; j < n; ++j) {
3641         $noinline$clobberObservables();
3642       }
3643       obj.i = tmp;
3644     }
3645     return obj.i;
3646   }
3647 
3648   /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (before)
3649   /// CHECK-DAG:                 InstanceFieldSet
3650   /// CHECK-DAG:                 Phi
3651   /// CHECK-DAG:                 InstanceFieldSet
3652   /// CHECK-DAG:                 Phi
3653   /// CHECK-DAG:                 InstanceFieldGet
3654   /// CHECK-DAG:                 InstanceFieldSet
3655   /// CHECK-DAG:                 InstanceFieldGet
3656 
3657   /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
3658   /// CHECK-DAG:                 InstanceFieldSet
3659   /// CHECK-DAG:                 Phi
3660   /// CHECK-DAG:                 Phi
3661   /// CHECK-DAG:                 InstanceFieldSet
3662   /// CHECK-DAG:                 Phi
3663   /// CHECK-DAG:                 InstanceFieldGet
3664   /// CHECK-DAG:                 InstanceFieldSet
3665 
3666   /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
3667   /// CHECK:                     InstanceFieldGet
3668   /// CHECK-NOT:                 InstanceFieldGet
3669 
3670   /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
3671   /// CHECK:                     Phi
3672   /// CHECK:                     Phi
3673   /// CHECK:                     Phi
3674   /// CHECK-NOT:                 Phi
3675 
3676   // Test heap value clobbering in the nested loop and load elimination for a heap
3677   // location then set to known value before the end of the outer loop.
testNestedLoop3(TestClass obj, int n)3678   private static int testNestedLoop3(TestClass obj, int n) {
3679     obj.i = 1;
3680     for (int i = 0; i < n; ++i) {
3681       obj.j = 2;
3682       for (int j = i + 1; j < n; ++j) {
3683         $noinline$clobberObservables();
3684       }
3685       obj.i = obj.j;
3686     }
3687     return obj.i;
3688   }
3689 
3690   /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (before)
3691   /// CHECK-DAG:                 InstanceFieldSet
3692   /// CHECK-DAG:                 Phi
3693   /// CHECK-DAG:                 Phi
3694   /// CHECK-DAG:                 InstanceFieldSet
3695   /// CHECK-DAG:                 InstanceFieldGet
3696 
3697   /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
3698   /// CHECK-DAG:                 InstanceFieldSet
3699   /// CHECK-DAG:                 Phi
3700   /// CHECK-DAG:                 Phi
3701   /// CHECK-DAG:                 Phi
3702   /// CHECK-DAG:                 Phi
3703   /// CHECK-DAG:                 InstanceFieldSet
3704 
3705   /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
3706   /// CHECK-NOT:                 InstanceFieldGet
3707 
3708   /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
3709   /// CHECK:                     Phi
3710   /// CHECK:                     Phi
3711   /// CHECK:                     Phi
3712   /// CHECK:                     Phi
3713   /// CHECK-NOT:                 Phi
3714 
3715   // Test creating loop Phis for both inner and outer loop to eliminate a load.
testNestedLoop4(TestClass obj, int n)3716   private static int testNestedLoop4(TestClass obj, int n) {
3717     obj.i = 1;
3718     for (int i = 0; i < n; ++i) {
3719       for (int j = i + 1; j < n; ++j) {
3720         obj.i = 2;
3721       }
3722     }
3723     return obj.i;
3724   }
3725 
3726   /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (before)
3727   /// CHECK-DAG:                 InstanceFieldSet
3728   /// CHECK-DAG:                 Phi
3729   /// CHECK-DAG:                 InstanceFieldSet
3730   /// CHECK-DAG:                 Phi
3731   /// CHECK-DAG:                 InstanceFieldSet
3732   /// CHECK-DAG:                 InstanceFieldGet
3733 
3734   /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
3735   /// CHECK-DAG:                 InstanceFieldSet
3736   /// CHECK-DAG:                 Phi
3737   /// CHECK-DAG:                 Phi
3738   /// CHECK-DAG:                 InstanceFieldSet
3739   /// CHECK-DAG:                 Phi
3740   /// CHECK-DAG:                 InstanceFieldSet
3741 
3742   /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
3743   /// CHECK-NOT:                 InstanceFieldGet
3744 
3745   /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
3746   /// CHECK:                     Phi
3747   /// CHECK:                     Phi
3748   /// CHECK:                     Phi
3749   /// CHECK-NOT:                 Phi
3750 
3751   // Test creating a loop Phi for outer loop to eliminate a load.
testNestedLoop5(TestClass obj, int n)3752   private static int testNestedLoop5(TestClass obj, int n) {
3753     obj.i = 1;
3754     for (int i = 0; i < n; ++i) {
3755       obj.i = 2;
3756       for (int j = i + 1; j < n; ++j) {
3757         obj.j = 3;  // Unrelated.
3758       }
3759     }
3760     return obj.i;
3761   }
3762 
3763   /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (before)
3764   /// CHECK-DAG:                 InstanceFieldSet
3765   /// CHECK-DAG:                 InstanceFieldSet
3766   /// CHECK-DAG:                 Phi
3767   /// CHECK-DAG:                 Phi
3768   /// CHECK-DAG:                 InstanceFieldGet
3769   /// CHECK-DAG:                 InstanceFieldSet
3770   /// CHECK-DAG:                 InstanceFieldGet
3771 
3772   /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
3773   /// CHECK-DAG:                 InstanceFieldSet
3774   /// CHECK-DAG:                 InstanceFieldSet
3775   /// CHECK-DAG:                 Phi
3776   /// CHECK-DAG:                 Phi
3777   /// CHECK-DAG:                 Phi
3778   /// CHECK-DAG:                 Phi
3779   /// CHECK-DAG:                 InstanceFieldGet
3780   /// CHECK-DAG:                 InstanceFieldSet
3781 
3782   /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
3783   /// CHECK:                     InstanceFieldGet
3784   /// CHECK-NOT:                 InstanceFieldGet
3785 
3786   /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
3787   /// CHECK:                     Phi
3788   /// CHECK:                     Phi
3789   /// CHECK:                     Phi
3790   /// CHECK:                     Phi
3791   /// CHECK-NOT:                 Phi
3792 
3793   // Test heap value clobbering in the nested loop and load elimination for a heap
3794   // location then set to known value before the end of that inner loop.
testNestedLoop6(TestClass obj, int n)3795   private static int testNestedLoop6(TestClass obj, int n) {
3796     obj.i = 1;
3797     obj.j = 2;
3798     for (int i = 0; i < n; ++i) {
3799       for (int j = i + 1; j < n; ++j) {
3800         int tmp = obj.j;
3801         $noinline$clobberObservables();
3802         obj.i = tmp;
3803       }
3804     }
3805     return obj.i;
3806   }
3807 
3808   /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (before)
3809   /// CHECK-DAG:                 NewArray
3810   /// CHECK-DAG:                 Phi
3811   /// CHECK-DAG:                 Phi
3812   /// CHECK-DAG:                 ArrayGet
3813   /// CHECK-DAG:                 InstanceFieldSet
3814 
3815   /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after)
3816   /// CHECK-DAG:                 NewArray
3817   /// CHECK-DAG:                 Phi
3818   /// CHECK-DAG:                 Phi
3819   /// CHECK-DAG:                 InstanceFieldSet
3820 
3821   /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after)
3822   /// CHECK-NOT:                 ArrayGet
3823 
3824   // Test load elimination in inner loop reading default value that is loop invariant
3825   // with an index defined inside the inner loop.
testNestedLoop7(TestClass obj, int n)3826   private static int testNestedLoop7(TestClass obj, int n) {
3827     // The NewArray is kept as it may throw for negative n.
3828     // TODO: Eliminate constructor fence even though the NewArray is kept.
3829     int[] a0 = new int[n];
3830     for (int i = 0; i < n; ++i) {
3831       for (int j = i + 1; j < n; ++j) {
3832         obj.i = a0[j];
3833       }
3834     }
3835     return n;
3836   }
3837 
3838   /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (before)
3839   /// CHECK-DAG:                 NewInstance
3840   /// CHECK-DAG:                 InstanceFieldSet
3841   /// CHECK-DAG:                 Phi
3842   /// CHECK-DAG:                 Phi
3843   /// CHECK-DAG:                 NewInstance
3844   /// CHECK-DAG:                 InstanceFieldSet
3845   /// CHECK-DAG:                 InstanceFieldGet
3846   /// CHECK-DAG:                 InstanceFieldGet
3847 
3848   /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after)
3849   /// CHECK-DAG:                 NewInstance
3850   /// CHECK-DAG:                 InstanceFieldSet
3851   /// CHECK-DAG:                 Phi
3852   /// CHECK-DAG:                 Phi
3853   /// CHECK-DAG:                 Phi
3854   /// CHECK-DAG:                 Phi
3855   /// CHECK-DAG:                 NewInstance
3856   /// CHECK-DAG:                 InstanceFieldSet
3857   /// CHECK-DAG:                 InstanceFieldGet
3858 
3859   /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after)
3860   /// CHECK:                     InstanceFieldGet
3861   /// CHECK-NOT:                 InstanceFieldGet
3862 
3863   // Test reference type propagation for Phis created for outer and inner loop.
testNestedLoop8(TestClass obj, int n)3864   private static int testNestedLoop8(TestClass obj, int n) {
3865     obj.next = new SubTestClass();
3866     for (int i = 0; i < n; ++i) {
3867       for (int j = i + 1; j < n; ++j) {
3868         obj.next = new TestClass();
3869       }
3870     }
3871     // The Phis created in both loop headers for replacing `obj.next` depend on each other.
3872     return obj.next.i;
3873   }
3874 
3875 
3876   /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (before)
3877   /// CHECK-DAG:                 NewArray
3878   /// CHECK-DAG:                 ArraySet
3879   /// CHECK-DAG:                 If
3880   /// CHECK-DAG:                 ArrayGet
3881   /// CHECK-DAG:                 ArrayGet
3882   /// CHECK-DAG:                 ArraySet
3883   /// CHECK-DAG:                 ArrayGet
3884   /// CHECK-DAG:                 Goto
3885 
3886   /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (after)
3887   /// CHECK-DAG:                 NewArray
3888   /// CHECK-DAG:                 ArraySet
3889   /// CHECK-DAG:                 If
3890   /// CHECK-DAG:                 ArrayGet
3891   /// CHECK-DAG:                 ArrayGet
3892   /// CHECK-DAG:                 ArraySet
3893   /// CHECK-DAG:                 Goto
3894   /// CHECK-NOT:                 ArrayGet
3895 
3896   // Test that we don't incorrectly remove writes needed by later loop iterations
3897   // NB This is fibonacci numbers
testOverlapLoop(int cnt)3898   private static long testOverlapLoop(int cnt) {
3899     long[] w = new long[cnt];
3900     w[1] = 1;
3901     long t = 1;
3902     for (int i = 2; i < cnt; ++i) {
3903       w[i] = w[i - 1] + w[i - 2];
3904       t = w[i];
3905     }
3906     return t;
3907   }
3908 
$noinline$getBoolean(boolean val)3909   private static boolean $noinline$getBoolean(boolean val) {
3910     return val;
3911   }
3912 
3913   /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (before)
3914   /// CHECK-DAG:     ParameterValue
3915   /// CHECK-DAG:     NewInstance
3916   /// CHECK-DAG:     InvokeStaticOrDirect
3917   /// CHECK-DAG:     InstanceFieldSet
3918   /// CHECK-DAG:     InvokeStaticOrDirect
3919   /// CHECK-DAG:     InstanceFieldGet
3920   /// CHECK-DAG:     InstanceFieldGet
3921   /// CHECK-DAG:     InstanceFieldSet
3922   /// CHECK-DAG:     InstanceFieldGet
3923   /// CHECK-DAG:     InstanceFieldGet
3924   /// CHECK-DAG:     Phi
3925   //
3926   /// CHECK-NOT:     NewInstance
3927   /// CHECK-NOT:     InvokeStaticOrDirect
3928   /// CHECK-NOT:     InstanceFieldSet
3929   /// CHECK-NOT:     InstanceFieldGet
3930   //
3931   /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
3932   /// CHECK-DAG:     ParameterValue
3933   /// CHECK-DAG:     NewInstance
3934   /// CHECK-DAG:     Phi
3935   //
3936   /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
3937   /// CHECK:         InvokeStaticOrDirect
3938   /// CHECK:         InvokeStaticOrDirect
3939   //
3940   /// CHECK-NOT:     InvokeStaticOrDirect
3941 
3942   /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
3943   /// CHECK:         InstanceFieldSet
3944   //
3945   /// CHECK-NOT:     InstanceFieldSet
3946   //
3947   /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
3948   /// CHECK:         InstanceFieldGet
3949   /// CHECK:         InstanceFieldGet
3950   /// CHECK:         InstanceFieldGet
3951   //
3952   /// CHECK-NOT:     InstanceFieldGet
$noinline$testPartialEscape1(TestClass obj, boolean escape)3953   private static int $noinline$testPartialEscape1(TestClass obj, boolean escape) {
3954     TestClass i = new SubTestClass();
3955     int res;
3956     if ($noinline$getBoolean(escape)) {
3957       i.next = obj;
3958       $noinline$Escape(i);
3959       res = i.next.i;
3960     } else {
3961       i.next = obj;
3962       res = i.next.i;
3963     }
3964     return res;
3965   }
3966 
$noinline$clobberObservables()3967   private static void $noinline$clobberObservables() {}
3968 
assertLongEquals(long result, long expected)3969   static void assertLongEquals(long result, long expected) {
3970     if (expected != result) {
3971       throw new Error("Expected: " + expected + ", found: " + result);
3972     }
3973   }
3974 
assertIntEquals(int result, int expected)3975   static void assertIntEquals(int result, int expected) {
3976     if (expected != result) {
3977       throw new Error("Expected: " + expected + ", found: " + result);
3978     }
3979   }
3980 
assertFloatEquals(float result, float expected)3981   static void assertFloatEquals(float result, float expected) {
3982     if (expected != result) {
3983       throw new Error("Expected: " + expected + ", found: " + result);
3984     }
3985   }
3986 
assertDoubleEquals(double result, double expected)3987   static void assertDoubleEquals(double result, double expected) {
3988     if (expected != result) {
3989       throw new Error("Expected: " + expected + ", found: " + result);
3990     }
3991   }
3992 
main(String[] args)3993   public static void main(String[] args) {
3994     assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
3995     assertIntEquals(test1(new TestClass(), new TestClass()), 3);
3996     assertIntEquals(test2(new TestClass()), 1);
3997     TestClass obj1 = new TestClass();
3998     TestClass obj2 = new TestClass();
3999     obj1.next = obj2;
4000     assertIntEquals(test3(obj1), 10);
4001     assertIntEquals(test4(new TestClass(), true), 1);
4002     assertIntEquals(test4(new TestClass(), false), 1);
4003     assertIntEquals(test5(new TestClass(), true), 1);
4004     assertIntEquals(test5(new TestClass(), false), 2);
4005     assertIntEquals(test6(new TestClass(), new TestClass(), true), 4);
4006     assertIntEquals(test6(new TestClass(), new TestClass(), false), 2);
4007     assertIntEquals(test7(new TestClass()), 1);
4008     assertIntEquals(test8(), 1);
4009     obj1 = new TestClass();
4010     obj2 = new TestClass();
4011     obj1.next = obj2;
4012     assertIntEquals(test9(new TestClass()), 1);
4013     assertIntEquals(test10(new TestClass(3, 4)), 3);
4014     assertIntEquals(TestClass.si, 3);
4015     assertIntEquals(test11(new TestClass()), 10);
4016     assertIntEquals(test12(new TestClass(), new TestClass()), 10);
4017     assertIntEquals(test13(new TestClass(), new TestClass2()), 3);
4018     SubTestClass obj3 = new SubTestClass();
4019     assertIntEquals(test14(obj3, obj3), 2);
4020     assertIntEquals(test15(), 2);
4021     assertIntEquals(test16(), 3);
4022     assertIntEquals(test17(), 0);
4023     assertIntEquals(test18(new TestClass()), 1);
4024     float[] fa1 = { 0.8f };
4025     float[] fa2 = { 1.8f };
4026     assertFloatEquals(test19(fa1, fa2), 1.8f);
4027     assertFloatEquals(test20().i, 0);
4028     test21(new TestClass());
4029     assertIntEquals(test22(), 13);
4030     assertIntEquals(test23(true), 4);
4031     assertIntEquals(test23(false), 5);
4032     assertFloatEquals(test24(), 8.0f);
4033     assertIntEquals(test25(false, true, true), 5);
4034     assertIntEquals(test25(true, false, true), 2);
4035     assertFloatEquals(test26(5), 0.0f);
4036     assertFloatEquals(test26(3), 1.0f);
4037     assertIntEquals(test27(false, true), 1);
4038     assertIntEquals(test27(true, false), 1);
4039     assertIntEquals(test28(false, true), 0);
4040     assertIntEquals(test28(true, true), 5);
4041     assertFloatEquals(test29(true), 5.0f);
4042     assertFloatEquals(test29(false), 2.0f);
4043     assertIntEquals(test30(new TestClass(), true), 1);
4044     assertIntEquals(test30(new TestClass(), false), 0);
4045     assertIntEquals(test31(true, true), 5);
4046     assertIntEquals(test31(true, false), 6);
4047     assertIntEquals(test32(1), 10);
4048     assertIntEquals(test32(2), 10);
4049     assertIntEquals(test33(new TestClass(), true), 1);
4050     assertIntEquals(test33(new TestClass(), false), 2);
4051     assertIntEquals(test34(new TestClass(), true, true), 3);
4052     assertIntEquals(test34(new TestClass(), false, true), 4);
4053     assertIntEquals(test34(new TestClass(), true, false), 1);
4054     assertIntEquals(test34(new TestClass(), false, false), 2);
4055     assertIntEquals(test35(new TestClass(), true, true), 3);
4056     assertIntEquals(test35(new TestClass(), false, true), 2);
4057     assertIntEquals(test35(new TestClass(), true, false), 1);
4058     assertIntEquals(test35(new TestClass(), false, false), 2);
4059     assertIntEquals(test36(new TestClass(), true), 2);
4060     assertIntEquals(test36(new TestClass(), false), 4);
4061     assertIntEquals(test37(new TestClass(), true), 1);
4062     assertIntEquals(test37(new TestClass(), false), 0);
4063     assertIntEquals(test38(new TestClass(), true), 1);
4064     assertIntEquals(test38(new TestClass(), false), 2);
4065     assertIntEquals(test39(new TestClass(), true), 0);
4066     assertIntEquals(test39(new TestClass(), false), 1);
4067 
4068     testFinalizableByForcingGc();
4069     assertIntEquals($noinline$testHSelect(true), 0xdead);
4070     int[] array = {2, 5, 9, -1, -3, 10, 8, 4};
4071     assertIntEquals(sumWithinRange(array, 1, 5), 11);
4072     assertFloatEquals(testAllocationEliminationWithLoops(), 1.0f);
4073     assertFloatEquals(mF, 0f);
4074     assertDoubleEquals(Math.PI * Math.PI * Math.PI, getCircleArea(Math.PI, true));
4075     assertDoubleEquals(0d, getCircleArea(Math.PI, false));
4076 
4077     assertIntEquals($noinline$testConversion1(new TestClass(), 300), 300);
4078     assertIntEquals($noinline$testConversion1(new TestClass(), 301), 45);
4079     assertIntEquals($noinline$testConversion2(new TestClass(), 300), 300);
4080     assertIntEquals($noinline$testConversion2(new TestClass(), 301), 90);
4081     assertIntEquals($noinline$testConversion3(new TestClass(), 0), 0);
4082     assertIntEquals($noinline$testConversion3(new TestClass(), 1), 0);
4083     assertIntEquals($noinline$testConversion3(new TestClass(), 128), 127);
4084     assertIntEquals($noinline$testConversion3(new TestClass(), 129), -128);
4085     assertIntEquals($noinline$testConversion4(new TestClass(), 0), 0);
4086     assertIntEquals($noinline$testConversion4(new TestClass(), 1), 0);
4087     assertIntEquals($noinline$testConversion4(new TestClass(), 128), 254);
4088     assertIntEquals($noinline$testConversion4(new TestClass(), 129), -256);
4089 
4090     int[] iarray = {0, 0, 0};
4091     double[] darray = {0d, 0d, 0d};
4092     try {
4093       assertDoubleEquals(Math.PI * Math.PI * Math.PI, testDeoptimize(iarray, darray, Math.PI));
4094     } catch (Exception e) {
4095       System.out.println(e.getClass().getName());
4096     }
4097     assertIntEquals(iarray[0], 1);
4098     assertIntEquals(iarray[1], 1);
4099     assertIntEquals(iarray[2], 1);
4100     assertDoubleEquals(darray[0], Math.PI);
4101     assertDoubleEquals(darray[1], Math.PI);
4102     assertDoubleEquals(darray[2], Math.PI);
4103 
4104     assertIntEquals(testAllocationEliminationOfArray1(), 11);
4105     assertIntEquals(testAllocationEliminationOfArray2(), 11);
4106     assertIntEquals(testAllocationEliminationOfArray3(2), 4);
4107     assertIntEquals(testAllocationEliminationOfArray4(2), 6);
4108     assertIntEquals(testAllocationEliminationOfArray5(2), 12);
4109     try {
4110       testAllocationEliminationOfArray5(-2);
4111     } catch (NegativeArraySizeException e) {
4112       System.out.println("Got NegativeArraySizeException.");
4113     }
4114 
4115     assertIntEquals(testStoreStore().i, 41);
4116     assertIntEquals(testStoreStore().j, 43);
4117 
4118     assertIntEquals(testExitMerge(true), 2);
4119     assertIntEquals(testExitMerge2(true), 2);
4120     assertIntEquals(testExitMerge2(false), 2);
4121 
4122     TestClass2 testclass2 = new TestClass2();
4123     testStoreStore2(testclass2);
4124     assertIntEquals(testclass2.i, 43);
4125     assertIntEquals(testclass2.j, 44);
4126 
4127     testStoreStore3(testclass2, true);
4128     assertIntEquals(testclass2.i, 41);
4129     assertIntEquals(testclass2.j, 43);
4130     testStoreStore3(testclass2, false);
4131     assertIntEquals(testclass2.i, 41);
4132     assertIntEquals(testclass2.j, 44);
4133 
4134     testStoreStore4();
4135     assertIntEquals(TestClass.si, 62);
4136 
4137     int ret = testStoreStore5(testclass2, testclass2);
4138     assertIntEquals(testclass2.i, 72);
4139     assertIntEquals(ret, 71);
4140 
4141     testclass2.j = 88;
4142     ret = testStoreStore6(testclass2, testclass2);
4143     assertIntEquals(testclass2.i, 82);
4144     assertIntEquals(ret, 88);
4145 
4146     ret = testNoSideEffects(iarray);
4147     assertIntEquals(iarray[0], 101);
4148     assertIntEquals(iarray[1], 103);
4149     assertIntEquals(ret, 108);
4150 
4151     try {
4152       testThrow(testclass2, new Exception());
4153     } catch (Exception e) {}
4154     assertIntEquals(testclass2.i, 55);
4155 
4156     assertIntEquals(testStoreStoreWithDeoptimize(new int[4]), 4);
4157 
4158     assertIntEquals($noinline$testByteArrayDefaultValue(), 0);
4159 
4160     assertIntEquals(testLocalArrayMerge1(true), 1);
4161     assertIntEquals(testLocalArrayMerge1(false), 1);
4162     assertIntEquals(testLocalArrayMerge2(true), 2);
4163     assertIntEquals(testLocalArrayMerge2(false), 3);
4164     assertIntEquals(testLocalArrayMerge3(true), 2);
4165     assertIntEquals(testLocalArrayMerge3(false), 1);
4166     assertIntEquals(testLocalArrayMerge4(true), 2);
4167     assertIntEquals(testLocalArrayMerge4(false), 2);
4168     assertIntEquals(testLocalArrayMerge5(new int[]{ 7 }, true), 7);
4169     assertIntEquals(testLocalArrayMerge5(new int[]{ 9 }, false), 9);
4170     assertIntEquals(testLocalArrayMerge6(new int[1], true, true), 1);
4171     assertIntEquals(testLocalArrayMerge6(new int[1], true, false), 2);
4172     assertIntEquals(testLocalArrayMerge6(new int[1], false, true), 2);
4173     assertIntEquals(testLocalArrayMerge6(new int[1], false, false), 1);
4174     assertIntEquals(testLocalArrayMerge7(new int[2], true, true), 1);
4175     assertIntEquals(testLocalArrayMerge7(new int[2], true, false), 2);
4176     assertIntEquals(testLocalArrayMerge7(new int[2], false, true), 0);
4177     assertIntEquals(testLocalArrayMerge7(new int[2], false, false), 0);
4178     assertIntEquals(testLocalArrayMerge8(true), 0);
4179     assertIntEquals(testLocalArrayMerge8(false), 0);
4180 
4181     TestClass[] tca = new TestClass[] { new TestClass(), null };
4182     try {
4183       $noinline$testThrowingArraySet(tca, new TestClass2());
4184     } catch (ArrayStoreException expected) {
4185       if (tca[0] != null) {
4186         throw new Error("tca[0] is not null");
4187       }
4188       if (tca[1] == null) {
4189         throw new Error("tca[1] is null");
4190       }
4191     }
4192 
4193     assertIntEquals(testLoop1(new TestClass(), 0), 0);
4194     assertIntEquals(testLoop1(new TestClass(), 1), 0);
4195     assertIntEquals(testLoop1(new TestClass(), 2), 1);
4196     assertIntEquals(testLoop1(new TestClass(), 3), 2);
4197     assertIntEquals(testLoop2(new TestClass(), 0), 1);
4198     assertIntEquals(testLoop2(new TestClass(), 1), 1);
4199     assertIntEquals(testLoop2(new TestClass(), 2), 1);
4200     assertIntEquals(testLoop2(new TestClass(), 3), 1);
4201     assertIntEquals(testLoop3(new TestClass(), 0), 1);
4202     assertIntEquals(testLoop3(new TestClass(), 1), 1);
4203     assertIntEquals(testLoop3(new TestClass(), 2), 1);
4204     assertIntEquals(testLoop3(new TestClass(), 3), 1);
4205     assertIntEquals(testLoop4(new TestClass(), 0), 0);
4206     assertIntEquals(testLoop4(new TestClass(), 1), 1);
4207     assertIntEquals(testLoop4(new TestClass(), 2), 2);
4208     assertIntEquals(testLoop4(new TestClass(), 3), 3);
4209     assertIntEquals(testLoop5(new TestClass(), 0), 0);
4210     assertIntEquals(testLoop5(new TestClass(), 1), 1);
4211     assertIntEquals(testLoop5(new TestClass(), 2), 2);
4212     assertIntEquals(testLoop5(new TestClass(), 3), 3);
4213     assertIntEquals(testLoop6(new TestClass(), 0), 0);
4214     assertIntEquals(testLoop6(new TestClass(), 1), 1);
4215     assertIntEquals(testLoop6(new TestClass(), 2), 2);
4216     assertIntEquals(testLoop6(new TestClass(), 3), 3);
4217     assertIntEquals(testLoop7(0), 0);
4218     assertIntEquals(testLoop7(1), 0);
4219     assertIntEquals(testLoop7(2), 0);
4220     assertIntEquals(testLoop7(3), 0);
4221     assertIntEquals(testLoop8(0), 1);
4222     assertIntEquals(testLoop8(1), 0);
4223     assertIntEquals(testLoop8(2), 1);
4224     assertIntEquals(testLoop8(3), 0);
4225     assertIntEquals(testLoop9(new TestClass(), 0), 0);
4226     assertIntEquals(testLoop9(new TestClass(), 1), 1);
4227     assertIntEquals(testLoop9(new TestClass(), 2), 2);
4228     assertIntEquals(testLoop9(new TestClass(), 3), 3);
4229     assertIntEquals(testLoop10(new TestClass(), 0), 2);
4230     assertIntEquals(testLoop10(new TestClass(), 1), 2);
4231     assertIntEquals(testLoop10(new TestClass(), 2), 2);
4232     assertIntEquals(testLoop10(new TestClass(), 3), 2);
4233     assertIntEquals(testLoop11(new TestClass(), 0), 1);
4234     assertIntEquals(testLoop11(new TestClass(), 1), 3);
4235     assertIntEquals(testLoop11(new TestClass(), 2), 2);
4236     assertIntEquals(testLoop11(new TestClass(), 3), 3);
4237     assertIntEquals(testLoop12(new TestClass(), 0), 1);
4238     assertIntEquals(testLoop12(new TestClass(), 1), 2);
4239     assertIntEquals(testLoop12(new TestClass(), 2), 3);
4240     assertIntEquals(testLoop12(new TestClass(), 3), 2);
4241     assertIntEquals(testLoop13(new TestClass(1, 2), 0), 0);
4242     assertIntEquals(testLoop13(new TestClass(1, 2), 1), 0);
4243     assertIntEquals(testLoop13(new TestClass(1, 2), 2), 0);
4244     assertIntEquals(testLoop13(new TestClass(1, 2), 3), 1);
4245     assertIntEquals(testLoop14(new TestClass2(), 0), 0);
4246     assertIntEquals(testLoop14(new TestClass2(), 1), 0);
4247     assertIntEquals(testLoop14(new TestClass2(), 2), 0);
4248     assertIntEquals(testLoop14(new TestClass2(), 3), 1);
4249     assertIntEquals(testLoop15(0), 0);
4250     assertIntEquals(testLoop15(1), 1);
4251     assertIntEquals(testLoop15(2), 1);
4252     assertIntEquals(testLoop15(3), 1);
4253     assertIntEquals(testLoop16(new TestClass(), 0), 0);
4254     assertIntEquals(testLoop16(new TestClass(), 1), 1);
4255     assertIntEquals(testLoop16(new TestClass(), 2), 2);
4256     assertIntEquals(testLoop16(new TestClass(), 3), 3);
4257     assertIntEquals(testLoop17(new TestClass(), 0), 2);
4258     assertIntEquals(testLoop17(new TestClass(), 1), 4);
4259     assertIntEquals(testLoop17(new TestClass(), 2), 2);
4260     assertIntEquals(testLoop17(new TestClass(), 3), 4);
4261     assertIntEquals(testLoop18(new TestClass(), 0), 0);
4262     assertIntEquals(testLoop18(new TestClass(), 1), 1);
4263     assertIntEquals(testLoop18(new TestClass(), 2), 2);
4264     assertIntEquals(testLoop18(new TestClass(), 3), 3);
4265     assertIntEquals(testLoop19(new TestClass(), 0), 0);
4266     assertIntEquals(testLoop19(new TestClass(), 1), 1);
4267     assertIntEquals(testLoop19(new TestClass(), 2), 2);
4268     assertIntEquals(testLoop19(new TestClass(), 3), 3);
4269     assertIntEquals(testLoop20(new TestClass(), 0), 0);
4270     assertIntEquals(testLoop20(new TestClass(), 1), 1);
4271     assertIntEquals(testLoop20(new TestClass(), 2), 2);
4272     assertIntEquals(testLoop20(new TestClass(), 3), 3);
4273     assertIntEquals(testLoop21(new TestClass(), 0), 0);
4274     assertIntEquals(testLoop21(new TestClass(), 1), 1);
4275     assertIntEquals(testLoop21(new TestClass(), 2), 2);
4276     assertIntEquals(testLoop21(new TestClass(), 3), 3);
4277     assertIntEquals(testLoop22(new TestClass(), 0), 0);
4278     assertIntEquals(testLoop22(new TestClass(), 1), 1);
4279     assertIntEquals(testLoop22(new TestClass(), 2), 2);
4280     assertIntEquals(testLoop22(new TestClass(), 3), 3);
4281     assertIntEquals(testLoop23(new TestClass(), 0), -1);
4282     assertIntEquals(testLoop23(new TestClass(), 1), 2);
4283     assertIntEquals(testLoop23(new TestClass(), 2), 1);
4284     assertIntEquals(testLoop23(new TestClass(), 3), 2);
4285     assertIntEquals(testLoop24(new TestClass(), 0), -1);
4286     assertIntEquals(testLoop24(new TestClass(), 1), 2);
4287     assertIntEquals(testLoop24(new TestClass(), 2), 1);
4288     assertIntEquals(testLoop24(new TestClass(), 3), -2);
4289     assertIntEquals(testLoop25(new TestClass(), 0), 2);
4290     assertIntEquals(testLoop25(new TestClass(), 1), 2);
4291     assertIntEquals(testLoop25(new TestClass(), 2), 4);
4292     assertIntEquals(testLoop25(new TestClass(), 3), -1);
4293     assertIntEquals(testLoop26(new TestClass(), 0), 1);
4294     assertIntEquals(testLoop26(new TestClass(), 1), 0);
4295     assertIntEquals(testLoop26(new TestClass(), 2), 0);
4296     assertIntEquals(testLoop26(new TestClass(), 3), 0);
4297     assertIntEquals(testLoop27(new TestClass(), 0), 1);
4298     assertIntEquals(testLoop27(new TestClass(), 1), 1);
4299     assertIntEquals(testLoop27(new TestClass(), 2), 0);
4300     assertIntEquals(testLoop27(new TestClass(), 3), 0);
4301     assertIntEquals(testLoop28(new TestClass(1, 2), 0), 0);
4302     assertIntEquals(testLoop28(new TestClass(1, 2), 1), 0);
4303     assertIntEquals(testLoop28(new TestClass(1, 2), 2), 0);
4304     assertIntEquals(testLoop28(new TestClass(1, 2), 3), 1);
4305     assertIntEquals(testLoop29(0), 0);
4306     assertIntEquals(testLoop29(1), 1);
4307     assertIntEquals(testLoop29(2), 3);
4308     assertIntEquals(testLoop29(3), 6);
4309     assertIntEquals(testLoop30(0), 0);
4310     assertIntEquals(testLoop30(1), 1);
4311     assertIntEquals(testLoop30(2), 2);
4312     assertIntEquals(testLoop30(3), 3);
4313     assertIntEquals(testLoop31(0), 0);
4314     assertIntEquals(testLoop31(1), 0);
4315     assertIntEquals(testLoop31(2), 0);
4316     assertIntEquals(testLoop31(3), 0);
4317     assertIntEquals(testLoop32(new TestClass(), 0), -1);
4318     assertIntEquals(testLoop32(new TestClass(), 1), 2);
4319     assertIntEquals(testLoop32(new TestClass(), 2), 1);
4320     assertIntEquals(testLoop32(new TestClass(), 3), -2);
4321     assertIntEquals(testLoop33(new TestClass(), 0), 0);
4322     assertIntEquals(testLoop33(new TestClass(), 1), 0);
4323     assertIntEquals(testLoop33(new TestClass(), 2), 0);
4324     assertIntEquals(testLoop33(new TestClass(), 3), 0);
4325     assertIntEquals(testLoop34(0), 0);
4326     assertIntEquals(testLoop34(1), 1);
4327     assertIntEquals(testLoop34(2), 3);
4328     assertIntEquals(testLoop34(3), 6);
4329     assertIntEquals(testLoop35(0), 0);
4330     assertIntEquals(testLoop35(1), 1);
4331     assertIntEquals(testLoop35(2), 3);
4332     assertIntEquals(testLoop35(3), 6);
4333     assertIntEquals(testLoop36(4), 6);
4334     assertIntEquals(testLoop37(4), 6);
4335     assertIntEquals(testLoop38(4, new int[4]), 0);
4336 
4337     assertIntEquals(testNestedLoop1(new TestClass(), 0), 1);
4338     assertIntEquals(testNestedLoop1(new TestClass(), 1), 1);
4339     assertIntEquals(testNestedLoop1(new TestClass(), 2), 1);
4340     assertIntEquals(testNestedLoop1(new TestClass(), 3), 1);
4341     assertIntEquals(testNestedLoop2(new TestClass(), 0), 1);
4342     assertIntEquals(testNestedLoop2(new TestClass(), 1), 2);
4343     assertIntEquals(testNestedLoop2(new TestClass(), 2), 2);
4344     assertIntEquals(testNestedLoop2(new TestClass(), 3), 2);
4345     assertIntEquals(testNestedLoop3(new TestClass(), 0), 1);
4346     assertIntEquals(testNestedLoop3(new TestClass(), 1), 2);
4347     assertIntEquals(testNestedLoop3(new TestClass(), 2), 2);
4348     assertIntEquals(testNestedLoop3(new TestClass(), 3), 2);
4349     assertIntEquals(testNestedLoop4(new TestClass(), 0), 1);
4350     assertIntEquals(testNestedLoop4(new TestClass(), 1), 1);
4351     assertIntEquals(testNestedLoop4(new TestClass(), 2), 2);
4352     assertIntEquals(testNestedLoop4(new TestClass(), 3), 2);
4353     assertIntEquals(testNestedLoop5(new TestClass(), 0), 1);
4354     assertIntEquals(testNestedLoop5(new TestClass(), 1), 2);
4355     assertIntEquals(testNestedLoop5(new TestClass(), 2), 2);
4356     assertIntEquals(testNestedLoop5(new TestClass(), 3), 2);
4357     assertIntEquals(testNestedLoop6(new TestClass(), 0), 1);
4358     assertIntEquals(testNestedLoop6(new TestClass(), 1), 1);
4359     assertIntEquals(testNestedLoop6(new TestClass(), 2), 2);
4360     assertIntEquals(testNestedLoop6(new TestClass(), 3), 2);
4361     assertIntEquals(testNestedLoop7(new TestClass(), 0), 0);
4362     assertIntEquals(testNestedLoop7(new TestClass(), 1), 1);
4363     assertIntEquals(testNestedLoop7(new TestClass(), 2), 2);
4364     assertIntEquals(testNestedLoop7(new TestClass(), 3), 3);
4365     assertIntEquals(testNestedLoop8(new TestClass(), 0), 0);
4366     assertIntEquals(testNestedLoop8(new TestClass(), 1), 0);
4367     assertIntEquals(testNestedLoop8(new TestClass(), 2), 0);
4368     assertIntEquals(testNestedLoop8(new TestClass(), 3), 0);
4369     assertLongEquals(testOverlapLoop(10), 34l);
4370     assertLongEquals(testOverlapLoop(50), 7778742049l);
4371     assertIntEquals($noinline$testPartialEscape1(new TestClass(), true), 1);
4372     assertIntEquals($noinline$testPartialEscape1(new TestClass(), false), 0);
4373   }
4374 }
4375