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 24 25 package org.graalvm.compiler.core.test.ea; 26 27 import java.util.List; 28 29 import org.junit.Test; 30 31 import org.graalvm.compiler.core.test.GraalCompilerTest; 32 import org.graalvm.compiler.nodes.ProxyNode; 33 import org.graalvm.compiler.nodes.ReturnNode; 34 import org.graalvm.compiler.nodes.StructuredGraph; 35 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 36 import org.graalvm.compiler.nodes.ValueNode; 37 import org.graalvm.compiler.nodes.ValuePhiNode; 38 import org.graalvm.compiler.nodes.java.LoadFieldNode; 39 import org.graalvm.compiler.nodes.java.StoreFieldNode; 40 import org.graalvm.compiler.nodes.memory.ReadNode; 41 import org.graalvm.compiler.nodes.spi.LoweringTool; 42 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 43 import org.graalvm.compiler.phases.common.LoweringPhase; 44 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 45 import org.graalvm.compiler.phases.tiers.HighTierContext; 46 import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; 47 48 public class EarlyReadEliminationTest extends GraalCompilerTest { 49 50 public static Object staticField; 51 52 public static class TestObject { 53 54 public int x; 55 public int y; 56 57 public TestObject(int x, int y) { 58 this.x = x; 59 this.y = y; 60 } 61 } 62 63 public static class TestObject2 { 64 65 public Object x; 66 public Object y; 67 68 public TestObject2(Object x, Object y) { 69 this.x = x; 70 this.y = y; 71 } 72 } 73 74 public static class TestObject3 extends TestObject { 75 76 public int z; 77 78 public TestObject3(int x, int y, int z) { 79 super(x, y); 80 this.z = z; 81 } 82 } 83 84 @SuppressWarnings("all") 85 public static int testSimpleSnippet(TestObject a) { 86 a.x = 2; 87 staticField = a; 88 return a.x; 89 } 90 91 @Test 92 public void testSimple() { 93 // Test without lowering. 94 ValueNode result = getReturn("testSimpleSnippet", false).result(); 95 assertTrue(result.graph().getNodes().filter(LoadFieldNode.class).isEmpty()); 96 assertTrue(result.isConstant()); 97 assertDeepEquals(2, result.asJavaConstant().asInt()); 98 99 // Test with lowering. 100 result = getReturn("testSimpleSnippet", true).result(); 101 assertTrue(result.graph().getNodes().filter(ReadNode.class).isEmpty()); 102 assertTrue(result.isConstant()); 103 assertDeepEquals(2, result.asJavaConstant().asInt()); 104 } 105 106 @SuppressWarnings("all") 107 public static int testSimpleConflictSnippet(TestObject a, TestObject b) { 108 a.x = 2; 109 b.x = 3; 110 staticField = a; 111 return a.x; 112 } 113 114 @Test 115 public void testSimpleConflict() { 116 ValueNode result = getReturn("testSimpleConflictSnippet", false).result(); 117 assertFalse(result.isConstant()); 118 assertTrue(result instanceof LoadFieldNode); 119 } 120 121 @SuppressWarnings("all") 122 public static int testParamSnippet(TestObject a, int b) { 123 a.x = b; 124 return a.x; 125 } 126 127 @Test 128 public void testParam() { 129 ValueNode result = getReturn("testParamSnippet", false).result(); 130 assertTrue(result.graph().getNodes().filter(LoadFieldNode.class).isEmpty()); 131 assertDeepEquals(result.graph().getParameter(1), result); 132 } 133 134 @SuppressWarnings("all") 135 public static int testMaterializedSnippet(int a) { 136 TestObject obj = new TestObject(a, 0); 137 staticField = obj; 138 return obj.x; 139 } 140 141 @Test 142 public void testMaterialized() { 143 ValueNode result = getReturn("testMaterializedSnippet", false).result(); 144 assertTrue(result.graph().getNodes().filter(LoadFieldNode.class).isEmpty()); 145 assertDeepEquals(result.graph().getParameter(0), result); 146 } 147 148 @SuppressWarnings("all") 149 public static int testSimpleLoopSnippet(TestObject obj, int a, int b) { 150 obj.x = a; 151 for (int i = 0; i < 10; i++) { 152 staticField = obj; 153 } 154 return obj.x; 155 } 156 157 @Test 158 public void testSimpleLoop() { 159 // Test without lowering. 160 ValueNode result = getReturn("testSimpleLoopSnippet", false).result(); 161 assertTrue(result.graph().getNodes().filter(LoadFieldNode.class).isEmpty()); 162 assertDeepEquals(result.graph().getParameter(1), result); 163 164 // Now test with lowering. 165 result = getReturn("testSimpleLoopSnippet", true).result(); 166 assertTrue(result.graph().getNodes().filter(ReadNode.class).isEmpty()); 167 assertDeepEquals(result.graph().getParameter(1), result); 168 } 169 170 @SuppressWarnings("all") 171 public static int testBadLoopSnippet(TestObject obj, TestObject obj2, int a, int b) { 172 obj.x = a; 173 for (int i = 0; i < 10; i++) { 174 staticField = obj; 175 obj2.x = 10; 176 obj.x = 0; 177 } 178 return obj.x; 179 } 180 181 @Test 182 public void testBadLoop() { 183 ValueNode result = getReturn("testBadLoopSnippet", false).result(); 184 assertDeepEquals(0, result.graph().getNodes().filter(LoadFieldNode.class).count()); 185 assertTrue(result instanceof ProxyNode); 186 assertTrue(((ProxyNode) result).value() instanceof ValuePhiNode); 187 } 188 189 @SuppressWarnings("all") 190 public static int testBadLoop2Snippet(TestObject obj, TestObject obj2, int a, int b) { 191 obj.x = a; 192 for (int i = 0; i < 10; i++) { 193 obj.x = 0; 194 obj2.x = 10; 195 } 196 return obj.x; 197 } 198 199 @Test 200 public void testBadLoop2() { 201 ValueNode result = getReturn("testBadLoop2Snippet", false).result(); 202 assertDeepEquals(1, result.graph().getNodes().filter(LoadFieldNode.class).count()); 203 assertTrue(result instanceof LoadFieldNode); 204 } 205 206 @SuppressWarnings("all") 207 public static int testPhiSnippet(TestObject a, int b) { 208 if (b < 0) { 209 a.x = 1; 210 } else { 211 a.x = 2; 212 } 213 return a.x; 214 } 215 216 @Test 217 public void testPhi() { 218 StructuredGraph graph = processMethod("testPhiSnippet", false); 219 assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty()); 220 List<ReturnNode> returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot(); 221 assertDeepEquals(2, returnNodes.size()); 222 assertTrue(returnNodes.get(0).predecessor() instanceof StoreFieldNode); 223 assertTrue(returnNodes.get(1).predecessor() instanceof StoreFieldNode); 224 assertTrue(returnNodes.get(0).result().isConstant()); 225 assertTrue(returnNodes.get(1).result().isConstant()); 226 } 227 228 @SuppressWarnings("all") 229 public static void testSimpleStoreSnippet(TestObject a, int b) { 230 a.x = b; 231 a.x = b; 232 } 233 234 @Test 235 public void testSimpleStore() { 236 StructuredGraph graph = processMethod("testSimpleStoreSnippet", false); 237 assertDeepEquals(1, graph.getNodes().filter(StoreFieldNode.class).count()); 238 } 239 240 public static int testValueProxySnippet(boolean b, TestObject o) { 241 int sum = 0; 242 if (b) { 243 sum += o.x; 244 } else { 245 TestObject3 p = (TestObject3) o; 246 sum += p.x; 247 } 248 sum += o.x; 249 return sum; 250 } 251 252 @Test 253 public void testValueProxy() { 254 StructuredGraph graph = processMethod("testValueProxySnippet", false); 255 assertDeepEquals(2, graph.getNodes().filter(LoadFieldNode.class).count()); 256 } 257 258 ReturnNode getReturn(String snippet, boolean doLowering) { 259 StructuredGraph graph = processMethod(snippet, doLowering); 260 assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count()); 261 return graph.getNodes(ReturnNode.TYPE).first(); 262 } 263 264 protected StructuredGraph processMethod(String snippet, boolean doLowering) { 265 StructuredGraph graph = parseEager(getResolvedJavaMethod(snippet), AllowAssumptions.NO); 266 HighTierContext context = getDefaultHighTierContext(); 267 new InliningPhase(new CanonicalizerPhase()).apply(graph, context); 268 if (doLowering) { 269 new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); 270 } 271 new EarlyReadEliminationPhase(new CanonicalizerPhase()).apply(graph, context); 272 return graph; 273 } 274 }