1 /* 2 * Copyright (c) 2011, 2015, 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 package org.graalvm.compiler.core.test; 24 25 import org.junit.Test; 26 27 import org.graalvm.compiler.debug.Debug; 28 import org.graalvm.compiler.graph.Node; 29 import org.graalvm.compiler.nodes.ConstantNode; 30 import org.graalvm.compiler.nodes.FrameState; 31 import org.graalvm.compiler.nodes.IfNode; 32 import org.graalvm.compiler.nodes.ParameterNode; 33 import org.graalvm.compiler.nodes.StructuredGraph; 34 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 35 import org.graalvm.compiler.nodes.spi.LoweringTool; 36 import org.graalvm.compiler.phases.OptimisticOptimizations; 37 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 38 import org.graalvm.compiler.phases.common.FloatingReadPhase; 39 import org.graalvm.compiler.phases.common.GuardLoweringPhase; 40 import org.graalvm.compiler.phases.common.LoweringPhase; 41 import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; 42 import org.graalvm.compiler.phases.tiers.MidTierContext; 43 import org.graalvm.compiler.phases.tiers.PhaseContext; 44 45 /** 46 * In the following tests, the usages of local variable "a" are replaced with the integer constant 47 * 0. Then canonicalization is applied and it is verified that the resulting graph is equal to the 48 * graph of the method that just has a "return 1" statement in it. 49 */ 50 public class IfCanonicalizerTest extends GraalCompilerTest { 51 52 private static final String REFERENCE_SNIPPET = "referenceSnippet"; 53 54 @SuppressWarnings("all") 55 public static int referenceSnippet(int a) { 56 return 1; 57 } 58 59 @Test 60 public void test1() { 61 test("test1Snippet"); 62 } 63 64 @SuppressWarnings("all") 65 public static int test1Snippet(int a) { 66 if (a == 0) { 67 return 1; 68 } else { 69 return 2; 70 } 71 } 72 73 @Test 74 public void test2() { 75 test("test2Snippet"); 76 } 77 78 @SuppressWarnings("all") 79 public static int test2Snippet(int a) { 80 if (a == 0) { 81 if (a == 0) { 82 if (a == 0) { 83 return 1; 84 } 85 } 86 } else { 87 return 2; 88 } 89 return 3; 90 } 91 92 @Test 93 public void test3() { 94 test("test3Snippet"); 95 } 96 97 @SuppressWarnings("all") 98 public static int test3Snippet(int a) { 99 if (a == 0) { 100 if (a != 1) { 101 if (a == 1) { 102 return 3; 103 } else { 104 if (a >= 0) { 105 if (a <= 0) { 106 if (a > -1) { 107 if (a < 1) { 108 return 1; 109 } 110 } 111 } 112 } 113 } 114 } 115 } else { 116 return 2; 117 } 118 return 3; 119 } 120 121 @Test 122 public void test4() { 123 test("test4Snippet"); 124 } 125 126 public static int test4Snippet(int a) { 127 if (a == 0) { 128 return 1; 129 } 130 return 1; 131 } 132 133 @Test 134 public void test5() { 135 test("test5Snippet"); 136 } 137 138 public static int test5Snippet(int a) { 139 int val = 2; 140 if (a == 0) { 141 val = 1; 142 } 143 if (a * (3 + val) == 0) { 144 return 1; 145 } 146 return 1; 147 } 148 149 @Test 150 public void test6() { 151 testCombinedIf("test6Snippet", 3); 152 test("test6Snippet", new int[]{0}); 153 } 154 155 public static int test6Snippet(int[] a) { 156 int i = a[0]; 157 if (i >= 0 && i < a.length) { 158 return a[i]; 159 } 160 return 1; 161 } 162 163 @Test 164 public void test7() { 165 testCombinedIf("test7Snippet", 1); 166 test("test7Snippet", -1); 167 } 168 169 public static int test7Snippet(int v) { 170 if (v >= 0 && v < 1024) { 171 return v + 1; 172 } 173 return v - 1; 174 } 175 176 @Test 177 public void test8() { 178 testCombinedIf("test8Snippet", 1); 179 test("test8Snippet", -1); 180 } 181 182 public static int test8Snippet(int v) { 183 if (v >= 0 && v <= 1024) { 184 return v + 1; 185 } 186 return v - 1; 187 } 188 189 @Test 190 public void test9() { 191 testCombinedIf("test9Snippet", 2); 192 test("test9Snippet", -1); 193 test("test9Snippet", 1025); 194 } 195 196 public static int test9Snippet(int n) { 197 return (n < 0) ? 1 : (n >= 1024) ? 1024 : n + 1; 198 } 199 200 private void testCombinedIf(String snippet, int count) { 201 StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); 202 PhaseContext context = new PhaseContext(getProviders()); 203 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); 204 new FloatingReadPhase().apply(graph); 205 MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); 206 new GuardLoweringPhase().apply(graph, midContext); 207 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); 208 new ValueAnchorCleanupPhase().apply(graph); 209 new CanonicalizerPhase().apply(graph, context); 210 assertDeepEquals(count, graph.getNodes().filter(IfNode.class).count()); 211 } 212 213 private void test(String snippet) { 214 StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); 215 ParameterNode param = graph.getNodes(ParameterNode.TYPE).iterator().next(); 216 ConstantNode constant = ConstantNode.forInt(0, graph); 217 for (Node n : param.usages().snapshot()) { 218 if (!(n instanceof FrameState)) { 219 n.replaceFirstInput(param, constant); 220 } 221 } 222 Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); 223 new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); 224 for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) { 225 fs.replaceFirstInput(param, null); 226 param.safeDelete(); 227 } 228 StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); 229 assertEquals(referenceGraph, graph); 230 } 231 }