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