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