FixedGuardNode.java revision 12995:5e441a7ec5e3
1169691Skan/* 2169691Skan * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3169691Skan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4169691Skan * 5169691Skan * This code is free software; you can redistribute it and/or modify it 6169691Skan * under the terms of the GNU General Public License version 2 only, as 7169691Skan * published by the Free Software Foundation. 8169691Skan * 9169691Skan * This code is distributed in the hope that it will be useful, but WITHOUT 10169691Skan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11169691Skan * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12169691Skan * version 2 for more details (a copy is included in the LICENSE file that 13169691Skan * accompanied this code). 14169691Skan * 15169691Skan * You should have received a copy of the GNU General Public License version 16169691Skan * 2 along with this work; if not, write to the Free Software Foundation, 17169691Skan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18169691Skan * 19169691Skan * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20169691Skan * or visit www.oracle.com if you need additional information or have any 21169691Skan * questions. 22169691Skan */ 23169691Skanpackage org.graalvm.compiler.nodes; 24169691Skan 25169691Skanimport static org.graalvm.compiler.nodeinfo.InputType.Guard; 26169691Skanimport static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; 27169691Skanimport static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; 28169691Skan 29169691Skanimport org.graalvm.compiler.graph.IterableNodeType; 30169691Skanimport org.graalvm.compiler.graph.NodeClass; 31169691Skanimport org.graalvm.compiler.graph.spi.SimplifierTool; 32169691Skanimport org.graalvm.compiler.nodeinfo.NodeInfo; 33169691Skanimport org.graalvm.compiler.nodes.spi.Lowerable; 34169691Skanimport org.graalvm.compiler.nodes.spi.LoweringTool; 35169691Skan 36169691Skanimport jdk.vm.ci.meta.DeoptimizationAction; 37169691Skanimport jdk.vm.ci.meta.DeoptimizationReason; 38169691Skanimport jdk.vm.ci.meta.JavaConstant; 39169691Skan 40169691Skan@NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}", allowedUsageTypes = Guard, size = SIZE_2, cycles = CYCLES_2) 41169691Skanpublic final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType { 42169691Skan public static final NodeClass<FixedGuardNode> TYPE = NodeClass.create(FixedGuardNode.class); 43169691Skan 44169691Skan public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) { 45169691Skan this(condition, deoptReason, action, JavaConstant.NULL_POINTER, false); 46169691Skan } 47169691Skan 48169691Skan public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { 49169691Skan this(condition, deoptReason, action, JavaConstant.NULL_POINTER, negated); 50169691Skan } 51169691Skan 52169691Skan public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, boolean negated) { 53169691Skan super(TYPE, condition, deoptReason, action, speculation, negated); 54169691Skan } 55169691Skan 56169691Skan @Override 57169691Skan public void simplify(SimplifierTool tool) { 58169691Skan super.simplify(tool); 59169691Skan 60169691Skan if (getCondition() instanceof LogicConstantNode) { 61169691Skan LogicConstantNode c = (LogicConstantNode) getCondition(); 62169691Skan if (c.getValue() == isNegated()) { 63169691Skan FixedNode currentNext = this.next(); 64169691Skan if (currentNext != null) { 65169691Skan tool.deleteBranch(currentNext); 66169691Skan } 67169691Skan 68169691Skan DeoptimizeNode deopt = graph().add(new DeoptimizeNode(getAction(), getReason(), getSpeculation())); 69169691Skan deopt.setStateBefore(stateBefore()); 70169691Skan setNext(deopt); 71169691Skan } 72169691Skan this.replaceAtUsages(null); 73169691Skan graph().removeFixed(this); 74169691Skan } else if (getCondition() instanceof ShortCircuitOrNode) { 75169691Skan ShortCircuitOrNode shortCircuitOr = (ShortCircuitOrNode) getCondition(); 76169691Skan if (isNegated() && hasNoUsages()) { 77169691Skan graph().addAfterFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getY(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isYNegated()))); 78169691Skan graph().replaceFixedWithFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getX(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isXNegated()))); 79169691Skan } 80169691Skan } 81169691Skan } 82169691Skan 83169691Skan @Override 84169691Skan public void lower(LoweringTool tool) { 85169691Skan if (graph().getGuardsStage().allowsFloatingGuards()) { 86169691Skan /* 87169691Skan * Don't allow guards with action None and reason RuntimeConstraint to float. In cases 88169691Skan * where 2 guards are testing equivalent conditions they might be lowered at the same 89169691Skan * location. If the guard with the None action is lowered before the other guard then 90169691Skan * the code will be stuck repeatedly deoptimizing without invalidating the code. 91169691Skan * Conditional elimination will eliminate the guard if it's truly redundant in this 92169691Skan * case. 93169691Skan */ 94169691Skan if (getAction() != DeoptimizationAction.None || getReason() != DeoptimizationReason.RuntimeConstraint) { 95169691Skan ValueNode guard = tool.createGuard(this, getCondition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode(); 96169691Skan this.replaceAtUsages(guard); 97169691Skan graph().removeFixed(this); 98169691Skan } 99169691Skan } else { 100169691Skan lowerToIf().lower(tool); 101169691Skan } 102169691Skan } 103169691Skan 104169691Skan @Override 105169691Skan public boolean canDeoptimize() { 106169691Skan return true; 107169691Skan } 108169691Skan} 109169691Skan