1 /*
2  * Copyright (c) 2015, 2019, 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 org.graalvm.compiler.debug.DebugContext;
28 import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
29 import org.graalvm.compiler.nodes.ProxyNode;
30 import org.graalvm.compiler.nodes.StructuredGraph;
31 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
32 import org.graalvm.compiler.nodes.spi.CoreProviders;
33 import org.graalvm.compiler.nodes.spi.LoweringTool;
34 import org.graalvm.compiler.phases.OptimisticOptimizations;
35 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
36 import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
37 import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
38 import org.graalvm.compiler.phases.common.LoweringPhase;
39 import org.graalvm.compiler.phases.schedule.SchedulePhase;
40 import org.junit.Assert;
41 
42 /**
43  * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase}
44  * including those that triggered bugs in this phase.
45  */
46 public class ConditionalEliminationTestBase extends GraalCompilerTest {
47     protected static int sink0;
48     protected static int sink1;
49     protected static int sink2;
50 
51     /**
52      * These tests assume all code paths in called routines are reachable so disable removal of dead
53      * code based on method profiles.
54      */
55     @Override
getOptimisticOptimizations()56     protected OptimisticOptimizations getOptimisticOptimizations() {
57         return OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.RemoveNeverExecutedCode);
58     }
59 
testConditionalElimination(String snippet, String referenceSnippet)60     protected void testConditionalElimination(String snippet, String referenceSnippet) {
61         testConditionalElimination(snippet, referenceSnippet, false, false);
62     }
63 
64     @SuppressWarnings("try")
testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference, boolean applyLowering)65     protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference, boolean applyLowering) {
66         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
67         DebugContext debug = graph.getDebug();
68         debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
69         CoreProviders context = getProviders();
70         CanonicalizerPhase canonicalizer1 = createCanonicalizerPhase();
71         CanonicalizerPhase canonicalizer = createCanonicalizerPhase();
72         try (DebugContext.Scope scope = debug.scope("ConditionalEliminationTest", graph)) {
73             prepareGraph(graph, canonicalizer1, context, applyLowering);
74             new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context);
75             canonicalizer.apply(graph, context);
76             canonicalizer.apply(graph, context);
77         } catch (Throwable t) {
78             debug.handle(t);
79         }
80         StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES);
81         try (DebugContext.Scope scope = debug.scope("ConditionalEliminationTest.ReferenceGraph", referenceGraph)) {
82             prepareGraph(referenceGraph, canonicalizer, context, applyLowering);
83             if (applyConditionalEliminationOnReference) {
84                 new ConditionalEliminationPhase(true).apply(referenceGraph, context);
85             }
86             canonicalizer.apply(referenceGraph, context);
87             canonicalizer.apply(referenceGraph, context);
88         } catch (Throwable t) {
89             debug.handle(t);
90         }
91         assertEquals(referenceGraph, graph);
92     }
93 
prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, CoreProviders context, boolean applyLowering)94     protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, CoreProviders context, boolean applyLowering) {
95         if (applyLowering) {
96             new ConvertDeoptimizeToGuardPhase().apply(graph, context);
97             new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
98             canonicalizer.apply(graph, context);
99         }
100         canonicalizer.apply(graph, context);
101         new ConvertDeoptimizeToGuardPhase().apply(graph, context);
102     }
103 
testProxies(String snippet, int expectedProxiesCreated)104     public void testProxies(String snippet, int expectedProxiesCreated) {
105         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
106         CoreProviders context = getProviders();
107         CanonicalizerPhase canonicalizer1 = CanonicalizerPhase.createWithoutCFGSimplification();
108         canonicalizer1.apply(graph, context);
109         CanonicalizerPhase canonicalizer = createCanonicalizerPhase();
110         new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
111         canonicalizer.apply(graph, context);
112 
113         int baseProxyCount = graph.getNodes().filter(ProxyNode.class).count();
114         new ConditionalEliminationPhase(true).apply(graph, context);
115         canonicalizer.apply(graph, context);
116         new SchedulePhase(graph.getOptions()).apply(graph, context);
117         int actualProxiesCreated = graph.getNodes().filter(ProxyNode.class).count() - baseProxyCount;
118         Assert.assertEquals(expectedProxiesCreated, actualProxiesCreated);
119     }
120 }
121