1 /* 2 * Copyright (c) 2016, 2017, 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.nodes.test; 24 25 import java.util.function.Function; 26 27 import org.junit.Assert; 28 import org.junit.Test; 29 30 import org.graalvm.compiler.core.test.GraalCompilerTest; 31 import org.graalvm.compiler.nodes.ConstantNode; 32 import org.graalvm.compiler.nodes.LogicNode; 33 import org.graalvm.compiler.nodes.ShortCircuitOrNode; 34 import org.graalvm.compiler.nodes.StructuredGraph; 35 import org.graalvm.compiler.nodes.ValueNode; 36 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 37 import org.graalvm.compiler.nodes.calc.ConditionalNode; 38 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; 39 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; 40 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; 41 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; 42 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; 43 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 44 import org.graalvm.compiler.phases.tiers.PhaseContext; 45 46 import jdk.vm.ci.meta.JavaKind; 47 import jdk.vm.ci.meta.ResolvedJavaMethod; 48 49 public class ShortCircuitOrNodeTest extends GraalCompilerTest { 50 51 static boolean shortCircuitOr(boolean b1, boolean b2) { 52 return b1 || b2; 53 } 54 55 @Override 56 protected Plugins getDefaultGraphBuilderPlugins() { 57 Plugins plugins = super.getDefaultGraphBuilderPlugins(); 58 Registration r = new Registration(plugins.getInvocationPlugins(), ShortCircuitOrNodeTest.class); 59 r.register2("shortCircuitOr", boolean.class, boolean.class, new InvocationPlugin() { 60 @Override 61 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode b1, ValueNode b2) { 62 LogicNode x = b.add(new IntegerEqualsNode(b1, b.add(ConstantNode.forInt(1)))); 63 LogicNode y = b.add(new IntegerEqualsNode(b2, b.add(ConstantNode.forInt(1)))); 64 ShortCircuitOrNode compare = b.add(new ShortCircuitOrNode(x, false, y, false, 0.5)); 65 b.addPush(JavaKind.Boolean, new ConditionalNode(compare, b.add(ConstantNode.forBoolean(true)), b.add(ConstantNode.forBoolean(false)))); 66 return true; 67 } 68 }); 69 70 return plugins; 71 } 72 73 public static int testSharedConditionSnippet(Object o) { 74 boolean b2 = o != null; 75 boolean b1 = o instanceof Function; 76 if (b1) { 77 if (shortCircuitOr(b1, b2)) { 78 return 4; 79 } else { 80 return 3; 81 } 82 } 83 return 1; 84 } 85 86 @Test 87 public void testSharedCondition() { 88 test("testSharedConditionSnippet", "String"); 89 } 90 91 private int testInputCombinations(String snippet) { 92 int trueCount = 0; 93 for (int i = 0; i < 4; ++i) { 94 boolean aValue = (i <= 1); 95 boolean bValue = ((i % 2) == 0); 96 boolean returnValue = (boolean) test(snippet, new Object[]{aValue, bValue}).returnValue; 97 98 if (returnValue) { 99 trueCount++; 100 } 101 } 102 103 return trueCount; 104 } 105 106 public boolean testSimpleSnippet(boolean a, boolean b) { 107 return shortCircuitOr(a, b); 108 } 109 110 @Test 111 public void testSimple() { 112 testInputCombinations("testSimpleSnippet"); 113 } 114 115 public static boolean testCascadeSnippet1(boolean a, boolean b) { 116 return shortCircuitOr(shortCircuitOr(a, b), a); 117 } 118 119 public static boolean testCascadeSnippet2(boolean a, boolean b) { 120 return shortCircuitOr(shortCircuitOr(b, a), a); 121 } 122 123 public static boolean testCascadeSnippet3(boolean a, boolean b) { 124 return shortCircuitOr(a, shortCircuitOr(a, b)); 125 } 126 127 public static boolean testCascadeSnippet4(boolean a, boolean b) { 128 return shortCircuitOr(a, shortCircuitOr(b, a)); 129 } 130 131 public static boolean testCascadeSnippet5(boolean a, boolean b) { 132 return shortCircuitOr(!shortCircuitOr(a, b), a); 133 } 134 135 public static boolean testCascadeSnippet6(boolean a, boolean b) { 136 return shortCircuitOr(!shortCircuitOr(b, a), a); 137 } 138 139 public static boolean testCascadeSnippet7(boolean a, boolean b) { 140 return shortCircuitOr(!a, shortCircuitOr(a, b)); 141 } 142 143 public static boolean testCascadeSnippet8(boolean a, boolean b) { 144 return shortCircuitOr(!a, shortCircuitOr(b, a)); 145 } 146 147 public static boolean testCascadeSnippet9(boolean a, boolean b) { 148 return shortCircuitOr(shortCircuitOr(!a, b), a); 149 } 150 151 public static boolean testCascadeSnippet10(boolean a, boolean b) { 152 return shortCircuitOr(shortCircuitOr(!b, a), a); 153 } 154 155 public static boolean testCascadeSnippet11(boolean a, boolean b) { 156 return shortCircuitOr(a, !shortCircuitOr(a, b)); 157 } 158 159 public static boolean testCascadeSnippet12(boolean a, boolean b) { 160 return shortCircuitOr(a, !shortCircuitOr(b, a)); 161 } 162 163 public static boolean testCascadeSnippet13(boolean a, boolean b) { 164 return shortCircuitOr(!shortCircuitOr(!a, b), a); 165 } 166 167 public static boolean testCascadeSnippet14(boolean a, boolean b) { 168 return shortCircuitOr(!shortCircuitOr(!b, a), a); 169 } 170 171 public static boolean testCascadeSnippet15(boolean a, boolean b) { 172 return shortCircuitOr(!a, !shortCircuitOr(a, b)); 173 } 174 175 public static boolean testCascadeSnippet16(boolean a, boolean b) { 176 return shortCircuitOr(!a, !shortCircuitOr(!b, a)); 177 } 178 179 public static boolean testCascadeSnippet17(boolean a, boolean b) { 180 return shortCircuitOr(shortCircuitOr(a, !b), a); 181 } 182 183 public static boolean testCascadeSnippet18(boolean a, boolean b) { 184 return shortCircuitOr(shortCircuitOr(b, !a), a); 185 } 186 187 public static boolean testCascadeSnippet19(boolean a, boolean b) { 188 return shortCircuitOr(a, shortCircuitOr(!a, b)); 189 } 190 191 public static boolean testCascadeSnippet20(boolean a, boolean b) { 192 return shortCircuitOr(a, shortCircuitOr(!b, a)); 193 } 194 195 public static boolean testCascadeSnippet21(boolean a, boolean b) { 196 return shortCircuitOr(!shortCircuitOr(a, !b), a); 197 } 198 199 public static boolean testCascadeSnippet22(boolean a, boolean b) { 200 return shortCircuitOr(!shortCircuitOr(b, !a), a); 201 } 202 203 public static boolean testCascadeSnippet23(boolean a, boolean b) { 204 return shortCircuitOr(!a, shortCircuitOr(!a, b)); 205 } 206 207 public static boolean testCascadeSnippet24(boolean a, boolean b) { 208 return shortCircuitOr(!a, shortCircuitOr(!b, a)); 209 } 210 211 public static boolean testCascadeSnippet25(boolean a, boolean b) { 212 return shortCircuitOr(shortCircuitOr(!a, !b), a); 213 } 214 215 public static boolean testCascadeSnippet26(boolean a, boolean b) { 216 return shortCircuitOr(shortCircuitOr(!b, !a), a); 217 } 218 219 public static boolean testCascadeSnippet27(boolean a, boolean b) { 220 return shortCircuitOr(a, !shortCircuitOr(!a, b)); 221 } 222 223 public static boolean testCascadeSnippet28(boolean a, boolean b) { 224 return shortCircuitOr(a, !shortCircuitOr(!b, a)); 225 } 226 227 public static boolean testCascadeSnippet29(boolean a, boolean b) { 228 return shortCircuitOr(!shortCircuitOr(!a, !b), a); 229 } 230 231 public static boolean testCascadeSnippet30(boolean a, boolean b) { 232 return shortCircuitOr(!shortCircuitOr(!b, !a), a); 233 } 234 235 public static boolean testCascadeSnippet31(boolean a, boolean b) { 236 return shortCircuitOr(!a, !shortCircuitOr(!a, b)); 237 } 238 239 public static boolean testCascadeSnippet32(boolean a, boolean b) { 240 return shortCircuitOr(!a, !shortCircuitOr(!b, a)); 241 } 242 243 public static boolean testCascadeSnippet33(boolean a, boolean b) { 244 return shortCircuitOr(shortCircuitOr(a, b), !a); 245 } 246 247 public static boolean testCascadeSnippet34(boolean a, boolean b) { 248 return shortCircuitOr(shortCircuitOr(b, a), !a); 249 } 250 251 public static boolean testCascadeSnippet35(boolean a, boolean b) { 252 return shortCircuitOr(a, shortCircuitOr(a, !b)); 253 } 254 255 public static boolean testCascadeSnippet36(boolean a, boolean b) { 256 return shortCircuitOr(a, shortCircuitOr(b, !a)); 257 } 258 259 public static boolean testCascadeSnippet37(boolean a, boolean b) { 260 return shortCircuitOr(!shortCircuitOr(a, b), !a); 261 } 262 263 public static boolean testCascadeSnippet38(boolean a, boolean b) { 264 return shortCircuitOr(!shortCircuitOr(b, a), !a); 265 } 266 267 public static boolean testCascadeSnippet39(boolean a, boolean b) { 268 return shortCircuitOr(!a, shortCircuitOr(a, !b)); 269 } 270 271 public static boolean testCascadeSnippet40(boolean a, boolean b) { 272 return shortCircuitOr(!a, shortCircuitOr(b, !a)); 273 } 274 275 public static boolean testCascadeSnippet41(boolean a, boolean b) { 276 return shortCircuitOr(shortCircuitOr(!a, b), !a); 277 } 278 279 public static boolean testCascadeSnippet42(boolean a, boolean b) { 280 return shortCircuitOr(shortCircuitOr(!b, a), !a); 281 } 282 283 public static boolean testCascadeSnippet43(boolean a, boolean b) { 284 return shortCircuitOr(a, !shortCircuitOr(a, !b)); 285 } 286 287 public static boolean testCascadeSnippet44(boolean a, boolean b) { 288 return shortCircuitOr(a, !shortCircuitOr(b, !a)); 289 } 290 291 public static boolean testCascadeSnippet45(boolean a, boolean b) { 292 return shortCircuitOr(!shortCircuitOr(!a, b), !a); 293 } 294 295 public static boolean testCascadeSnippet46(boolean a, boolean b) { 296 return shortCircuitOr(!shortCircuitOr(!b, a), !a); 297 } 298 299 public static boolean testCascadeSnippet47(boolean a, boolean b) { 300 return shortCircuitOr(!a, !shortCircuitOr(a, !b)); 301 } 302 303 public static boolean testCascadeSnippet48(boolean a, boolean b) { 304 return shortCircuitOr(!a, !shortCircuitOr(!b, !a)); 305 } 306 307 public static boolean testCascadeSnippet49(boolean a, boolean b) { 308 return shortCircuitOr(shortCircuitOr(a, !b), !a); 309 } 310 311 public static boolean testCascadeSnippet50(boolean a, boolean b) { 312 return shortCircuitOr(shortCircuitOr(b, !a), !a); 313 } 314 315 public static boolean testCascadeSnippet51(boolean a, boolean b) { 316 return shortCircuitOr(a, shortCircuitOr(!a, !b)); 317 } 318 319 public static boolean testCascadeSnippet52(boolean a, boolean b) { 320 return shortCircuitOr(a, shortCircuitOr(!b, !a)); 321 } 322 323 public static boolean testCascadeSnippet53(boolean a, boolean b) { 324 return shortCircuitOr(!shortCircuitOr(a, !b), !a); 325 } 326 327 public static boolean testCascadeSnippet54(boolean a, boolean b) { 328 return shortCircuitOr(!shortCircuitOr(b, !a), !a); 329 } 330 331 public static boolean testCascadeSnippet55(boolean a, boolean b) { 332 return shortCircuitOr(!a, shortCircuitOr(!a, !b)); 333 } 334 335 public static boolean testCascadeSnippet56(boolean a, boolean b) { 336 return shortCircuitOr(!a, shortCircuitOr(!b, !a)); 337 } 338 339 public static boolean testCascadeSnippet57(boolean a, boolean b) { 340 return shortCircuitOr(shortCircuitOr(!a, !b), !a); 341 } 342 343 public static boolean testCascadeSnippet58(boolean a, boolean b) { 344 return shortCircuitOr(shortCircuitOr(!b, !a), !a); 345 } 346 347 public static boolean testCascadeSnippet59(boolean a, boolean b) { 348 return shortCircuitOr(a, !shortCircuitOr(!a, !b)); 349 } 350 351 public static boolean testCascadeSnippet60(boolean a, boolean b) { 352 return shortCircuitOr(a, !shortCircuitOr(!b, !a)); 353 } 354 355 public static boolean testCascadeSnippet61(boolean a, boolean b) { 356 return shortCircuitOr(!shortCircuitOr(!a, !b), !a); 357 } 358 359 public static boolean testCascadeSnippet62(boolean a, boolean b) { 360 return shortCircuitOr(!shortCircuitOr(!b, !a), !a); 361 } 362 363 public static boolean testCascadeSnippet63(boolean a, boolean b) { 364 return shortCircuitOr(!a, !shortCircuitOr(!a, !b)); 365 } 366 367 public static boolean testCascadeSnippet64(boolean a, boolean b) { 368 return shortCircuitOr(!a, !shortCircuitOr(!b, !a)); 369 } 370 371 @Test 372 public void testCascade() { 373 for (int i = 1; i <= 64; ++i) { 374 String snippet = "testCascadeSnippet" + i; 375 StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); 376 PhaseContext context = new PhaseContext(getProviders()); 377 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 378 canonicalizer.apply(graph, context); 379 int shortCircuitCount = graph.getNodes(ShortCircuitOrNode.TYPE).count(); 380 381 int trueCount = testInputCombinations(snippet); 382 383 if (trueCount % 2 == 0) { 384 // No ShortCircuitOrNode expected in the graph. 385 Assert.assertEquals(0, shortCircuitCount); 386 } else { 387 // Only a single ShortCircuitOrNode expected in the graph. 388 Assert.assertEquals(1, shortCircuitCount); 389 } 390 } 391 } 392 }