1 /* 2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package org.graalvm.compiler.core.test; 26 27 import static org.graalvm.compiler.core.common.GraalOptions.OptImplicitNullChecks; 28 import static org.graalvm.compiler.core.common.GraalOptions.OptScheduleOutOfLoops; 29 import static org.graalvm.compiler.graph.test.matchers.NodeIterableCount.hasCount; 30 import static org.hamcrest.core.IsInstanceOf.instanceOf; 31 import static org.junit.Assert.assertThat; 32 33 import java.util.ArrayList; 34 import java.util.List; 35 36 import org.graalvm.compiler.api.directives.GraalDirectives; 37 import org.graalvm.compiler.debug.DebugContext; 38 import org.graalvm.compiler.graph.Node; 39 import org.graalvm.compiler.graph.iterators.NodeIterable; 40 import org.graalvm.compiler.nodes.ReturnNode; 41 import org.graalvm.compiler.nodes.StartNode; 42 import org.graalvm.compiler.nodes.StructuredGraph; 43 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 44 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; 45 import org.graalvm.compiler.nodes.cfg.Block; 46 import org.graalvm.compiler.nodes.memory.FloatingReadNode; 47 import org.graalvm.compiler.nodes.memory.WriteNode; 48 import org.graalvm.compiler.nodes.spi.LoweringTool; 49 import org.graalvm.compiler.options.OptionValues; 50 import org.graalvm.compiler.phases.OptimisticOptimizations; 51 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 52 import org.graalvm.compiler.phases.common.FloatingReadPhase; 53 import org.graalvm.compiler.phases.common.GuardLoweringPhase; 54 import org.graalvm.compiler.phases.common.LoweringPhase; 55 import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; 56 import org.graalvm.compiler.phases.schedule.SchedulePhase; 57 import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; 58 import org.graalvm.compiler.phases.tiers.HighTierContext; 59 import org.graalvm.compiler.phases.tiers.MidTierContext; 60 import org.junit.Assert; 61 import org.junit.Test; 62 63 /** 64 * In these test the FrameStates are explicitly cleared out, so that the scheduling of 65 * FloatingReadNodes depends solely on the scheduling algorithm. The FrameStates normally keep the 66 * FloatingReadNodes above a certain point, so that they (most of the time...) magically do the 67 * right thing. 68 * 69 * The scheduling shouldn't depend on FrameStates, which is tested by this class. 70 */ 71 public class MemoryScheduleTest extends GraphScheduleTest { 72 73 private enum TestMode { 74 WITH_FRAMESTATES, 75 WITHOUT_FRAMESTATES, 76 INLINED_WITHOUT_FRAMESTATES 77 } 78 79 public static class Container { 80 81 public int a; 82 public int b; 83 public int c; 84 85 public Object obj; 86 } 87 88 private static final Container container = new Container(); 89 private static final List<Container> containerList = new ArrayList<>(); 90 private static final double LOOP_ENTRY_PROBABILITY = 0.9; 91 92 /** 93 * In this test the read should be scheduled before the write. 94 */ 95 public static int testSimpleSnippet() { 96 try { 97 return container.a; 98 } finally { 99 container.a = 15; 100 } 101 } 102 103 @Test 104 public void testSimple() { 105 for (TestMode mode : TestMode.values()) { 106 ScheduleResult schedule = getFinalSchedule("testSimpleSnippet", mode); 107 StructuredGraph graph = schedule.getCFG().graph; 108 assertReadAndWriteInSameBlock(schedule, true); 109 assertOrderedAfterSchedule(schedule, graph.getNodes().filter(FloatingReadNode.class).first(), graph.getNodes().filter(WriteNode.class).first()); 110 } 111 } 112 113 /** 114 * In this case the read should be scheduled in the first block. 115 */ 116 public static int testSplit1Snippet(int a) { 117 try { 118 return container.a; 119 } finally { 120 if (a < 0) { 121 container.a = 15; 122 } else { 123 container.b = 15; 124 } 125 } 126 } 127 128 @Test 129 public void testSplit1() { 130 for (TestMode mode : TestMode.values()) { 131 ScheduleResult schedule = getFinalSchedule("testSplit1Snippet", mode); 132 assertReadWithinStartBlock(schedule, true); 133 assertReadWithinAllReturnBlocks(schedule, false); 134 } 135 } 136 137 /** 138 * Here the read should float to the end. 139 */ 140 public static int testSplit2Snippet(int a) { 141 try { 142 return container.a; 143 } finally { 144 if (a < 0) { 145 container.c = 15; 146 } else { 147 container.b = 15; 148 } 149 container.obj = null; 150 } 151 } 152 153 @Test 154 public void testSplit2() { 155 ScheduleResult schedule = getFinalSchedule("testSplit2Snippet", TestMode.WITHOUT_FRAMESTATES); 156 assertReadWithinStartBlock(schedule, false); 157 assertReadWithinAllReturnBlocks(schedule, true); 158 } 159 160 /** 161 * Here the read should not float to the end. 162 */ 163 public static int testLoop1Snippet(int a, int b) { 164 try { 165 return container.a; 166 } finally { 167 for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { 168 if (b < 0) { 169 container.b = 10; 170 } else { 171 container.a = 15; 172 } 173 } 174 } 175 } 176 177 @Test 178 public void testLoop1() { 179 ScheduleResult schedule = getFinalSchedule("testLoop1Snippet", TestMode.WITHOUT_FRAMESTATES); 180 assertDeepEquals(6, schedule.getCFG().getBlocks().length); 181 assertReadWithinStartBlock(schedule, true); 182 assertReadWithinAllReturnBlocks(schedule, false); 183 } 184 185 /** 186 * Here the read should float to the end. 187 */ 188 public static int testLoop2Snippet(int a, int b) { 189 try { 190 return container.a; 191 } finally { 192 for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { 193 if (b < 0) { 194 container.b = 10; 195 } else { 196 container.c = 15; 197 } 198 } 199 } 200 } 201 202 @Test 203 public void testLoop2() { 204 ScheduleResult schedule = getFinalSchedule("testLoop2Snippet", TestMode.WITHOUT_FRAMESTATES); 205 assertDeepEquals(6, schedule.getCFG().getBlocks().length); 206 assertReadWithinStartBlock(schedule, false); 207 assertReadWithinAllReturnBlocks(schedule, true); 208 } 209 210 /** 211 * Here the read should float out of the loop. 212 */ 213 public static int testLoop3Snippet(int a) { 214 int j = 0; 215 for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { 216 if (i - container.a == 0) { 217 break; 218 } 219 j++; 220 } 221 return j; 222 } 223 224 @Test 225 public void testLoop3() { 226 ScheduleResult schedule = getFinalSchedule("testLoop3Snippet", TestMode.WITHOUT_FRAMESTATES); 227 assertDeepEquals(6, schedule.getCFG().getBlocks().length); 228 assertReadWithinStartBlock(schedule, true); 229 assertReadWithinAllReturnBlocks(schedule, false); 230 } 231 232 public String testStringReplaceSnippet(String input) { 233 return input.replace('a', 'b'); 234 } 235 236 @Test 237 public void testStringReplace() { 238 getFinalSchedule("testStringReplaceSnippet", TestMode.INLINED_WITHOUT_FRAMESTATES); 239 test("testStringReplaceSnippet", "acbaaa"); 240 } 241 242 /** 243 * Here the read should float out of the loop. 244 */ 245 public static int testLoop5Snippet(int a, int b, MemoryScheduleTest obj) { 246 int ret = 0; 247 int bb = b; 248 for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { 249 ret = obj.hash; 250 if (a > 10) { 251 bb++; 252 } else { 253 bb--; 254 } 255 ret = ret / 10; 256 } 257 return ret + bb; 258 } 259 260 @Test 261 public void testLoop5() { 262 ScheduleResult schedule = getFinalSchedule("testLoop5Snippet", TestMode.WITHOUT_FRAMESTATES); 263 assertDeepEquals(10, schedule.getCFG().getBlocks().length); 264 assertReadWithinStartBlock(schedule, false); 265 assertReadWithinAllReturnBlocks(schedule, false); 266 } 267 268 /** 269 * Here the read should not float out of the loop. 270 */ 271 public static int testLoop6Snippet(int a, int b, MemoryScheduleTest obj) { 272 int ret = 0; 273 int bb = b; 274 for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { 275 ret = obj.hash; 276 if (a > 10) { 277 bb++; 278 } else { 279 bb--; 280 for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); ++j) { 281 obj.hash = 3; 282 } 283 } 284 ret = ret / 10; 285 } 286 return ret + bb; 287 } 288 289 @Test 290 public void testLoop6() { 291 ScheduleResult schedule = getFinalSchedule("testLoop6Snippet", TestMode.WITHOUT_FRAMESTATES); 292 assertDeepEquals(13, schedule.getCFG().getBlocks().length); 293 assertReadWithinStartBlock(schedule, false); 294 assertReadWithinAllReturnBlocks(schedule, false); 295 } 296 297 /** 298 * Here the read should not float out of the loop. 299 */ 300 public static int testLoop7Snippet(int a, int b, MemoryScheduleTest obj) { 301 int ret = 0; 302 int bb = b; 303 for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { 304 ret = obj.hash; 305 if (a > 10) { 306 bb++; 307 } else { 308 bb--; 309 for (int k = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, k < a); ++k) { 310 if (k % 2 == 1) { 311 for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); ++j) { 312 obj.hash = 3; 313 } 314 } 315 } 316 } 317 ret = ret / 10; 318 } 319 return ret + bb; 320 } 321 322 @Test 323 public void testLoop7() { 324 ScheduleResult schedule = getFinalSchedule("testLoop7Snippet", TestMode.WITHOUT_FRAMESTATES); 325 assertDeepEquals(18, schedule.getCFG().getBlocks().length); 326 assertReadWithinStartBlock(schedule, false); 327 assertReadWithinAllReturnBlocks(schedule, false); 328 } 329 330 /** 331 * Here the read should not float to the end. 332 */ 333 public static int testLoop8Snippet(int a, int b) { 334 int result = container.a; 335 for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { 336 if (b < 0) { 337 container.b = 10; 338 break; 339 } else { 340 for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); j++) { 341 container.a = 0; 342 } 343 } 344 } 345 GraalDirectives.controlFlowAnchor(); 346 return result; 347 } 348 349 @Test 350 public void testLoop8() { 351 ScheduleResult schedule = getFinalSchedule("testLoop8Snippet", TestMode.WITHOUT_FRAMESTATES); 352 assertDeepEquals(10, schedule.getCFG().getBlocks().length); 353 assertReadWithinStartBlock(schedule, true); 354 assertReadWithinAllReturnBlocks(schedule, false); 355 } 356 357 /** 358 * Here the read should float after the loop. 359 */ 360 public static int testLoop9Snippet(int a, int b) { 361 container.a = b; 362 for (int i = 0; i < a; i++) { 363 container.a = i; 364 } 365 GraalDirectives.controlFlowAnchor(); 366 return container.a; 367 } 368 369 @Test 370 public void testLoop9() { 371 ScheduleResult schedule = getFinalSchedule("testLoop9Snippet", TestMode.WITHOUT_FRAMESTATES); 372 StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph(); 373 assertThat(graph.getNodes(ReturnNode.TYPE), hasCount(1)); 374 ReturnNode ret = graph.getNodes(ReturnNode.TYPE).first(); 375 assertThat(ret.result(), instanceOf(FloatingReadNode.class)); 376 Block readBlock = schedule.getNodeToBlockMap().get(ret.result()); 377 Assert.assertEquals(0, readBlock.getLoopDepth()); 378 } 379 380 /** 381 * Here the read should not float to the end. 382 */ 383 public static int testIfRead1Snippet(int a) { 384 int res = container.a; 385 if (a < 0) { 386 container.a = 10; 387 } 388 return res; 389 } 390 391 @Test 392 public void testIfRead1() { 393 ScheduleResult schedule = getFinalSchedule("testIfRead1Snippet", TestMode.WITHOUT_FRAMESTATES); 394 assertDeepEquals(3, schedule.getCFG().getBlocks().length); 395 assertReadWithinStartBlock(schedule, true); 396 assertReadAndWriteInSameBlock(schedule, false); 397 } 398 399 /** 400 * Here the read should float in the else block. 401 */ 402 public static int testIfRead2Snippet(int a) { 403 int res = 0; 404 if (a < 0) { 405 container.a = 10; 406 } else { 407 res = container.a; 408 } 409 return res; 410 } 411 412 @Test 413 public void testIfRead2() { 414 ScheduleResult schedule = getFinalSchedule("testIfRead2Snippet", TestMode.WITHOUT_FRAMESTATES); 415 assertDeepEquals(3, schedule.getCFG().getBlocks().length); 416 assertDeepEquals(1, schedule.getCFG().graph.getNodes().filter(FloatingReadNode.class).count()); 417 assertReadWithinStartBlock(schedule, false); 418 assertReadWithinAllReturnBlocks(schedule, false); 419 assertReadAndWriteInSameBlock(schedule, false); 420 } 421 422 /** 423 * Here the read should float to the end, right before the write. 424 */ 425 public static int testIfRead3Snippet(int a) { 426 if (a < 0) { 427 container.a = 10; 428 } 429 int res = container.a; 430 container.a = 20; 431 return res; 432 } 433 434 @Test 435 public void testIfRead3() { 436 ScheduleResult schedule = getFinalSchedule("testIfRead3Snippet", TestMode.WITHOUT_FRAMESTATES); 437 assertDeepEquals(4, schedule.getCFG().getBlocks().length); 438 assertReadWithinStartBlock(schedule, false); 439 assertReadWithinAllReturnBlocks(schedule, true); 440 } 441 442 /** 443 * Here the read should be just in the if branch (with the write). 444 */ 445 public static int testIfRead4Snippet(int a) { 446 if (a > 0) { 447 int res = container.a; 448 container.a = 0x20; 449 return res; 450 } else { 451 return 0x10; 452 } 453 } 454 455 @Test 456 public void testIfRead4() { 457 ScheduleResult schedule = getFinalSchedule("testIfRead4Snippet", TestMode.WITHOUT_FRAMESTATES); 458 assertDeepEquals(3, schedule.getCFG().getBlocks().length); 459 assertReadWithinStartBlock(schedule, false); 460 assertReadWithinAllReturnBlocks(schedule, false); 461 assertReadAndWriteInSameBlock(schedule, true); 462 } 463 464 /** 465 * Here the read should float to the end. 466 */ 467 public static int testIfRead5Snippet(int a) { 468 if (a < 0) { 469 container.a = 10; 470 } 471 return container.a; 472 } 473 474 @Test 475 public void testIfRead5() { 476 ScheduleResult schedule = getFinalSchedule("testIfRead5Snippet", TestMode.WITHOUT_FRAMESTATES); 477 assertDeepEquals(4, schedule.getCFG().getBlocks().length); 478 assertReadWithinStartBlock(schedule, false); 479 assertReadWithinAllReturnBlocks(schedule, true); 480 assertReadAndWriteInSameBlock(schedule, false); 481 } 482 483 public static int testAntiDependencySnippet(int a) { 484 /* 485 * This read must not be scheduled after the following write. 486 */ 487 int res = container.a; 488 container.a = 10; 489 490 /* 491 * Add some more basic blocks. 492 */ 493 if (a < 0) { 494 container.b = 20; 495 } 496 container.c = 30; 497 return res; 498 } 499 500 @Test 501 public void testAntiDependency() { 502 ScheduleResult schedule = getFinalSchedule("testAntiDependencySnippet", TestMode.WITHOUT_FRAMESTATES); 503 assertDeepEquals(4, schedule.getCFG().getBlocks().length); 504 assertReadBeforeAllWritesInStartBlock(schedule); 505 } 506 507 /** 508 * testing scheduling within a block. 509 */ 510 public static int testBlockScheduleSnippet() { 511 int res = 0; 512 container.a = 0x00; 513 container.a = 0x10; 514 container.a = 0x20; 515 container.a = 0x30; 516 container.a = 0x40; 517 res = container.a; 518 container.a = 0x50; 519 container.a = 0x60; 520 container.a = 0x70; 521 return res; 522 } 523 524 @Test 525 public void testBlockSchedule() { 526 ScheduleResult schedule = getFinalSchedule("testBlockScheduleSnippet", TestMode.WITHOUT_FRAMESTATES); 527 StructuredGraph graph = schedule.getCFG().graph; 528 NodeIterable<WriteNode> writeNodes = graph.getNodes().filter(WriteNode.class); 529 530 assertDeepEquals(1, schedule.getCFG().getBlocks().length); 531 assertDeepEquals(8, writeNodes.count()); 532 assertDeepEquals(1, graph.getNodes().filter(FloatingReadNode.class).count()); 533 534 FloatingReadNode read = graph.getNodes().filter(FloatingReadNode.class).first(); 535 536 WriteNode[] writes = new WriteNode[8]; 537 int i = 0; 538 for (WriteNode n : writeNodes) { 539 writes[i] = n; 540 i++; 541 } 542 assertOrderedAfterSchedule(schedule, writes[4], read); 543 assertOrderedAfterSchedule(schedule, read, writes[5]); 544 for (int j = 0; j < 7; j++) { 545 assertOrderedAfterSchedule(schedule, writes[j], writes[j + 1]); 546 } 547 } 548 549 /** 550 * read should move inside the loop (out of loop is disabled). 551 */ 552 public static int testBlockSchedule2Snippet(int value) { 553 int res = 0; 554 555 container.a = value; 556 for (int i = 0; i < 100; i++) { 557 if (i == 10) { 558 return container.a; 559 } 560 res += i; 561 } 562 return res; 563 } 564 565 @Test 566 public void testBlockSchedule2() { 567 ScheduleResult schedule = getFinalSchedule("testBlockSchedule2Snippet", TestMode.WITHOUT_FRAMESTATES, SchedulingStrategy.LATEST); 568 assertReadWithinStartBlock(schedule, false); 569 assertReadWithinAllReturnBlocks(schedule, false); 570 assertReadAndWriteInSameBlock(schedule, false); 571 } 572 573 public static void testProxySnippet() { 574 while (container.a < container.b) { 575 List<Container> list = new ArrayList<>(containerList); 576 while (container.c < list.size()) { 577 if (container.obj != null) { 578 return; 579 } 580 container.c++; 581 } 582 container.a = 0; 583 container.b--; 584 } 585 container.b++; 586 } 587 588 @Test 589 public void testProxy() { 590 ScheduleResult schedule = getFinalSchedule("testProxySnippet", TestMode.WITHOUT_FRAMESTATES); 591 assertReadWithinStartBlock(schedule, false); 592 assertReadWithinAllReturnBlocks(schedule, false); 593 } 594 595 private int hash = 0; 596 private final char[] value = new char[3]; 597 598 public int testStringHashCodeSnippet() { 599 int h = hash; 600 if (h == 0 && value.length > 0) { 601 char[] val = value; 602 603 for (int i = 0; i < value.length; i++) { 604 h = 31 * h + val[i]; 605 } 606 hash = h; 607 } 608 return h; 609 } 610 611 @Test 612 public void testStringHashCode() { 613 ScheduleResult schedule = getFinalSchedule("testStringHashCodeSnippet", TestMode.WITHOUT_FRAMESTATES); 614 assertReadWithinStartBlock(schedule, true); 615 assertReadWithinAllReturnBlocks(schedule, false); 616 617 hash = 0x1337; 618 value[0] = 'a'; 619 value[1] = 'b'; 620 value[2] = 'c'; 621 test("testStringHashCodeSnippet"); 622 } 623 624 public static int testLoop4Snippet(int count) { 625 int[] a = new int[count]; 626 627 for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a.length); i++) { 628 a[i] = i; 629 } 630 631 int i = 0; 632 int iwrap = count - 1; 633 int sum = 0; 634 635 while (GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < count)) { 636 sum += (a[i] + a[iwrap]) / 2; 637 iwrap = i; 638 i++; 639 } 640 return sum; 641 } 642 643 @Test 644 public void testLoop4() { 645 ScheduleResult schedule = getFinalSchedule("testLoop4Snippet", TestMode.WITHOUT_FRAMESTATES); 646 assertReadWithinStartBlock(schedule, false); 647 assertReadWithinAllReturnBlocks(schedule, false); 648 } 649 650 private void assertReadWithinAllReturnBlocks(ScheduleResult schedule, boolean withinReturnBlock) { 651 StructuredGraph graph = schedule.getCFG().graph; 652 assertTrue(graph.getNodes(ReturnNode.TYPE).isNotEmpty()); 653 654 int withRead = 0; 655 int returnBlocks = 0; 656 for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) { 657 Block block = schedule.getCFG().getNodeToBlock().get(returnNode); 658 for (Node node : schedule.getBlockToNodesMap().get(block)) { 659 if (node instanceof FloatingReadNode) { 660 withRead++; 661 break; 662 } 663 } 664 returnBlocks++; 665 } 666 assertDeepEquals(withRead == returnBlocks, withinReturnBlock); 667 } 668 669 private void assertReadWithinStartBlock(ScheduleResult schedule, boolean withinStartBlock) { 670 boolean readEncountered = false; 671 for (Node node : schedule.getBlockToNodesMap().get(schedule.getCFG().getStartBlock())) { 672 if (node instanceof FloatingReadNode) { 673 readEncountered = true; 674 } 675 } 676 assertDeepEquals(withinStartBlock, readEncountered); 677 } 678 679 private static void assertReadAndWriteInSameBlock(ScheduleResult schedule, boolean inSame) { 680 StructuredGraph graph = schedule.getCFG().graph; 681 FloatingReadNode read = graph.getNodes().filter(FloatingReadNode.class).first(); 682 WriteNode write = graph.getNodes().filter(WriteNode.class).first(); 683 assertTrue(!(inSame ^ schedule.getCFG().blockFor(read) == schedule.getCFG().blockFor(write))); 684 } 685 686 private static void assertReadBeforeAllWritesInStartBlock(ScheduleResult schedule) { 687 boolean writeNodeFound = false; 688 boolean readNodeFound = false; 689 for (Node node : schedule.nodesFor(schedule.getCFG().getStartBlock())) { 690 if (node instanceof FloatingReadNode) { 691 assertTrue(!writeNodeFound); 692 readNodeFound = true; 693 } else if (node instanceof WriteNode) { 694 writeNodeFound = true; 695 } 696 } 697 assertTrue(readNodeFound); 698 } 699 700 private ScheduleResult getFinalSchedule(final String snippet, final TestMode mode) { 701 return getFinalSchedule(snippet, mode, SchedulingStrategy.LATEST_OUT_OF_LOOPS); 702 } 703 704 @SuppressWarnings("try") 705 private ScheduleResult getFinalSchedule(final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) { 706 OptionValues options = new OptionValues(getInitialOptions(), OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false); 707 final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, options); 708 DebugContext debug = graph.getDebug(); 709 try (DebugContext.Scope d = debug.scope("FloatingReadTest", graph)) { 710 HighTierContext context = getDefaultHighTierContext(); 711 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 712 canonicalizer.apply(graph, context); 713 if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { 714 createInliningPhase(canonicalizer).apply(graph, context); 715 } 716 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); 717 if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { 718 graph.clearAllStateAfter(); 719 } 720 debug.dump(DebugContext.BASIC_LEVEL, graph, "after removal of framestates"); 721 722 new FloatingReadPhase().apply(graph); 723 new RemoveValueProxyPhase().apply(graph); 724 725 MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); 726 new GuardLoweringPhase().apply(graph, midContext); 727 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); 728 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); 729 730 SchedulePhase schedule = new SchedulePhase(schedulingStrategy); 731 schedule.apply(graph); 732 assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); 733 return graph.getLastSchedule(); 734 } catch (Throwable e) { 735 throw debug.handle(e); 736 } 737 } 738 }