001/* 002 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.nodes; 024 025import jdk.internal.jvmci.meta.*; 026 027import com.oracle.graal.graph.*; 028import com.oracle.graal.graph.spi.*; 029import com.oracle.graal.nodeinfo.*; 030import com.oracle.graal.nodes.extended.*; 031import com.oracle.graal.nodes.spi.*; 032 033@NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard}) 034public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType { 035 public static final NodeClass<FixedGuardNode> TYPE = NodeClass.create(FixedGuardNode.class); 036 037 public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) { 038 this(condition, deoptReason, action, JavaConstant.NULL_POINTER, false); 039 } 040 041 public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { 042 this(condition, deoptReason, action, JavaConstant.NULL_POINTER, negated); 043 } 044 045 public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation, boolean negated) { 046 super(TYPE, condition, deoptReason, action, speculation, negated); 047 } 048 049 @Override 050 public void simplify(SimplifierTool tool) { 051 super.simplify(tool); 052 053 if (condition() instanceof LogicConstantNode) { 054 LogicConstantNode c = (LogicConstantNode) condition(); 055 if (c.getValue() == isNegated()) { 056 FixedNode currentNext = this.next(); 057 if (currentNext != null) { 058 tool.deleteBranch(currentNext); 059 } 060 061 DeoptimizeNode deopt = graph().add(new DeoptimizeNode(getAction(), getReason(), getSpeculation())); 062 deopt.setStateBefore(stateBefore()); 063 setNext(deopt); 064 } 065 this.replaceAtUsages(null); 066 graph().removeFixed(this); 067 } else if (condition() instanceof ShortCircuitOrNode) { 068 ShortCircuitOrNode shortCircuitOr = (ShortCircuitOrNode) condition(); 069 if (isNegated() && hasNoUsages()) { 070 graph().addAfterFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getY(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isYNegated()))); 071 graph().replaceFixedWithFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getX(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isXNegated()))); 072 } 073 } 074 } 075 076 @Override 077 public void lower(LoweringTool tool) { 078 if (graph().getGuardsStage().allowsFloatingGuards()) { 079 /* 080 * Don't allow guards with action None and reason RuntimeConstraint to float. In cases 081 * where 2 guards are testing equivalent conditions they might be lowered at the same 082 * location. If the guard with the None action is lowered before the the other guard 083 * then the code will be stuck repeatedly deoptimizing without invalidating the code. 084 * Conditional elimination will eliminate the guard if it's truly redundant in this 085 * case. 086 */ 087 if (getAction() != DeoptimizationAction.None || getReason() != DeoptimizationReason.RuntimeConstraint) { 088 ValueNode guard = tool.createGuard(this, condition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode(); 089 this.replaceAtUsages(guard); 090 ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode())); 091 graph().replaceFixedWithFixed(this, newAnchor); 092 } 093 } else { 094 lowerToIf().lower(tool); 095 } 096 } 097 098 @Override 099 public boolean canDeoptimize() { 100 return true; 101 } 102}