src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java
changeset 50330 2cbc42a5764b
parent 47216 71c04702a3d5
child 50858 2d3e99a72541
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java	Thu May 31 10:14:41 2018 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/UnaryOpLogicNode.java	Thu May 31 10:38:05 2018 -0700
@@ -28,6 +28,7 @@
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.graalvm.compiler.nodes.spi.ValueProxy;
 
 import jdk.vm.ci.meta.TriState;
 
@@ -52,7 +53,58 @@
     public void generate(NodeLIRBuilderTool gen) {
     }
 
+    /**
+     * In general the input stamp cannot be trusted, this method is reserved for the cases when it's
+     * "safe" to use the input stamp. To ensure safety use
+     * {@link #getSucceedingStampForValue(boolean)} instead.
+     */
+    public Stamp getSucceedingStampForValue(boolean negated, Stamp valueStamp) {
+        Stamp succStamp = getSucceedingStampForValue(negated);
+        if (succStamp != null) {
+            succStamp = succStamp.join(valueStamp);
+        }
+        return succStamp;
+    }
+
+    /**
+     * The input stamp cannot be trusted, the returned stamp cannot use the input stamp to narrow
+     * itself or derive any assumptions. This method does not use the input stamp and is considered
+     * safe.
+     *
+     * It's responsibility of the caller to determine when it's "safe" to "trust" the input stamp
+     * and use {@link #getSucceedingStampForValue(boolean, Stamp)} instead.
+     */
     public abstract Stamp getSucceedingStampForValue(boolean negated);
 
     public abstract TriState tryFold(Stamp valueStamp);
+
+    @Override
+    public TriState implies(boolean thisNegated, LogicNode other) {
+        if (other instanceof UnaryOpLogicNode) {
+            UnaryOpLogicNode unaryY = (UnaryOpLogicNode) other;
+            if (this.getValue() == unaryY.getValue() || // fast path
+                            skipThroughPisAndProxies(this.getValue()) == skipThroughPisAndProxies(unaryY.getValue())) {
+                Stamp succStamp = this.getSucceedingStampForValue(thisNegated);
+                TriState fold = unaryY.tryFold(succStamp);
+                if (fold.isKnown()) {
+                    return fold;
+                }
+            }
+        }
+        return super.implies(thisNegated, other);
+    }
+
+    private static ValueNode skipThroughPisAndProxies(ValueNode node) {
+        ValueNode n = node;
+        while (n != null) {
+            if (n instanceof PiNode) {
+                n = ((PiNode) n).getOriginalNode();
+            } else if (n instanceof ValueProxy) {
+                n = ((ValueProxy) n).getOriginalNode();
+            } else {
+                break;
+            }
+        }
+        return n;
+    }
 }