1 /* 2 * Copyright (c) 2011, 2018, 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.nodes.GuardNode; 29 import org.graalvm.compiler.nodes.StructuredGraph; 30 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 31 import org.graalvm.compiler.nodes.java.InstanceOfNode; 32 import org.graalvm.compiler.nodes.spi.CoreProviders; 33 import org.graalvm.compiler.nodes.spi.LoweringTool; 34 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 35 import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; 36 import org.graalvm.compiler.phases.common.FloatingReadPhase; 37 import org.graalvm.compiler.phases.common.LoweringPhase; 38 import org.junit.Assert; 39 import org.junit.Test; 40 41 /** 42 * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} 43 * including those that triggered bugs in this phase. 44 */ 45 public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase { 46 47 public static Object field; 48 49 static class Entry { 50 51 final String name; 52 53 Entry(String name) { 54 this.name = name; 55 } 56 } 57 58 static class EntryWithNext extends Entry { 59 60 EntryWithNext(String name, Entry next) { 61 super(name); 62 this.next = next; 63 } 64 65 final Entry next; 66 } 67 68 static class A { 69 } 70 71 static class B extends A { 72 } 73 74 static class C extends A { 75 } 76 77 public static Entry search(Entry start, String name, Entry alternative) { 78 Entry current = start; 79 do { 80 while (current instanceof EntryWithNext) { 81 if (name != null && current.name == name) { 82 current = null; 83 } else { 84 Entry next = ((EntryWithNext) current).next; 85 current = next; 86 } 87 } 88 89 if (current != null) { 90 if (current.name.equals(name)) { 91 return current; 92 } 93 } 94 if (current == alternative) { 95 return null; 96 } 97 current = alternative; 98 99 } while (true); 100 } 101 102 public static int testRedundantComparesSnippet(int[] array) { 103 if (array == null) { 104 return 0; 105 } 106 return array[0] + array[1] + array[2] + array[3]; 107 } 108 109 @Test 110 public void testRedundantCompares() { 111 StructuredGraph graph = parseEager("testRedundantComparesSnippet", AllowAssumptions.YES); 112 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 113 CoreProviders context = getProviders(); 114 115 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); 116 canonicalizer.apply(graph, context); 117 new FloatingReadPhase().apply(graph); 118 new ConditionalEliminationPhase(true).apply(graph, context); 119 canonicalizer.apply(graph, context); 120 121 assertDeepEquals(1, graph.getNodes().filter(GuardNode.class).count()); 122 } 123 124 public static String testInstanceOfCheckCastSnippet(Object e) { 125 if (e instanceof Entry) { 126 return ((Entry) e).name; 127 } 128 return null; 129 } 130 131 @Test 132 public void testInstanceOfCheckCastLowered() { 133 StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet", AllowAssumptions.YES); 134 135 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 136 CoreProviders context = getProviders(); 137 138 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); 139 canonicalizer.apply(graph, context); 140 new ConditionalEliminationPhase(true).apply(graph, context); 141 canonicalizer.apply(graph, context); 142 143 assertDeepEquals(0, graph.getNodes().filter(GuardNode.class).count()); 144 } 145 146 private void checkInstanceOfCount(String methodName, int count) { 147 StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES); 148 149 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 150 CoreProviders context = getProviders(); 151 152 canonicalizer.apply(graph, context); 153 new ConditionalEliminationPhase(true).apply(graph, context); 154 getDebugContext().dump(DebugContext.BASIC_LEVEL, graph, "After ConditionalEliminationPhase"); 155 canonicalizer.apply(graph, context); 156 157 Assert.assertEquals(count, graph.getNodes().filter(InstanceOfNode.class).count()); 158 } 159 160 public static A testRedundantInstanceOfClass(Object value) { 161 if (value != null && value.getClass() == A.class) { 162 return (A) value; 163 } 164 return null; 165 } 166 167 public static Object testRedundantInstanceOfArray(Object value) { 168 if (value != null && value.getClass() == Object[].class) { 169 return ((Object[]) value)[0]; 170 } 171 return null; 172 } 173 174 public static boolean testRedundantInstanceOfPrecise(Object value) { 175 if (value != null && value.getClass() == A.class) { 176 return value instanceof A; 177 } 178 return false; 179 } 180 181 public static boolean testRedundantInstanceOfImplicitNonNull(Object value) { 182 if (value.getClass() == A.class) { 183 return value instanceof A; 184 } 185 return false; 186 } 187 188 @Test 189 public void testRedundantInstanceOf() { 190 checkInstanceOfCount("testRedundantInstanceOfClass", 1); 191 checkInstanceOfCount("testRedundantInstanceOfArray", 1); 192 checkInstanceOfCount("testRedundantInstanceOfPrecise", 1); 193 checkInstanceOfCount("testRedundantInstanceOfImplicitNonNull", 1); 194 } 195 196 public static boolean testNonRedundantInstanceOfClass(Object value) { 197 if (value instanceof A) { 198 return (value != null && value.getClass() == A.class); 199 } 200 return false; 201 } 202 203 public static boolean testNonRedundantInstanceOfArray(Object value) { 204 if (value instanceof Object[]) { 205 return (value != null && value.getClass() == Object[].class); 206 } 207 return false; 208 } 209 210 public static boolean testNonRedundantInstanceOfImplicitNonNull(Object value) { 211 if (value instanceof Object[]) { 212 return value.getClass() == Object[].class; 213 } 214 return false; 215 } 216 217 @Test 218 public void testNonRedundantInstanceOf() { 219 checkInstanceOfCount("testNonRedundantInstanceOfClass", 2); 220 checkInstanceOfCount("testNonRedundantInstanceOfArray", 2); 221 checkInstanceOfCount("testNonRedundantInstanceOfImplicitNonNull", 2); 222 } 223 }