blob: 5d55d3e3825b1c4c7443b43bc21d6da26136e4b4 [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
Santiago Aboy Solanes42f1af82022-04-22 16:20:39 +01001024 /// CHECK-DAG: InstanceFieldSet
1025 /// CHECK-DAG: <<Phi:i\d+>> Phi
Vladimir Marko3224f382020-06-23 14:19:53 +01001026
1027 /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (after)
1028 /// CHECK: InstanceFieldSet
Santiago Aboy Solanes42f1af82022-04-22 16:20:39 +01001029 /// CHECK: InstanceFieldSet
Vladimir Marko3224f382020-06-23 14:19:53 +01001030 /// CHECK-NOT: InstanceFieldSet
1031
Santiago Aboy Solanes42f1af82022-04-22 16:20:39 +01001032 // Test that we are not eliminating the if/else sets to `obj.i`. We have `NullCheck`s on `obj`
1033 // when doing `obj.i`. Since `NullCheck` can throw, we save the stores.
1034 // The 3rd `obj.i` set is redundant and can be eliminated. It will have the same value and it is
1035 // not needed.
Vladimir Marko3224f382020-06-23 14:19:53 +01001036 static int test33(TestClass obj, boolean x) {
1037 int phi;
1038 if (x) {
1039 obj.i = 1;
1040 phi = 1;
1041 } else {
1042 obj.i = 2;
1043 phi = 2;
1044 }
1045 obj.i = phi;
1046 return phi;
1047 }
1048
1049 /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (before)
1050 /// CHECK-DAG: InstanceFieldSet
1051 /// CHECK-DAG: InstanceFieldSet
1052 /// CHECK-DAG: <<Phi:i\d+>> Phi
1053 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Phi>>]
1054
1055 /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (after)
1056 /// CHECK-DAG: InstanceFieldSet
1057 /// CHECK-DAG: InstanceFieldSet
1058 /// CHECK-DAG: Phi
1059
1060 /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (after)
1061 /// CHECK: InstanceFieldSet
1062 /// CHECK: InstanceFieldSet
1063 /// CHECK-NOT: InstanceFieldSet
1064
1065 // Test eliminating a store that writes a Phi equivalent to merged
1066 // heap values of observable stores.
1067 static int test34(TestClass obj, boolean x, boolean y) {
1068 int phi;
1069 if (x) {
1070 obj.i = 1;
1071 phi = 1;
1072 if (y) {
1073 return 3;
1074 }
1075 } else {
1076 obj.i = 2;
1077 phi = 2;
1078 if (y) {
1079 return 4;
1080 }
1081 }
1082 obj.i = phi;
1083 return phi;
1084 }
1085
1086 /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (before)
1087 /// CHECK-DAG: InstanceFieldSet
1088 /// CHECK-DAG: InstanceFieldSet
1089 /// CHECK-DAG: InstanceFieldSet
1090 /// CHECK-DAG: InstanceFieldSet
1091 /// CHECK-DAG: InstanceFieldGet
1092
1093 /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (after)
1094 /// CHECK-DAG: InstanceFieldSet
1095 /// CHECK-DAG: InstanceFieldSet
1096 /// CHECK-DAG: InstanceFieldSet
1097 /// CHECK-DAG: InstanceFieldSet
1098 /// CHECK-DAG: Phi
1099 /// CHECK-DAG: Phi
1100 /// CHECK-DAG: Phi
1101
1102 /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (after)
1103 /// CHECK-NOT: InstanceFieldGet
1104
1105 // Test Phi creation for load elimination.
1106 static int test35(TestClass obj, boolean x, boolean y) {
1107 if (x) {
1108 obj.i = 1;
1109 } else {
1110 obj.i = 2;
1111 }
1112 if (y) {
1113 if (x) {
1114 obj.i = 3;
1115 }
1116 obj.j = 5;
1117 }
1118 return obj.i;
1119 }
1120
1121 /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (before)
1122 /// CHECK-DAG: InstanceFieldSet
1123 /// CHECK-DAG: InstanceFieldSet
1124 /// CHECK-DAG: Phi
1125 /// CHECK-DAG: InstanceFieldGet
1126
1127 /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after)
1128 /// CHECK-DAG: InstanceFieldSet
1129 /// CHECK-DAG: InstanceFieldSet
1130 /// CHECK-DAG: Phi
1131
1132 /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after)
1133 /// CHECK-NOT: InstanceFieldGet
1134
1135 /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after)
1136 /// CHECK: Phi
1137 /// CHECK-NOT: Phi
1138
1139 // Test Phi matching for load elimination.
1140 static int test36(TestClass obj, boolean x) {
1141 int phi;
1142 if (x) {
1143 obj.i = 1;
1144 phi = 1;
1145 } else {
1146 obj.i = 2;
1147 phi = 2;
1148 }
1149 // The load is replaced by the existing Phi instead of constructing a new one.
1150 return obj.i + phi;
1151 }
1152
1153 /// CHECK-START: int Main.test37(TestClass, boolean) load_store_elimination (before)
1154 /// CHECK-DAG: InstanceFieldSet
1155 /// CHECK-DAG: InstanceFieldGet
1156 /// CHECK-DAG: InstanceFieldSet
1157
1158 /// CHECK-START: int Main.test37(TestClass, boolean) load_store_elimination (after)
1159 /// CHECK-DAG: InstanceFieldSet
1160 /// CHECK-DAG: InstanceFieldGet
1161 /// CHECK-DAG: InstanceFieldSet
1162
1163 // Test preserving observable stores.
1164 static int test37(TestClass obj, boolean x) {
1165 if (x) {
1166 obj.i = 1;
1167 }
1168 int tmp = obj.i; // The store above must be kept.
1169 obj.i = 2;
1170 return tmp;
1171 }
1172
1173 /// CHECK-START: int Main.test38(TestClass, boolean) load_store_elimination (before)
1174 /// CHECK-DAG: InstanceFieldSet
1175 /// CHECK-DAG: InstanceFieldSet
1176 /// CHECK-DAG: InstanceFieldSet
1177 /// CHECK-DAG: InstanceFieldSet
1178
1179 /// CHECK-START: int Main.test38(TestClass, boolean) load_store_elimination (after)
1180 /// CHECK: InstanceFieldSet
1181 /// CHECK-NOT: InstanceFieldSet
1182
1183 // Test eliminating store of the same value after eliminating non-observable stores.
1184 static int test38(TestClass obj, boolean x) {
1185 obj.i = 1;
1186 if (x) {
1187 return 1; // The store above must be kept.
1188 }
1189 obj.i = 2; // Not observable, shall be eliminated.
1190 obj.i = 3; // Not observable, shall be eliminated.
1191 obj.i = 1; // After eliminating the non-observable stores above, this stores the
1192 // same value that is already stored in `obj.i` and shall be eliminated.
1193 return 2;
1194 }
1195
1196 /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (before)
1197 /// CHECK-DAG: NewInstance
1198 /// CHECK-DAG: InstanceFieldSet
1199 /// CHECK-DAG: NewInstance
1200 /// CHECK-DAG: InstanceFieldSet
1201 /// CHECK-DAG: InstanceFieldGet
1202 /// CHECK-DAG: InstanceFieldGet
1203
1204 /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (after)
1205 /// CHECK-DAG: NewInstance
1206 /// CHECK-DAG: InstanceFieldSet
1207 /// CHECK-DAG: NewInstance
1208 /// CHECK-DAG: InstanceFieldSet
1209 /// CHECK-DAG: Phi
1210 /// CHECK-DAG: InstanceFieldGet
1211
1212 /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (after)
1213 /// CHECK: InstanceFieldGet
1214 /// CHECK-NOT: InstanceFieldGet
1215
1216 // Test creating a reference Phi for load elimination.
1217 static int test39(TestClass obj, boolean x) {
1218 obj.next = new TestClass(1, 2);
1219 if (x) {
1220 obj.next = new SubTestClass();
1221 }
1222 return obj.next.i;
1223 }
1224
Santiago Aboy Solanes42f1af82022-04-22 16:20:39 +01001225 private static int test40() {
1226 int[] array = new int[1];
1227 try {
1228 $noinline$fillArrayTest40(array, 100, 0);
1229 System.out.println("UNREACHABLE");
1230 } catch (Throwable expected) {
1231 }
1232 assertIntEquals(array[0], 1);
1233 try {
1234 $noinline$fillArrayTest40(array, 100, 1);
1235 System.out.println("UNREACHABLE");
1236 } catch (Throwable expected) {
1237 }
1238 assertIntEquals(array[0], 2);
1239 $noinline$fillArrayTest40(array, 100, 2);
1240 assertIntEquals(array[0], 150);
1241 return array[0];
1242 }
1243
1244 /// CHECK-START: void Main.$noinline$fillArrayTest40(int[], int, int) load_store_elimination (before)
1245 /// CHECK: ArraySet
1246 /// CHECK: DivZeroCheck
1247 /// CHECK: ArraySet
1248 /// CHECK: DivZeroCheck
1249 /// CHECK: ArraySet
1250
1251 /// CHECK-START: void Main.$noinline$fillArrayTest40(int[], int, int) load_store_elimination (after)
1252 /// CHECK: ArraySet
1253 /// CHECK: DivZeroCheck
1254 /// CHECK: ArraySet
1255 /// CHECK: DivZeroCheck
1256 /// CHECK: ArraySet
1257
1258 // Check that the stores to array[0] are not eliminated since we can throw in between the stores.
1259 private static void $noinline$fillArrayTest40(int[] array, int a, int b) {
1260 array[0] = 1;
1261 int x = a / b;
1262 array[0] = 2;
1263 int y = a / (b - 1);
1264 array[0] = x + y;
1265 }
1266
Vladimir Marko4307cd72020-07-17 14:35:56 +01001267 /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (before)
1268 /// CHECK-DAG: InstanceFieldSet
1269 /// CHECK-DAG: InstanceFieldSet
1270 /// CHECK-DAG: InstanceFieldGet
1271 /// CHECK-DAG: InstanceFieldSet
1272 /// CHECK-DAG: InstanceFieldGet
1273
1274 /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (after)
1275 /// CHECK-DAG: InstanceFieldSet
1276 /// CHECK-DAG: InstanceFieldSet
1277 /// CHECK-DAG: TypeConversion
1278 /// CHECK-DAG: InstanceFieldSet
Vladimir Marko3224f382020-06-23 14:19:53 +01001279 /// CHECK-DAG: Phi
1280
1281 /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (after)
1282 /// CHECK: Phi
1283 /// CHECK-NOT: Phi
1284
1285 // Test tracking values containing type conversion.
1286 // Regression test for b/161521389 .
Vladimir Marko4307cd72020-07-17 14:35:56 +01001287 static int $noinline$testConversion1(TestClass obj, int x) {
1288 obj.i = x;
1289 if ((x & 1) != 0) {
1290 obj.b = (byte) x;
1291 obj.i = obj.b;
1292 }
1293 return obj.i;
1294 }
1295
1296 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (before)
1297 /// CHECK-DAG: InstanceFieldSet
1298 /// CHECK-DAG: InstanceFieldSet
1299 /// CHECK-DAG: InstanceFieldGet
1300 /// CHECK-DAG: InstanceFieldSet
Vladimir Marko3224f382020-06-23 14:19:53 +01001301 /// CHECK-DAG: TypeConversion
1302 /// CHECK-DAG: Phi
Vladimir Marko4307cd72020-07-17 14:35:56 +01001303 /// CHECK-DAG: InstanceFieldGet
1304
1305 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
1306 /// CHECK-DAG: InstanceFieldSet
1307 /// CHECK-DAG: InstanceFieldSet
1308 /// CHECK-DAG: TypeConversion
1309 /// CHECK-DAG: InstanceFieldSet
Vladimir Marko3224f382020-06-23 14:19:53 +01001310 /// CHECK-DAG: Phi
1311 /// CHECK-DAG: Phi
1312
1313 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
1314 /// CHECK: Phi
1315 /// CHECK: Phi
1316 /// CHECK-NOT: Phi
Vladimir Marko4307cd72020-07-17 14:35:56 +01001317
1318 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
1319 /// CHECK: TypeConversion
1320 /// CHECK-NOT: TypeConversion
Vladimir Marko3224f382020-06-23 14:19:53 +01001321
1322 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after)
1323 /// CHECK-NOT: InstanceFieldGet
1324
1325 // Test moving type conversion when needed.
Vladimir Marko4307cd72020-07-17 14:35:56 +01001326 static int $noinline$testConversion2(TestClass obj, int x) {
1327 int tmp = 0;
1328 obj.i = x;
1329 if ((x & 1) != 0) {
1330 // The instruction simplifier can remove this TypeConversion if there are
1331 // no environment uses. Currently, there is an environment use in NullCheck,
1332 // so this TypeConversion remains and GVN removes the second TypeConversion
1333 // below. Since we really want to test that the TypeConversion from below
1334 // can be moved and used for the load of `obj.b`, we have a similar test
1335 // written in smali in 530-checker-lse3, StoreLoad.test3(int), except that
1336 // it's using static fields (which would not help with the environment use).
1337 obj.b = (byte) x;
1338 obj.i = obj.b;
1339 tmp = (byte) x;
1340 }
1341 return obj.i + tmp;
1342 }
1343
Vladimir Marko3224f382020-06-23 14:19:53 +01001344 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (before)
1345 /// CHECK-DAG: InstanceFieldSet
1346 /// CHECK-DAG: Phi
1347 /// CHECK-DAG: InstanceFieldSet
1348 /// CHECK-DAG: InstanceFieldGet
1349 /// CHECK-DAG: InstanceFieldSet
1350 /// CHECK-DAG: InstanceFieldGet
1351
1352 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
1353 /// CHECK-DAG: InstanceFieldSet
1354 /// CHECK-DAG: Phi
1355 /// CHECK-DAG: Phi
1356 /// CHECK-DAG: InstanceFieldSet
1357 /// CHECK-DAG: TypeConversion
1358 /// CHECK-DAG: InstanceFieldSet
1359
1360 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
1361 /// CHECK: Phi
1362 /// CHECK: Phi
1363 /// CHECK-NOT: Phi
1364
1365 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
1366 /// CHECK: TypeConversion
1367 /// CHECK-NOT: TypeConversion
1368
1369 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after)
1370 /// CHECK-NOT: InstanceFieldGet
1371
1372 // Test tracking values containing type conversion with loop.
1373 static int $noinline$testConversion3(TestClass obj, int x) {
1374 obj.i = x;
1375 for (int i = 0; i < x; ++i) {
1376 obj.b = (byte) i;
1377 obj.i = obj.b;
1378 }
1379 return obj.i;
1380 }
1381
1382 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (before)
1383 /// CHECK-DAG: InstanceFieldSet
1384 /// CHECK-DAG: Phi
1385 /// CHECK-DAG: Phi
1386 /// CHECK-DAG: InstanceFieldSet
1387 /// CHECK-DAG: InstanceFieldGet
1388 /// CHECK-DAG: InstanceFieldSet
1389 /// CHECK-DAG: TypeConversion
1390 /// CHECK-DAG: InstanceFieldGet
1391
1392 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
1393 /// CHECK-DAG: InstanceFieldSet
1394 /// CHECK-DAG: Phi
1395 /// CHECK-DAG: Phi
1396 /// CHECK-DAG: InstanceFieldSet
1397 /// CHECK-DAG: TypeConversion
1398 /// CHECK-DAG: InstanceFieldSet
1399
1400 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
1401 /// CHECK: Phi
1402 /// CHECK: Phi
1403 /// CHECK-NOT: Phi
1404
1405 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
1406 /// CHECK: TypeConversion
1407 /// CHECK-NOT: TypeConversion
1408
1409 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after)
1410 /// CHECK-NOT: InstanceFieldGet
1411
1412 // Test moving type conversion when needed with loop.
1413 static int $noinline$testConversion4(TestClass obj, int x) {
1414 int tmp = x;
1415 obj.i = x;
1416 for (int i = 0; i < x; ++i) {
1417 obj.b = (byte) i;
1418 obj.i = obj.b;
1419 tmp = (byte) i;
1420 }
1421 return obj.i + tmp;
1422 }
1423
Mingyao Yangfb8464a2015-11-02 10:56:59 -08001424 /// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
1425 /// CHECK: NewInstance
1426 /// CHECK: InstanceFieldSet
Mingyao Yang025c1a62017-10-30 11:19:57 -07001427 /// CHECK: InstanceFieldSet
Mingyao Yangfb8464a2015-11-02 10:56:59 -08001428
1429 /// CHECK-START: void Main.testFinalizable() load_store_elimination (after)
1430 /// CHECK: NewInstance
1431 /// CHECK: InstanceFieldSet
Mingyao Yang025c1a62017-10-30 11:19:57 -07001432 /// CHECK-NOT: InstanceFieldSet
Mingyao Yangfb8464a2015-11-02 10:56:59 -08001433
Mingyao Yang025c1a62017-10-30 11:19:57 -07001434 // Allocations of finalizable objects cannot be eliminated.
Mingyao Yangfb8464a2015-11-02 10:56:59 -08001435 static void testFinalizable() {
1436 Finalizable finalizable = new Finalizable();
Mingyao Yang025c1a62017-10-30 11:19:57 -07001437 finalizable.i = Finalizable.VALUE2;
1438 finalizable.i = Finalizable.VALUE1;
Mingyao Yangfb8464a2015-11-02 10:56:59 -08001439 }
1440
1441 static java.lang.ref.WeakReference<Object> getWeakReference() {
1442 return new java.lang.ref.WeakReference<>(new Object());
1443 }
1444
1445 static void testFinalizableByForcingGc() {
1446 testFinalizable();
1447 java.lang.ref.WeakReference<Object> reference = getWeakReference();
1448
1449 Runtime runtime = Runtime.getRuntime();
1450 for (int i = 0; i < 20; ++i) {
1451 runtime.gc();
1452 System.runFinalization();
1453 try {
1454 Thread.sleep(1);
1455 } catch (InterruptedException e) {
1456 throw new AssertionError(e);
1457 }
1458
1459 // Check to see if the weak reference has been garbage collected.
1460 if (reference.get() == null) {
1461 // A little bit more sleep time to make sure.
1462 try {
1463 Thread.sleep(100);
1464 } catch (InterruptedException e) {
1465 throw new AssertionError(e);
1466 }
1467 if (!Finalizable.sVisited) {
1468 System.out.println("finalize() not called.");
1469 }
1470 return;
1471 }
1472 }
1473 System.out.println("testFinalizableByForcingGc() failed to force gc.");
1474 }
1475
Santiago Aboy Solanes4ebfcac2022-03-31 11:19:25 +01001476 /// CHECK-START: void Main.testFinalizable() load_store_elimination (before)
1477 /// CHECK: NewInstance
1478 /// CHECK: InstanceFieldSet
1479 /// CHECK: InstanceFieldSet
1480
1481 /// CHECK-START: void Main.testFinalizableWithLoop() load_store_elimination (after)
1482 /// CHECK: NewInstance
1483 /// CHECK: InstanceFieldSet
1484 /// CHECK-NOT: InstanceFieldSet
1485
1486 // Allocations of finalizable objects cannot be eliminated.
1487 static void testFinalizableWithLoop() {
1488 for (int i = 0; i < 1000; ++i) {
1489 Finalizable finalizable = new Finalizable();
1490 finalizable.i = Finalizable.VALUE2;
1491 finalizable.i = Finalizable.VALUE1;
1492 }
1493 }
1494
1495 static void testFinalizableWithLoopByForcingGc() {
1496 testFinalizableWithLoop();
1497 java.lang.ref.WeakReference<Object> reference = getWeakReference();
1498
1499 Runtime runtime = Runtime.getRuntime();
1500 for (int i = 0; i < 20; ++i) {
1501 runtime.gc();
1502 System.runFinalization();
1503 try {
1504 Thread.sleep(1);
1505 } catch (InterruptedException e) {
1506 throw new AssertionError(e);
1507 }
1508
1509 // Check to see if the weak reference has been garbage collected.
1510 if (reference.get() == null) {
1511 // A little bit more sleep time to make sure.
1512 try {
1513 Thread.sleep(100);
1514 } catch (InterruptedException e) {
1515 throw new AssertionError(e);
1516 }
1517 if (!Finalizable.sVisited) {
1518 System.out.println("finalize() not called.");
1519 }
1520 return;
1521 }
1522 }
1523 System.out.println("testFinalizableWithLoopByForcingGc() failed to force gc.");
1524 }
1525
Mingyao Yang40bcb932016-02-03 05:46:57 -08001526 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (before)
Mingyao Yange5c71f92016-02-02 20:10:32 -08001527 /// CHECK: InstanceFieldSet
1528 /// CHECK: Select
1529
Mingyao Yang40bcb932016-02-03 05:46:57 -08001530 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (after)
Mingyao Yange5c71f92016-02-02 20:10:32 -08001531 /// CHECK: InstanceFieldSet
1532 /// CHECK: Select
1533
1534 // Test that HSelect creates alias.
Mingyao Yang062157f2016-03-02 10:15:36 -08001535 static int $noinline$testHSelect(boolean b) {
Mingyao Yange5c71f92016-02-02 20:10:32 -08001536 TestClass obj = new TestClass();
1537 TestClass obj2 = null;
1538 obj.i = 0xdead;
1539 if (b) {
1540 obj2 = obj;
1541 }
1542 return obj2.i;
1543 }
1544
Mingyao Yang062157f2016-03-02 10:15:36 -08001545 static int sumWithFilter(int[] array, Filter f) {
1546 int sum = 0;
1547 for (int i = 0; i < array.length; i++) {
1548 if (f.isValid(array[i])) {
1549 sum += array[i];
1550 }
1551 }
1552 return sum;
1553 }
1554
1555 /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (before)
Vladimir Marko3224f382020-06-23 14:19:53 +01001556 /// CHECK-DAG: NewInstance
1557 /// CHECK-DAG: InstanceFieldSet
1558 /// CHECK-DAG: InstanceFieldSet
1559 /// CHECK-DAG: InstanceFieldGet
1560 /// CHECK-DAG: InstanceFieldGet
Mingyao Yang062157f2016-03-02 10:15:36 -08001561
1562 /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (after)
1563 /// CHECK-NOT: NewInstance
1564 /// CHECK-NOT: InstanceFieldSet
1565 /// CHECK-NOT: InstanceFieldGet
1566
1567 // A lambda-style allocation can be eliminated after inlining.
1568 static int sumWithinRange(int[] array, final int low, final int high) {
1569 Filter filter = new Filter() {
1570 public boolean isValid(int i) {
1571 return (i >= low) && (i <= high);
1572 }
1573 };
1574 return sumWithFilter(array, filter);
1575 }
1576
Mingyao Yang0a845202016-10-14 16:26:08 -07001577 private static int mI = 0;
1578 private static float mF = 0f;
1579
1580 /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (before)
1581 /// CHECK: NewInstance
1582 /// CHECK: NewInstance
1583 /// CHECK: NewInstance
1584
1585 /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (after)
1586 /// CHECK-NOT: NewInstance
1587
1588 private static float testAllocationEliminationWithLoops() {
1589 for (int i0 = 0; i0 < 5; i0++) {
1590 for (int i1 = 0; i1 < 5; i1++) {
1591 for (int i2 = 0; i2 < 5; i2++) {
1592 int lI0 = ((int) new Integer(((int) new Integer(mI))));
1593 if (((boolean) new Boolean(false))) {
1594 for (int i3 = 576 - 1; i3 >= 0; i3--) {
1595 mF -= 976981405.0f;
1596 }
1597 }
1598 }
1599 }
1600 }
1601 return 1.0f;
1602 }
1603
Mingyao Yangeb2d2d346e2017-03-02 13:26:17 -08001604 /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (before)
1605 /// CHECK: NewInstance
1606 /// CHECK: InstanceFieldSet
1607 /// CHECK: InstanceFieldSet
1608 /// CHECK: InstanceFieldSet
1609 /// CHECK: InstanceFieldSet
1610
1611 /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (after)
1612 /// CHECK: NewInstance
1613 /// CHECK: InstanceFieldSet
1614 /// CHECK: InstanceFieldSet
1615 /// CHECK-NOT: InstanceFieldSet
1616
1617 private static TestClass2 testStoreStore() {
1618 TestClass2 obj = new TestClass2();
1619 obj.i = 41;
1620 obj.j = 42;
1621 obj.i = 41;
1622 obj.j = 43;
1623 return obj;
1624 }
1625
Mingyao Yanga3540532018-01-25 12:17:28 -08001626 /// CHECK-START: void Main.testStoreStore2(TestClass2) load_store_elimination (before)
1627 /// CHECK: InstanceFieldSet
1628 /// CHECK: InstanceFieldSet
1629 /// CHECK: InstanceFieldSet
1630 /// CHECK: InstanceFieldSet
1631
1632 /// CHECK-START: void Main.testStoreStore2(TestClass2) load_store_elimination (after)
1633 /// CHECK: InstanceFieldSet
1634 /// CHECK: InstanceFieldSet
1635 /// CHECK-NOT: InstanceFieldSet
1636
1637 private static void testStoreStore2(TestClass2 obj) {
1638 obj.i = 41;
1639 obj.j = 42;
1640 obj.i = 43;
1641 obj.j = 44;
1642 }
1643
1644 /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (before)
1645 /// CHECK: InstanceFieldSet
1646 /// CHECK: InstanceFieldSet
1647 /// CHECK: InstanceFieldSet
1648 /// CHECK: InstanceFieldSet
1649
1650 /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (after)
1651 /// CHECK: InstanceFieldSet
1652 /// CHECK: InstanceFieldSet
1653 /// CHECK: InstanceFieldSet
1654 /// CHECK-NOT: InstanceFieldSet
1655
Vladimir Marko3224f382020-06-23 14:19:53 +01001656 /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (after)
1657 /// CHECK-NOT: Phi
1658
Mingyao Yanga3540532018-01-25 12:17:28 -08001659 private static void testStoreStore3(TestClass2 obj, boolean flag) {
1660 obj.i = 41;
1661 obj.j = 42; // redundant since it's overwritten in both branches below.
1662 if (flag) {
1663 obj.j = 43;
1664 } else {
1665 obj.j = 44;
1666 }
1667 }
1668
1669 /// CHECK-START: void Main.testStoreStore4() load_store_elimination (before)
1670 /// CHECK: StaticFieldSet
1671 /// CHECK: StaticFieldSet
1672
1673 /// CHECK-START: void Main.testStoreStore4() load_store_elimination (after)
1674 /// CHECK: StaticFieldSet
1675 /// CHECK-NOT: StaticFieldSet
1676
1677 private static void testStoreStore4() {
1678 TestClass.si = 61;
1679 TestClass.si = 62;
1680 }
1681
1682 /// CHECK-START: int Main.testStoreStore5(TestClass2, TestClass2) load_store_elimination (before)
1683 /// CHECK: InstanceFieldSet
1684 /// CHECK: InstanceFieldGet
1685 /// CHECK: InstanceFieldSet
1686
1687 /// CHECK-START: int Main.testStoreStore5(TestClass2, TestClass2) load_store_elimination (after)
1688 /// CHECK: InstanceFieldSet
1689 /// CHECK: InstanceFieldGet
1690 /// CHECK: InstanceFieldSet
1691
1692 private static int testStoreStore5(TestClass2 obj1, TestClass2 obj2) {
1693 obj1.i = 71; // This store is needed since obj2.i may load from it.
1694 int i = obj2.i;
1695 obj1.i = 72;
1696 return i;
1697 }
1698
1699 /// CHECK-START: int Main.testStoreStore6(TestClass2, TestClass2) load_store_elimination (before)
1700 /// CHECK: InstanceFieldSet
1701 /// CHECK: InstanceFieldGet
1702 /// CHECK: InstanceFieldSet
1703
1704 /// CHECK-START: int Main.testStoreStore6(TestClass2, TestClass2) load_store_elimination (after)
Santiago Aboy Solanes42f1af82022-04-22 16:20:39 +01001705 /// CHECK: InstanceFieldSet
Mingyao Yanga3540532018-01-25 12:17:28 -08001706 /// CHECK: InstanceFieldGet
1707 /// CHECK: InstanceFieldSet
1708
1709 private static int testStoreStore6(TestClass2 obj1, TestClass2 obj2) {
Santiago Aboy Solanes42f1af82022-04-22 16:20:39 +01001710 obj1.i = 81; // Even though the value in `obj1.i` will be overridden below, this store is needed
1711 // since obj2.j has a NullCheck and can throw.
Mingyao Yanga3540532018-01-25 12:17:28 -08001712 int j = obj2.j;
1713 obj1.i = 82;
1714 return j;
1715 }
1716
1717 /// CHECK-START: int Main.testNoSideEffects(int[]) load_store_elimination (before)
1718 /// CHECK: ArraySet
1719 /// CHECK: ArraySet
1720 /// CHECK: ArraySet
1721 /// CHECK: ArrayGet
1722
1723 /// CHECK-START: int Main.testNoSideEffects(int[]) load_store_elimination (after)
1724 /// CHECK: ArraySet
1725 /// CHECK: ArraySet
1726 /// CHECK-NOT: ArraySet
1727 /// CHECK-NOT: ArrayGet
1728
1729 private static int testNoSideEffects(int[] array) {
1730 array[0] = 101;
1731 array[1] = 102;
1732 int bitCount = Integer.bitCount(0x3456);
1733 array[1] = 103;
1734 return array[0] + bitCount;
1735 }
1736
1737 /// CHECK-START: void Main.testThrow(TestClass2, java.lang.Exception) load_store_elimination (before)
1738 /// CHECK: InstanceFieldSet
1739 /// CHECK: Throw
1740
1741 /// CHECK-START: void Main.testThrow(TestClass2, java.lang.Exception) load_store_elimination (after)
1742 /// CHECK: InstanceFieldSet
1743 /// CHECK: Throw
1744
1745 // Make sure throw keeps the store.
1746 private static void testThrow(TestClass2 obj, Exception e) throws Exception {
1747 obj.i = 55;
1748 throw e;
1749 }
1750
Mingyao Yangeb2d2d346e2017-03-02 13:26:17 -08001751 /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (before)
1752 /// CHECK: NewInstance
1753 /// CHECK: InstanceFieldSet
1754 /// CHECK: InstanceFieldSet
1755 /// CHECK: InstanceFieldSet
1756 /// CHECK: InstanceFieldSet
1757 /// CHECK: Deoptimize
1758 /// CHECK: ArraySet
1759 /// CHECK: ArraySet
1760 /// CHECK: ArraySet
1761 /// CHECK: ArraySet
1762 /// CHECK: ArrayGet
1763 /// CHECK: ArrayGet
1764 /// CHECK: ArrayGet
1765 /// CHECK: ArrayGet
1766
1767 /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (after)
1768 /// CHECK: NewInstance
1769 /// CHECK: InstanceFieldSet
1770 /// CHECK: InstanceFieldSet
1771 /// CHECK-NOT: InstanceFieldSet
1772 /// CHECK: Deoptimize
1773 /// CHECK: ArraySet
1774 /// CHECK: ArraySet
1775 /// CHECK: ArraySet
1776 /// CHECK: ArraySet
1777 /// CHECK-NOT: ArrayGet
1778
1779 private static int testStoreStoreWithDeoptimize(int[] arr) {
1780 TestClass2 obj = new TestClass2();
1781 obj.i = 41;
1782 obj.j = 42;
1783 obj.i = 41;
1784 obj.j = 43;
1785 arr[0] = 1; // One HDeoptimize here.
1786 arr[1] = 1;
1787 arr[2] = 1;
1788 arr[3] = 1;
1789 return arr[0] + arr[1] + arr[2] + arr[3];
1790 }
1791
Mingyao Yang58d9bfc2016-11-01 13:31:58 -07001792 /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (before)
1793 /// CHECK: NewInstance
1794
1795 /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (after)
1796 /// CHECK-NOT: NewInstance
1797
1798 private static double getCircleArea(double radius, boolean b) {
1799 double area = 0d;
1800 if (b) {
1801 area = new Circle(radius).getArea();
1802 }
1803 return area;
1804 }
1805
Mingyao Yange58bdca2016-10-28 11:07:24 -07001806 /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (before)
1807 /// CHECK: Deoptimize
1808 /// CHECK: NewInstance
1809 /// CHECK: Deoptimize
1810 /// CHECK: NewInstance
1811
1812 /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (after)
1813 /// CHECK: Deoptimize
1814 /// CHECK: NewInstance
1815 /// CHECK: Deoptimize
1816 /// CHECK-NOT: NewInstance
1817
1818 private static double testDeoptimize(int[] iarr, double[] darr, double radius) {
1819 iarr[0] = 1; // One HDeoptimize here. Not triggered.
1820 iarr[1] = 1;
1821 Circle circle1 = new Circle(radius);
1822 iarr[2] = 1;
1823 darr[0] = circle1.getRadius(); // One HDeoptimize here, which holds circle1 live. Triggered.
1824 darr[1] = circle1.getRadius();
1825 darr[2] = circle1.getRadius();
1826 darr[3] = circle1.getRadius();
1827 return new Circle(Math.PI).getArea();
1828 }
1829
Mingyao Yang86974902017-03-01 14:03:51 -08001830 /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (before)
1831 /// CHECK: NewArray
1832 /// CHECK: ArraySet
1833 /// CHECK: ArraySet
1834 /// CHECK: ArrayGet
1835 /// CHECK: ArrayGet
1836 /// CHECK: ArrayGet
1837 /// CHECK: ArrayGet
1838
1839 /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (after)
1840 /// CHECK-NOT: NewArray
1841 /// CHECK-NOT: ArraySet
1842 /// CHECK-NOT: ArrayGet
1843 private static int testAllocationEliminationOfArray1() {
1844 int[] array = new int[4];
1845 array[2] = 4;
1846 array[3] = 7;
1847 return array[0] + array[1] + array[2] + array[3];
1848 }
1849
1850 /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (before)
1851 /// CHECK: NewArray
1852 /// CHECK: ArraySet
1853 /// CHECK: ArraySet
1854 /// CHECK: ArrayGet
1855
1856 /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (after)
1857 /// CHECK: NewArray
1858 /// CHECK: ArraySet
1859 /// CHECK: ArraySet
1860 /// CHECK: ArrayGet
1861 private static int testAllocationEliminationOfArray2() {
1862 // Cannot eliminate array allocation since array is accessed with non-constant
Aart Bik0148de42017-09-05 09:25:01 -07001863 // index (only 3 elements to prevent vectorization of the reduction).
1864 int[] array = new int[3];
1865 array[1] = 4;
1866 array[2] = 7;
Mingyao Yang86974902017-03-01 14:03:51 -08001867 int sum = 0;
1868 for (int e : array) {
1869 sum += e;
1870 }
1871 return sum;
1872 }
1873
1874 /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (before)
1875 /// CHECK: NewArray
1876 /// CHECK: ArraySet
1877 /// CHECK: ArrayGet
1878
1879 /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (after)
1880 /// CHECK-NOT: NewArray
1881 /// CHECK-NOT: ArraySet
1882 /// CHECK-NOT: ArrayGet
1883 private static int testAllocationEliminationOfArray3(int i) {
1884 int[] array = new int[4];
1885 array[i] = 4;
1886 return array[i];
1887 }
1888
1889 /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (before)
1890 /// CHECK: NewArray
1891 /// CHECK: ArraySet
1892 /// CHECK: ArraySet
1893 /// CHECK: ArrayGet
1894 /// CHECK: ArrayGet
1895
1896 /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (after)
1897 /// CHECK: NewArray
1898 /// CHECK: ArraySet
1899 /// CHECK: ArraySet
1900 /// CHECK: ArrayGet
1901 /// CHECK-NOT: ArrayGet
1902 private static int testAllocationEliminationOfArray4(int i) {
1903 // Cannot eliminate array allocation due to index aliasing between 1 and i.
1904 int[] array = new int[4];
1905 array[1] = 2;
1906 array[i] = 4;
1907 return array[1] + array[i];
1908 }
1909
Mingyao Yang7cf9af22018-02-06 15:02:42 -08001910 /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (before)
1911 /// CHECK: NewArray
1912 /// CHECK: ArraySet
1913 /// CHECK: ArrayGet
1914
1915 /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (after)
1916 /// CHECK: NewArray
1917 /// CHECK-NOT: ArraySet
1918 /// CHECK-NOT: ArrayGet
1919 private static int testAllocationEliminationOfArray5(int i) {
1920 // Cannot eliminate array allocation due to unknown i that may
1921 // cause NegativeArraySizeException.
1922 int[] array = new int[i];
1923 array[1] = 12;
1924 return array[1];
1925 }
1926
Mingyao Yang46721ef2017-10-05 14:45:17 -07001927 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (before)
Vladimir Marko3224f382020-06-23 14:19:53 +01001928 /// CHECK-DAG: NewInstance
Vladimir Markoe7e123a2021-10-28 11:15:08 +01001929 /// CHECK-DAG: InstanceFieldSet field_name:TestClass.i
1930 /// CHECK-DAG: InstanceFieldGet field_name:TestClass.i
Vladimir Marko3224f382020-06-23 14:19:53 +01001931 /// CHECK-DAG: Return
Vladimir Markoe7e123a2021-10-28 11:15:08 +01001932 /// CHECK-DAG: InstanceFieldSet field_name:TestClass.i
Vladimir Marko3224f382020-06-23 14:19:53 +01001933 /// CHECK-DAG: Throw
Mingyao Yang46721ef2017-10-05 14:45:17 -07001934
1935 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after)
Vladimir Marko3224f382020-06-23 14:19:53 +01001936 /// CHECK-DAG: Return
1937 /// CHECK-DAG: Throw
1938
1939 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after)
Vladimir Markoe7e123a2021-10-28 11:15:08 +01001940 /// CHECK-NOT: InstanceFieldSet field_name:TestClass.i
1941 /// CHECK-NOT: InstanceFieldGet field_name:TestClass.i
Vladimir Marko3224f382020-06-23 14:19:53 +01001942
1943 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after)
1944 /// CHECK: NewInstance
1945 /// CHECK-NOT: NewInstance
Mingyao Yang46721ef2017-10-05 14:45:17 -07001946 private static int testExitMerge(boolean cond) {
1947 TestClass obj = new TestClass();
1948 if (cond) {
1949 obj.i = 1;
1950 return obj.i + 1;
1951 } else {
1952 obj.i = 2;
Vladimir Marko3224f382020-06-23 14:19:53 +01001953 throw new Error(); // Note: We have a NewInstance here.
Mingyao Yang46721ef2017-10-05 14:45:17 -07001954 }
1955 }
1956
1957 /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (before)
Vladimir Marko3224f382020-06-23 14:19:53 +01001958 /// CHECK-DAG: NewInstance
1959 /// CHECK-DAG: InstanceFieldSet
1960 /// CHECK-DAG: InstanceFieldGet
1961 /// CHECK-DAG: InstanceFieldSet
1962 /// CHECK-DAG: InstanceFieldGet
Mingyao Yang46721ef2017-10-05 14:45:17 -07001963
1964 /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (after)
1965 /// CHECK-NOT: NewInstance
1966 /// CHECK-NOT: InstanceFieldSet
1967 /// CHECK-NOT: InstanceFieldGet
1968 private static int testExitMerge2(boolean cond) {
1969 TestClass obj = new TestClass();
1970 int res;
1971 if (cond) {
1972 obj.i = 1;
1973 res = obj.i + 1;
1974 } else {
1975 obj.i = 2;
1976 res = obj.j + 2;
1977 }
1978 return res;
1979 }
1980
Mingyao Yang206070c2017-11-29 23:01:58 -08001981 /// CHECK-START: void Main.testStoreSameValue() load_store_elimination (before)
1982 /// CHECK: NewArray
1983 /// CHECK: ArrayGet
1984 /// CHECK: ArraySet
1985
1986 /// CHECK-START: void Main.testStoreSameValue() load_store_elimination (after)
1987 /// CHECK: NewArray
1988 /// CHECK-NOT: ArrayGet
1989 /// CHECK-NOT: ArraySet
1990 private static void testStoreSameValue() {
1991 Object[] array = new Object[2];
1992 sArray = array;
1993 Object obj = array[0];
Vladimir Marko3224f382020-06-23 14:19:53 +01001994 array[1] = obj; // Store the same value as the default value.
Mingyao Yang206070c2017-11-29 23:01:58 -08001995 }
1996
Vladimir Marko4307cd72020-07-17 14:35:56 +01001997 /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (before)
1998 /// CHECK-DAG: NewArray
1999 /// CHECK-DAG: <<Value:b\d+>> ArrayGet
2000 /// CHECK-DAG: Return [<<Value>>]
2001
2002 /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after)
2003 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
2004 /// CHECK-DAG: Return [<<Const0>>]
2005
2006 /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after)
2007 /// CHECK-NOT: NewArray
2008 /// CHECK-NOT: ArrayGet
2009 /// CHECK-NOT: TypeConversion
2010 private static int $noinline$testByteArrayDefaultValue() {
2011 byte[] array = new byte[2];
2012 array[1] = 1; // FIXME: Without any stores, LSA tells LSE not to run.
2013 return array[0];
2014 }
2015
Mingyao Yang206070c2017-11-29 23:01:58 -08002016 static Object[] sArray;
2017
Aart Bik4dc09e72018-05-11 14:40:31 -07002018 /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (before)
2019 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
2020 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2021 /// CHECK-DAG: <<A:l\d+>> NewArray
2022 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const0>>]
2023 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>]
2024 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>]
2025 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>]
2026 /// CHECK-DAG: Return [<<Get>>]
2027 //
2028 /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (after)
2029 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2030 /// CHECK-DAG: Return [<<Const1>>]
2031 //
2032 /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (after)
2033 /// CHECK-NOT: NewArray
2034 /// CHECK-NOT: ArraySet
2035 /// CHECK-NOT: ArrayGet
2036 private static int testLocalArrayMerge1(boolean x) {
2037 // The explicit store can be removed right away
2038 // since it is equivalent to the default.
2039 int[] a = { 0 };
2040 // The diamond pattern stores/load can be replaced
2041 // by the direct value.
2042 if (x) {
2043 a[0] = 1;
2044 } else {
2045 a[0] = 1;
2046 }
2047 return a[0];
2048 }
2049
2050 /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (before)
2051 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
2052 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2053 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
2054 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
2055 /// CHECK-DAG: <<A:l\d+>> NewArray
2056 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>]
2057 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const2>>]
2058 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const3>>]
2059 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>]
2060 /// CHECK-DAG: Return [<<Get>>]
Vladimir Marko3224f382020-06-23 14:19:53 +01002061
Aart Bik4dc09e72018-05-11 14:40:31 -07002062 /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after)
Vladimir Marko3224f382020-06-23 14:19:53 +01002063 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
2064 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
2065 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
2066 /// CHECK-DAG: Return [<<Phi>>]
2067 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const2>>","<<Const3>>"])
2068
Aart Bik4dc09e72018-05-11 14:40:31 -07002069 /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after)
Vladimir Marko3224f382020-06-23 14:19:53 +01002070 /// CHECK-NOT: NewArray
Aart Bik4dc09e72018-05-11 14:40:31 -07002071 /// CHECK-NOT: ArraySet
Vladimir Marko3224f382020-06-23 14:19:53 +01002072 /// CHECK-NOT: ArrayGet
Aart Bik4dc09e72018-05-11 14:40:31 -07002073 private static int testLocalArrayMerge2(boolean x) {
2074 // The explicit store can be removed eventually even
2075 // though it is not equivalent to the default.
2076 int[] a = { 1 };
Vladimir Marko3224f382020-06-23 14:19:53 +01002077 // The load after the diamond pattern is eliminated and replaced with a Phi,
2078 // stores are then also eliminated.
Aart Bik4dc09e72018-05-11 14:40:31 -07002079 if (x) {
2080 a[0] = 2;
2081 } else {
2082 a[0] = 3;
2083 }
2084 return a[0];
2085 }
2086
Vladimir Marko3224f382020-06-23 14:19:53 +01002087 /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (before)
Aart Bik4dc09e72018-05-11 14:40:31 -07002088 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
2089 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2090 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
2091 /// CHECK-DAG: <<A:l\d+>> NewArray
2092 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>]
2093 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const2>>]
2094 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>]
2095 /// CHECK-DAG: Return [<<Get>>]
Vladimir Marko3224f382020-06-23 14:19:53 +01002096
2097 /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (after)
2098 /// CHECK-NOT: NewArray
2099 /// CHECK-NOT: ArraySet
2100 /// CHECK-NOT: ArrayGet
Aart Bik4dc09e72018-05-11 14:40:31 -07002101 private static int testLocalArrayMerge3(boolean x) {
Aart Bik4dc09e72018-05-11 14:40:31 -07002102 int[] a = { 1 };
2103 if (x) {
2104 a[0] = 2;
2105 }
2106 return a[0];
2107 }
2108
2109 /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (before)
2110 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
2111 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2112 /// CHECK-DAG: <<A:l\d+>> NewArray
2113 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const0>>]
2114 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>]
2115 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>]
2116 /// CHECK-DAG: <<Get1:b\d+>> ArrayGet [<<A>>,<<Const0>>]
2117 /// CHECK-DAG: <<Get2:a\d+>> ArrayGet [<<A>>,<<Const0>>]
2118 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get1>>,<<Get2>>]
2119 /// CHECK-DAG: Return [<<Add>>]
2120 //
2121 /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (after)
2122 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2123 /// CHECK-DAG: <<Cnv1:b\d+>> TypeConversion [<<Const1>>]
2124 /// CHECK-DAG: <<Cnv2:a\d+>> TypeConversion [<<Const1>>]
2125 /// CHECK-DAG: <<Add:i\d+>> Add [<<Cnv1>>,<<Cnv2>>]
2126 /// CHECK-DAG: Return [<<Add>>]
2127 //
2128 /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (after)
2129 /// CHECK-NOT: NewArray
2130 /// CHECK-NOT: ArraySet
2131 /// CHECK-NOT: ArrayGet
2132 private static int testLocalArrayMerge4(boolean x) {
2133 byte[] a = { 0 };
2134 if (x) {
2135 a[0] = 1;
2136 } else {
2137 a[0] = 1;
2138 }
2139 // Differently typed (signed vs unsigned),
2140 // but same reference.
2141 return a[0] + (a[0] & 0xff);
2142 }
2143
Vladimir Marko3224f382020-06-23 14:19:53 +01002144 /// CHECK-START: int Main.testLocalArrayMerge5(int[], boolean) load_store_elimination (before)
2145 /// CHECK: ArraySet
2146 /// CHECK: ArraySet
2147 /// CHECK: ArraySet
2148
2149 /// CHECK-START: int Main.testLocalArrayMerge5(int[], boolean) load_store_elimination (after)
2150 /// CHECK-NOT: ArraySet
2151
2152 // Test eliminating store of the same value after eliminating non-observable stores.
2153 private static int testLocalArrayMerge5(int[] a, boolean x) {
2154 int old = a[0];
2155 if (x) {
2156 a[0] = 1;
2157 } else {
2158 a[0] = 1;
2159 }
2160 // This store makes the stores above dead and they will be eliminated.
2161 // That makes this store unnecessary as we're storing the same value already
2162 // present in this location, so it shall also be eliminated.
2163 a[0] = old;
2164 return old;
2165 }
2166
2167 /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (before)
2168 /// CHECK-DAG: ArraySet
2169 /// CHECK-DAG: ArraySet
2170 /// CHECK-DAG: ArraySet
2171 /// CHECK-DAG: ArrayGet
2172 /// CHECK-DAG: ArrayGet
2173
2174 /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after)
2175 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2176 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
2177 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
2178 /// CHECK-DAG: ArraySet
2179 /// CHECK-DAG: ArraySet
2180 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
2181 /// CHECK-DAG: Return [<<Phi>>]
2182 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const3>>,<<Phi>>]
2183 /// CHECK-DAG: Return [<<Sub>>]
2184 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const1>>","<<Const2>>"])
2185
2186 /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after)
2187 /// CHECK: Phi
2188 /// CHECK-NOT: Phi
2189
2190 /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after)
2191 /// CHECK-NOT: ArrayGet
2192
2193 // Test that we create a single Phi for eliminating two loads in different blocks.
2194 private static int testLocalArrayMerge6(int[] a, boolean x, boolean y) {
2195 a[0] = 0;
2196 if (x) {
2197 a[0] = 1;
2198 } else {
2199 a[0] = 2;
2200 }
2201 // Phi for load elimination is created here.
2202 if (y) {
2203 return a[0];
2204 } else {
2205 return 3 - a[0];
2206 }
2207 }
2208
2209 /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (before)
2210 /// CHECK-DAG: ArraySet
2211 /// CHECK-DAG: ArraySet
2212 /// CHECK-DAG: ArraySet
2213 /// CHECK-DAG: ArrayGet
2214 /// CHECK-DAG: ArraySet
2215 /// CHECK-DAG: ArrayGet
2216
2217 /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (after)
2218 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
2219 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
2220 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
2221 /// CHECK-DAG: ArraySet
2222 /// CHECK-DAG: ArraySet
2223 /// CHECK-DAG: ArraySet
2224 /// CHECK-DAG: ArraySet
2225 /// CHECK-DAG: Return [<<Phi2:i\d+>>]
2226 /// CHECK-DAG: <<Phi2>> Phi [<<Arg3:i\d+>>,<<Arg4:i\d+>>]
2227 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
2228 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const1>>","<<Const2>>"])
2229 /// CHECK-EVAL: set(["<<Arg3>>","<<Arg4>>"]) == set(["<<Const0>>","<<Phi1>>"])
2230
2231 /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (after)
2232 /// CHECK-NOT: ArrayGet
2233
2234 // Test Phi creation for load elimination.
2235 private static int testLocalArrayMerge7(int[] a, boolean x, boolean y) {
2236 a[1] = 0;
2237 if (x) {
2238 if (y) {
2239 a[0] = 1;
2240 } else {
2241 a[0] = 2;
2242 }
2243 a[1] = a[0];
2244 }
2245 return a[1];
2246 }
2247
Vladimir Markocbeedc82020-08-25 14:31:10 +01002248 /// CHECK-START: int Main.testLocalArrayMerge8(boolean) load_store_elimination (before)
2249 /// CHECK-DAG: NewArray
2250 /// CHECK-DAG: ArraySet
2251 /// CHECK-DAG: ArraySet
2252 /// CHECK-DAG: ArraySet
2253 /// CHECK-DAG: ArraySet
2254 /// CHECK-DAG: ArrayGet
2255 /// CHECK-DAG: ArrayGet
2256
2257 /// CHECK-START: int Main.testLocalArrayMerge8(boolean) load_store_elimination (after)
2258 /// CHECK-NOT: NewArray
2259 /// CHECK-NOT: ArraySet
2260 /// CHECK-NOT: ArrayGet
2261
2262 // Test Merging default value and an identical value.
2263 private static int testLocalArrayMerge8(boolean x) {
2264 int[] a = new int[2];
2265 if (x) {
2266 a[0] = 1; // Make sure the store below is not eliminated immediately as
2267 // storing the same value already present in the heap location.
2268 a[0] = 0; // Store the same value as default value to test merging with
2269 // the default value from else-block.
2270 } else {
2271 // Do the same as then-block for a different heap location to avoid
2272 // relying on block ordering. (Test both `default+0` and `0+default`.)
2273 a[1] = 1;
2274 a[1] = 0;
2275 }
2276 return a[0] + a[1];
2277 }
2278
Vladimir Markofab6f1c2020-07-14 16:25:05 +01002279 /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (before)
2280 /// CHECK-DAG: ArrayGet
2281 /// CHECK-DAG: ArraySet
2282 /// CHECK-DAG: ArraySet
2283 /// CHECK-DAG: ArraySet
2284 /// CHECK-DAG: ArraySet
2285
2286 /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (after)
2287 /// CHECK-DAG: ArrayGet
2288 /// CHECK-DAG: ArraySet
2289 /// CHECK-DAG: ArraySet
2290 /// CHECK-DAG: ArraySet
2291 /// CHECK-DAG: ArraySet
2292 private static void $noinline$testThrowingArraySet(Object[] a, Object o) {
2293 Object olda0 = a[0];
2294 a[0] = null;
2295 a[1] = olda0;
2296 a[0] = o;
2297 a[1] = null;
2298 }
2299
Vladimir Marko3224f382020-06-23 14:19:53 +01002300 /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (before)
2301 /// CHECK-DAG: InstanceFieldSet
2302 /// CHECK-DAG: InstanceFieldSet
2303 /// CHECK-DAG: InstanceFieldGet
2304 /// CHECK-DAG: Phi
2305
2306 /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (after)
2307 /// CHECK-DAG: InstanceFieldSet
2308 /// CHECK-DAG: InstanceFieldSet
2309 /// CHECK-DAG: Phi
2310 /// CHECK-DAG: Phi
2311
2312 /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (after)
2313 /// CHECK-NOT: InstanceFieldGet
2314
2315 // Test Phi creation for load elimination with loop.
2316 private static int testLoop1(TestClass obj, int n) {
2317 obj.i = 0;
2318 for (int i = 0; i < n; ++i) {
2319 obj.i = i;
2320 }
2321 return obj.i;
2322 }
2323
2324 /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (before)
2325 /// CHECK-DAG: InstanceFieldSet
2326 /// CHECK-DAG: InstanceFieldSet
2327 /// CHECK-DAG: InstanceFieldGet
2328 /// CHECK-DAG: Phi
2329
2330 /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after)
2331 /// CHECK-DAG: InstanceFieldSet
2332 /// CHECK-DAG: InstanceFieldSet
2333
2334 /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after)
2335 /// CHECK-NOT: InstanceFieldGet
2336
2337 /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after)
2338 /// CHECK: Phi
2339 /// CHECK-NOT: Phi
2340
2341 // Test that we do not create any Phis for load elimination when
2342 // the heap value was not modified in the loop.
2343 private static int testLoop2(TestClass obj, int n) {
2344 obj.i = 1;
2345 for (int i = 0; i < n; ++i) {
2346 obj.j = i;
2347 }
2348 return obj.i;
2349 }
2350
2351 /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (before)
2352 /// CHECK-DAG: InstanceFieldSet
2353 /// CHECK-DAG: InstanceFieldSet
2354 /// CHECK-DAG: InstanceFieldGet
2355
2356 /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (after)
2357 /// CHECK: InstanceFieldSet
2358 /// CHECK-NOT: InstanceFieldSet
2359
2360 /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (after)
2361 /// CHECK-NOT: InstanceFieldGet
2362
2363 // Test elimination of a store in the loop that stores the same value that was already
2364 // stored before the loop and eliminating the load of that value after the loop.
2365 private static int testLoop3(TestClass obj, int n) {
2366 obj.i = 1;
2367 for (int i = 0; i < n; ++i) {
2368 obj.i = 1;
2369 }
2370 return obj.i;
2371 }
2372
2373 /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (before)
2374 /// CHECK-DAG: InstanceFieldSet
2375 /// CHECK-DAG: InstanceFieldSet
2376
2377 /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (after)
2378 /// CHECK: InstanceFieldSet
2379 /// CHECK-NOT: InstanceFieldSet
2380
2381 /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (after)
2382 /// CHECK-NOT: InstanceFieldGet
2383
2384 // Test store elimination in the loop that stores the same value that was already
2385 // stored before the loop, without any loads of that value.
2386 private static int testLoop4(TestClass obj, int n) {
2387 obj.i = 1;
2388 for (int i = 0; i < n; ++i) {
2389 obj.i = 1;
2390 }
2391 return n;
2392 }
2393
2394 /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (before)
2395 /// CHECK-DAG: InstanceFieldSet
2396 /// CHECK-DAG: InstanceFieldSet
2397 /// CHECK-DAG: InstanceFieldGet
2398 /// CHECK-DAG: InstanceFieldGet
2399 /// CHECK-DAG: InstanceFieldSet
2400 /// CHECK-DAG: InstanceFieldSet
2401 /// CHECK-DAG: InstanceFieldGet
2402
2403 /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (after)
2404 /// CHECK: InstanceFieldSet
2405 /// CHECK: InstanceFieldSet
2406 /// CHECK-NOT: InstanceFieldSet
2407
2408 /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (after)
2409 /// CHECK-NOT: InstanceFieldGet
2410
2411 // Test eliminating loads and stores that just shuffle the same value between
2412 // different heap locations.
2413 private static int testLoop5(TestClass obj, int n) {
2414 // Initialize both `obj.i` and `obj.j` to the same value and then swap these values
2415 // in the loop. We should be able to determine that the values are always the same.
2416 obj.i = n;
2417 obj.j = n;
2418 for (int i = 0; i < n; ++i) {
2419 if ((i & 1) != 0) {
2420 int tmp = obj.i;
2421 obj.i = obj.j;
2422 obj.j = tmp;
2423 }
2424 }
2425 return obj.i;
2426 }
2427
2428 /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (before)
2429 /// CHECK-DAG: InstanceFieldSet
2430 /// CHECK-DAG: InstanceFieldSet
2431 /// CHECK-DAG: InstanceFieldGet
2432 /// CHECK-DAG: InstanceFieldGet
2433 /// CHECK-DAG: InstanceFieldSet
2434 /// CHECK-DAG: InstanceFieldSet
2435 /// CHECK-DAG: InstanceFieldSet
2436 /// CHECK-DAG: InstanceFieldGet
2437
2438 /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (after)
2439 /// CHECK: InstanceFieldSet
2440 /// CHECK: InstanceFieldSet
2441 /// CHECK-NOT: InstanceFieldSet
2442
2443 /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (after)
2444 /// CHECK-NOT: InstanceFieldGet
2445
2446 // Test eliminating loads and stores that just shuffle the same value between
2447 // different heap locations, or store the same value.
2448 private static int testLoop6(TestClass obj, int n) {
2449 // Initialize both `obj.i` and `obj.j` to the same value and then swap these values
2450 // in the loop or set `obj.i` to the same value. We should be able to determine
2451 // that the values are always the same.
2452 obj.i = n;
2453 obj.j = n;
2454 for (int i = 0; i < n; ++i) {
2455 if ((i & 1) != 0) {
2456 int tmp = obj.i;
2457 obj.i = obj.j;
2458 obj.j = tmp;
2459 } else {
2460 obj.i = n;
2461 }
2462 }
2463 return obj.i;
2464 }
2465
2466 /// CHECK-START: int Main.testLoop7(int) load_store_elimination (before)
2467 /// CHECK-DAG: NewInstance
2468 /// CHECK-DAG: InstanceFieldGet
2469 /// CHECK-DAG: InstanceFieldGet
2470 /// CHECK-DAG: InstanceFieldSet
2471 /// CHECK-DAG: InstanceFieldSet
2472 /// CHECK-DAG: InstanceFieldSet
2473 /// CHECK-DAG: InstanceFieldGet
2474
2475 /// CHECK-START: int Main.testLoop7(int) load_store_elimination (after)
2476 /// CHECK-NOT: NewInstance
2477 /// CHECK-NOT: InstanceFieldSet
2478 /// CHECK-NOT: InstanceFieldGet
2479
2480 // Test eliminating loads and stores that just shuffle the default value between
2481 // different heap locations, or store the same value.
2482 private static int testLoop7(int n) {
2483 // Leave both `obj.i` and `obj.j` initialized to the default value and then
2484 // swap these values in the loop or set some to the identical value 0.
2485 // We should be able to determine that the values are always the same.
2486 TestClass obj = new TestClass();
2487 for (int i = 0; i < n; ++i) {
2488 if ((i & 1) != 0) {
2489 int tmp = obj.i;
2490 obj.i = obj.j;
2491 obj.j = tmp;
2492 } else {
2493 obj.i = 0;
2494 }
2495 }
2496 return obj.i;
2497 }
2498
2499 /// CHECK-START: int Main.testLoop8(int) load_store_elimination (before)
2500 /// CHECK-DAG: NewInstance
2501 /// CHECK-DAG: InstanceFieldGet
2502 /// CHECK-DAG: InstanceFieldGet
2503 /// CHECK-DAG: InstanceFieldSet
2504 /// CHECK-DAG: InstanceFieldSet
2505 /// CHECK-DAG: InstanceFieldSet
2506 /// CHECK-DAG: InstanceFieldSet
2507 /// CHECK-DAG: InstanceFieldGet
2508
2509 /// CHECK-START: int Main.testLoop8(int) load_store_elimination (after)
2510 /// CHECK-NOT: NewInstance
2511 /// CHECK-NOT: InstanceFieldSet
2512 /// CHECK-NOT: InstanceFieldGet
2513
2514 /// CHECK-START: int Main.testLoop8(int) load_store_elimination (after)
2515 /// CHECK: Phi
2516 /// CHECK: Phi
2517 /// CHECK-NOT: Phi
2518
2519 // Test eliminating loads and stores that just shuffle the same value between
2520 // different heap locations, or store the same value. The value is loaded
2521 // after conditionally setting a different value after the loop to test that
2522 // this does not cause creation of excessive Phis.
2523 private static int testLoop8(int n) {
2524 // Leave both `obj.i` and `obj.j` initialized to the default value and then
2525 // swap these values in the loop or set some to the identical value 0.
2526 // We should be able to determine that the values are always the same.
2527 TestClass obj = new TestClass();
2528 for (int i = 0; i < n; ++i) {
2529 if ((i & 1) != 0) {
2530 int tmp = obj.i;
2531 obj.i = obj.j;
2532 obj.j = tmp;
2533 } else {
2534 obj.i = 0;
2535 }
2536 }
2537 // Up to this point, `obj.i` is always 0 but the Phi placeholder below
2538 // must not be included in that determination despite using lazy search
2539 // for Phi placeholders triggered by the `obj.i` load below.
2540 if ((n & 1) == 0) {
2541 obj.i = 1;
2542 }
2543 return obj.i;
2544 }
2545
2546 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (before)
2547 /// CHECK-DAG: NewInstance
2548 /// CHECK-DAG: InstanceFieldSet
2549 /// CHECK-DAG: InstanceFieldSet
2550 /// CHECK-DAG: Phi
2551 /// CHECK-DAG: InstanceFieldGet
2552 /// CHECK-DAG: InstanceFieldGet
2553 /// CHECK-DAG: InstanceFieldSet
2554 /// CHECK-DAG: InstanceFieldSet
2555 /// CHECK-DAG: InvokeStaticOrDirect
2556 /// CHECK-DAG: InstanceFieldGet
2557
2558 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2559 /// CHECK-DAG: InstanceFieldSet
2560 /// CHECK-DAG: Phi
2561 /// CHECK-DAG: Phi
2562 /// CHECK-DAG: InstanceFieldGet
2563 /// CHECK-DAG: InstanceFieldSet
2564 /// CHECK-DAG: Phi
2565
2566 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2567 /// CHECK: InstanceFieldSet
2568 /// CHECK: InstanceFieldSet
2569 /// CHECK-NOT: InstanceFieldSet
2570
2571 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2572 /// CHECK-NOT: NewInstance
2573
2574 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2575 /// CHECK: InstanceFieldGet
2576 /// CHECK-NOT: InstanceFieldGet
2577
2578 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after)
2579 /// CHECK: Phi
2580 /// CHECK: Phi
2581 /// CHECK: Phi
2582 /// CHECK-NOT: Phi
2583
2584 // Test that unknown value flowing through a loop back-edge prevents
2585 // elimination of a load but that load can be used as an input to a Phi
2586 // created to eliminate another load.
2587 private static int testLoop9(TestClass obj, int n) {
2588 TestClass obj0 = new TestClass();
2589 // Initialize both `obj.i` and `obj0.i` to the same value and then swap these values
2590 // in the loop or clobber `obj.i`. We should determine that the `obj.i` load in the
2591 // loop must be kept but the `obj0.i` load can be replaced by a Phi chain.
2592 obj0.i = n;
2593 obj.i = n;
2594 for (int i = 0; i < n; ++i) {
2595 if ((i & 1) != 0) {
2596 int tmp = obj0.i;
2597 obj0.i = obj.i; // Load cannot be eliminated.
2598 obj.i = tmp;
2599 } else {
2600 $noinline$clobberObservables(); // Makes obj.i unknown.
2601 }
2602 }
2603 return obj0.i;
2604 }
2605
2606 /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (before)
2607 /// CHECK-DAG: InstanceFieldSet
2608 /// CHECK-DAG: InstanceFieldGet
2609 /// CHECK-DAG: InstanceFieldSet
2610 /// CHECK-DAG: InstanceFieldGet
2611
2612 /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (after)
2613 /// CHECK-DAG: InstanceFieldSet
2614 /// CHECK-DAG: InstanceFieldGet
2615 /// CHECK-DAG: InstanceFieldSet
2616
2617 /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (after)
2618 /// CHECK: InstanceFieldGet
2619 /// CHECK-NOT: InstanceFieldGet
2620
2621 // Test load elimination after finding a non-eliminated load depending
2622 // on loop Phi placeholder.
2623 private static int testLoop10(TestClass obj, int n) {
2624 obj.i = 1;
2625 for (int i = 0; i < n; ++i) {
2626 $noinline$clobberObservables();
2627 }
2628 int i1 = obj.i;
2629 obj.j = 2; // Use write side effects to stop GVN from eliminating the load below.
2630 int i2 = obj.i;
2631 return i1 + i2;
2632 }
2633
2634 /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (before)
2635 /// CHECK-DAG: InstanceFieldSet
2636 /// CHECK-DAG: Phi
2637 /// CHECK-DAG: InstanceFieldSet
2638 /// CHECK-DAG: InstanceFieldSet
2639 /// CHECK-DAG: InstanceFieldGet
2640
2641 /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after)
2642 /// CHECK-DAG: InstanceFieldSet
2643 /// CHECK-DAG: Phi
2644 /// CHECK-DAG: Phi
2645 /// CHECK-DAG: InstanceFieldSet
2646 /// CHECK-DAG: InstanceFieldSet
2647 /// CHECK-DAG: Phi
2648
2649 /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after)
2650 /// CHECK: Phi
2651 /// CHECK: Phi
2652 /// CHECK: Phi
2653 /// CHECK-NOT: Phi
2654
2655 /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after)
2656 /// CHECK-NOT: InstanceFieldGet
2657
2658 // Test load elimination creating two Phis that depend on each other.
2659 private static int testLoop11(TestClass obj, int n) {
2660 obj.i = 1;
2661 for (int i = 0; i < n; ++i) {
2662 if ((i & 1) != 0) {
2663 obj.i = 2;
2664 } else {
2665 obj.i = 3;
2666 }
2667 // There shall be a Phi created here for `obj.i` before the "++i".
2668 // This Phi and the loop Phi that shall be created for `obj.i` depend on each other.
2669 }
2670 return obj.i;
2671 }
2672
2673 /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (before)
2674 /// CHECK-DAG: InstanceFieldSet
2675 /// CHECK-DAG: Phi
2676 /// CHECK-DAG: InstanceFieldSet
2677 /// CHECK-DAG: InstanceFieldSet
2678 /// CHECK-DAG: InstanceFieldGet
2679
2680 /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after)
2681 /// CHECK-DAG: InstanceFieldSet
2682 /// CHECK-DAG: Phi
2683 /// CHECK-DAG: Phi
2684 /// CHECK-DAG: InstanceFieldSet
2685 /// CHECK-DAG: InstanceFieldSet
2686
2687 /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after)
2688 /// CHECK: Phi
2689 /// CHECK: Phi
2690 /// CHECK-NOT: Phi
2691
2692 /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after)
2693 /// CHECK-NOT: InstanceFieldGet
2694
2695 // Test load elimination creating a single Phi with more than 2 inputs.
2696 private static int testLoop12(TestClass obj, int n) {
2697 obj.i = 1;
2698 for (int i = 0; i < n; ) {
2699 // Do the loop variable increment first, so that there are back-edges
2700 // directly from the "then" and "else" blocks below.
2701 ++i;
2702 if ((i & 1) != 0) {
2703 obj.i = 2;
2704 } else {
2705 obj.i = 3;
2706 }
2707 }
2708 return obj.i;
2709 }
2710
2711 /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (before)
2712 /// CHECK-DAG: NewArray
2713 /// CHECK-DAG: Phi
2714 /// CHECK-DAG: ArrayGet
2715 /// CHECK-DAG: ArraySet
2716 /// CHECK-DAG: ArrayGet
2717 /// CHECK-DAG: ArraySet
2718 /// CHECK-DAG: InstanceFieldGet
2719 /// CHECK-DAG: ArraySet
2720 /// CHECK-DAG: ArrayGet
2721
2722 /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after)
2723 /// CHECK-DAG: Phi
2724 /// CHECK-DAG: Phi
2725 /// CHECK-DAG: Phi
2726 /// CHECK-DAG: Phi
2727 /// CHECK-DAG: InstanceFieldGet
2728
2729 /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after)
2730 /// CHECK-NOT: NewArray
2731 /// CHECK-NOT: ArrayGet
2732 /// CHECK-NOT: ArraySet
2733
2734 /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after)
2735 /// CHECK: Phi
2736 /// CHECK: Phi
2737 /// CHECK: Phi
2738 /// CHECK: Phi
2739 /// CHECK-NOT: Phi
2740
2741 // Test eliminating array allocation, loads and stores and creating loop Phis.
2742 private static int testLoop13(TestClass obj, int n) {
2743 int[] a = new int[3];
2744 for (int i = 0; i < n; ++i) {
2745 a[0] = a[1];
2746 a[1] = a[2];
2747 a[2] = obj.i;
2748 }
2749 return a[0];
2750 }
2751
2752 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (before)
2753 /// CHECK-DAG: NewArray
2754 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.i
2755 /// CHECK-DAG: Phi
2756 /// CHECK-DAG: ArrayGet
2757 /// CHECK-DAG: ArraySet
2758 /// CHECK-DAG: ArrayGet
2759 /// CHECK-DAG: ArraySet
2760 /// CHECK-DAG: InstanceFieldGet field_name:TestClass2.i
2761 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.j
2762 /// CHECK-DAG: InstanceFieldGet field_name:TestClass2.i
2763 /// CHECK-DAG: ArraySet
2764 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.k
2765 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.j
2766 /// CHECK-DAG: InstanceFieldGet field_name:TestClass2.i
2767 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.k
2768 /// CHECK-DAG: ArrayGet
2769
2770 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
2771 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.i
2772 /// CHECK-DAG: Phi
2773 /// CHECK-DAG: Phi
2774 /// CHECK-DAG: Phi
2775 /// CHECK-DAG: Phi
2776 /// CHECK-DAG: InstanceFieldGet field_name:TestClass2.i
2777 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.j
2778 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.k
2779 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.j
2780 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.k
2781
2782 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
2783 /// CHECK-NOT: NewArray
2784
2785 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
2786 /// CHECK: InstanceFieldGet field_name:TestClass2.i
2787 /// CHECK-NOT: InstanceFieldGet field_name:TestClass2.i
2788
2789 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after)
2790 /// CHECK: Phi
2791 /// CHECK: Phi
2792 /// CHECK: Phi
2793 /// CHECK: Phi
2794 /// CHECK-NOT: Phi
2795
2796 // Test load elimination in a loop after determing that the first field load
2797 // (depending on loop Phi placeholder) cannot be eliminated.
2798 private static int testLoop14(TestClass2 obj, int n) {
2799 int[] a = new int[3];
2800 obj.i = 1;
2801 for (int i = 0; i < n; ++i) {
2802 a[0] = a[1];
2803 a[1] = a[2];
2804 int i1 = obj.i;
2805 obj.j = 2; // Use write side effects to stop GVN from eliminating the load below.
2806 int i2 = obj.i;
2807 a[2] = i1;
2808 if ((i & 2) != 0) {
2809 obj.k = i2;
2810 } else {
2811 obj.j = 3; // Use write side effects to stop GVN from eliminating the load below.
2812 obj.k = obj.i;
2813 $noinline$clobberObservables(); // Make obj.i unknown.
2814 }
2815 }
2816 return a[0];
2817 }
2818
2819 /// CHECK-START: int Main.testLoop15(int) load_store_elimination (before)
2820 /// CHECK-DAG: NewArray
Artem Serov2558abe2020-10-14 18:01:37 +01002821 /// CHECK-IF: hasIsaFeature("sve")
2822 //
2823 /// CHECK-DAG: VecPredWhile
2824 /// CHECK-DAG: VecStore
2825 //
2826 /// CHECK-ELSE:
2827 //
2828 /// CHECK-DAG: ArraySet
2829 //
2830 /// CHECK-FI:
2831 //
Vladimir Marko3224f382020-06-23 14:19:53 +01002832 /// CHECK-DAG: ArrayGet
2833
2834 /// CHECK-START: int Main.testLoop15(int) load_store_elimination (after)
2835 /// CHECK-DAG: NewArray
Artem Serov2558abe2020-10-14 18:01:37 +01002836 /// CHECK-IF: hasIsaFeature("sve")
2837 //
2838 /// CHECK-DAG: VecPredWhile
2839 /// CHECK-DAG: VecStore
2840 //
2841 /// CHECK-ELSE:
2842 //
2843 /// CHECK-DAG: ArraySet
2844 //
2845 /// CHECK-FI:
2846 //
Vladimir Marko3224f382020-06-23 14:19:53 +01002847 /// CHECK-DAG: ArrayGet
Vladimir Marko3224f382020-06-23 14:19:53 +01002848 // Test that aliasing array store in the loop is not eliminated
2849 // when a loop Phi placeholder is marked for keeping.
2850 private static int testLoop15(int n) {
2851 int[] a = new int[n + 1];
2852 for (int i = 0; i < n; ++i) {
2853 a[i] = 1; // Cannot be eliminated due to aliasing.
2854 }
2855 return a[0];
2856 }
2857
2858 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (before)
2859 /// CHECK-DAG: InstanceFieldSet
2860 /// CHECK-DAG: Phi
2861 /// CHECK-DAG: InstanceFieldSet
2862 /// CHECK-DAG: InstanceFieldGet
2863
2864 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
2865 /// CHECK-DAG: InstanceFieldSet
2866 /// CHECK-DAG: Phi
2867 /// CHECK-DAG: InstanceFieldSet
2868
2869 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
2870 /// CHECK-NOT: InstanceFieldGet
2871
2872 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after)
2873 /// CHECK: Phi
2874 /// CHECK-NOT: Phi
2875
2876 // Test that we match an existing loop Phi for eliminating a load.
2877 static int testLoop16(TestClass obj, int n) {
2878 obj.i = 0;
2879 for (int i = 0; i < n; ) {
2880 ++i;
2881 obj.i = i;
2882 }
2883 // The load is replaced by the existing Phi instead of constructing a new one.
2884 return obj.i;
2885 }
2886
2887 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (before)
2888 /// CHECK-DAG: InstanceFieldSet
2889 /// CHECK-DAG: Phi
2890 /// CHECK-DAG: InstanceFieldSet
2891 /// CHECK-DAG: InstanceFieldSet
2892 /// CHECK-DAG: Phi
2893 /// CHECK-DAG: InstanceFieldGet
2894
2895 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
2896 /// CHECK-DAG: InstanceFieldSet
2897 /// CHECK-DAG: Phi
2898 /// CHECK-DAG: InstanceFieldSet
2899 /// CHECK-DAG: InstanceFieldSet
2900 /// CHECK-DAG: Phi
2901
2902 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
2903 /// CHECK-NOT: InstanceFieldGet
2904
2905 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after)
2906 /// CHECK: Phi
2907 /// CHECK: Phi
2908 /// CHECK-NOT: Phi
2909
2910 // Test that we match an existing non-loop Phi for eliminating a load,
2911 // one input of the Phi being invariant across a preceding loop.
2912 static int testLoop17(TestClass obj, int n) {
2913 obj.i = 1;
2914 int phi = 1;
2915 for (int i = 0; i < n; ++i) {
2916 obj.j = 2; // Unrelated.
2917 }
2918 if ((n & 1) != 0) {
2919 obj.i = 2;
2920 phi = 2;
2921 }
2922 // The load is replaced by the existing Phi instead of constructing a new one.
2923 return obj.i + phi;
2924 }
2925
2926 /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (before)
2927 /// CHECK-DAG: NewArray
2928 /// CHECK-DAG: Phi
2929 /// CHECK-DAG: ArrayGet
2930 /// CHECK-DAG: InstanceFieldSet
2931
2932 /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after)
2933 /// CHECK-DAG: NewArray
2934 /// CHECK-DAG: Phi
2935 /// CHECK-DAG: InstanceFieldSet
2936
2937 /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after)
2938 /// CHECK-NOT: ArrayGet
2939
2940 // Test eliminating a load of the default value in a loop
2941 // with the array index being defined inside the loop.
2942 static int testLoop18(TestClass obj, int n) {
2943 // The NewArray is kept as it may throw for negative n.
2944 // TODO: Eliminate constructor fence even though the NewArray is kept.
2945 int[] a0 = new int[n];
2946 for (int i = 0; i < n; ++i) {
2947 obj.i = a0[i];
2948 }
2949 return n;
2950 }
2951
2952 /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (before)
2953 /// CHECK-DAG: NewArray
2954 /// CHECK-DAG: Phi
2955 /// CHECK-DAG: ArrayGet
2956 /// CHECK-DAG: InstanceFieldSet
2957 /// CHECK-DAG: ArraySet
2958
2959 /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after)
2960 /// CHECK-DAG: NewArray
2961 /// CHECK-DAG: Phi
2962 /// CHECK-DAG: InstanceFieldSet
2963
2964 /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after)
2965 /// CHECK-NOT: ArrayGet
2966 /// CHECK-NOT: ArraySet
2967
2968 // Test eliminating a load of the default value and store of an identical value
2969 // in a loop with the array index being defined inside the loop.
2970 static int testLoop19(TestClass obj, int n) {
2971 // The NewArray is kept as it may throw for negative n.
2972 // TODO: Eliminate constructor fence even though the NewArray is kept.
2973 int[] a0 = new int[n];
2974 for (int i = 0; i < n; ++i) {
2975 obj.i = a0[i];
2976 a0[i] = 0; // Store the same value as default.
2977 }
2978 return n;
2979 }
2980
2981 /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (before)
2982 /// CHECK-DAG: NewArray
2983 /// CHECK-DAG: Phi
2984 /// CHECK-DAG: ArrayGet
2985 /// CHECK-DAG: InstanceFieldSet
2986 /// CHECK-DAG: ArraySet
2987
2988 /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after)
2989 /// CHECK-DAG: NewArray
2990 /// CHECK-DAG: Phi
2991 /// CHECK-DAG: InstanceFieldSet
2992
2993 /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after)
2994 /// CHECK-NOT: ArrayGet
2995 /// CHECK-NOT: ArraySet
2996
2997 // Test eliminating a load of the default value and a conditional store of an
2998 // identical value in a loop with the array index being defined inside the loop.
2999 static int testLoop20(TestClass obj, int n) {
3000 // The NewArray is kept as it may throw for negative n.
3001 // TODO: Eliminate constructor fence even though the NewArray is kept.
3002 int[] a0 = new int[n];
3003 for (int i = 0; i < n; ++i) {
3004 obj.i = a0[i];
3005 if ((i & 1) != 0) {
3006 a0[i] = 0; // Store the same value as default.
3007 }
3008 }
3009 return n;
3010 }
3011
3012 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before)
3013 /// CHECK-DAG: InstanceFieldSet
3014 /// CHECK-DAG: InstanceFieldGet
3015 /// CHECK-DAG: InstanceFieldSet
3016 /// CHECK-DAG: InstanceFieldGet
3017 /// CHECK-DAG: InstanceFieldSet
3018 /// CHECK-DAG: InstanceFieldGet
3019 /// CHECK-DAG: InstanceFieldSet
3020
3021 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before)
3022 /// CHECK-NOT: Phi
3023
3024 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
3025 /// CHECK-NOT: InstanceFieldGet
3026
3027 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
3028 /// CHECK: InstanceFieldSet
3029 /// CHECK: InstanceFieldSet
3030 /// CHECK: InstanceFieldSet
3031 /// CHECK-NOT: InstanceFieldSet
3032
3033 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after)
3034 /// CHECK: Phi
3035 /// CHECK-NOT: Phi
3036
3037 // Test load elimination when an instance field is used as the loop variable.
3038 static int testLoop21(TestClass obj, int n) {
3039 for (obj.i = 0; obj.i < n; ++obj.i) {
3040 obj.j = 0; // Use write side effects to stop GVN from eliminating the load below.
3041 obj.j = obj.i;
3042 }
3043 return n;
3044 }
3045
3046 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before)
3047 /// CHECK-DAG: InstanceFieldSet
3048 /// CHECK-DAG: InstanceFieldGet
3049 /// CHECK-DAG: InstanceFieldSet
3050 /// CHECK-DAG: InstanceFieldGet
3051 /// CHECK-DAG: InstanceFieldSet
3052 /// CHECK-DAG: InstanceFieldGet
3053 /// CHECK-DAG: InstanceFieldSet
3054 /// CHECK-DAG: InstanceFieldSet
3055
3056 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before)
3057 /// CHECK-NOT: Phi
3058
3059 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
3060 /// CHECK-NOT: InstanceFieldGet
3061
3062 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
3063 /// CHECK: InstanceFieldSet
3064 /// CHECK: InstanceFieldSet
3065 /// CHECK-NOT: InstanceFieldSet
3066
3067 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after)
3068 /// CHECK: Phi
3069 /// CHECK-NOT: Phi
3070
3071 // Test load and store elimination when an instance field is used as the loop
3072 // variable and then overwritten after the loop.
3073 static int testLoop22(TestClass obj, int n) {
3074 for (obj.i = 0; obj.i < n; ++obj.i) {
3075 obj.j = 0; // Use write side effects to stop GVN from eliminating the load below.
3076 obj.j = obj.i;
3077 }
3078 obj.i = 0;
3079 return n;
3080 }
3081
3082 /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (before)
3083 /// CHECK-DAG: InstanceFieldSet
3084 /// CHECK-DAG: Phi
3085 /// CHECK-DAG: Phi
3086 /// CHECK-DAG: InstanceFieldSet
3087 /// CHECK-DAG: InstanceFieldSet
3088 /// CHECK-DAG: Phi
3089 /// CHECK-DAG: InstanceFieldSet
3090
3091 /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after)
3092 /// CHECK-DAG: Phi
3093 /// CHECK-DAG: Phi
3094 /// CHECK-DAG: Phi
3095 /// CHECK-DAG: InstanceFieldSet
3096
3097 /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after)
3098 /// CHECK: InstanceFieldSet
3099 /// CHECK-NOT: InstanceFieldSet
3100
3101 // Test elimination of non-observable stores.
3102 static int testLoop23(TestClass obj, int n) {
3103 obj.i = -1;
3104 int phi = -1;
3105 for (int i = 0; i < n; ++i) {
3106 obj.i = i;
3107 phi = i;
3108 }
3109 if ((n & 1) != 0) {
3110 obj.i = 2;
3111 phi = 2;
3112 }
3113 obj.i = phi; // This store shall be kept, the stores above shall be eliminated.
3114 return phi;
3115 }
3116
3117 /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (before)
3118 /// CHECK-DAG: InstanceFieldSet
3119 /// CHECK-DAG: Phi
3120 /// CHECK-DAG: Phi
3121 /// CHECK-DAG: InstanceFieldSet
3122 /// CHECK-DAG: InstanceFieldSet
3123 /// CHECK-DAG: Phi
3124 /// CHECK-DAG: InstanceFieldSet
3125
3126 /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after)
3127 /// CHECK-DAG: InstanceFieldSet
3128 /// CHECK-DAG: Phi
3129 /// CHECK-DAG: Phi
3130 /// CHECK-DAG: InstanceFieldSet
3131 /// CHECK-DAG: InstanceFieldSet
3132 /// CHECK-DAG: Phi
3133
3134 /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after)
3135 /// CHECK: InstanceFieldSet
3136 /// CHECK: InstanceFieldSet
3137 /// CHECK: InstanceFieldSet
3138 /// CHECK-NOT: InstanceFieldSet
3139
3140 // Test matching Phis for store elimination.
3141 static int testLoop24(TestClass obj, int n) {
3142 obj.i = -1;
3143 int phi = -1;
3144 for (int i = 0; i < n; ++i) {
3145 obj.i = i;
3146 phi = i;
3147 }
3148 if ((n & 1) != 0) {
3149 obj.i = 2;
3150 phi = 2;
3151 }
3152 if (n == 3) {
3153 return -2; // Make the above stores observable.
3154 }
3155 // As the stores above are observable and kept, we match the merged
3156 // heap value with existing Phis and determine that we're storing
3157 // the same value that's already there, so we eliminate this store.
3158 obj.i = phi;
3159 return phi;
3160 }
3161
3162 /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (before)
3163 /// CHECK-DAG: InstanceFieldSet
3164 /// CHECK-DAG: Phi
3165 /// CHECK-DAG: Phi
3166 /// CHECK-DAG: InstanceFieldSet
3167 /// CHECK-DAG: Phi
3168 /// CHECK-DAG: InstanceFieldGet
3169 /// CHECK-DAG: InstanceFieldSet
3170
3171 /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after)
3172 /// CHECK-DAG: InstanceFieldSet
3173 /// CHECK-DAG: Phi
3174 /// CHECK-DAG: Phi
3175 /// CHECK-DAG: Phi
3176 /// CHECK-DAG: InstanceFieldSet
3177 /// CHECK-DAG: Phi
3178 /// CHECK-DAG: Phi
3179 /// CHECK-DAG: InstanceFieldSet
3180
3181 /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after)
3182 /// CHECK-NOT: InstanceFieldGet
3183
3184 // Test that we do not match multiple dependent Phis for load and store elimination.
3185 static int testLoop25(TestClass obj, int n) {
3186 obj.i = 1;
3187 int phi = 1;
3188 for (int i = 0; i < n; ++i) {
3189 if ((i & 1) != 0) {
3190 obj.i = 2;
3191 phi = 2;
3192 }
3193 // There is a Phi here for the variable `phi` before the "++i".
3194 // This Phi and the loop Phi for `phi` depend on each other.
3195 }
3196 if (n == 3) {
3197 return -1; // Make above stores observable.
3198 }
3199 // We're not matching multiple Phi placeholders to existing Phis. Therefore the load
3200 // below requires 2 extra Phis to be created and the store below shall not be eliminated
3201 // even though it stores the same value that's already present in the heap location.
3202 int tmp = obj.i;
3203 obj.i = phi;
3204 return tmp + phi;
3205 }
3206
3207 /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (before)
3208 /// CHECK-DAG: NewInstance
3209 /// CHECK-DAG: InstanceFieldSet
3210 /// CHECK-DAG: Phi
3211 /// CHECK-DAG: NewInstance
3212 /// CHECK-DAG: InstanceFieldSet
3213 /// CHECK-DAG: InstanceFieldGet
3214 /// CHECK-DAG: InstanceFieldGet
3215
3216 /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after)
3217 /// CHECK-DAG: NewInstance
3218 /// CHECK-DAG: InstanceFieldSet
3219 /// CHECK-DAG: Phi
3220 /// CHECK-DAG: Phi
3221 /// CHECK-DAG: NewInstance
3222 /// CHECK-DAG: InstanceFieldSet
3223 /// CHECK-DAG: InstanceFieldGet
3224
3225 /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after)
3226 /// CHECK: InstanceFieldGet
3227 /// CHECK-NOT: InstanceFieldGet
3228
3229 // Test load elimination creating a reference Phi.
3230 static int testLoop26(TestClass obj, int n) {
3231 obj.next = new TestClass(1, 2);
3232 for (int i = 0; i < n; ++i) {
3233 obj.next = new SubTestClass();
3234 }
3235 return obj.next.i;
3236 }
3237
3238 /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (before)
3239 /// CHECK-DAG: NewInstance
3240 /// CHECK-DAG: InstanceFieldSet
3241 /// CHECK-DAG: Phi
3242 /// CHECK-DAG: NewInstance
3243 /// CHECK-DAG: InstanceFieldSet
3244 /// CHECK-DAG: InstanceFieldGet
3245 /// CHECK-DAG: InstanceFieldGet
3246
3247 /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after)
3248 /// CHECK-DAG: NewInstance
3249 /// CHECK-DAG: InstanceFieldSet
3250 /// CHECK-DAG: Phi
3251 /// CHECK-DAG: Phi
3252 /// CHECK-DAG: NewInstance
3253 /// CHECK-DAG: InstanceFieldSet
3254 /// CHECK-DAG: Phi
3255 /// CHECK-DAG: InstanceFieldGet
3256
3257 /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after)
3258 /// CHECK: InstanceFieldGet
3259 /// CHECK-NOT: InstanceFieldGet
3260
3261 // Test load elimination creating two reference Phis that depend on each other.
3262 static int testLoop27(TestClass obj, int n) {
3263 obj.next = new TestClass(1, 2);
3264 for (int i = 0; i < n; ++i) {
3265 if ((i & 1) != 0) {
3266 obj.next = new SubTestClass();
3267 }
3268 // There shall be a Phi created here for `obj.next` before the "++i".
3269 // This Phi and the loop Phi that shall be created for `obj.next` depend on each other.
3270 }
3271 return obj.next.i;
3272 }
3273
3274 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (before)
3275 /// CHECK-DAG: InstanceFieldSet
3276 /// CHECK-DAG: NewArray
3277 /// CHECK-DAG: Phi
3278 /// CHECK-DAG: ArrayGet
3279 /// CHECK-DAG: ArraySet
3280 /// CHECK-DAG: ArrayGet
3281 /// CHECK-DAG: ArraySet
3282 /// CHECK-DAG: InstanceFieldGet
3283 /// CHECK-DAG: ArraySet
3284 /// CHECK-DAG: ArrayGet
3285
3286 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
3287 /// CHECK-DAG: InstanceFieldSet
3288 /// CHECK-DAG: Phi
3289 /// CHECK-DAG: Phi
3290 /// CHECK-DAG: Phi
3291 /// CHECK-DAG: Phi
3292 /// CHECK-DAG: InstanceFieldGet
3293
3294 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
3295 /// CHECK-NOT: NewArray
3296 /// CHECK-NOT: ArrayGet
3297 /// CHECK-NOT: ArraySet
3298
3299 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after)
3300 /// CHECK: Phi
3301 /// CHECK: Phi
3302 /// CHECK: Phi
3303 /// CHECK: Phi
3304 /// CHECK-NOT: Phi
3305
3306 // Test eliminating array allocation, loads and stores and creating loop Phis
3307 // after determining that a field load depending on loop Phi placeholder cannot
3308 // be eliminated.
3309 private static int testLoop28(TestClass obj, int n) {
3310 obj.i = 1;
3311 int[] a = new int[3];
3312 for (int i = 0; i < n; ++i) {
3313 a[0] = a[1];
3314 a[1] = a[2];
3315 a[2] = obj.i;
3316 $noinline$clobberObservables();
3317 }
3318 return a[0];
3319 }
3320
3321 /// CHECK-START: int Main.testLoop29(int) load_store_elimination (before)
3322 /// CHECK-DAG: NewArray
3323 /// CHECK-DAG: Phi
3324 /// CHECK-DAG: Phi
3325 /// CHECK-DAG: ArrayGet
3326 /// CHECK-DAG: ArraySet
3327
3328 /// CHECK-START: int Main.testLoop29(int) load_store_elimination (after)
3329 /// CHECK-DAG: NewArray
3330 /// CHECK-DAG: Phi
3331 /// CHECK-DAG: Phi
3332 /// CHECK-DAG: ArrayGet
3333 /// CHECK-DAG: ArraySet
3334
3335 // Test that ArraySet with non-default value prevents matching ArrayGet for
3336 // the same array to default value even when the ArraySet is using an index
3337 // offset by one, making LSA declare that the two heap locations do not alias.
3338 private static int testLoop29(int n) {
3339 int[] a = new int[4];
3340 int sum = 0;
3341 for (int i = 0; i < n; ) {
3342 int value = a[i] + 1;
3343 sum += value;
3344 ++i;
3345 a[i] = value;
3346 }
3347 return sum;
3348 }
3349
3350 /// CHECK-START: int Main.testLoop30(int) load_store_elimination (before)
3351 /// CHECK-DAG: NewArray
3352 /// CHECK-DAG: Phi
3353 /// CHECK-DAG: Phi
3354 /// CHECK-DAG: ArrayGet
3355 /// CHECK-DAG: ArraySet
3356
3357 /// CHECK-START: int Main.testLoop30(int) load_store_elimination (after)
3358 /// CHECK-NOT: ArrayGet
3359 /// CHECK-NOT: ArraySet
3360
3361 // Test that ArraySet with default value does not prevent matching ArrayGet
3362 // for the same array to the default value.
3363 private static int testLoop30(int n) {
3364 int[] a = new int[4]; // NewArray is kept due to environment use by Deoptimize.
3365 int sum = 0;
3366 for (int i = 0; i < n; ) {
3367 int value = a[i] + 1;
3368 sum += value;
3369 ++i;
3370 a[i] = 0;
3371 }
3372 return sum;
3373 }
3374
3375 /// CHECK-START: int Main.testLoop31(int) load_store_elimination (before)
3376 /// CHECK-DAG: NewArray
3377 /// CHECK-DAG: Phi
3378 /// CHECK-DAG: Phi
3379 /// CHECK-DAG: ArrayGet
3380 /// CHECK-DAG: ArraySet
3381
3382 /// CHECK-START: int Main.testLoop31(int) load_store_elimination (after)
3383 /// CHECK-NOT: ArrayGet
3384 /// CHECK-NOT: ArraySet
3385
3386 // Test that ArraySet with default value read from the array does not
3387 // prevent matching ArrayGet for the same array to the default value.
3388 private static int testLoop31(int n) {
3389 int[] a = new int[4]; // NewArray is kept due to environment use by Deoptimize.
3390 int sum = 0;
3391 for (int i = 0; i < n; ) {
3392 int value = a[i];
3393 sum += value;
3394 ++i;
3395 a[i] = value;
3396 }
3397 return sum;
3398 }
3399
3400 /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (before)
3401 /// CHECK-DAG: InstanceFieldSet
3402 /// CHECK-DAG: Phi
3403 /// CHECK-DAG: Phi
3404 /// CHECK-DAG: InstanceFieldSet
3405 /// CHECK-DAG: InstanceFieldSet
3406 /// CHECK-DAG: Phi
3407 /// CHECK-DAG: InstanceFieldSet
3408
3409 /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after)
3410 /// CHECK-DAG: InstanceFieldSet
3411 /// CHECK-DAG: Phi
3412 /// CHECK-DAG: Phi
3413 /// CHECK-DAG: InstanceFieldSet
3414 /// CHECK-DAG: InstanceFieldSet
3415 /// CHECK-DAG: Phi
3416
3417 /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after)
3418 /// CHECK: InstanceFieldSet
3419 /// CHECK: InstanceFieldSet
3420 /// CHECK: InstanceFieldSet
3421 /// CHECK-NOT: InstanceFieldSet
3422
3423 // Test matching Phis for store elimination.
3424 static int testLoop32(TestClass obj, int n) {
3425 obj.i = -1;
3426 int phi = -1;
3427 for (int i = 0; i < n; ) {
3428 ++i;
3429 if ((i & 1) != 0) {
3430 obj.i = i;
3431 phi = i;
3432 }
3433 }
3434 if ((n & 1) != 0) {
3435 obj.i = 2;
3436 phi = 2;
3437 }
3438 if (n == 3) {
3439 return -2; // Make the above stores observable.
3440 }
3441 // As the stores above are observable and kept, we match the merged
3442 // heap value with existing Phis and determine that we're storing
3443 // the same value that's already there, so we eliminate this store.
3444 obj.i = phi;
3445 return phi;
3446 }
3447
3448 // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (before)
3449 // CHECK-DAG: InstanceFieldSet
3450 // CHECK-DAG: NewArray
3451 // CHECK-DAG: Phi
3452 // CHECK-DAG: ArrayGet
3453 // CHECK-DAG: InstanceFieldSet
3454 // CHECK-DAG: Phi
3455 // CHECK-DAG: ArrayGet
3456 // CHECK-DAG: InstanceFieldGet
3457 // CHECK-DAG: InstanceFieldSet
3458 // CHECK-DAG: InstanceFieldGet
3459
3460 // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after)
3461 // CHECK-DAG: InstanceFieldSet
3462 // CHECK-DAG: Phi
3463 // CHECK-DAG: InstanceFieldSet
3464 // CHECK-DAG: Phi
3465 // CHECK-DAG: InstanceFieldGet
3466 // CHECK-DAG: InstanceFieldSet
3467 // CHECK-DAG: InstanceFieldGet
3468
3469 // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after)
3470 // CHECK-NOT: ArrayGet
3471
3472 // Test that when processing Phi placeholder with unknown input, we allow materialized
3473 // default value in pre-header for array location with index defined in the loop.
3474 static int testLoop33(TestClass obj, int n) {
3475 obj.i = 0;
3476 int[] a0 = new int[n];
3477 for (int i = 0; i < n; ++i) {
3478 obj.i = a0[i];
3479 $noinline$clobberObservables(); // Make `obj.i` unknown.
3480 }
3481 for (int i = 0; i < n; ++i) {
3482 int zero = a0[i];
3483 int unknown = obj.i;
3484 obj.j += zero + unknown;
3485 }
3486 return obj.j;
3487 }
3488
Vladimir Marko0571d472020-09-22 10:14:39 +01003489 /// CHECK-START: int Main.testLoop34(int) load_store_elimination (before)
3490 /// CHECK-DAG: NewArray
3491 /// CHECK-DAG: Phi
3492 /// CHECK-DAG: Phi
3493 /// CHECK-DAG: ArrayGet
3494 /// CHECK-DAG: ArraySet
3495
3496 /// CHECK-START: int Main.testLoop34(int) load_store_elimination (after)
3497 /// CHECK-DAG: NewArray
3498 /// CHECK-DAG: Phi
3499 /// CHECK-DAG: Phi
3500 /// CHECK-DAG: ArrayGet
3501 /// CHECK-DAG: ArraySet
3502
3503 // Test that ArraySet with non-default value prevents matching ArrayGet for
3504 // the same array to default value even when the ArraySet is using an index
3505 // offset by one, making LSA declare that the two heap locations do not alias.
3506 // Also test that the ArraySet is not eliminated.
3507 private static int testLoop34(int n) {
3508 int[] a = new int[n + 1];
3509 int sum = 0;
3510 for (int i = 0; i < n; ) {
3511 int value = a[i] + 1;
3512 sum += value;
3513 ++i;
3514 a[i] = value;
3515 }
3516 return sum;
3517 }
3518
3519 /// CHECK-START: int Main.testLoop35(int) load_store_elimination (before)
3520 /// CHECK-DAG: NewArray
3521 /// CHECK-DAG: Phi
3522 /// CHECK-DAG: Phi
3523 /// CHECK-DAG: ArrayGet
3524 /// CHECK-DAG: ArraySet
3525 /// CHECK-DAG: ArraySet
3526
3527 /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after)
3528 /// CHECK-DAG: NewArray
3529 /// CHECK-DAG: Phi
3530 /// CHECK-DAG: Phi
3531 /// CHECK-DAG: ArrayGet
3532 /// CHECK-DAG: ArraySet
3533
3534 /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after)
3535 /// CHECK: ArraySet
3536 /// CHECK-NOT: ArraySet
3537
3538 // Test that ArraySet with non-default value prevents matching ArrayGet for
3539 // the same array to default value even when the ArraySet is using an index
3540 // offset by one, making LSA declare that the two heap locations do not alias.
3541 // Also test that the ArraySet is not eliminated and that a store after the
3542 // loop is eliminated.
3543 private static int testLoop35(int n) {
3544 int[] a = new int[n + 1];
3545 int sum = 0;
3546 for (int i = 0; i < n; ) {
3547 int value = a[i] + 1;
3548 sum += value;
3549 ++i;
3550 a[i] = value;
3551 }
3552 a[0] = 1;
3553 return sum;
3554 }
3555
Vladimir Markodac82392021-05-10 15:44:24 +00003556 /// CHECK-START: int Main.testLoop36(int) load_store_elimination (before)
3557 /// CHECK-DAG: ArraySet
3558 /// CHECK-DAG: Deoptimize
3559 /// CHECK-DAG: ArrayGet
3560 /// CHECK-DAG: ArrayGet
3561 /// CHECK-DAG: ArrayGet
3562 /// CHECK-DAG: ArrayGet
3563
3564 /// CHECK-START: int Main.testLoop36(int) load_store_elimination (before)
3565 /// CHECK-NOT: BoundsCheck
3566
3567 /// CHECK-START: int Main.testLoop36(int) load_store_elimination (after)
3568 /// CHECK-DAG: ArraySet
3569 /// CHECK-DAG: Deoptimize
3570 /// CHECK-DAG: ArrayGet
3571 /// CHECK-DAG: ArrayGet
3572 /// CHECK-DAG: ArrayGet
3573 /// CHECK-DAG: ArrayGet
3574
3575 // Regression test for b/187487955.
3576 // We previously failed a DCHECK() during the search for kept stores when
3577 // we encountered two array locations for the same array and considered
3578 // non-aliasing by LSA when only one of the array locations had index
3579 // defined inside the loop. Note that this situation requires that BCE
3580 // eliminates BoundsCheck instructions, otherwise LSA considers those
3581 // locations aliasing.
3582 private static int testLoop36(int n) {
3583 int[] a = new int[n];
3584 int zero = 0;
3585 int i = 0;
3586 for (; i < n; ++i) {
3587 a[i] = i;
3588 // Extra instructions to avoid loop unrolling.
3589 zero = (((zero ^ 1) + 2) ^ 1) - 2;
3590 zero = (((zero ^ 4) + 8) ^ 4) - 8;
3591 }
3592 // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`.
3593 // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are
3594 // the Phi plus/minus a constant, something that LSA considers non-aliasing
3595 // with the Phi (LSA does not take different loop iterations into account)
3596 // but LSE must consider aliasing across dfferent loop iterations.
3597 return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero;
3598 }
3599
3600 /// CHECK-START: int Main.testLoop37(int) load_store_elimination (before)
3601 /// CHECK-DAG: ArraySet
3602 /// CHECK-DAG: Deoptimize
3603 /// CHECK-DAG: ArrayGet
3604 /// CHECK-DAG: ArrayGet
3605 /// CHECK-DAG: ArrayGet
3606 /// CHECK-DAG: ArrayGet
3607
3608 /// CHECK-START: int Main.testLoop37(int) load_store_elimination (before)
3609 /// CHECK-NOT: BoundsCheck
3610
3611 /// CHECK-START: int Main.testLoop37(int) load_store_elimination (after)
3612 /// CHECK-DAG: ArraySet
3613 /// CHECK-DAG: Deoptimize
3614 /// CHECK-DAG: ArrayGet
3615 /// CHECK-DAG: ArrayGet
3616 /// CHECK-DAG: ArrayGet
3617 /// CHECK-DAG: ArrayGet
3618
3619 // Similar to testLoop36 but the writes are done via a different reference to the same array.
3620 // We previously used a reference comparison for back-edge aliasing analysis but this test
3621 // has different references and therefore needs `HeapLocationCollector::CanReferencesAlias()`.
3622 private static int testLoop37(int n) {
3623 int[] a = new int[n];
3624 int[] b = $noinline$returnArg(a);
3625 int zero = 0;
3626 int i = 0;
3627 for (; i < n; ++i) {
3628 b[i] = i;
3629 // Extra instructions to avoid loop unrolling.
3630 zero = (((zero ^ 1) + 2) ^ 1) - 2;
3631 zero = (((zero ^ 4) + 8) ^ 4) - 8;
3632 }
3633 // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`.
3634 // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are
3635 // the Phi plus/minus a constant, something that LSA considers non-aliasing
3636 // with the Phi (LSA does not take different loop iterations into account)
3637 // but LSE must consider aliasing across dfferent loop iterations.
3638 return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero;
3639 }
3640
3641 private static int[] $noinline$returnArg(int[] a) {
3642 return a;
3643 }
3644
3645 /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (before)
3646 /// CHECK-DAG: ArraySet
3647 /// CHECK-DAG: Deoptimize
3648 /// CHECK-DAG: ArrayGet
3649 /// CHECK-DAG: ArrayGet
3650 /// CHECK-DAG: ArrayGet
3651 /// CHECK-DAG: ArrayGet
3652
3653 /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (before)
3654 /// CHECK-NOT: BoundsCheck
3655
3656 /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (after)
3657 /// CHECK-DAG: ArraySet
3658 /// CHECK-DAG: Deoptimize
3659
3660 /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (after)
3661 /// CHECK-NOT: ArrayGet
3662
3663 // Similar to testLoop37 but writing to a different array that exists before allocating `a`,
3664 // so that `HeapLocationCollector::CanReferencesAlias()` returns false and all the ArrayGet
3665 // instructions are actually eliminated.
3666 private static int testLoop38(int n, int[] b) {
3667 int[] a = new int[n];
3668 int zero = 0;
3669 int i = 0;
3670 for (; i < n; ++i) {
3671 b[i] = i;
3672 // Extra instructions to avoid loop unrolling.
3673 zero = (((zero ^ 1) + 2) ^ 1) - 2;
3674 zero = (((zero ^ 4) + 8) ^ 4) - 8;
3675 }
3676 // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`.
3677 // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are
3678 // the Phi plus/minus a constant, something that LSA considers non-aliasing
3679 // with the Phi (LSA does not take different loop iterations into account)
3680 // but LSE must consider aliasing across dfferent loop iterations.
3681 return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero;
3682 }
3683
Vladimir Marko3224f382020-06-23 14:19:53 +01003684 /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (before)
3685 /// CHECK-DAG: InstanceFieldSet
3686 /// CHECK-DAG: InstanceFieldGet
3687
3688 /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (after)
3689 /// CHECK-DAG: InstanceFieldSet
3690 /// CHECK-DAG: InstanceFieldGet
3691
3692 // Test heap value clobbering in nested loop.
3693 private static int testNestedLoop1(TestClass obj, int n) {
3694 obj.i = 1;
3695 for (int i = 0; i < n; ++i) {
3696 for (int j = i + 1; j < n; ++j) {
3697 $noinline$clobberObservables();
3698 }
3699 }
3700 return obj.i;
3701 }
3702
3703 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (before)
3704 /// CHECK-DAG: InstanceFieldSet
3705 /// CHECK-DAG: InstanceFieldSet
3706 /// CHECK-DAG: Phi
3707 /// CHECK-DAG: InstanceFieldGet
3708 /// CHECK-DAG: Phi
3709 /// CHECK-DAG: InstanceFieldSet
3710 /// CHECK-DAG: InstanceFieldGet
3711
3712 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
3713 /// CHECK-DAG: InstanceFieldSet
3714 /// CHECK-DAG: InstanceFieldSet
3715 /// CHECK-DAG: Phi
3716 /// CHECK-DAG: Phi
3717 /// CHECK-DAG: InstanceFieldGet
3718 /// CHECK-DAG: Phi
3719 /// CHECK-DAG: InstanceFieldSet
3720
3721 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
3722 /// CHECK: InstanceFieldGet
3723 /// CHECK-NOT: InstanceFieldGet
3724
3725 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after)
3726 /// CHECK: Phi
3727 /// CHECK: Phi
3728 /// CHECK: Phi
3729 /// CHECK-NOT: Phi
3730
3731 // Test heap value clobbering in the nested loop and load elimination for a heap
3732 // location then set to known value before the end of the outer loop.
3733 private static int testNestedLoop2(TestClass obj, int n) {
3734 obj.i = 1;
3735 obj.j = 2;
3736 for (int i = 0; i < n; ++i) {
3737 int tmp = obj.j;
3738 for (int j = i + 1; j < n; ++j) {
3739 $noinline$clobberObservables();
3740 }
3741 obj.i = tmp;
3742 }
3743 return obj.i;
3744 }
3745
3746 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (before)
3747 /// CHECK-DAG: InstanceFieldSet
3748 /// CHECK-DAG: Phi
3749 /// CHECK-DAG: InstanceFieldSet
3750 /// CHECK-DAG: Phi
3751 /// CHECK-DAG: InstanceFieldGet
3752 /// CHECK-DAG: InstanceFieldSet
3753 /// CHECK-DAG: InstanceFieldGet
3754
3755 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
3756 /// CHECK-DAG: InstanceFieldSet
3757 /// CHECK-DAG: Phi
3758 /// CHECK-DAG: Phi
3759 /// CHECK-DAG: InstanceFieldSet
3760 /// CHECK-DAG: Phi
3761 /// CHECK-DAG: InstanceFieldGet
3762 /// CHECK-DAG: InstanceFieldSet
3763
3764 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
3765 /// CHECK: InstanceFieldGet
3766 /// CHECK-NOT: InstanceFieldGet
3767
3768 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after)
3769 /// CHECK: Phi
3770 /// CHECK: Phi
3771 /// CHECK: Phi
3772 /// CHECK-NOT: Phi
3773
3774 // Test heap value clobbering in the nested loop and load elimination for a heap
3775 // location then set to known value before the end of the outer loop.
3776 private static int testNestedLoop3(TestClass obj, int n) {
3777 obj.i = 1;
3778 for (int i = 0; i < n; ++i) {
3779 obj.j = 2;
3780 for (int j = i + 1; j < n; ++j) {
3781 $noinline$clobberObservables();
3782 }
3783 obj.i = obj.j;
3784 }
3785 return obj.i;
3786 }
3787
3788 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (before)
3789 /// CHECK-DAG: InstanceFieldSet
3790 /// CHECK-DAG: Phi
3791 /// CHECK-DAG: Phi
3792 /// CHECK-DAG: InstanceFieldSet
3793 /// CHECK-DAG: InstanceFieldGet
3794
3795 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
3796 /// CHECK-DAG: InstanceFieldSet
3797 /// CHECK-DAG: Phi
3798 /// CHECK-DAG: Phi
3799 /// CHECK-DAG: Phi
3800 /// CHECK-DAG: Phi
3801 /// CHECK-DAG: InstanceFieldSet
3802
3803 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
3804 /// CHECK-NOT: InstanceFieldGet
3805
3806 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after)
3807 /// CHECK: Phi
3808 /// CHECK: Phi
3809 /// CHECK: Phi
3810 /// CHECK: Phi
3811 /// CHECK-NOT: Phi
3812
3813 // Test creating loop Phis for both inner and outer loop to eliminate a load.
3814 private static int testNestedLoop4(TestClass obj, int n) {
3815 obj.i = 1;
3816 for (int i = 0; i < n; ++i) {
3817 for (int j = i + 1; j < n; ++j) {
3818 obj.i = 2;
3819 }
3820 }
3821 return obj.i;
3822 }
3823
3824 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (before)
3825 /// CHECK-DAG: InstanceFieldSet
3826 /// CHECK-DAG: Phi
3827 /// CHECK-DAG: InstanceFieldSet
3828 /// CHECK-DAG: Phi
3829 /// CHECK-DAG: InstanceFieldSet
3830 /// CHECK-DAG: InstanceFieldGet
3831
3832 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
3833 /// CHECK-DAG: InstanceFieldSet
3834 /// CHECK-DAG: Phi
3835 /// CHECK-DAG: Phi
3836 /// CHECK-DAG: InstanceFieldSet
3837 /// CHECK-DAG: Phi
3838 /// CHECK-DAG: InstanceFieldSet
3839
3840 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
3841 /// CHECK-NOT: InstanceFieldGet
3842
3843 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after)
3844 /// CHECK: Phi
3845 /// CHECK: Phi
3846 /// CHECK: Phi
3847 /// CHECK-NOT: Phi
3848
3849 // Test creating a loop Phi for outer loop to eliminate a load.
3850 private static int testNestedLoop5(TestClass obj, int n) {
3851 obj.i = 1;
3852 for (int i = 0; i < n; ++i) {
3853 obj.i = 2;
3854 for (int j = i + 1; j < n; ++j) {
3855 obj.j = 3; // Unrelated.
3856 }
3857 }
3858 return obj.i;
3859 }
3860
3861 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (before)
3862 /// CHECK-DAG: InstanceFieldSet
3863 /// CHECK-DAG: InstanceFieldSet
3864 /// CHECK-DAG: Phi
3865 /// CHECK-DAG: Phi
3866 /// CHECK-DAG: InstanceFieldGet
3867 /// CHECK-DAG: InstanceFieldSet
3868 /// CHECK-DAG: InstanceFieldGet
3869
3870 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
3871 /// CHECK-DAG: InstanceFieldSet
3872 /// CHECK-DAG: InstanceFieldSet
3873 /// CHECK-DAG: Phi
3874 /// CHECK-DAG: Phi
3875 /// CHECK-DAG: Phi
3876 /// CHECK-DAG: Phi
3877 /// CHECK-DAG: InstanceFieldGet
3878 /// CHECK-DAG: InstanceFieldSet
3879
3880 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
3881 /// CHECK: InstanceFieldGet
3882 /// CHECK-NOT: InstanceFieldGet
3883
3884 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after)
3885 /// CHECK: Phi
3886 /// CHECK: Phi
3887 /// CHECK: Phi
3888 /// CHECK: Phi
3889 /// CHECK-NOT: Phi
3890
3891 // Test heap value clobbering in the nested loop and load elimination for a heap
3892 // location then set to known value before the end of that inner loop.
3893 private static int testNestedLoop6(TestClass obj, int n) {
3894 obj.i = 1;
3895 obj.j = 2;
3896 for (int i = 0; i < n; ++i) {
3897 for (int j = i + 1; j < n; ++j) {
3898 int tmp = obj.j;
3899 $noinline$clobberObservables();
3900 obj.i = tmp;
3901 }
3902 }
3903 return obj.i;
3904 }
3905
3906 /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (before)
3907 /// CHECK-DAG: NewArray
3908 /// CHECK-DAG: Phi
3909 /// CHECK-DAG: Phi
3910 /// CHECK-DAG: ArrayGet
3911 /// CHECK-DAG: InstanceFieldSet
3912
3913 /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after)
3914 /// CHECK-DAG: NewArray
3915 /// CHECK-DAG: Phi
3916 /// CHECK-DAG: Phi
3917 /// CHECK-DAG: InstanceFieldSet
3918
3919 /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after)
3920 /// CHECK-NOT: ArrayGet
3921
3922 // Test load elimination in inner loop reading default value that is loop invariant
3923 // with an index defined inside the inner loop.
3924 private static int testNestedLoop7(TestClass obj, int n) {
3925 // The NewArray is kept as it may throw for negative n.
3926 // TODO: Eliminate constructor fence even though the NewArray is kept.
3927 int[] a0 = new int[n];
3928 for (int i = 0; i < n; ++i) {
3929 for (int j = i + 1; j < n; ++j) {
3930 obj.i = a0[j];
3931 }
3932 }
3933 return n;
3934 }
3935
3936 /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (before)
3937 /// CHECK-DAG: NewInstance
3938 /// CHECK-DAG: InstanceFieldSet
3939 /// CHECK-DAG: Phi
3940 /// CHECK-DAG: Phi
3941 /// CHECK-DAG: NewInstance
3942 /// CHECK-DAG: InstanceFieldSet
3943 /// CHECK-DAG: InstanceFieldGet
3944 /// CHECK-DAG: InstanceFieldGet
3945
3946 /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after)
3947 /// CHECK-DAG: NewInstance
3948 /// CHECK-DAG: InstanceFieldSet
3949 /// CHECK-DAG: Phi
3950 /// CHECK-DAG: Phi
3951 /// CHECK-DAG: Phi
3952 /// CHECK-DAG: Phi
3953 /// CHECK-DAG: NewInstance
3954 /// CHECK-DAG: InstanceFieldSet
3955 /// CHECK-DAG: InstanceFieldGet
3956
3957 /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after)
3958 /// CHECK: InstanceFieldGet
3959 /// CHECK-NOT: InstanceFieldGet
3960
3961 // Test reference type propagation for Phis created for outer and inner loop.
3962 private static int testNestedLoop8(TestClass obj, int n) {
3963 obj.next = new SubTestClass();
3964 for (int i = 0; i < n; ++i) {
3965 for (int j = i + 1; j < n; ++j) {
3966 obj.next = new TestClass();
3967 }
3968 }
3969 // The Phis created in both loop headers for replacing `obj.next` depend on each other.
3970 return obj.next.i;
3971 }
3972
Alex Light9dec90a2020-09-14 17:58:28 -07003973
3974 /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (before)
3975 /// CHECK-DAG: NewArray
3976 /// CHECK-DAG: ArraySet
3977 /// CHECK-DAG: If
3978 /// CHECK-DAG: ArrayGet
3979 /// CHECK-DAG: ArrayGet
3980 /// CHECK-DAG: ArraySet
3981 /// CHECK-DAG: ArrayGet
3982 /// CHECK-DAG: Goto
3983
3984 /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (after)
3985 /// CHECK-DAG: NewArray
3986 /// CHECK-DAG: ArraySet
3987 /// CHECK-DAG: If
3988 /// CHECK-DAG: ArrayGet
3989 /// CHECK-DAG: ArrayGet
3990 /// CHECK-DAG: ArraySet
3991 /// CHECK-DAG: Goto
3992 /// CHECK-NOT: ArrayGet
3993
3994 // Test that we don't incorrectly remove writes needed by later loop iterations
3995 // NB This is fibonacci numbers
3996 private static long testOverlapLoop(int cnt) {
3997 long[] w = new long[cnt];
3998 w[1] = 1;
3999 long t = 1;
4000 for (int i = 2; i < cnt; ++i) {
4001 w[i] = w[i - 1] + w[i - 2];
4002 t = w[i];
4003 }
4004 return t;
4005 }
4006
Alex Light86fe9b82020-11-16 16:54:01 +00004007 private static boolean $noinline$getBoolean(boolean val) {
4008 return val;
4009 }
4010
4011 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (before)
4012 /// CHECK-DAG: ParameterValue
4013 /// CHECK-DAG: NewInstance
4014 /// CHECK-DAG: InvokeStaticOrDirect
4015 /// CHECK-DAG: InstanceFieldSet
4016 /// CHECK-DAG: InvokeStaticOrDirect
4017 /// CHECK-DAG: InstanceFieldGet
4018 /// CHECK-DAG: InstanceFieldGet
4019 /// CHECK-DAG: InstanceFieldSet
4020 /// CHECK-DAG: InstanceFieldGet
4021 /// CHECK-DAG: InstanceFieldGet
4022 /// CHECK-DAG: Phi
4023 //
4024 /// CHECK-NOT: NewInstance
4025 /// CHECK-NOT: InvokeStaticOrDirect
4026 /// CHECK-NOT: InstanceFieldSet
4027 /// CHECK-NOT: InstanceFieldGet
4028 //
4029 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
4030 /// CHECK-DAG: ParameterValue
4031 /// CHECK-DAG: NewInstance
4032 /// CHECK-DAG: Phi
4033 //
4034 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
4035 /// CHECK: InvokeStaticOrDirect
4036 /// CHECK: InvokeStaticOrDirect
4037 //
4038 /// CHECK-NOT: InvokeStaticOrDirect
4039
4040 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
4041 /// CHECK: InstanceFieldSet
4042 //
Nicolas Geoffray2498d852021-11-16 15:12:04 +00004043 // TODO: We should be able to remove this setter by realizing `i` only escapes in a branch.
4044 /// CHECK: InstanceFieldSet
Alex Light86fe9b82020-11-16 16:54:01 +00004045 /// CHECK-NOT: InstanceFieldSet
4046 //
4047 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after)
4048 /// CHECK: InstanceFieldGet
4049 /// CHECK: InstanceFieldGet
4050 /// CHECK: InstanceFieldGet
4051 //
4052 /// CHECK-NOT: InstanceFieldGet
4053 private static int $noinline$testPartialEscape1(TestClass obj, boolean escape) {
4054 TestClass i = new SubTestClass();
4055 int res;
4056 if ($noinline$getBoolean(escape)) {
4057 i.next = obj;
4058 $noinline$Escape(i);
4059 res = i.next.i;
4060 } else {
4061 i.next = obj;
4062 res = i.next.i;
4063 }
4064 return res;
4065 }
4066
Vladimir Marko3224f382020-06-23 14:19:53 +01004067 private static void $noinline$clobberObservables() {}
4068
Alex Light9dec90a2020-09-14 17:58:28 -07004069 static void assertLongEquals(long result, long expected) {
4070 if (expected != result) {
4071 throw new Error("Expected: " + expected + ", found: " + result);
4072 }
4073 }
4074
Mingyao Yang062157f2016-03-02 10:15:36 -08004075 static void assertIntEquals(int result, int expected) {
Mingyao Yang8df69d42015-10-22 15:40:58 -07004076 if (expected != result) {
4077 throw new Error("Expected: " + expected + ", found: " + result);
4078 }
4079 }
4080
Mingyao Yang062157f2016-03-02 10:15:36 -08004081 static void assertFloatEquals(float result, float expected) {
Mingyao Yang8df69d42015-10-22 15:40:58 -07004082 if (expected != result) {
4083 throw new Error("Expected: " + expected + ", found: " + result);
4084 }
4085 }
4086
Mingyao Yang062157f2016-03-02 10:15:36 -08004087 static void assertDoubleEquals(double result, double expected) {
Mingyao Yang8df69d42015-10-22 15:40:58 -07004088 if (expected != result) {
4089 throw new Error("Expected: " + expected + ", found: " + result);
4090 }
4091 }
4092
Vladimir Markob122cd62020-06-11 09:15:21 +00004093 public static void main(String[] args) {
Mingyao Yang8df69d42015-10-22 15:40:58 -07004094 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI));
4095 assertIntEquals(test1(new TestClass(), new TestClass()), 3);
4096 assertIntEquals(test2(new TestClass()), 1);
4097 TestClass obj1 = new TestClass();
4098 TestClass obj2 = new TestClass();
4099 obj1.next = obj2;
4100 assertIntEquals(test3(obj1), 10);
Vladimir Markob122cd62020-06-11 09:15:21 +00004101 assertIntEquals(test4(new TestClass(), true), 1);
4102 assertIntEquals(test4(new TestClass(), false), 1);
4103 assertIntEquals(test5(new TestClass(), true), 1);
4104 assertIntEquals(test5(new TestClass(), false), 2);
Mingyao Yang8df69d42015-10-22 15:40:58 -07004105 assertIntEquals(test6(new TestClass(), new TestClass(), true), 4);
4106 assertIntEquals(test6(new TestClass(), new TestClass(), false), 2);
4107 assertIntEquals(test7(new TestClass()), 1);
4108 assertIntEquals(test8(), 1);
4109 obj1 = new TestClass();
4110 obj2 = new TestClass();
4111 obj1.next = obj2;
4112 assertIntEquals(test9(new TestClass()), 1);
Vladimir Markofaada5e2020-06-10 10:38:40 +00004113 assertIntEquals(test10(new TestClass(3, 4)), 3);
Mingyao Yang8df69d42015-10-22 15:40:58 -07004114 assertIntEquals(TestClass.si, 3);
4115 assertIntEquals(test11(new TestClass()), 10);
4116 assertIntEquals(test12(new TestClass(), new TestClass()), 10);
4117 assertIntEquals(test13(new TestClass(), new TestClass2()), 3);
4118 SubTestClass obj3 = new SubTestClass();
4119 assertIntEquals(test14(obj3, obj3), 2);
4120 assertIntEquals(test15(), 2);
4121 assertIntEquals(test16(), 3);
4122 assertIntEquals(test17(), 0);
4123 assertIntEquals(test18(new TestClass()), 1);
4124 float[] fa1 = { 0.8f };
4125 float[] fa2 = { 1.8f };
4126 assertFloatEquals(test19(fa1, fa2), 1.8f);
4127 assertFloatEquals(test20().i, 0);
Mingyao Yang803cbb92015-12-01 12:24:36 -08004128 test21(new TestClass());
Mingyao Yangfb8464a2015-11-02 10:56:59 -08004129 assertIntEquals(test22(), 13);
Vladimir Markob122cd62020-06-11 09:15:21 +00004130 assertIntEquals(test23(true), 4);
4131 assertIntEquals(test23(false), 5);
4132 assertFloatEquals(test24(), 8.0f);
Vladimir Marko3224f382020-06-23 14:19:53 +01004133 assertIntEquals(test25(false, true, true), 5);
4134 assertIntEquals(test25(true, false, true), 2);
4135 assertFloatEquals(test26(5), 0.0f);
4136 assertFloatEquals(test26(3), 1.0f);
4137 assertIntEquals(test27(false, true), 1);
4138 assertIntEquals(test27(true, false), 1);
4139 assertIntEquals(test28(false, true), 0);
4140 assertIntEquals(test28(true, true), 5);
4141 assertFloatEquals(test29(true), 5.0f);
4142 assertFloatEquals(test29(false), 2.0f);
4143 assertIntEquals(test30(new TestClass(), true), 1);
4144 assertIntEquals(test30(new TestClass(), false), 0);
4145 assertIntEquals(test31(true, true), 5);
4146 assertIntEquals(test31(true, false), 6);
4147 assertIntEquals(test32(1), 10);
4148 assertIntEquals(test32(2), 10);
4149 assertIntEquals(test33(new TestClass(), true), 1);
4150 assertIntEquals(test33(new TestClass(), false), 2);
4151 assertIntEquals(test34(new TestClass(), true, true), 3);
4152 assertIntEquals(test34(new TestClass(), false, true), 4);
4153 assertIntEquals(test34(new TestClass(), true, false), 1);
4154 assertIntEquals(test34(new TestClass(), false, false), 2);
4155 assertIntEquals(test35(new TestClass(), true, true), 3);
4156 assertIntEquals(test35(new TestClass(), false, true), 2);
4157 assertIntEquals(test35(new TestClass(), true, false), 1);
4158 assertIntEquals(test35(new TestClass(), false, false), 2);
4159 assertIntEquals(test36(new TestClass(), true), 2);
4160 assertIntEquals(test36(new TestClass(), false), 4);
4161 assertIntEquals(test37(new TestClass(), true), 1);
4162 assertIntEquals(test37(new TestClass(), false), 0);
4163 assertIntEquals(test38(new TestClass(), true), 1);
4164 assertIntEquals(test38(new TestClass(), false), 2);
4165 assertIntEquals(test39(new TestClass(), true), 0);
4166 assertIntEquals(test39(new TestClass(), false), 1);
Santiago Aboy Solanes42f1af82022-04-22 16:20:39 +01004167 assertIntEquals(test40(), 150);
Vladimir Marko3224f382020-06-23 14:19:53 +01004168
Mingyao Yangfb8464a2015-11-02 10:56:59 -08004169 testFinalizableByForcingGc();
Santiago Aboy Solanes4ebfcac2022-03-31 11:19:25 +01004170 testFinalizableWithLoopByForcingGc();
Mingyao Yang40bcb932016-02-03 05:46:57 -08004171 assertIntEquals($noinline$testHSelect(true), 0xdead);
Mingyao Yang062157f2016-03-02 10:15:36 -08004172 int[] array = {2, 5, 9, -1, -3, 10, 8, 4};
4173 assertIntEquals(sumWithinRange(array, 1, 5), 11);
Mingyao Yang0a845202016-10-14 16:26:08 -07004174 assertFloatEquals(testAllocationEliminationWithLoops(), 1.0f);
4175 assertFloatEquals(mF, 0f);
Mingyao Yang58d9bfc2016-11-01 13:31:58 -07004176 assertDoubleEquals(Math.PI * Math.PI * Math.PI, getCircleArea(Math.PI, true));
4177 assertDoubleEquals(0d, getCircleArea(Math.PI, false));
Mingyao Yange58bdca2016-10-28 11:07:24 -07004178
Vladimir Marko4307cd72020-07-17 14:35:56 +01004179 assertIntEquals($noinline$testConversion1(new TestClass(), 300), 300);
4180 assertIntEquals($noinline$testConversion1(new TestClass(), 301), 45);
4181 assertIntEquals($noinline$testConversion2(new TestClass(), 300), 300);
4182 assertIntEquals($noinline$testConversion2(new TestClass(), 301), 90);
Vladimir Marko3224f382020-06-23 14:19:53 +01004183 assertIntEquals($noinline$testConversion3(new TestClass(), 0), 0);
4184 assertIntEquals($noinline$testConversion3(new TestClass(), 1), 0);
4185 assertIntEquals($noinline$testConversion3(new TestClass(), 128), 127);
4186 assertIntEquals($noinline$testConversion3(new TestClass(), 129), -128);
4187 assertIntEquals($noinline$testConversion4(new TestClass(), 0), 0);
4188 assertIntEquals($noinline$testConversion4(new TestClass(), 1), 0);
4189 assertIntEquals($noinline$testConversion4(new TestClass(), 128), 254);
4190 assertIntEquals($noinline$testConversion4(new TestClass(), 129), -256);
Vladimir Marko4307cd72020-07-17 14:35:56 +01004191
Mingyao Yange58bdca2016-10-28 11:07:24 -07004192 int[] iarray = {0, 0, 0};
4193 double[] darray = {0d, 0d, 0d};
4194 try {
4195 assertDoubleEquals(Math.PI * Math.PI * Math.PI, testDeoptimize(iarray, darray, Math.PI));
4196 } catch (Exception e) {
Vladimir Markob122cd62020-06-11 09:15:21 +00004197 System.out.println(e.getClass().getName());
Mingyao Yange58bdca2016-10-28 11:07:24 -07004198 }
4199 assertIntEquals(iarray[0], 1);
4200 assertIntEquals(iarray[1], 1);
4201 assertIntEquals(iarray[2], 1);
4202 assertDoubleEquals(darray[0], Math.PI);
4203 assertDoubleEquals(darray[1], Math.PI);
4204 assertDoubleEquals(darray[2], Math.PI);
Mingyao Yang86974902017-03-01 14:03:51 -08004205
4206 assertIntEquals(testAllocationEliminationOfArray1(), 11);
4207 assertIntEquals(testAllocationEliminationOfArray2(), 11);
4208 assertIntEquals(testAllocationEliminationOfArray3(2), 4);
4209 assertIntEquals(testAllocationEliminationOfArray4(2), 6);
Mingyao Yang7cf9af22018-02-06 15:02:42 -08004210 assertIntEquals(testAllocationEliminationOfArray5(2), 12);
4211 try {
4212 testAllocationEliminationOfArray5(-2);
4213 } catch (NegativeArraySizeException e) {
4214 System.out.println("Got NegativeArraySizeException.");
4215 }
Mingyao Yangeb2d2d346e2017-03-02 13:26:17 -08004216
4217 assertIntEquals(testStoreStore().i, 41);
4218 assertIntEquals(testStoreStore().j, 43);
Mingyao Yang293f1c02017-11-08 15:22:17 -08004219
Mingyao Yang46721ef2017-10-05 14:45:17 -07004220 assertIntEquals(testExitMerge(true), 2);
4221 assertIntEquals(testExitMerge2(true), 2);
4222 assertIntEquals(testExitMerge2(false), 2);
4223
Mingyao Yanga3540532018-01-25 12:17:28 -08004224 TestClass2 testclass2 = new TestClass2();
4225 testStoreStore2(testclass2);
4226 assertIntEquals(testclass2.i, 43);
4227 assertIntEquals(testclass2.j, 44);
4228
4229 testStoreStore3(testclass2, true);
4230 assertIntEquals(testclass2.i, 41);
4231 assertIntEquals(testclass2.j, 43);
4232 testStoreStore3(testclass2, false);
4233 assertIntEquals(testclass2.i, 41);
4234 assertIntEquals(testclass2.j, 44);
4235
4236 testStoreStore4();
4237 assertIntEquals(TestClass.si, 62);
4238
4239 int ret = testStoreStore5(testclass2, testclass2);
4240 assertIntEquals(testclass2.i, 72);
4241 assertIntEquals(ret, 71);
4242
4243 testclass2.j = 88;
4244 ret = testStoreStore6(testclass2, testclass2);
4245 assertIntEquals(testclass2.i, 82);
4246 assertIntEquals(ret, 88);
4247
4248 ret = testNoSideEffects(iarray);
Mingyao Yang293f1c02017-11-08 15:22:17 -08004249 assertIntEquals(iarray[0], 101);
Mingyao Yanga3540532018-01-25 12:17:28 -08004250 assertIntEquals(iarray[1], 103);
Mingyao Yang293f1c02017-11-08 15:22:17 -08004251 assertIntEquals(ret, 108);
Mingyao Yanga3540532018-01-25 12:17:28 -08004252
4253 try {
4254 testThrow(testclass2, new Exception());
4255 } catch (Exception e) {}
4256 assertIntEquals(testclass2.i, 55);
4257
4258 assertIntEquals(testStoreStoreWithDeoptimize(new int[4]), 4);
Aart Bik4dc09e72018-05-11 14:40:31 -07004259
Vladimir Marko4307cd72020-07-17 14:35:56 +01004260 assertIntEquals($noinline$testByteArrayDefaultValue(), 0);
4261
Aart Bik4dc09e72018-05-11 14:40:31 -07004262 assertIntEquals(testLocalArrayMerge1(true), 1);
4263 assertIntEquals(testLocalArrayMerge1(false), 1);
4264 assertIntEquals(testLocalArrayMerge2(true), 2);
4265 assertIntEquals(testLocalArrayMerge2(false), 3);
4266 assertIntEquals(testLocalArrayMerge3(true), 2);
4267 assertIntEquals(testLocalArrayMerge3(false), 1);
4268 assertIntEquals(testLocalArrayMerge4(true), 2);
4269 assertIntEquals(testLocalArrayMerge4(false), 2);
Vladimir Marko3224f382020-06-23 14:19:53 +01004270 assertIntEquals(testLocalArrayMerge5(new int[]{ 7 }, true), 7);
4271 assertIntEquals(testLocalArrayMerge5(new int[]{ 9 }, false), 9);
4272 assertIntEquals(testLocalArrayMerge6(new int[1], true, true), 1);
4273 assertIntEquals(testLocalArrayMerge6(new int[1], true, false), 2);
4274 assertIntEquals(testLocalArrayMerge6(new int[1], false, true), 2);
4275 assertIntEquals(testLocalArrayMerge6(new int[1], false, false), 1);
4276 assertIntEquals(testLocalArrayMerge7(new int[2], true, true), 1);
4277 assertIntEquals(testLocalArrayMerge7(new int[2], true, false), 2);
4278 assertIntEquals(testLocalArrayMerge7(new int[2], false, true), 0);
4279 assertIntEquals(testLocalArrayMerge7(new int[2], false, false), 0);
Vladimir Markocbeedc82020-08-25 14:31:10 +01004280 assertIntEquals(testLocalArrayMerge8(true), 0);
4281 assertIntEquals(testLocalArrayMerge8(false), 0);
Vladimir Markofab6f1c2020-07-14 16:25:05 +01004282
4283 TestClass[] tca = new TestClass[] { new TestClass(), null };
4284 try {
4285 $noinline$testThrowingArraySet(tca, new TestClass2());
4286 } catch (ArrayStoreException expected) {
4287 if (tca[0] != null) {
4288 throw new Error("tca[0] is not null");
4289 }
4290 if (tca[1] == null) {
4291 throw new Error("tca[1] is null");
4292 }
4293 }
Mingyao Yang40bcb932016-02-03 05:46:57 -08004294
Vladimir Marko3224f382020-06-23 14:19:53 +01004295 assertIntEquals(testLoop1(new TestClass(), 0), 0);
4296 assertIntEquals(testLoop1(new TestClass(), 1), 0);
4297 assertIntEquals(testLoop1(new TestClass(), 2), 1);
4298 assertIntEquals(testLoop1(new TestClass(), 3), 2);
4299 assertIntEquals(testLoop2(new TestClass(), 0), 1);
4300 assertIntEquals(testLoop2(new TestClass(), 1), 1);
4301 assertIntEquals(testLoop2(new TestClass(), 2), 1);
4302 assertIntEquals(testLoop2(new TestClass(), 3), 1);
4303 assertIntEquals(testLoop3(new TestClass(), 0), 1);
4304 assertIntEquals(testLoop3(new TestClass(), 1), 1);
4305 assertIntEquals(testLoop3(new TestClass(), 2), 1);
4306 assertIntEquals(testLoop3(new TestClass(), 3), 1);
4307 assertIntEquals(testLoop4(new TestClass(), 0), 0);
4308 assertIntEquals(testLoop4(new TestClass(), 1), 1);
4309 assertIntEquals(testLoop4(new TestClass(), 2), 2);
4310 assertIntEquals(testLoop4(new TestClass(), 3), 3);
4311 assertIntEquals(testLoop5(new TestClass(), 0), 0);
4312 assertIntEquals(testLoop5(new TestClass(), 1), 1);
4313 assertIntEquals(testLoop5(new TestClass(), 2), 2);
4314 assertIntEquals(testLoop5(new TestClass(), 3), 3);
4315 assertIntEquals(testLoop6(new TestClass(), 0), 0);
4316 assertIntEquals(testLoop6(new TestClass(), 1), 1);
4317 assertIntEquals(testLoop6(new TestClass(), 2), 2);
4318 assertIntEquals(testLoop6(new TestClass(), 3), 3);
4319 assertIntEquals(testLoop7(0), 0);
4320 assertIntEquals(testLoop7(1), 0);
4321 assertIntEquals(testLoop7(2), 0);
4322 assertIntEquals(testLoop7(3), 0);
4323 assertIntEquals(testLoop8(0), 1);
4324 assertIntEquals(testLoop8(1), 0);
4325 assertIntEquals(testLoop8(2), 1);
4326 assertIntEquals(testLoop8(3), 0);
4327 assertIntEquals(testLoop9(new TestClass(), 0), 0);
4328 assertIntEquals(testLoop9(new TestClass(), 1), 1);
4329 assertIntEquals(testLoop9(new TestClass(), 2), 2);
4330 assertIntEquals(testLoop9(new TestClass(), 3), 3);
4331 assertIntEquals(testLoop10(new TestClass(), 0), 2);
4332 assertIntEquals(testLoop10(new TestClass(), 1), 2);
4333 assertIntEquals(testLoop10(new TestClass(), 2), 2);
4334 assertIntEquals(testLoop10(new TestClass(), 3), 2);
4335 assertIntEquals(testLoop11(new TestClass(), 0), 1);
4336 assertIntEquals(testLoop11(new TestClass(), 1), 3);
4337 assertIntEquals(testLoop11(new TestClass(), 2), 2);
4338 assertIntEquals(testLoop11(new TestClass(), 3), 3);
4339 assertIntEquals(testLoop12(new TestClass(), 0), 1);
4340 assertIntEquals(testLoop12(new TestClass(), 1), 2);
4341 assertIntEquals(testLoop12(new TestClass(), 2), 3);
4342 assertIntEquals(testLoop12(new TestClass(), 3), 2);
4343 assertIntEquals(testLoop13(new TestClass(1, 2), 0), 0);
4344 assertIntEquals(testLoop13(new TestClass(1, 2), 1), 0);
4345 assertIntEquals(testLoop13(new TestClass(1, 2), 2), 0);
4346 assertIntEquals(testLoop13(new TestClass(1, 2), 3), 1);
4347 assertIntEquals(testLoop14(new TestClass2(), 0), 0);
4348 assertIntEquals(testLoop14(new TestClass2(), 1), 0);
4349 assertIntEquals(testLoop14(new TestClass2(), 2), 0);
4350 assertIntEquals(testLoop14(new TestClass2(), 3), 1);
4351 assertIntEquals(testLoop15(0), 0);
4352 assertIntEquals(testLoop15(1), 1);
4353 assertIntEquals(testLoop15(2), 1);
4354 assertIntEquals(testLoop15(3), 1);
4355 assertIntEquals(testLoop16(new TestClass(), 0), 0);
4356 assertIntEquals(testLoop16(new TestClass(), 1), 1);
4357 assertIntEquals(testLoop16(new TestClass(), 2), 2);
4358 assertIntEquals(testLoop16(new TestClass(), 3), 3);
4359 assertIntEquals(testLoop17(new TestClass(), 0), 2);
4360 assertIntEquals(testLoop17(new TestClass(), 1), 4);
4361 assertIntEquals(testLoop17(new TestClass(), 2), 2);
4362 assertIntEquals(testLoop17(new TestClass(), 3), 4);
4363 assertIntEquals(testLoop18(new TestClass(), 0), 0);
4364 assertIntEquals(testLoop18(new TestClass(), 1), 1);
4365 assertIntEquals(testLoop18(new TestClass(), 2), 2);
4366 assertIntEquals(testLoop18(new TestClass(), 3), 3);
4367 assertIntEquals(testLoop19(new TestClass(), 0), 0);
4368 assertIntEquals(testLoop19(new TestClass(), 1), 1);
4369 assertIntEquals(testLoop19(new TestClass(), 2), 2);
4370 assertIntEquals(testLoop19(new TestClass(), 3), 3);
4371 assertIntEquals(testLoop20(new TestClass(), 0), 0);
4372 assertIntEquals(testLoop20(new TestClass(), 1), 1);
4373 assertIntEquals(testLoop20(new TestClass(), 2), 2);
4374 assertIntEquals(testLoop20(new TestClass(), 3), 3);
4375 assertIntEquals(testLoop21(new TestClass(), 0), 0);
4376 assertIntEquals(testLoop21(new TestClass(), 1), 1);
4377 assertIntEquals(testLoop21(new TestClass(), 2), 2);
4378 assertIntEquals(testLoop21(new TestClass(), 3), 3);
4379 assertIntEquals(testLoop22(new TestClass(), 0), 0);
4380 assertIntEquals(testLoop22(new TestClass(), 1), 1);
4381 assertIntEquals(testLoop22(new TestClass(), 2), 2);
4382 assertIntEquals(testLoop22(new TestClass(), 3), 3);
4383 assertIntEquals(testLoop23(new TestClass(), 0), -1);
4384 assertIntEquals(testLoop23(new TestClass(), 1), 2);
4385 assertIntEquals(testLoop23(new TestClass(), 2), 1);
4386 assertIntEquals(testLoop23(new TestClass(), 3), 2);
4387 assertIntEquals(testLoop24(new TestClass(), 0), -1);
4388 assertIntEquals(testLoop24(new TestClass(), 1), 2);
4389 assertIntEquals(testLoop24(new TestClass(), 2), 1);
4390 assertIntEquals(testLoop24(new TestClass(), 3), -2);
4391 assertIntEquals(testLoop25(new TestClass(), 0), 2);
4392 assertIntEquals(testLoop25(new TestClass(), 1), 2);
4393 assertIntEquals(testLoop25(new TestClass(), 2), 4);
4394 assertIntEquals(testLoop25(new TestClass(), 3), -1);
4395 assertIntEquals(testLoop26(new TestClass(), 0), 1);
4396 assertIntEquals(testLoop26(new TestClass(), 1), 0);
4397 assertIntEquals(testLoop26(new TestClass(), 2), 0);
4398 assertIntEquals(testLoop26(new TestClass(), 3), 0);
4399 assertIntEquals(testLoop27(new TestClass(), 0), 1);
4400 assertIntEquals(testLoop27(new TestClass(), 1), 1);
4401 assertIntEquals(testLoop27(new TestClass(), 2), 0);
4402 assertIntEquals(testLoop27(new TestClass(), 3), 0);
4403 assertIntEquals(testLoop28(new TestClass(1, 2), 0), 0);
4404 assertIntEquals(testLoop28(new TestClass(1, 2), 1), 0);
4405 assertIntEquals(testLoop28(new TestClass(1, 2), 2), 0);
4406 assertIntEquals(testLoop28(new TestClass(1, 2), 3), 1);
4407 assertIntEquals(testLoop29(0), 0);
4408 assertIntEquals(testLoop29(1), 1);
4409 assertIntEquals(testLoop29(2), 3);
4410 assertIntEquals(testLoop29(3), 6);
4411 assertIntEquals(testLoop30(0), 0);
4412 assertIntEquals(testLoop30(1), 1);
4413 assertIntEquals(testLoop30(2), 2);
4414 assertIntEquals(testLoop30(3), 3);
4415 assertIntEquals(testLoop31(0), 0);
4416 assertIntEquals(testLoop31(1), 0);
4417 assertIntEquals(testLoop31(2), 0);
4418 assertIntEquals(testLoop31(3), 0);
4419 assertIntEquals(testLoop32(new TestClass(), 0), -1);
4420 assertIntEquals(testLoop32(new TestClass(), 1), 2);
4421 assertIntEquals(testLoop32(new TestClass(), 2), 1);
4422 assertIntEquals(testLoop32(new TestClass(), 3), -2);
4423 assertIntEquals(testLoop33(new TestClass(), 0), 0);
4424 assertIntEquals(testLoop33(new TestClass(), 1), 0);
4425 assertIntEquals(testLoop33(new TestClass(), 2), 0);
4426 assertIntEquals(testLoop33(new TestClass(), 3), 0);
Vladimir Marko0571d472020-09-22 10:14:39 +01004427 assertIntEquals(testLoop34(0), 0);
4428 assertIntEquals(testLoop34(1), 1);
4429 assertIntEquals(testLoop34(2), 3);
4430 assertIntEquals(testLoop34(3), 6);
4431 assertIntEquals(testLoop35(0), 0);
4432 assertIntEquals(testLoop35(1), 1);
4433 assertIntEquals(testLoop35(2), 3);
4434 assertIntEquals(testLoop35(3), 6);
Vladimir Markodac82392021-05-10 15:44:24 +00004435 assertIntEquals(testLoop36(4), 6);
4436 assertIntEquals(testLoop37(4), 6);
4437 assertIntEquals(testLoop38(4, new int[4]), 0);
Vladimir Marko3224f382020-06-23 14:19:53 +01004438
4439 assertIntEquals(testNestedLoop1(new TestClass(), 0), 1);
4440 assertIntEquals(testNestedLoop1(new TestClass(), 1), 1);
4441 assertIntEquals(testNestedLoop1(new TestClass(), 2), 1);
4442 assertIntEquals(testNestedLoop1(new TestClass(), 3), 1);
4443 assertIntEquals(testNestedLoop2(new TestClass(), 0), 1);
4444 assertIntEquals(testNestedLoop2(new TestClass(), 1), 2);
4445 assertIntEquals(testNestedLoop2(new TestClass(), 2), 2);
4446 assertIntEquals(testNestedLoop2(new TestClass(), 3), 2);
4447 assertIntEquals(testNestedLoop3(new TestClass(), 0), 1);
4448 assertIntEquals(testNestedLoop3(new TestClass(), 1), 2);
4449 assertIntEquals(testNestedLoop3(new TestClass(), 2), 2);
4450 assertIntEquals(testNestedLoop3(new TestClass(), 3), 2);
4451 assertIntEquals(testNestedLoop4(new TestClass(), 0), 1);
4452 assertIntEquals(testNestedLoop4(new TestClass(), 1), 1);
4453 assertIntEquals(testNestedLoop4(new TestClass(), 2), 2);
4454 assertIntEquals(testNestedLoop4(new TestClass(), 3), 2);
4455 assertIntEquals(testNestedLoop5(new TestClass(), 0), 1);
4456 assertIntEquals(testNestedLoop5(new TestClass(), 1), 2);
4457 assertIntEquals(testNestedLoop5(new TestClass(), 2), 2);
4458 assertIntEquals(testNestedLoop5(new TestClass(), 3), 2);
4459 assertIntEquals(testNestedLoop6(new TestClass(), 0), 1);
4460 assertIntEquals(testNestedLoop6(new TestClass(), 1), 1);
4461 assertIntEquals(testNestedLoop6(new TestClass(), 2), 2);
4462 assertIntEquals(testNestedLoop6(new TestClass(), 3), 2);
4463 assertIntEquals(testNestedLoop7(new TestClass(), 0), 0);
4464 assertIntEquals(testNestedLoop7(new TestClass(), 1), 1);
4465 assertIntEquals(testNestedLoop7(new TestClass(), 2), 2);
4466 assertIntEquals(testNestedLoop7(new TestClass(), 3), 3);
4467 assertIntEquals(testNestedLoop8(new TestClass(), 0), 0);
4468 assertIntEquals(testNestedLoop8(new TestClass(), 1), 0);
4469 assertIntEquals(testNestedLoop8(new TestClass(), 2), 0);
4470 assertIntEquals(testNestedLoop8(new TestClass(), 3), 0);
Alex Light9dec90a2020-09-14 17:58:28 -07004471 assertLongEquals(testOverlapLoop(10), 34l);
4472 assertLongEquals(testOverlapLoop(50), 7778742049l);
Alex Light86fe9b82020-11-16 16:54:01 +00004473 assertIntEquals($noinline$testPartialEscape1(new TestClass(), true), 1);
4474 assertIntEquals($noinline$testPartialEscape1(new TestClass(), false), 0);
Vladimir Marko3224f382020-06-23 14:19:53 +01004475 }
Mingyao Yang8df69d42015-10-22 15:40:58 -07004476}