blob: 23e1d53e986393fc572daf3336bf9e6f37fdba65 [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
Artem Serov2558abe2020-10-14 18:01:37 +01002723 /// CHECK-IF: hasIsaFeature("sve")
2724 //
2725 /// CHECK-DAG: VecPredWhile
2726 /// CHECK-DAG: VecStore
2727 //
2728 /// CHECK-ELSE:
2729 //
2730 /// CHECK-DAG: ArraySet
2731 //
2732 /// CHECK-FI:
2733 //
Vladimir Marko3224f382020-06-23 14:19:53 +01002734 /// CHECK-DAG: ArrayGet
2735
2736 /// CHECK-START: int Main.testLoop15(int) load_store_elimination (after)
2737 /// CHECK-DAG: NewArray
Artem Serov2558abe2020-10-14 18:01:37 +01002738 /// CHECK-IF: hasIsaFeature("sve")
2739 //
2740 /// CHECK-DAG: VecPredWhile
2741 /// CHECK-DAG: VecStore
2742 //
2743 /// CHECK-ELSE:
2744 //
2745 /// CHECK-DAG: ArraySet
2746 //
2747 /// CHECK-FI:
2748 //
Vladimir Marko3224f382020-06-23 14:19:53 +01002749 /// CHECK-DAG: ArrayGet
Vladimir Marko3224f382020-06-23 14:19:53 +01002750 // Test that aliasing array store in the loop is not eliminated
2751 // when a loop Phi placeholder is marked for keeping.
2752 private static int testLoop15(int n) {
2753 int[] a = new int[n + 1];
2754 for (int i = 0; i < n; ++i) {
2755 a[i] = 1; // Cannot be eliminated due to aliasing.
2756 }
2757 return a[0];
2758 }
2759
2760 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (before)
2761 /// CHECK-DAG: InstanceFieldSet
2762 /// CHECK-DAG: Phi
2763 /// CHECK-DAG: InstanceFieldSet
2764 /// CHECK-DAG: InstanceFieldGet
2765
2766 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
2767 /// CHECK-DAG: InstanceFieldSet
2768 /// CHECK-DAG: Phi
2769 /// CHECK-DAG: InstanceFieldSet
2770
2771 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
2772 /// CHECK-NOT: InstanceFieldGet
2773
2774 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
2775 /// CHECK: Phi
2776 /// CHECK-NOT: Phi
2777
2778 // Test that we match an existing loop Phi for eliminating a load.
2779 static int testLoop16(TestClass obj, int n) {
2780 obj.i = 0;
2781 for (int i = 0; i < n; ) {
2782 ++i;
2783 obj.i = i;
2784 }
2785 // The load is replaced by the existing Phi instead of constructing a new one.
2786 return obj.i;
2787 }
2788
2789 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (before)
2790 /// CHECK-DAG: InstanceFieldSet
2791 /// CHECK-DAG: Phi
2792 /// CHECK-DAG: InstanceFieldSet
2793 /// CHECK-DAG: InstanceFieldSet
2794 /// CHECK-DAG: Phi
2795 /// CHECK-DAG: InstanceFieldGet
2796
2797 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
2798 /// CHECK-DAG: InstanceFieldSet
2799 /// CHECK-DAG: Phi
2800 /// CHECK-DAG: InstanceFieldSet
2801 /// CHECK-DAG: InstanceFieldSet
2802 /// CHECK-DAG: Phi
2803
2804 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
2805 /// CHECK-NOT: InstanceFieldGet
2806
2807 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
2808 /// CHECK: Phi
2809 /// CHECK: Phi
2810 /// CHECK-NOT: Phi
2811
2812 // Test that we match an existing non-loop Phi for eliminating a load,
2813 // one input of the Phi being invariant across a preceding loop.
2814 static int testLoop17(TestClass obj, int n) {
2815 obj.i = 1;
2816 int phi = 1;
2817 for (int i = 0; i < n; ++i) {
2818 obj.j = 2; // Unrelated.
2819 }
2820 if ((n & 1) != 0) {
2821 obj.i = 2;
2822 phi = 2;
2823 }
2824 // The load is replaced by the existing Phi instead of constructing a new one.
2825 return obj.i + phi;
2826 }
2827
2828 /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (before)
2829 /// CHECK-DAG: NewArray
2830 /// CHECK-DAG: Phi
2831 /// CHECK-DAG: ArrayGet
2832 /// CHECK-DAG: InstanceFieldSet
2833
2834 /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after)
2835 /// CHECK-DAG: NewArray
2836 /// CHECK-DAG: Phi
2837 /// CHECK-DAG: InstanceFieldSet
2838
2839 /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after)
2840 /// CHECK-NOT: ArrayGet
2841
2842 // Test eliminating a load of the default value in a loop
2843 // with the array index being defined inside the loop.
2844 static int testLoop18(TestClass obj, int n) {
2845 // The NewArray is kept as it may throw for negative n.
2846 // TODO: Eliminate constructor fence even though the NewArray is kept.
2847 int[] a0 = new int[n];
2848 for (int i = 0; i < n; ++i) {
2849 obj.i = a0[i];
2850 }
2851 return n;
2852 }
2853
2854 /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (before)
2855 /// CHECK-DAG: NewArray
2856 /// CHECK-DAG: Phi
2857 /// CHECK-DAG: ArrayGet
2858 /// CHECK-DAG: InstanceFieldSet
2859 /// CHECK-DAG: ArraySet
2860
2861 /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after)
2862 /// CHECK-DAG: NewArray
2863 /// CHECK-DAG: Phi
2864 /// CHECK-DAG: InstanceFieldSet
2865
2866 /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after)
2867 /// CHECK-NOT: ArrayGet
2868 /// CHECK-NOT: ArraySet
2869
2870 // Test eliminating a load of the default value and store of an identical value
2871 // in a loop with the array index being defined inside the loop.
2872 static int testLoop19(TestClass obj, int n) {
2873 // The NewArray is kept as it may throw for negative n.
2874 // TODO: Eliminate constructor fence even though the NewArray is kept.
2875 int[] a0 = new int[n];
2876 for (int i = 0; i < n; ++i) {
2877 obj.i = a0[i];
2878 a0[i] = 0; // Store the same value as default.
2879 }
2880 return n;
2881 }
2882
2883 /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (before)
2884 /// CHECK-DAG: NewArray
2885 /// CHECK-DAG: Phi
2886 /// CHECK-DAG: ArrayGet
2887 /// CHECK-DAG: InstanceFieldSet
2888 /// CHECK-DAG: ArraySet
2889
2890 /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after)
2891 /// CHECK-DAG: NewArray
2892 /// CHECK-DAG: Phi
2893 /// CHECK-DAG: InstanceFieldSet
2894
2895 /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after)
2896 /// CHECK-NOT: ArrayGet
2897 /// CHECK-NOT: ArraySet
2898
2899 // Test eliminating a load of the default value and a conditional store of an
2900 // identical value in a loop with the array index being defined inside the loop.
2901 static int testLoop20(TestClass obj, int n) {
2902 // The NewArray is kept as it may throw for negative n.
2903 // TODO: Eliminate constructor fence even though the NewArray is kept.
2904 int[] a0 = new int[n];
2905 for (int i = 0; i < n; ++i) {
2906 obj.i = a0[i];
2907 if ((i & 1) != 0) {
2908 a0[i] = 0; // Store the same value as default.
2909 }
2910 }
2911 return n;
2912 }
2913
2914 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before)
2915 /// CHECK-DAG: InstanceFieldSet
2916 /// CHECK-DAG: InstanceFieldGet
2917 /// CHECK-DAG: InstanceFieldSet
2918 /// CHECK-DAG: InstanceFieldGet
2919 /// CHECK-DAG: InstanceFieldSet
2920 /// CHECK-DAG: InstanceFieldGet
2921 /// CHECK-DAG: InstanceFieldSet
2922
2923 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before)
2924 /// CHECK-NOT: Phi
2925
2926 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
2927 /// CHECK-NOT: InstanceFieldGet
2928
2929 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
2930 /// CHECK: InstanceFieldSet
2931 /// CHECK: InstanceFieldSet
2932 /// CHECK: InstanceFieldSet
2933 /// CHECK-NOT: InstanceFieldSet
2934
2935 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
2936 /// CHECK: Phi
2937 /// CHECK-NOT: Phi
2938
2939 // Test load elimination when an instance field is used as the loop variable.
2940 static int testLoop21(TestClass obj, int n) {
2941 for (obj.i = 0; obj.i < n; ++obj.i) {
2942 obj.j = 0; // Use write side effects to stop GVN from eliminating the load below.
2943 obj.j = obj.i;
2944 }
2945 return n;
2946 }
2947
2948 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before)
2949 /// CHECK-DAG: InstanceFieldSet
2950 /// CHECK-DAG: InstanceFieldGet
2951 /// CHECK-DAG: InstanceFieldSet
2952 /// CHECK-DAG: InstanceFieldGet
2953 /// CHECK-DAG: InstanceFieldSet
2954 /// CHECK-DAG: InstanceFieldGet
2955 /// CHECK-DAG: InstanceFieldSet
2956 /// CHECK-DAG: InstanceFieldSet
2957
2958 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before)
2959 /// CHECK-NOT: Phi
2960
2961 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
2962 /// CHECK-NOT: InstanceFieldGet
2963
2964 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
2965 /// CHECK: InstanceFieldSet
2966 /// CHECK: InstanceFieldSet
2967 /// CHECK-NOT: InstanceFieldSet
2968
2969 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
2970 /// CHECK: Phi
2971 /// CHECK-NOT: Phi
2972
2973 // Test load and store elimination when an instance field is used as the loop
2974 // variable and then overwritten after the loop.
2975 static int testLoop22(TestClass obj, int n) {
2976 for (obj.i = 0; obj.i < n; ++obj.i) {
2977 obj.j = 0; // Use write side effects to stop GVN from eliminating the load below.
2978 obj.j = obj.i;
2979 }
2980 obj.i = 0;
2981 return n;
2982 }
2983
2984 /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (before)
2985 /// CHECK-DAG: InstanceFieldSet
2986 /// CHECK-DAG: Phi
2987 /// CHECK-DAG: Phi
2988 /// CHECK-DAG: InstanceFieldSet
2989 /// CHECK-DAG: InstanceFieldSet
2990 /// CHECK-DAG: Phi
2991 /// CHECK-DAG: InstanceFieldSet
2992
2993 /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after)
2994 /// CHECK-DAG: Phi
2995 /// CHECK-DAG: Phi
2996 /// CHECK-DAG: Phi
2997 /// CHECK-DAG: InstanceFieldSet
2998
2999 /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after)
3000 /// CHECK: InstanceFieldSet
3001 /// CHECK-NOT: InstanceFieldSet
3002
3003 // Test elimination of non-observable stores.
3004 static int testLoop23(TestClass obj, int n) {
3005 obj.i = -1;
3006 int phi = -1;
3007 for (int i = 0; i < n; ++i) {
3008 obj.i = i;
3009 phi = i;
3010 }
3011 if ((n & 1) != 0) {
3012 obj.i = 2;
3013 phi = 2;
3014 }
3015 obj.i = phi; // This store shall be kept, the stores above shall be eliminated.
3016 return phi;
3017 }
3018
3019 /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (before)
3020 /// CHECK-DAG: InstanceFieldSet
3021 /// CHECK-DAG: Phi
3022 /// CHECK-DAG: Phi
3023 /// CHECK-DAG: InstanceFieldSet
3024 /// CHECK-DAG: InstanceFieldSet
3025 /// CHECK-DAG: Phi
3026 /// CHECK-DAG: InstanceFieldSet
3027
3028 /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after)
3029 /// CHECK-DAG: InstanceFieldSet
3030 /// CHECK-DAG: Phi
3031 /// CHECK-DAG: Phi
3032 /// CHECK-DAG: InstanceFieldSet
3033 /// CHECK-DAG: InstanceFieldSet
3034 /// CHECK-DAG: Phi
3035
3036 /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after)
3037 /// CHECK: InstanceFieldSet
3038 /// CHECK: InstanceFieldSet
3039 /// CHECK: InstanceFieldSet
3040 /// CHECK-NOT: InstanceFieldSet
3041
3042 // Test matching Phis for store elimination.
3043 static int testLoop24(TestClass obj, int n) {
3044 obj.i = -1;
3045 int phi = -1;
3046 for (int i = 0; i < n; ++i) {
3047 obj.i = i;
3048 phi = i;
3049 }
3050 if ((n & 1) != 0) {
3051 obj.i = 2;
3052 phi = 2;
3053 }
3054 if (n == 3) {
3055 return -2; // Make the above stores observable.
3056 }
3057 // As the stores above are observable and kept, we match the merged
3058 // heap value with existing Phis and determine that we're storing
3059 // the same value that's already there, so we eliminate this store.
3060 obj.i = phi;
3061 return phi;
3062 }
3063
3064 /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (before)
3065 /// CHECK-DAG: InstanceFieldSet
3066 /// CHECK-DAG: Phi
3067 /// CHECK-DAG: Phi
3068 /// CHECK-DAG: InstanceFieldSet
3069 /// CHECK-DAG: Phi
3070 /// CHECK-DAG: InstanceFieldGet
3071 /// CHECK-DAG: InstanceFieldSet
3072
3073 /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after)
3074 /// CHECK-DAG: InstanceFieldSet
3075 /// CHECK-DAG: Phi
3076 /// CHECK-DAG: Phi
3077 /// CHECK-DAG: Phi
3078 /// CHECK-DAG: InstanceFieldSet
3079 /// CHECK-DAG: Phi
3080 /// CHECK-DAG: Phi
3081 /// CHECK-DAG: InstanceFieldSet
3082
3083 /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after)
3084 /// CHECK-NOT: InstanceFieldGet
3085
3086 // Test that we do not match multiple dependent Phis for load and store elimination.
3087 static int testLoop25(TestClass obj, int n) {
3088 obj.i = 1;
3089 int phi = 1;
3090 for (int i = 0; i < n; ++i) {
3091 if ((i & 1) != 0) {
3092 obj.i = 2;
3093 phi = 2;
3094 }
3095 // There is a Phi here for the variable `phi` before the "++i".
3096 // This Phi and the loop Phi for `phi` depend on each other.
3097 }
3098 if (n == 3) {
3099 return -1; // Make above stores observable.
3100 }
3101 // We're not matching multiple Phi placeholders to existing Phis. Therefore the load
3102 // below requires 2 extra Phis to be created and the store below shall not be eliminated
3103 // even though it stores the same value that's already present in the heap location.
3104 int tmp = obj.i;
3105 obj.i = phi;
3106 return tmp + phi;
3107 }
3108
3109 /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (before)
3110 /// CHECK-DAG: NewInstance
3111 /// CHECK-DAG: InstanceFieldSet
3112 /// CHECK-DAG: Phi
3113 /// CHECK-DAG: NewInstance
3114 /// CHECK-DAG: InstanceFieldSet
3115 /// CHECK-DAG: InstanceFieldGet
3116 /// CHECK-DAG: InstanceFieldGet
3117
3118 /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after)
3119 /// CHECK-DAG: NewInstance
3120 /// CHECK-DAG: InstanceFieldSet
3121 /// CHECK-DAG: Phi
3122 /// CHECK-DAG: Phi
3123 /// CHECK-DAG: NewInstance
3124 /// CHECK-DAG: InstanceFieldSet
3125 /// CHECK-DAG: InstanceFieldGet
3126
3127 /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after)
3128 /// CHECK: InstanceFieldGet
3129 /// CHECK-NOT: InstanceFieldGet
3130
3131 // Test load elimination creating a reference Phi.
3132 static int testLoop26(TestClass obj, int n) {
3133 obj.next = new TestClass(1, 2);
3134 for (int i = 0; i < n; ++i) {
3135 obj.next = new SubTestClass();
3136 }
3137 return obj.next.i;
3138 }
3139
3140 /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (before)
3141 /// CHECK-DAG: NewInstance
3142 /// CHECK-DAG: InstanceFieldSet
3143 /// CHECK-DAG: Phi
3144 /// CHECK-DAG: NewInstance
3145 /// CHECK-DAG: InstanceFieldSet
3146 /// CHECK-DAG: InstanceFieldGet
3147 /// CHECK-DAG: InstanceFieldGet
3148
3149 /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after)
3150 /// CHECK-DAG: NewInstance
3151 /// CHECK-DAG: InstanceFieldSet
3152 /// CHECK-DAG: Phi
3153 /// CHECK-DAG: Phi
3154 /// CHECK-DAG: NewInstance
3155 /// CHECK-DAG: InstanceFieldSet
3156 /// CHECK-DAG: Phi
3157 /// CHECK-DAG: InstanceFieldGet
3158
3159 /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after)
3160 /// CHECK: InstanceFieldGet
3161 /// CHECK-NOT: InstanceFieldGet
3162
3163 // Test load elimination creating two reference Phis that depend on each other.
3164 static int testLoop27(TestClass obj, int n) {
3165 obj.next = new TestClass(1, 2);
3166 for (int i = 0; i < n; ++i) {
3167 if ((i & 1) != 0) {
3168 obj.next = new SubTestClass();
3169 }
3170 // There shall be a Phi created here for `obj.next` before the "++i".
3171 // This Phi and the loop Phi that shall be created for `obj.next` depend on each other.
3172 }
3173 return obj.next.i;
3174 }
3175
3176 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (before)
3177 /// CHECK-DAG: InstanceFieldSet
3178 /// CHECK-DAG: NewArray
3179 /// CHECK-DAG: Phi
3180 /// CHECK-DAG: ArrayGet
3181 /// CHECK-DAG: ArraySet
3182 /// CHECK-DAG: ArrayGet
3183 /// CHECK-DAG: ArraySet
3184 /// CHECK-DAG: InstanceFieldGet
3185 /// CHECK-DAG: ArraySet
3186 /// CHECK-DAG: ArrayGet
3187
3188 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
3189 /// CHECK-DAG: InstanceFieldSet
3190 /// CHECK-DAG: Phi
3191 /// CHECK-DAG: Phi
3192 /// CHECK-DAG: Phi
3193 /// CHECK-DAG: Phi
3194 /// CHECK-DAG: InstanceFieldGet
3195
3196 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
3197 /// CHECK-NOT: NewArray
3198 /// CHECK-NOT: ArrayGet
3199 /// CHECK-NOT: ArraySet
3200
3201 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
3202 /// CHECK: Phi
3203 /// CHECK: Phi
3204 /// CHECK: Phi
3205 /// CHECK: Phi
3206 /// CHECK-NOT: Phi
3207
3208 // Test eliminating array allocation, loads and stores and creating loop Phis
3209 // after determining that a field load depending on loop Phi placeholder cannot
3210 // be eliminated.
3211 private static int testLoop28(TestClass obj, int n) {
3212 obj.i = 1;
3213 int[] a = new int[3];
3214 for (int i = 0; i < n; ++i) {
3215 a[0] = a[1];
3216 a[1] = a[2];
3217 a[2] = obj.i;
3218 $noinline$clobberObservables();
3219 }
3220 return a[0];
3221 }
3222
3223 /// CHECK-START: int Main.testLoop29(int) load_store_elimination (before)
3224 /// CHECK-DAG: NewArray
3225 /// CHECK-DAG: Phi
3226 /// CHECK-DAG: Phi
3227 /// CHECK-DAG: ArrayGet
3228 /// CHECK-DAG: ArraySet
3229
3230 /// CHECK-START: int Main.testLoop29(int) load_store_elimination (after)
3231 /// CHECK-DAG: NewArray
3232 /// CHECK-DAG: Phi
3233 /// CHECK-DAG: Phi
3234 /// CHECK-DAG: ArrayGet
3235 /// CHECK-DAG: ArraySet
3236
3237 // Test that ArraySet with non-default value prevents matching ArrayGet for
3238 // the same array to default value even when the ArraySet is using an index
3239 // offset by one, making LSA declare that the two heap locations do not alias.
3240 private static int testLoop29(int n) {
3241 int[] a = new int[4];
3242 int sum = 0;
3243 for (int i = 0; i < n; ) {
3244 int value = a[i] + 1;
3245 sum += value;
3246 ++i;
3247 a[i] = value;
3248 }
3249 return sum;
3250 }
3251
3252 /// CHECK-START: int Main.testLoop30(int) load_store_elimination (before)
3253 /// CHECK-DAG: NewArray
3254 /// CHECK-DAG: Phi
3255 /// CHECK-DAG: Phi
3256 /// CHECK-DAG: ArrayGet
3257 /// CHECK-DAG: ArraySet
3258
3259 /// CHECK-START: int Main.testLoop30(int) load_store_elimination (after)
3260 /// CHECK-NOT: ArrayGet
3261 /// CHECK-NOT: ArraySet
3262
3263 // Test that ArraySet with default value does not prevent matching ArrayGet
3264 // for the same array to the default value.
3265 private static int testLoop30(int n) {
3266 int[] a = new int[4]; // NewArray is kept due to environment use by Deoptimize.
3267 int sum = 0;
3268 for (int i = 0; i < n; ) {
3269 int value = a[i] + 1;
3270 sum += value;
3271 ++i;
3272 a[i] = 0;
3273 }
3274 return sum;
3275 }
3276
3277 /// CHECK-START: int Main.testLoop31(int) load_store_elimination (before)
3278 /// CHECK-DAG: NewArray
3279 /// CHECK-DAG: Phi
3280 /// CHECK-DAG: Phi
3281 /// CHECK-DAG: ArrayGet
3282 /// CHECK-DAG: ArraySet
3283
3284 /// CHECK-START: int Main.testLoop31(int) load_store_elimination (after)
3285 /// CHECK-NOT: ArrayGet
3286 /// CHECK-NOT: ArraySet
3287
3288 // Test that ArraySet with default value read from the array does not
3289 // prevent matching ArrayGet for the same array to the default value.
3290 private static int testLoop31(int n) {
3291 int[] a = new int[4]; // NewArray is kept due to environment use by Deoptimize.
3292 int sum = 0;
3293 for (int i = 0; i < n; ) {
3294 int value = a[i];
3295 sum += value;
3296 ++i;
3297 a[i] = value;
3298 }
3299 return sum;
3300 }
3301
3302 /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (before)
3303 /// CHECK-DAG: InstanceFieldSet
3304 /// CHECK-DAG: Phi
3305 /// CHECK-DAG: Phi
3306 /// CHECK-DAG: InstanceFieldSet
3307 /// CHECK-DAG: InstanceFieldSet
3308 /// CHECK-DAG: Phi
3309 /// CHECK-DAG: InstanceFieldSet
3310
3311 /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after)
3312 /// CHECK-DAG: InstanceFieldSet
3313 /// CHECK-DAG: Phi
3314 /// CHECK-DAG: Phi
3315 /// CHECK-DAG: InstanceFieldSet
3316 /// CHECK-DAG: InstanceFieldSet
3317 /// CHECK-DAG: Phi
3318
3319 /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after)
3320 /// CHECK: InstanceFieldSet
3321 /// CHECK: InstanceFieldSet
3322 /// CHECK: InstanceFieldSet
3323 /// CHECK-NOT: InstanceFieldSet
3324
3325 // Test matching Phis for store elimination.
3326 static int testLoop32(TestClass obj, int n) {
3327 obj.i = -1;
3328 int phi = -1;
3329 for (int i = 0; i < n; ) {
3330 ++i;
3331 if ((i & 1) != 0) {
3332 obj.i = i;
3333 phi = i;
3334 }
3335 }
3336 if ((n & 1) != 0) {
3337 obj.i = 2;
3338 phi = 2;
3339 }
3340 if (n == 3) {
3341 return -2; // Make the above stores observable.
3342 }
3343 // As the stores above are observable and kept, we match the merged
3344 // heap value with existing Phis and determine that we're storing
3345 // the same value that's already there, so we eliminate this store.
3346 obj.i = phi;
3347 return phi;
3348 }
3349
3350 // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (before)
3351 // CHECK-DAG: InstanceFieldSet
3352 // CHECK-DAG: NewArray
3353 // CHECK-DAG: Phi
3354 // CHECK-DAG: ArrayGet
3355 // CHECK-DAG: InstanceFieldSet
3356 // CHECK-DAG: Phi
3357 // CHECK-DAG: ArrayGet
3358 // CHECK-DAG: InstanceFieldGet
3359 // CHECK-DAG: InstanceFieldSet
3360 // CHECK-DAG: InstanceFieldGet
3361
3362 // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after)
3363 // CHECK-DAG: InstanceFieldSet
3364 // CHECK-DAG: Phi
3365 // CHECK-DAG: InstanceFieldSet
3366 // CHECK-DAG: Phi
3367 // CHECK-DAG: InstanceFieldGet
3368 // CHECK-DAG: InstanceFieldSet
3369 // CHECK-DAG: InstanceFieldGet
3370
3371 // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after)
3372 // CHECK-NOT: ArrayGet
3373
3374 // Test that when processing Phi placeholder with unknown input, we allow materialized
3375 // default value in pre-header for array location with index defined in the loop.
3376 static int testLoop33(TestClass obj, int n) {
3377 obj.i = 0;
3378 int[] a0 = new int[n];
3379 for (int i = 0; i < n; ++i) {
3380 obj.i = a0[i];
3381 $noinline$clobberObservables(); // Make `obj.i` unknown.
3382 }
3383 for (int i = 0; i < n; ++i) {
3384 int zero = a0[i];
3385 int unknown = obj.i;
3386 obj.j += zero + unknown;
3387 }
3388 return obj.j;
3389 }
3390
Vladimir Marko0571d472020-09-22 10:14:39 +01003391 /// CHECK-START: int Main.testLoop34(int) load_store_elimination (before)
3392 /// CHECK-DAG: NewArray
3393 /// CHECK-DAG: Phi
3394 /// CHECK-DAG: Phi
3395 /// CHECK-DAG: ArrayGet
3396 /// CHECK-DAG: ArraySet
3397
3398 /// CHECK-START: int Main.testLoop34(int) load_store_elimination (after)
3399 /// CHECK-DAG: NewArray
3400 /// CHECK-DAG: Phi
3401 /// CHECK-DAG: Phi
3402 /// CHECK-DAG: ArrayGet
3403 /// CHECK-DAG: ArraySet
3404
3405 // Test that ArraySet with non-default value prevents matching ArrayGet for
3406 // the same array to default value even when the ArraySet is using an index
3407 // offset by one, making LSA declare that the two heap locations do not alias.
3408 // Also test that the ArraySet is not eliminated.
3409 private static int testLoop34(int n) {
3410 int[] a = new int[n + 1];
3411 int sum = 0;
3412 for (int i = 0; i < n; ) {
3413 int value = a[i] + 1;
3414 sum += value;
3415 ++i;
3416 a[i] = value;
3417 }
3418 return sum;
3419 }
3420
3421 /// CHECK-START: int Main.testLoop35(int) load_store_elimination (before)
3422 /// CHECK-DAG: NewArray
3423 /// CHECK-DAG: Phi
3424 /// CHECK-DAG: Phi
3425 /// CHECK-DAG: ArrayGet
3426 /// CHECK-DAG: ArraySet
3427 /// CHECK-DAG: ArraySet
3428
3429 /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after)
3430 /// CHECK-DAG: NewArray
3431 /// CHECK-DAG: Phi
3432 /// CHECK-DAG: Phi
3433 /// CHECK-DAG: ArrayGet
3434 /// CHECK-DAG: ArraySet
3435
3436 /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after)
3437 /// CHECK: ArraySet
3438 /// CHECK-NOT: ArraySet
3439
3440 // Test that ArraySet with non-default value prevents matching ArrayGet for
3441 // the same array to default value even when the ArraySet is using an index
3442 // offset by one, making LSA declare that the two heap locations do not alias.
3443 // Also test that the ArraySet is not eliminated and that a store after the
3444 // loop is eliminated.
3445 private static int testLoop35(int n) {
3446 int[] a = new int[n + 1];
3447 int sum = 0;
3448 for (int i = 0; i < n; ) {
3449 int value = a[i] + 1;
3450 sum += value;
3451 ++i;
3452 a[i] = value;
3453 }
3454 a[0] = 1;
3455 return sum;
3456 }
3457
Vladimir Marko3224f382020-06-23 14:19:53 +01003458 /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (before)
3459 /// CHECK-DAG: InstanceFieldSet
3460 /// CHECK-DAG: InstanceFieldGet
3461
3462 /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (after)
3463 /// CHECK-DAG: InstanceFieldSet
3464 /// CHECK-DAG: InstanceFieldGet
3465
3466 // Test heap value clobbering in nested loop.
3467 private static int testNestedLoop1(TestClass obj, int n) {
3468 obj.i = 1;
3469 for (int i = 0; i < n; ++i) {
3470 for (int j = i + 1; j < n; ++j) {
3471 $noinline$clobberObservables();
3472 }
3473 }
3474 return obj.i;
3475 }
3476
3477 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (before)
3478 /// CHECK-DAG: InstanceFieldSet
3479 /// CHECK-DAG: InstanceFieldSet
3480 /// CHECK-DAG: Phi
3481 /// CHECK-DAG: InstanceFieldGet
3482 /// CHECK-DAG: Phi
3483 /// CHECK-DAG: InstanceFieldSet
3484 /// CHECK-DAG: InstanceFieldGet
3485
3486 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
3487 /// CHECK-DAG: InstanceFieldSet
3488 /// CHECK-DAG: InstanceFieldSet
3489 /// CHECK-DAG: Phi
3490 /// CHECK-DAG: Phi
3491 /// CHECK-DAG: InstanceFieldGet
3492 /// CHECK-DAG: Phi
3493 /// CHECK-DAG: InstanceFieldSet
3494
3495 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
3496 /// CHECK: InstanceFieldGet
3497 /// CHECK-NOT: InstanceFieldGet
3498
3499 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
3500 /// CHECK: Phi
3501 /// CHECK: Phi
3502 /// CHECK: Phi
3503 /// CHECK-NOT: Phi
3504
3505 // Test heap value clobbering in the nested loop and load elimination for a heap
3506 // location then set to known value before the end of the outer loop.
3507 private static int testNestedLoop2(TestClass obj, int n) {
3508 obj.i = 1;
3509 obj.j = 2;
3510 for (int i = 0; i < n; ++i) {
3511 int tmp = obj.j;
3512 for (int j = i + 1; j < n; ++j) {
3513 $noinline$clobberObservables();
3514 }
3515 obj.i = tmp;
3516 }
3517 return obj.i;
3518 }
3519
3520 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (before)
3521 /// CHECK-DAG: InstanceFieldSet
3522 /// CHECK-DAG: Phi
3523 /// CHECK-DAG: InstanceFieldSet
3524 /// CHECK-DAG: Phi
3525 /// CHECK-DAG: InstanceFieldGet
3526 /// CHECK-DAG: InstanceFieldSet
3527 /// CHECK-DAG: InstanceFieldGet
3528
3529 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
3530 /// CHECK-DAG: InstanceFieldSet
3531 /// CHECK-DAG: Phi
3532 /// CHECK-DAG: Phi
3533 /// CHECK-DAG: InstanceFieldSet
3534 /// CHECK-DAG: Phi
3535 /// CHECK-DAG: InstanceFieldGet
3536 /// CHECK-DAG: InstanceFieldSet
3537
3538 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
3539 /// CHECK: InstanceFieldGet
3540 /// CHECK-NOT: InstanceFieldGet
3541
3542 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
3543 /// CHECK: Phi
3544 /// CHECK: Phi
3545 /// CHECK: Phi
3546 /// CHECK-NOT: Phi
3547
3548 // Test heap value clobbering in the nested loop and load elimination for a heap
3549 // location then set to known value before the end of the outer loop.
3550 private static int testNestedLoop3(TestClass obj, int n) {
3551 obj.i = 1;
3552 for (int i = 0; i < n; ++i) {
3553 obj.j = 2;
3554 for (int j = i + 1; j < n; ++j) {
3555 $noinline$clobberObservables();
3556 }
3557 obj.i = obj.j;
3558 }
3559 return obj.i;
3560 }
3561
3562 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (before)
3563 /// CHECK-DAG: InstanceFieldSet
3564 /// CHECK-DAG: Phi
3565 /// CHECK-DAG: Phi
3566 /// CHECK-DAG: InstanceFieldSet
3567 /// CHECK-DAG: InstanceFieldGet
3568
3569 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
3570 /// CHECK-DAG: InstanceFieldSet
3571 /// CHECK-DAG: Phi
3572 /// CHECK-DAG: Phi
3573 /// CHECK-DAG: Phi
3574 /// CHECK-DAG: Phi
3575 /// CHECK-DAG: InstanceFieldSet
3576
3577 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
3578 /// CHECK-NOT: InstanceFieldGet
3579
3580 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
3581 /// CHECK: Phi
3582 /// CHECK: Phi
3583 /// CHECK: Phi
3584 /// CHECK: Phi
3585 /// CHECK-NOT: Phi
3586
3587 // Test creating loop Phis for both inner and outer loop to eliminate a load.
3588 private static int testNestedLoop4(TestClass obj, int n) {
3589 obj.i = 1;
3590 for (int i = 0; i < n; ++i) {
3591 for (int j = i + 1; j < n; ++j) {
3592 obj.i = 2;
3593 }
3594 }
3595 return obj.i;
3596 }
3597
3598 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (before)
3599 /// CHECK-DAG: InstanceFieldSet
3600 /// CHECK-DAG: Phi
3601 /// CHECK-DAG: InstanceFieldSet
3602 /// CHECK-DAG: Phi
3603 /// CHECK-DAG: InstanceFieldSet
3604 /// CHECK-DAG: InstanceFieldGet
3605
3606 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
3607 /// CHECK-DAG: InstanceFieldSet
3608 /// CHECK-DAG: Phi
3609 /// CHECK-DAG: Phi
3610 /// CHECK-DAG: InstanceFieldSet
3611 /// CHECK-DAG: Phi
3612 /// CHECK-DAG: InstanceFieldSet
3613
3614 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
3615 /// CHECK-NOT: InstanceFieldGet
3616
3617 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
3618 /// CHECK: Phi
3619 /// CHECK: Phi
3620 /// CHECK: Phi
3621 /// CHECK-NOT: Phi
3622
3623 // Test creating a loop Phi for outer loop to eliminate a load.
3624 private static int testNestedLoop5(TestClass obj, int n) {
3625 obj.i = 1;
3626 for (int i = 0; i < n; ++i) {
3627 obj.i = 2;
3628 for (int j = i + 1; j < n; ++j) {
3629 obj.j = 3; // Unrelated.
3630 }
3631 }
3632 return obj.i;
3633 }
3634
3635 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (before)
3636 /// CHECK-DAG: InstanceFieldSet
3637 /// CHECK-DAG: InstanceFieldSet
3638 /// CHECK-DAG: Phi
3639 /// CHECK-DAG: Phi
3640 /// CHECK-DAG: InstanceFieldGet
3641 /// CHECK-DAG: InstanceFieldSet
3642 /// CHECK-DAG: InstanceFieldGet
3643
3644 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
3645 /// CHECK-DAG: InstanceFieldSet
3646 /// CHECK-DAG: InstanceFieldSet
3647 /// CHECK-DAG: Phi
3648 /// CHECK-DAG: Phi
3649 /// CHECK-DAG: Phi
3650 /// CHECK-DAG: Phi
3651 /// CHECK-DAG: InstanceFieldGet
3652 /// CHECK-DAG: InstanceFieldSet
3653
3654 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
3655 /// CHECK: InstanceFieldGet
3656 /// CHECK-NOT: InstanceFieldGet
3657
3658 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
3659 /// CHECK: Phi
3660 /// CHECK: Phi
3661 /// CHECK: Phi
3662 /// CHECK: Phi
3663 /// CHECK-NOT: Phi
3664
3665 // Test heap value clobbering in the nested loop and load elimination for a heap
3666 // location then set to known value before the end of that inner loop.
3667 private static int testNestedLoop6(TestClass obj, int n) {
3668 obj.i = 1;
3669 obj.j = 2;
3670 for (int i = 0; i < n; ++i) {
3671 for (int j = i + 1; j < n; ++j) {
3672 int tmp = obj.j;
3673 $noinline$clobberObservables();
3674 obj.i = tmp;
3675 }
3676 }
3677 return obj.i;
3678 }
3679
3680 /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (before)
3681 /// CHECK-DAG: NewArray
3682 /// CHECK-DAG: Phi
3683 /// CHECK-DAG: Phi
3684 /// CHECK-DAG: ArrayGet
3685 /// CHECK-DAG: InstanceFieldSet
3686
3687 /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after)
3688 /// CHECK-DAG: NewArray
3689 /// CHECK-DAG: Phi
3690 /// CHECK-DAG: Phi
3691 /// CHECK-DAG: InstanceFieldSet
3692
3693 /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after)
3694 /// CHECK-NOT: ArrayGet
3695
3696 // Test load elimination in inner loop reading default value that is loop invariant
3697 // with an index defined inside the inner loop.
3698 private static int testNestedLoop7(TestClass obj, int n) {
3699 // The NewArray is kept as it may throw for negative n.
3700 // TODO: Eliminate constructor fence even though the NewArray is kept.
3701 int[] a0 = new int[n];
3702 for (int i = 0; i < n; ++i) {
3703 for (int j = i + 1; j < n; ++j) {
3704 obj.i = a0[j];
3705 }
3706 }
3707 return n;
3708 }
3709
3710 /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (before)
3711 /// CHECK-DAG: NewInstance
3712 /// CHECK-DAG: InstanceFieldSet
3713 /// CHECK-DAG: Phi
3714 /// CHECK-DAG: Phi
3715 /// CHECK-DAG: NewInstance
3716 /// CHECK-DAG: InstanceFieldSet
3717 /// CHECK-DAG: InstanceFieldGet
3718 /// CHECK-DAG: InstanceFieldGet
3719
3720 /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after)
3721 /// CHECK-DAG: NewInstance
3722 /// CHECK-DAG: InstanceFieldSet
3723 /// CHECK-DAG: Phi
3724 /// CHECK-DAG: Phi
3725 /// CHECK-DAG: Phi
3726 /// CHECK-DAG: Phi
3727 /// CHECK-DAG: NewInstance
3728 /// CHECK-DAG: InstanceFieldSet
3729 /// CHECK-DAG: InstanceFieldGet
3730
3731 /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after)
3732 /// CHECK: InstanceFieldGet
3733 /// CHECK-NOT: InstanceFieldGet
3734
3735 // Test reference type propagation for Phis created for outer and inner loop.
3736 private static int testNestedLoop8(TestClass obj, int n) {
3737 obj.next = new SubTestClass();
3738 for (int i = 0; i < n; ++i) {
3739 for (int j = i + 1; j < n; ++j) {
3740 obj.next = new TestClass();
3741 }
3742 }
3743 // The Phis created in both loop headers for replacing `obj.next` depend on each other.
3744 return obj.next.i;
3745 }
3746
Alex Light9dec90a2020-09-14 17:58:28 -07003747
3748 /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (before)
3749 /// CHECK-DAG: NewArray
3750 /// CHECK-DAG: ArraySet
3751 /// CHECK-DAG: If
3752 /// CHECK-DAG: ArrayGet
3753 /// CHECK-DAG: ArrayGet
3754 /// CHECK-DAG: ArraySet
3755 /// CHECK-DAG: ArrayGet
3756 /// CHECK-DAG: Goto
3757
3758 /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (after)
3759 /// CHECK-DAG: NewArray
3760 /// CHECK-DAG: ArraySet
3761 /// CHECK-DAG: If
3762 /// CHECK-DAG: ArrayGet
3763 /// CHECK-DAG: ArrayGet
3764 /// CHECK-DAG: ArraySet
3765 /// CHECK-DAG: Goto
3766 /// CHECK-NOT: ArrayGet
3767
3768 // Test that we don't incorrectly remove writes needed by later loop iterations
3769 // NB This is fibonacci numbers
3770 private static long testOverlapLoop(int cnt) {
3771 long[] w = new long[cnt];
3772 w[1] = 1;
3773 long t = 1;
3774 for (int i = 2; i < cnt; ++i) {
3775 w[i] = w[i - 1] + w[i - 2];
3776 t = w[i];
3777 }
3778 return t;
3779 }
3780
Alex Light86fe9b82020-11-16 16:54:01 +00003781 private static boolean $noinline$getBoolean(boolean val) {
3782 return val;
3783 }
3784
3785 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (before)
3786 /// CHECK-DAG: ParameterValue
3787 /// CHECK-DAG: NewInstance
3788 /// CHECK-DAG: InvokeStaticOrDirect
3789 /// CHECK-DAG: InstanceFieldSet
3790 /// CHECK-DAG: InvokeStaticOrDirect
3791 /// CHECK-DAG: InstanceFieldGet
3792 /// CHECK-DAG: InstanceFieldGet
3793 /// CHECK-DAG: InstanceFieldSet
3794 /// CHECK-DAG: InstanceFieldGet
3795 /// CHECK-DAG: InstanceFieldGet
3796 /// CHECK-DAG: Phi
3797 //
3798 /// CHECK-NOT: NewInstance
3799 /// CHECK-NOT: InvokeStaticOrDirect
3800 /// CHECK-NOT: InstanceFieldSet
3801 /// CHECK-NOT: InstanceFieldGet
3802 //
3803 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
3804 /// CHECK-DAG: ParameterValue
3805 /// CHECK-DAG: NewInstance
3806 /// CHECK-DAG: Phi
3807 //
3808 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
3809 /// CHECK: InvokeStaticOrDirect
3810 /// CHECK: InvokeStaticOrDirect
3811 //
3812 /// CHECK-NOT: InvokeStaticOrDirect
3813
3814 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
3815 /// CHECK: InstanceFieldSet
3816 //
3817 /// CHECK-NOT: InstanceFieldSet
3818 //
3819 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
3820 /// CHECK: InstanceFieldGet
3821 /// CHECK: InstanceFieldGet
3822 /// CHECK: InstanceFieldGet
3823 //
3824 /// CHECK-NOT: InstanceFieldGet
3825 private static int $noinline$testPartialEscape1(TestClass obj, boolean escape) {
3826 TestClass i = new SubTestClass();
3827 int res;
3828 if ($noinline$getBoolean(escape)) {
3829 i.next = obj;
3830 $noinline$Escape(i);
3831 res = i.next.i;
3832 } else {
3833 i.next = obj;
3834 res = i.next.i;
3835 }
3836 return res;
3837 }
3838
Alex Light3a73ffb2021-01-25 14:11:05 +00003839 /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (before)
3840 /// CHECK-DAG: ParameterValue
3841 /// CHECK-DAG: NewInstance
3842 /// CHECK-DAG: InvokeStaticOrDirect
3843 /// CHECK-DAG: InvokeStaticOrDirect
3844 /// CHECK-DAG: InvokeStaticOrDirect
3845 /// CHECK-DAG: InstanceFieldSet
3846 /// CHECK-DAG: InstanceFieldSet
3847 /// CHECK-DAG: InstanceFieldSet
3848 /// CHECK-DAG: InstanceFieldGet
3849 /// CHECK-DAG: InstanceFieldGet
3850 //
3851 /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
3852 /// CHECK-DAG: ParameterValue
3853 /// CHECK-DAG: NewInstance
3854 /// CHECK-DAG: Phi
3855 //
3856 /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
3857 /// CHECK: InvokeStaticOrDirect
3858 /// CHECK: InvokeStaticOrDirect
3859 /// CHECK: InvokeStaticOrDirect
3860 //
3861 /// CHECK-NOT: InvokeStaticOrDirect
3862
3863 /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
3864 /// CHECK: InstanceFieldSet predicated:false
3865 /// CHECK-NOT: InstanceFieldSet predicated:false
3866 //
3867 /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
3868 /// CHECK: InstanceFieldSet predicated:true
3869 /// CHECK-NOT: InstanceFieldSet predicated:true
3870 //
3871 /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
3872 /// CHECK: InstanceFieldGet
3873 //
3874 /// CHECK-NOT: InstanceFieldGet
3875 //
3876 /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
3877 /// CHECK: PredicatedInstanceFieldGet
3878 //
3879 /// CHECK-NOT: PredicatedInstanceFieldGet
3880 private static int $noinline$testPartialEscape2(TestClass obj, boolean escape) {
3881 TestClass i = new SubTestClass();
3882 if ($noinline$getBoolean(escape)) {
3883 i.next = obj;
3884 $noinline$Escape(i);
3885 } else {
3886 i.next = obj;
3887 }
3888 $noinline$clobberObservables();
3889 // Predicated-get
3890 TestClass res = i.next;
3891 // Predicated-set
3892 i.next = null;
3893 return res.i;
3894 }
3895
3896 /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (before)
3897 /// CHECK-NOT: Phi
3898 /// CHECK-NOT: PredicatedInstanceFieldGet
3899 //
3900 /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (after)
3901 /// CHECK: Phi
3902 /// CHECK: Phi
3903 /// CHECK-NOT: Phi
3904 //
3905 /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (after)
3906 /// CHECK: InstanceFieldSet predicated:true
3907 /// CHECK-NOT: InstanceFieldSet predicated:true
3908 //
3909 /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (after)
3910 /// CHECK: PredicatedInstanceFieldGet
3911 /// CHECK-NOT: PredicatedInstanceFieldGet
3912 private static float $noinline$testPartialEscape3_float(boolean escape) {
3913 TestClass4 tc = new TestClass4();
3914 if ($noinline$getBoolean(escape)) {
3915 $noinline$Escape4(tc);
3916 } else {
3917 tc.floatField -= 1f;
3918 }
3919 // Partial escape
3920 $noinline$clobberObservables();
3921 // Predicated set
3922 tc.floatField *= 10;
3923 // Predicated get
3924 return tc.floatField;
3925 }
3926
3927 /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (before)
3928 /// CHECK-NOT: Phi
3929 /// CHECK-NOT: PredicatedInstanceFieldGet
3930 //
3931 /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (after)
3932 /// CHECK: Phi
3933 /// CHECK: Phi
3934 /// CHECK-NOT: Phi
3935 //
3936 /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (after)
3937 /// CHECK: InstanceFieldSet predicated:true
3938 /// CHECK-NOT: InstanceFieldSet predicated:true
3939 //
3940 /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (after)
3941 /// CHECK: PredicatedInstanceFieldGet
3942 /// CHECK-NOT: PredicatedInstanceFieldGet
3943 private static double $noinline$testPartialEscape3_double(boolean escape) {
3944 TestClass4 tc = new TestClass4();
3945 if ($noinline$getBoolean(escape)) {
3946 $noinline$Escape4(tc);
3947 } else {
3948 tc.doubleField -= 1d;
3949 }
3950 // Partial escape
3951 $noinline$clobberObservables();
3952 // Predicated set
3953 tc.doubleField *= 10;
3954 // Predicated get
3955 return tc.doubleField;
3956 }
3957
3958 /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (before)
3959 /// CHECK-NOT: Phi
3960 /// CHECK-NOT: PredicatedInstanceFieldGet
3961 //
3962 /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (after)
3963 /// CHECK: Phi
3964 /// CHECK: Phi
3965 /// CHECK-NOT: Phi
3966 //
3967 /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (after)
3968 /// CHECK: InstanceFieldSet predicated:true
3969 /// CHECK-NOT: InstanceFieldSet predicated:true
3970 //
3971 /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (after)
3972 /// CHECK: PredicatedInstanceFieldGet
3973 /// CHECK-NOT: PredicatedInstanceFieldGet
3974 private static short $noinline$testPartialEscape3_short(boolean escape) {
3975 TestClass4 tc = new TestClass4();
3976 if ($noinline$getBoolean(escape)) {
3977 $noinline$Escape4(tc);
3978 } else {
3979 tc.shortField -= 1;
3980 }
3981 // Partial escape
3982 $noinline$clobberObservables();
3983 // Predicated set
3984 tc.shortField *= 10;
3985 // Predicated get
3986 return tc.shortField;
3987 }
3988
3989 /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (before)
3990 /// CHECK-NOT: Phi
3991 /// CHECK-NOT: PredicatedInstanceFieldGet
3992 //
3993 /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (after)
3994 /// CHECK: Phi
3995 /// CHECK: Phi
3996 /// CHECK-NOT: Phi
3997 //
3998 /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (after)
3999 /// CHECK: InstanceFieldSet predicated:true
4000 /// CHECK-NOT: InstanceFieldSet predicated:true
4001 //
4002 /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (after)
4003 /// CHECK: PredicatedInstanceFieldGet
4004 /// CHECK-NOT: PredicatedInstanceFieldGet
4005 private static byte $noinline$testPartialEscape3_byte(boolean escape) {
4006 TestClass4 tc = new TestClass4();
4007 if ($noinline$getBoolean(escape)) {
4008 $noinline$Escape4(tc);
4009 } else {
4010 tc.byteField -= 1;
4011 }
4012 // Partial escape
4013 $noinline$clobberObservables();
4014 // Predicated set
4015 tc.byteField *= 10;
4016 // Predicated get
4017 return tc.byteField;
4018 }
4019
4020 /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (before)
4021 /// CHECK-NOT: Phi
4022 /// CHECK-NOT: PredicatedInstanceFieldGet
4023 //
4024 /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (after)
4025 /// CHECK: Phi
4026 /// CHECK: Phi
4027 /// CHECK-NOT: Phi
4028 //
4029 /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (after)
4030 /// CHECK: InstanceFieldSet predicated:true
4031 /// CHECK-NOT: InstanceFieldSet predicated:true
4032 //
4033 /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (after)
4034 /// CHECK: PredicatedInstanceFieldGet
4035 /// CHECK-NOT: PredicatedInstanceFieldGet
4036 private static int $noinline$testPartialEscape3_int(boolean escape) {
4037 TestClass4 tc = new TestClass4();
4038 if ($noinline$getBoolean(escape)) {
4039 $noinline$Escape4(tc);
4040 } else {
4041 tc.intField -= 1;
4042 }
4043 // Partial escape
4044 $noinline$clobberObservables();
4045 // Predicated set
4046 tc.intField *= 10;
4047 // Predicated get
4048 return tc.intField;
4049 }
4050
4051 /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (before)
4052 /// CHECK-NOT: Phi
4053 /// CHECK-NOT: PredicatedInstanceFieldGet
4054 //
4055 /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (after)
4056 /// CHECK: Phi
4057 /// CHECK: Phi
4058 /// CHECK-NOT: Phi
4059 //
4060 /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (after)
4061 /// CHECK: InstanceFieldSet predicated:true
4062 /// CHECK-NOT: InstanceFieldSet predicated:true
4063 //
4064 /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (after)
4065 /// CHECK: PredicatedInstanceFieldGet
4066 /// CHECK-NOT: PredicatedInstanceFieldGet
4067 private static long $noinline$testPartialEscape3_long(boolean escape) {
4068 TestClass4 tc = new TestClass4();
4069 if ($noinline$getBoolean(escape)) {
4070 $noinline$Escape4(tc);
4071 } else {
4072 tc.longField -= 1;
4073 }
4074 // Partial escape
4075 $noinline$clobberObservables();
4076 // Predicated set
4077 tc.longField *= 10;
4078 // Predicated get
4079 return tc.longField;
4080 }
Alex Light86fe9b82020-11-16 16:54:01 +00004081
Vladimir Marko3224f382020-06-23 14:19:53 +01004082 private static void $noinline$clobberObservables() {}
4083
Alex Light9dec90a2020-09-14 17:58:28 -07004084 static void assertLongEquals(long result, long expected) {
4085 if (expected != result) {
4086 throw new Error("Expected: " + expected + ", found: " + result);
4087 }
4088 }
4089
Mingyao Yang062157f2016-03-02 10:15:36 -08004090 static void assertIntEquals(int result, int expected) {
Mingyao Yang8df69d42015-10-22 15:40:58 -07004091 if (expected != result) {
4092 throw new Error("Expected: " + expected + ", found: " + result);
4093 }
4094 }
4095
Mingyao Yang062157f2016-03-02 10:15:36 -08004096 static void assertFloatEquals(float result, float expected) {
Mingyao Yang8df69d42015-10-22 15:40:58 -07004097 if (expected != result) {
4098 throw new Error("Expected: " + expected + ", found: " + result);
4099 }
4100 }
4101
Mingyao Yang062157f2016-03-02 10:15:36 -08004102 static void assertDoubleEquals(double result, double expected) {
Mingyao Yang8df69d42015-10-22 15:40:58 -07004103 if (expected != result) {
4104 throw new Error("Expected: " + expected + ", found: " + result);
4105 }
4106 }
4107
Vladimir Markob122cd62020-06-11 09:15:21 +00004108 public static void main(String[] args) {
Mingyao Yang8df69d42015-10-22 15:40:58 -07004109 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
4110 assertIntEquals(test1(new TestClass(), new TestClass()), 3);
4111 assertIntEquals(test2(new TestClass()), 1);
4112 TestClass obj1 = new TestClass();
4113 TestClass obj2 = new TestClass();
4114 obj1.next = obj2;
4115 assertIntEquals(test3(obj1), 10);
Vladimir Markob122cd62020-06-11 09:15:21 +00004116 assertIntEquals(test4(new TestClass(), true), 1);
4117 assertIntEquals(test4(new TestClass(), false), 1);
4118 assertIntEquals(test5(new TestClass(), true), 1);
4119 assertIntEquals(test5(new TestClass(), false), 2);
Mingyao Yang8df69d42015-10-22 15:40:58 -07004120 assertIntEquals(test6(new TestClass(), new TestClass(), true), 4);
4121 assertIntEquals(test6(new TestClass(), new TestClass(), false), 2);
4122 assertIntEquals(test7(new TestClass()), 1);
4123 assertIntEquals(test8(), 1);
4124 obj1 = new TestClass();
4125 obj2 = new TestClass();
4126 obj1.next = obj2;
4127 assertIntEquals(test9(new TestClass()), 1);
Vladimir Markofaada5e2020-06-10 10:38:40 +00004128 assertIntEquals(test10(new TestClass(3, 4)), 3);
Mingyao Yang8df69d42015-10-22 15:40:58 -07004129 assertIntEquals(TestClass.si, 3);
4130 assertIntEquals(test11(new TestClass()), 10);
4131 assertIntEquals(test12(new TestClass(), new TestClass()), 10);
4132 assertIntEquals(test13(new TestClass(), new TestClass2()), 3);
4133 SubTestClass obj3 = new SubTestClass();
4134 assertIntEquals(test14(obj3, obj3), 2);
4135 assertIntEquals(test15(), 2);
4136 assertIntEquals(test16(), 3);
4137 assertIntEquals(test17(), 0);
4138 assertIntEquals(test18(new TestClass()), 1);
4139 float[] fa1 = { 0.8f };
4140 float[] fa2 = { 1.8f };
4141 assertFloatEquals(test19(fa1, fa2), 1.8f);
4142 assertFloatEquals(test20().i, 0);
Mingyao Yang803cbb92015-12-01 12:24:36 -08004143 test21(new TestClass());
Mingyao Yangfb8464a2015-11-02 10:56:59 -08004144 assertIntEquals(test22(), 13);
Vladimir Markob122cd62020-06-11 09:15:21 +00004145 assertIntEquals(test23(true), 4);
4146 assertIntEquals(test23(false), 5);
4147 assertFloatEquals(test24(), 8.0f);
Vladimir Marko3224f382020-06-23 14:19:53 +01004148 assertIntEquals(test25(false, true, true), 5);
4149 assertIntEquals(test25(true, false, true), 2);
4150 assertFloatEquals(test26(5), 0.0f);
4151 assertFloatEquals(test26(3), 1.0f);
4152 assertIntEquals(test27(false, true), 1);
4153 assertIntEquals(test27(true, false), 1);
4154 assertIntEquals(test28(false, true), 0);
4155 assertIntEquals(test28(true, true), 5);
4156 assertFloatEquals(test29(true), 5.0f);
4157 assertFloatEquals(test29(false), 2.0f);
4158 assertIntEquals(test30(new TestClass(), true), 1);
4159 assertIntEquals(test30(new TestClass(), false), 0);
4160 assertIntEquals(test31(true, true), 5);
4161 assertIntEquals(test31(true, false), 6);
4162 assertIntEquals(test32(1), 10);
4163 assertIntEquals(test32(2), 10);
4164 assertIntEquals(test33(new TestClass(), true), 1);
4165 assertIntEquals(test33(new TestClass(), false), 2);
4166 assertIntEquals(test34(new TestClass(), true, true), 3);
4167 assertIntEquals(test34(new TestClass(), false, true), 4);
4168 assertIntEquals(test34(new TestClass(), true, false), 1);
4169 assertIntEquals(test34(new TestClass(), false, false), 2);
4170 assertIntEquals(test35(new TestClass(), true, true), 3);
4171 assertIntEquals(test35(new TestClass(), false, true), 2);
4172 assertIntEquals(test35(new TestClass(), true, false), 1);
4173 assertIntEquals(test35(new TestClass(), false, false), 2);
4174 assertIntEquals(test36(new TestClass(), true), 2);
4175 assertIntEquals(test36(new TestClass(), false), 4);
4176 assertIntEquals(test37(new TestClass(), true), 1);
4177 assertIntEquals(test37(new TestClass(), false), 0);
4178 assertIntEquals(test38(new TestClass(), true), 1);
4179 assertIntEquals(test38(new TestClass(), false), 2);
4180 assertIntEquals(test39(new TestClass(), true), 0);
4181 assertIntEquals(test39(new TestClass(), false), 1);
4182
Mingyao Yangfb8464a2015-11-02 10:56:59 -08004183 testFinalizableByForcingGc();
Mingyao Yang40bcb932016-02-03 05:46:57 -08004184 assertIntEquals($noinline$testHSelect(true), 0xdead);
Mingyao Yang062157f2016-03-02 10:15:36 -08004185 int[] array = {2, 5, 9, -1, -3, 10, 8, 4};
4186 assertIntEquals(sumWithinRange(array, 1, 5), 11);
Mingyao Yang0a845202016-10-14 16:26:08 -07004187 assertFloatEquals(testAllocationEliminationWithLoops(), 1.0f);
4188 assertFloatEquals(mF, 0f);
Mingyao Yang58d9bfc2016-11-01 13:31:58 -07004189 assertDoubleEquals(Math.PI * Math.PI * Math.PI, getCircleArea(Math.PI, true));
4190 assertDoubleEquals(0d, getCircleArea(Math.PI, false));
Mingyao Yange58bdca2016-10-28 11:07:24 -07004191
Vladimir Marko4307cd72020-07-17 14:35:56 +01004192 assertIntEquals($noinline$testConversion1(new TestClass(), 300), 300);
4193 assertIntEquals($noinline$testConversion1(new TestClass(), 301), 45);
4194 assertIntEquals($noinline$testConversion2(new TestClass(), 300), 300);
4195 assertIntEquals($noinline$testConversion2(new TestClass(), 301), 90);
Vladimir Marko3224f382020-06-23 14:19:53 +01004196 assertIntEquals($noinline$testConversion3(new TestClass(), 0), 0);
4197 assertIntEquals($noinline$testConversion3(new TestClass(), 1), 0);
4198 assertIntEquals($noinline$testConversion3(new TestClass(), 128), 127);
4199 assertIntEquals($noinline$testConversion3(new TestClass(), 129), -128);
4200 assertIntEquals($noinline$testConversion4(new TestClass(), 0), 0);
4201 assertIntEquals($noinline$testConversion4(new TestClass(), 1), 0);
4202 assertIntEquals($noinline$testConversion4(new TestClass(), 128), 254);
4203 assertIntEquals($noinline$testConversion4(new TestClass(), 129), -256);
Vladimir Marko4307cd72020-07-17 14:35:56 +01004204
Mingyao Yange58bdca2016-10-28 11:07:24 -07004205 int[] iarray = {0, 0, 0};
4206 double[] darray = {0d, 0d, 0d};
4207 try {
4208 assertDoubleEquals(Math.PI * Math.PI * Math.PI, testDeoptimize(iarray, darray, Math.PI));
4209 } catch (Exception e) {
Vladimir Markob122cd62020-06-11 09:15:21 +00004210 System.out.println(e.getClass().getName());
Mingyao Yange58bdca2016-10-28 11:07:24 -07004211 }
4212 assertIntEquals(iarray[0], 1);
4213 assertIntEquals(iarray[1], 1);
4214 assertIntEquals(iarray[2], 1);
4215 assertDoubleEquals(darray[0], Math.PI);
4216 assertDoubleEquals(darray[1], Math.PI);
4217 assertDoubleEquals(darray[2], Math.PI);
Mingyao Yang86974902017-03-01 14:03:51 -08004218
4219 assertIntEquals(testAllocationEliminationOfArray1(), 11);
4220 assertIntEquals(testAllocationEliminationOfArray2(), 11);
4221 assertIntEquals(testAllocationEliminationOfArray3(2), 4);
4222 assertIntEquals(testAllocationEliminationOfArray4(2), 6);
Mingyao Yang7cf9af22018-02-06 15:02:42 -08004223 assertIntEquals(testAllocationEliminationOfArray5(2), 12);
4224 try {
4225 testAllocationEliminationOfArray5(-2);
4226 } catch (NegativeArraySizeException e) {
4227 System.out.println("Got NegativeArraySizeException.");
4228 }
Mingyao Yangeb2d2d346e2017-03-02 13:26:17 -08004229
4230 assertIntEquals(testStoreStore().i, 41);
4231 assertIntEquals(testStoreStore().j, 43);
Mingyao Yang293f1c02017-11-08 15:22:17 -08004232
Mingyao Yang46721ef2017-10-05 14:45:17 -07004233 assertIntEquals(testExitMerge(true), 2);
4234 assertIntEquals(testExitMerge2(true), 2);
4235 assertIntEquals(testExitMerge2(false), 2);
4236
Mingyao Yanga3540532018-01-25 12:17:28 -08004237 TestClass2 testclass2 = new TestClass2();
4238 testStoreStore2(testclass2);
4239 assertIntEquals(testclass2.i, 43);
4240 assertIntEquals(testclass2.j, 44);
4241
4242 testStoreStore3(testclass2, true);
4243 assertIntEquals(testclass2.i, 41);
4244 assertIntEquals(testclass2.j, 43);
4245 testStoreStore3(testclass2, false);
4246 assertIntEquals(testclass2.i, 41);
4247 assertIntEquals(testclass2.j, 44);
4248
4249 testStoreStore4();
4250 assertIntEquals(TestClass.si, 62);
4251
4252 int ret = testStoreStore5(testclass2, testclass2);
4253 assertIntEquals(testclass2.i, 72);
4254 assertIntEquals(ret, 71);
4255
4256 testclass2.j = 88;
4257 ret = testStoreStore6(testclass2, testclass2);
4258 assertIntEquals(testclass2.i, 82);
4259 assertIntEquals(ret, 88);
4260
4261 ret = testNoSideEffects(iarray);
Mingyao Yang293f1c02017-11-08 15:22:17 -08004262 assertIntEquals(iarray[0], 101);
Mingyao Yanga3540532018-01-25 12:17:28 -08004263 assertIntEquals(iarray[1], 103);
Mingyao Yang293f1c02017-11-08 15:22:17 -08004264 assertIntEquals(ret, 108);
Mingyao Yanga3540532018-01-25 12:17:28 -08004265
4266 try {
4267 testThrow(testclass2, new Exception());
4268 } catch (Exception e) {}
4269 assertIntEquals(testclass2.i, 55);
4270
4271 assertIntEquals(testStoreStoreWithDeoptimize(new int[4]), 4);
Aart Bik4dc09e72018-05-11 14:40:31 -07004272
Vladimir Marko4307cd72020-07-17 14:35:56 +01004273 assertIntEquals($noinline$testByteArrayDefaultValue(), 0);
4274
Aart Bik4dc09e72018-05-11 14:40:31 -07004275 assertIntEquals(testLocalArrayMerge1(true), 1);
4276 assertIntEquals(testLocalArrayMerge1(false), 1);
4277 assertIntEquals(testLocalArrayMerge2(true), 2);
4278 assertIntEquals(testLocalArrayMerge2(false), 3);
4279 assertIntEquals(testLocalArrayMerge3(true), 2);
4280 assertIntEquals(testLocalArrayMerge3(false), 1);
4281 assertIntEquals(testLocalArrayMerge4(true), 2);
4282 assertIntEquals(testLocalArrayMerge4(false), 2);
Vladimir Marko3224f382020-06-23 14:19:53 +01004283 assertIntEquals(testLocalArrayMerge5(new int[]{ 7 }, true), 7);
4284 assertIntEquals(testLocalArrayMerge5(new int[]{ 9 }, false), 9);
4285 assertIntEquals(testLocalArrayMerge6(new int[1], true, true), 1);
4286 assertIntEquals(testLocalArrayMerge6(new int[1], true, false), 2);
4287 assertIntEquals(testLocalArrayMerge6(new int[1], false, true), 2);
4288 assertIntEquals(testLocalArrayMerge6(new int[1], false, false), 1);
4289 assertIntEquals(testLocalArrayMerge7(new int[2], true, true), 1);
4290 assertIntEquals(testLocalArrayMerge7(new int[2], true, false), 2);
4291 assertIntEquals(testLocalArrayMerge7(new int[2], false, true), 0);
4292 assertIntEquals(testLocalArrayMerge7(new int[2], false, false), 0);
Vladimir Markocbeedc82020-08-25 14:31:10 +01004293 assertIntEquals(testLocalArrayMerge8(true), 0);
4294 assertIntEquals(testLocalArrayMerge8(false), 0);
Vladimir Markofab6f1c2020-07-14 16:25:05 +01004295
4296 TestClass[] tca = new TestClass[] { new TestClass(), null };
4297 try {
4298 $noinline$testThrowingArraySet(tca, new TestClass2());
4299 } catch (ArrayStoreException expected) {
4300 if (tca[0] != null) {
4301 throw new Error("tca[0] is not null");
4302 }
4303 if (tca[1] == null) {
4304 throw new Error("tca[1] is null");
4305 }
4306 }
Mingyao Yang40bcb932016-02-03 05:46:57 -08004307
Vladimir Marko3224f382020-06-23 14:19:53 +01004308 assertIntEquals(testLoop1(new TestClass(), 0), 0);
4309 assertIntEquals(testLoop1(new TestClass(), 1), 0);
4310 assertIntEquals(testLoop1(new TestClass(), 2), 1);
4311 assertIntEquals(testLoop1(new TestClass(), 3), 2);
4312 assertIntEquals(testLoop2(new TestClass(), 0), 1);
4313 assertIntEquals(testLoop2(new TestClass(), 1), 1);
4314 assertIntEquals(testLoop2(new TestClass(), 2), 1);
4315 assertIntEquals(testLoop2(new TestClass(), 3), 1);
4316 assertIntEquals(testLoop3(new TestClass(), 0), 1);
4317 assertIntEquals(testLoop3(new TestClass(), 1), 1);
4318 assertIntEquals(testLoop3(new TestClass(), 2), 1);
4319 assertIntEquals(testLoop3(new TestClass(), 3), 1);
4320 assertIntEquals(testLoop4(new TestClass(), 0), 0);
4321 assertIntEquals(testLoop4(new TestClass(), 1), 1);
4322 assertIntEquals(testLoop4(new TestClass(), 2), 2);
4323 assertIntEquals(testLoop4(new TestClass(), 3), 3);
4324 assertIntEquals(testLoop5(new TestClass(), 0), 0);
4325 assertIntEquals(testLoop5(new TestClass(), 1), 1);
4326 assertIntEquals(testLoop5(new TestClass(), 2), 2);
4327 assertIntEquals(testLoop5(new TestClass(), 3), 3);
4328 assertIntEquals(testLoop6(new TestClass(), 0), 0);
4329 assertIntEquals(testLoop6(new TestClass(), 1), 1);
4330 assertIntEquals(testLoop6(new TestClass(), 2), 2);
4331 assertIntEquals(testLoop6(new TestClass(), 3), 3);
4332 assertIntEquals(testLoop7(0), 0);
4333 assertIntEquals(testLoop7(1), 0);
4334 assertIntEquals(testLoop7(2), 0);
4335 assertIntEquals(testLoop7(3), 0);
4336 assertIntEquals(testLoop8(0), 1);
4337 assertIntEquals(testLoop8(1), 0);
4338 assertIntEquals(testLoop8(2), 1);
4339 assertIntEquals(testLoop8(3), 0);
4340 assertIntEquals(testLoop9(new TestClass(), 0), 0);
4341 assertIntEquals(testLoop9(new TestClass(), 1), 1);
4342 assertIntEquals(testLoop9(new TestClass(), 2), 2);
4343 assertIntEquals(testLoop9(new TestClass(), 3), 3);
4344 assertIntEquals(testLoop10(new TestClass(), 0), 2);
4345 assertIntEquals(testLoop10(new TestClass(), 1), 2);
4346 assertIntEquals(testLoop10(new TestClass(), 2), 2);
4347 assertIntEquals(testLoop10(new TestClass(), 3), 2);
4348 assertIntEquals(testLoop11(new TestClass(), 0), 1);
4349 assertIntEquals(testLoop11(new TestClass(), 1), 3);
4350 assertIntEquals(testLoop11(new TestClass(), 2), 2);
4351 assertIntEquals(testLoop11(new TestClass(), 3), 3);
4352 assertIntEquals(testLoop12(new TestClass(), 0), 1);
4353 assertIntEquals(testLoop12(new TestClass(), 1), 2);
4354 assertIntEquals(testLoop12(new TestClass(), 2), 3);
4355 assertIntEquals(testLoop12(new TestClass(), 3), 2);
4356 assertIntEquals(testLoop13(new TestClass(1, 2), 0), 0);
4357 assertIntEquals(testLoop13(new TestClass(1, 2), 1), 0);
4358 assertIntEquals(testLoop13(new TestClass(1, 2), 2), 0);
4359 assertIntEquals(testLoop13(new TestClass(1, 2), 3), 1);
4360 assertIntEquals(testLoop14(new TestClass2(), 0), 0);
4361 assertIntEquals(testLoop14(new TestClass2(), 1), 0);
4362 assertIntEquals(testLoop14(new TestClass2(), 2), 0);
4363 assertIntEquals(testLoop14(new TestClass2(), 3), 1);
4364 assertIntEquals(testLoop15(0), 0);
4365 assertIntEquals(testLoop15(1), 1);
4366 assertIntEquals(testLoop15(2), 1);
4367 assertIntEquals(testLoop15(3), 1);
4368 assertIntEquals(testLoop16(new TestClass(), 0), 0);
4369 assertIntEquals(testLoop16(new TestClass(), 1), 1);
4370 assertIntEquals(testLoop16(new TestClass(), 2), 2);
4371 assertIntEquals(testLoop16(new TestClass(), 3), 3);
4372 assertIntEquals(testLoop17(new TestClass(), 0), 2);
4373 assertIntEquals(testLoop17(new TestClass(), 1), 4);
4374 assertIntEquals(testLoop17(new TestClass(), 2), 2);
4375 assertIntEquals(testLoop17(new TestClass(), 3), 4);
4376 assertIntEquals(testLoop18(new TestClass(), 0), 0);
4377 assertIntEquals(testLoop18(new TestClass(), 1), 1);
4378 assertIntEquals(testLoop18(new TestClass(), 2), 2);
4379 assertIntEquals(testLoop18(new TestClass(), 3), 3);
4380 assertIntEquals(testLoop19(new TestClass(), 0), 0);
4381 assertIntEquals(testLoop19(new TestClass(), 1), 1);
4382 assertIntEquals(testLoop19(new TestClass(), 2), 2);
4383 assertIntEquals(testLoop19(new TestClass(), 3), 3);
4384 assertIntEquals(testLoop20(new TestClass(), 0), 0);
4385 assertIntEquals(testLoop20(new TestClass(), 1), 1);
4386 assertIntEquals(testLoop20(new TestClass(), 2), 2);
4387 assertIntEquals(testLoop20(new TestClass(), 3), 3);
4388 assertIntEquals(testLoop21(new TestClass(), 0), 0);
4389 assertIntEquals(testLoop21(new TestClass(), 1), 1);
4390 assertIntEquals(testLoop21(new TestClass(), 2), 2);
4391 assertIntEquals(testLoop21(new TestClass(), 3), 3);
4392 assertIntEquals(testLoop22(new TestClass(), 0), 0);
4393 assertIntEquals(testLoop22(new TestClass(), 1), 1);
4394 assertIntEquals(testLoop22(new TestClass(), 2), 2);
4395 assertIntEquals(testLoop22(new TestClass(), 3), 3);
4396 assertIntEquals(testLoop23(new TestClass(), 0), -1);
4397 assertIntEquals(testLoop23(new TestClass(), 1), 2);
4398 assertIntEquals(testLoop23(new TestClass(), 2), 1);
4399 assertIntEquals(testLoop23(new TestClass(), 3), 2);
4400 assertIntEquals(testLoop24(new TestClass(), 0), -1);
4401 assertIntEquals(testLoop24(new TestClass(), 1), 2);
4402 assertIntEquals(testLoop24(new TestClass(), 2), 1);
4403 assertIntEquals(testLoop24(new TestClass(), 3), -2);
4404 assertIntEquals(testLoop25(new TestClass(), 0), 2);
4405 assertIntEquals(testLoop25(new TestClass(), 1), 2);
4406 assertIntEquals(testLoop25(new TestClass(), 2), 4);
4407 assertIntEquals(testLoop25(new TestClass(), 3), -1);
4408 assertIntEquals(testLoop26(new TestClass(), 0), 1);
4409 assertIntEquals(testLoop26(new TestClass(), 1), 0);
4410 assertIntEquals(testLoop26(new TestClass(), 2), 0);
4411 assertIntEquals(testLoop26(new TestClass(), 3), 0);
4412 assertIntEquals(testLoop27(new TestClass(), 0), 1);
4413 assertIntEquals(testLoop27(new TestClass(), 1), 1);
4414 assertIntEquals(testLoop27(new TestClass(), 2), 0);
4415 assertIntEquals(testLoop27(new TestClass(), 3), 0);
4416 assertIntEquals(testLoop28(new TestClass(1, 2), 0), 0);
4417 assertIntEquals(testLoop28(new TestClass(1, 2), 1), 0);
4418 assertIntEquals(testLoop28(new TestClass(1, 2), 2), 0);
4419 assertIntEquals(testLoop28(new TestClass(1, 2), 3), 1);
4420 assertIntEquals(testLoop29(0), 0);
4421 assertIntEquals(testLoop29(1), 1);
4422 assertIntEquals(testLoop29(2), 3);
4423 assertIntEquals(testLoop29(3), 6);
4424 assertIntEquals(testLoop30(0), 0);
4425 assertIntEquals(testLoop30(1), 1);
4426 assertIntEquals(testLoop30(2), 2);
4427 assertIntEquals(testLoop30(3), 3);
4428 assertIntEquals(testLoop31(0), 0);
4429 assertIntEquals(testLoop31(1), 0);
4430 assertIntEquals(testLoop31(2), 0);
4431 assertIntEquals(testLoop31(3), 0);
4432 assertIntEquals(testLoop32(new TestClass(), 0), -1);
4433 assertIntEquals(testLoop32(new TestClass(), 1), 2);
4434 assertIntEquals(testLoop32(new TestClass(), 2), 1);
4435 assertIntEquals(testLoop32(new TestClass(), 3), -2);
4436 assertIntEquals(testLoop33(new TestClass(), 0), 0);
4437 assertIntEquals(testLoop33(new TestClass(), 1), 0);
4438 assertIntEquals(testLoop33(new TestClass(), 2), 0);
4439 assertIntEquals(testLoop33(new TestClass(), 3), 0);
Vladimir Marko0571d472020-09-22 10:14:39 +01004440 assertIntEquals(testLoop34(0), 0);
4441 assertIntEquals(testLoop34(1), 1);
4442 assertIntEquals(testLoop34(2), 3);
4443 assertIntEquals(testLoop34(3), 6);
4444 assertIntEquals(testLoop35(0), 0);
4445 assertIntEquals(testLoop35(1), 1);
4446 assertIntEquals(testLoop35(2), 3);
4447 assertIntEquals(testLoop35(3), 6);
Vladimir Marko3224f382020-06-23 14:19:53 +01004448
4449 assertIntEquals(testNestedLoop1(new TestClass(), 0), 1);
4450 assertIntEquals(testNestedLoop1(new TestClass(), 1), 1);
4451 assertIntEquals(testNestedLoop1(new TestClass(), 2), 1);
4452 assertIntEquals(testNestedLoop1(new TestClass(), 3), 1);
4453 assertIntEquals(testNestedLoop2(new TestClass(), 0), 1);
4454 assertIntEquals(testNestedLoop2(new TestClass(), 1), 2);
4455 assertIntEquals(testNestedLoop2(new TestClass(), 2), 2);
4456 assertIntEquals(testNestedLoop2(new TestClass(), 3), 2);
4457 assertIntEquals(testNestedLoop3(new TestClass(), 0), 1);
4458 assertIntEquals(testNestedLoop3(new TestClass(), 1), 2);
4459 assertIntEquals(testNestedLoop3(new TestClass(), 2), 2);
4460 assertIntEquals(testNestedLoop3(new TestClass(), 3), 2);
4461 assertIntEquals(testNestedLoop4(new TestClass(), 0), 1);
4462 assertIntEquals(testNestedLoop4(new TestClass(), 1), 1);
4463 assertIntEquals(testNestedLoop4(new TestClass(), 2), 2);
4464 assertIntEquals(testNestedLoop4(new TestClass(), 3), 2);
4465 assertIntEquals(testNestedLoop5(new TestClass(), 0), 1);
4466 assertIntEquals(testNestedLoop5(new TestClass(), 1), 2);
4467 assertIntEquals(testNestedLoop5(new TestClass(), 2), 2);
4468 assertIntEquals(testNestedLoop5(new TestClass(), 3), 2);
4469 assertIntEquals(testNestedLoop6(new TestClass(), 0), 1);
4470 assertIntEquals(testNestedLoop6(new TestClass(), 1), 1);
4471 assertIntEquals(testNestedLoop6(new TestClass(), 2), 2);
4472 assertIntEquals(testNestedLoop6(new TestClass(), 3), 2);
4473 assertIntEquals(testNestedLoop7(new TestClass(), 0), 0);
4474 assertIntEquals(testNestedLoop7(new TestClass(), 1), 1);
4475 assertIntEquals(testNestedLoop7(new TestClass(), 2), 2);
4476 assertIntEquals(testNestedLoop7(new TestClass(), 3), 3);
4477 assertIntEquals(testNestedLoop8(new TestClass(), 0), 0);
4478 assertIntEquals(testNestedLoop8(new TestClass(), 1), 0);
4479 assertIntEquals(testNestedLoop8(new TestClass(), 2), 0);
4480 assertIntEquals(testNestedLoop8(new TestClass(), 3), 0);
Alex Light9dec90a2020-09-14 17:58:28 -07004481 assertLongEquals(testOverlapLoop(10), 34l);
4482 assertLongEquals(testOverlapLoop(50), 7778742049l);
Alex Light86fe9b82020-11-16 16:54:01 +00004483 assertIntEquals($noinline$testPartialEscape1(new TestClass(), true), 1);
4484 assertIntEquals($noinline$testPartialEscape1(new TestClass(), false), 0);
Alex Light3a73ffb2021-01-25 14:11:05 +00004485 assertIntEquals($noinline$testPartialEscape2(new TestClass(), true), 1);
4486 assertIntEquals($noinline$testPartialEscape2(new TestClass(), false), 0);
4487 assertDoubleEquals($noinline$testPartialEscape3_double(true), -20d);
4488 assertDoubleEquals($noinline$testPartialEscape3_double(false), -40d);
4489 assertFloatEquals($noinline$testPartialEscape3_float(true), -20f);
4490 assertFloatEquals($noinline$testPartialEscape3_float(false), -40f);
4491 assertIntEquals($noinline$testPartialEscape3_int(true), -20);
4492 assertIntEquals($noinline$testPartialEscape3_int(false), -40);
4493 assertIntEquals($noinline$testPartialEscape3_byte(true), -20);
4494 assertIntEquals($noinline$testPartialEscape3_byte(false), -40);
4495 assertIntEquals($noinline$testPartialEscape3_short(true), -20);
4496 assertIntEquals($noinline$testPartialEscape3_short(false), -40);
4497 assertLongEquals($noinline$testPartialEscape3_long(true), -20);
4498 assertLongEquals($noinline$testPartialEscape3_long(false), -40);
Vladimir Marko3224f382020-06-23 14:19:53 +01004499 }
Mingyao Yang8df69d42015-10-22 15:40:58 -07004500}