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