1 /* 2 * Copyright (c) 2015, 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.graph.iterators.NodeIterable; 28 import org.graalvm.compiler.nodes.ConstantNode; 29 import org.graalvm.compiler.nodes.FixedGuardNode; 30 import org.graalvm.compiler.nodes.GuardNode; 31 import org.graalvm.compiler.nodes.LogicNode; 32 import org.graalvm.compiler.nodes.StructuredGraph; 33 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 34 import org.graalvm.compiler.nodes.calc.IntegerBelowNode; 35 import org.graalvm.compiler.nodes.java.LoadIndexedNode; 36 import org.graalvm.compiler.nodes.memory.FloatingReadNode; 37 import org.graalvm.compiler.nodes.memory.ReadNode; 38 import org.graalvm.compiler.nodes.spi.CoreProviders; 39 import org.graalvm.compiler.nodes.spi.LoweringTool; 40 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 41 import org.graalvm.compiler.phases.common.FloatingReadPhase; 42 import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; 43 import org.graalvm.compiler.phases.common.LoweringPhase; 44 import org.junit.Assert; 45 import org.junit.Test; 46 47 import jdk.vm.ci.meta.DeoptimizationReason; 48 49 /** 50 * Check that multiple bounds checks are correctly grouped together. 51 */ 52 public class ConditionalEliminationTest14 extends ConditionalEliminationTestBase { 53 54 public static void test1Snippet(Object[] args) { 55 Object a5 = args[5]; 56 Object a7 = args[7]; 57 Object a6 = args[6]; 58 59 /* 60 * The order of the conditions matters: The scheduler processes the floating reads for the 61 * array loads in the order of the conditions here, and we want the index 7 access to be 62 * processed before the index 6 access. 63 */ 64 if (a5 != null && a7 != null && a6 != null) { 65 sink1 = 1; 66 } 67 sink0 = 0; 68 } 69 70 @Test 71 public void test1() { 72 StructuredGraph graph = parseEager("test1Snippet", AllowAssumptions.YES); 73 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 74 CoreProviders context = getProviders(); 75 76 /* Convert the LoadIndexNode to ReadNode with floating guards. */ 77 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); 78 /* Convert the ReadNode to FloatingReadNode. */ 79 new FloatingReadPhase().apply(graph); 80 /* Apply the phase that we want to test. */ 81 new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); 82 83 Assert.assertEquals("All guards must be floating", 0, graph.getNodes(FixedGuardNode.TYPE).count()); 84 Assert.assertEquals("All array accesses must have been lowered", 0, graph.getNodes().filter(LoadIndexedNode.class).count()); 85 Assert.assertEquals("All reads must be floating", 0, graph.getNodes().filter(ReadNode.class).count()); 86 Assert.assertEquals("Must have floating reads (3 array accesses, 1 array length)", 4, graph.getNodes().filter(FloatingReadNode.class).count()); 87 88 NodeIterable<GuardNode> boundsChecks = graph.getNodes(GuardNode.TYPE).filter(n -> ((GuardNode) n).getReason() == DeoptimizationReason.BoundsCheckException); 89 Assert.assertEquals("Must have only 1 bounds check remaining", 1, boundsChecks.count()); 90 LogicNode condition = boundsChecks.first().getCondition(); 91 Assert.assertTrue("Bounds check must check for array length 8", condition instanceof IntegerBelowNode && ((IntegerBelowNode) condition).getY().valueEquals(ConstantNode.forInt(8))); 92 } 93 }