1 /*
2  * Copyright (c) 2011, 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.nodes;
26 
27 import static org.graalvm.compiler.nodeinfo.InputType.Condition;
28 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
29 
30 import jdk.vm.ci.meta.TriState;
31 import org.graalvm.compiler.core.common.type.StampFactory;
32 import org.graalvm.compiler.graph.Node.IndirectCanonicalization;
33 import org.graalvm.compiler.graph.NodeClass;
34 import org.graalvm.compiler.nodeinfo.NodeInfo;
35 import org.graalvm.compiler.nodes.calc.FloatingNode;
36 
37 @NodeInfo(allowedUsageTypes = {Condition}, size = SIZE_1)
38 public abstract class LogicNode extends FloatingNode implements IndirectCanonicalization {
39 
40     public static final NodeClass<LogicNode> TYPE = NodeClass.create(LogicNode.class);
41 
LogicNode(NodeClass<? extends LogicNode> c)42     public LogicNode(NodeClass<? extends LogicNode> c) {
43         super(c, StampFactory.forVoid());
44     }
45 
and(LogicNode a, LogicNode b, double shortCircuitProbability)46     public static LogicNode and(LogicNode a, LogicNode b, double shortCircuitProbability) {
47         return and(a, false, b, false, shortCircuitProbability);
48     }
49 
and(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability)50     public static LogicNode and(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) {
51         StructuredGraph graph = a.graph();
52         ShortCircuitOrNode notAorNotB = graph.unique(new ShortCircuitOrNode(a, !negateA, b, !negateB, shortCircuitProbability));
53         return graph.unique(new LogicNegationNode(notAorNotB));
54     }
55 
or(LogicNode a, LogicNode b, double shortCircuitProbability)56     public static LogicNode or(LogicNode a, LogicNode b, double shortCircuitProbability) {
57         return or(a, false, b, false, shortCircuitProbability);
58     }
59 
or(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability)60     public static LogicNode or(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) {
61         return a.graph().unique(new ShortCircuitOrNode(a, negateA, b, negateB, shortCircuitProbability));
62     }
63 
isTautology()64     public final boolean isTautology() {
65         if (this instanceof LogicConstantNode) {
66             LogicConstantNode logicConstantNode = (LogicConstantNode) this;
67             return logicConstantNode.getValue();
68         }
69 
70         return false;
71     }
72 
isContradiction()73     public final boolean isContradiction() {
74         if (this instanceof LogicConstantNode) {
75             LogicConstantNode logicConstantNode = (LogicConstantNode) this;
76             return !logicConstantNode.getValue();
77         }
78 
79         return false;
80     }
81 
82     /**
83      * Determines what this condition implies about the other.
84      *
85      * <ul>
86      * <li>If negate(this, thisNegated) => other, returns {@link TriState#TRUE}</li>
87      * <li>If negate(this, thisNegated) => !other, returns {@link TriState#FALSE}</li>
88      * </ul>
89      *
90      * @param thisNegated whether this condition should be considered as false.
91      * @param other the other condition.
92      */
implies(boolean thisNegated, LogicNode other)93     public TriState implies(boolean thisNegated, LogicNode other) {
94         if (this == other) {
95             return TriState.get(!thisNegated);
96         }
97         if (other instanceof LogicNegationNode) {
98             return flip(this.implies(thisNegated, ((LogicNegationNode) other).getValue()));
99         }
100         return TriState.UNKNOWN;
101     }
102 
flip(TriState triState)103     private static TriState flip(TriState triState) {
104         return triState.isUnknown()
105                         ? triState
106                         : TriState.get(!triState.toBoolean());
107     }
108 }
109