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