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