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