changeset 15349:7766f486f5d6

evaluate for BinaryOpLogicNodes
author Lukas Stadler <lukas.stadler@oracle.com>
date Thu, 24 Apr 2014 10:44:12 +0200
parents 1c347436d596
children c216071b1a00
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java
diffstat 9 files changed, 155 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Thu Apr 24 10:44:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Thu Apr 24 10:44:12 2014 +0200
@@ -22,10 +22,14 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
-public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable {
+public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable, Canonicalizable {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
@@ -54,6 +58,8 @@
         this.y = y;
     }
 
+    public abstract TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY);
+
     @Override
     public boolean verify() {
         assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp());
@@ -61,6 +67,17 @@
     }
 
     @Override
+    public Node canonical(CanonicalizerTool tool) {
+        switch (evaluate(tool.getConstantReflection(), x(), y())) {
+            case FALSE:
+                return LogicConstantNode.contradiction(graph());
+            case TRUE:
+                return LogicConstantNode.tautology(graph());
+        }
+        return this;
+    }
+
+    @Override
     public void generate(NodeLIRBuilderTool gen) {
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Thu Apr 24 10:44:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Thu Apr 24 10:44:12 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
@@ -35,7 +36,7 @@
  * Compare should probably be made a value (so that it can be canonicalized for example) and in later stages some Compare usage should be transformed
  * into variants that do not materialize the value (CompareIf, CompareGuard...)
  */
-public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable {
+public abstract class CompareNode extends BinaryOpLogicNode {
 
     /**
      * Constructs a new Compare instruction.
@@ -90,9 +91,18 @@
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (x().isConstant() && y().isConstant()) {
+            return TriState.get(condition().foldCondition(x().asConstant(), y().asConstant(), constantReflection, unorderedIsTrue()));
+        }
+        return TriState.UNKNOWN;
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant() && tool.getMetaAccess() != null) {
-            return LogicConstantNode.forBoolean(condition().foldCondition(x().asConstant(), y().asConstant(), tool.getConstantReflection(), unorderedIsTrue()), graph());
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
         }
         if (x().isConstant()) {
             if (y() instanceof ConditionalNode) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Thu Apr 24 10:44:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Thu Apr 24 10:44:12 2014 +0200
@@ -22,17 +22,20 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
 public final class FloatEqualsNode extends CompareNode {
 
     /**
      * Constructs a new floating point equality comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -51,4 +54,18 @@
     public boolean unorderedIsTrue() {
         return false;
     }
+
+    @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (forX.stamp() instanceof FloatStamp && forY.stamp() instanceof FloatStamp) {
+            FloatStamp xStamp = (FloatStamp) forX.stamp();
+            FloatStamp yStamp = (FloatStamp) forY.stamp();
+            if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && xStamp.isNonNaN() && yStamp.isNonNaN()) {
+                return TriState.TRUE;
+            } else if (xStamp.alwaysDistinct(yStamp)) {
+                return TriState.FALSE;
+            }
+        }
+        return super.evaluate(constantReflection, forX, forY);
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Thu Apr 24 10:44:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Thu Apr 24 10:44:12 2014 +0200
@@ -22,11 +22,13 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "<")
 public final class FloatLessThanNode extends CompareNode {
@@ -35,7 +37,7 @@
 
     /**
      * Constructs a new floating point comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      * @param unorderedIsTrue whether a comparison that is undecided (involving NaNs, etc.) leads to
@@ -59,10 +61,10 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y() && !unorderedIsTrue()) {
-            return LogicConstantNode.contradiction(graph());
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && !unorderedIsTrue()) {
+            return TriState.FALSE;
         }
-        return super.canonical(tool);
+        return super.evaluate(constantReflection, forX, forY);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Thu Apr 24 10:44:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Thu Apr 24 10:44:12 2014 +0200
@@ -23,18 +23,20 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "|<|")
 public final class IntegerBelowThanNode extends CompareNode {
 
     /**
      * Constructs a new unsigned integer comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -55,28 +57,33 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return LogicConstantNode.contradiction(graph());
-        } else {
-            if (x().isConstant() && x().asConstant().asLong() == 0) {
-                // 0 |<| y is the same as 0 != y
-                return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y())));
-            }
-
-            if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-                IntegerStamp xStamp = (IntegerStamp) x().stamp();
-                IntegerStamp yStamp = (IntegerStamp) y().stamp();
-                if (yStamp.isPositive()) {
-                    if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
-                        return LogicConstantNode.tautology(graph());
-                    } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
-                        return LogicConstantNode.contradiction(graph());
-                    }
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.FALSE;
+        } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+            IntegerStamp yStamp = (IntegerStamp) forY.stamp();
+            if (yStamp.isPositive()) {
+                if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
+                    return TriState.TRUE;
+                } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
+                    return TriState.FALSE;
                 }
             }
         }
+        return super.evaluate(constantReflection, forX, forY);
+    }
 
-        return super.canonical(tool);
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
+        }
+        if (x().isConstant() && x().asConstant().asLong() == 0) {
+            // 0 |<| y is the same as 0 != y
+            return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y())));
+        }
+        return this;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Thu Apr 24 10:44:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Thu Apr 24 10:44:12 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
@@ -35,7 +36,7 @@
 
     /**
      * Constructs a new integer equality comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -71,24 +72,28 @@
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.TRUE;
+        } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
+            return TriState.FALSE;
+        }
+        return super.evaluate(constantReflection, forX, forY);
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (GraphUtil.unproxify(x()) == GraphUtil.unproxify(y())) {
-            return LogicConstantNode.tautology(graph());
-        } else if (x().stamp().alwaysDistinct(y().stamp())) {
-            return LogicConstantNode.contradiction(graph());
-        }
-
-        ValueNode result = canonicalizeSymmetric(x(), y());
-        if (result != null) {
+        Node result = super.canonical(tool);
+        if (result != this) {
             return result;
         }
 
-        result = canonicalizeSymmetric(y(), x());
-        if (result != null) {
+        result = canonicalizeSymmetric(x(), y());
+        if (result != this) {
             return result;
         }
 
-        return super.canonical(tool);
+        return canonicalizeSymmetric(y(), x());
     }
 
     private ValueNode canonicalizeSymmetric(ValueNode x, ValueNode y) {
@@ -133,6 +138,6 @@
                 }
             }
         }
-        return null;
+        return this;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Thu Apr 24 10:44:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Thu Apr 24 10:44:12 2014 +0200
@@ -23,18 +23,20 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "<")
 public final class IntegerLessThanNode extends CompareNode {
 
     /**
      * Constructs a new integer comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -71,22 +73,32 @@
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.FALSE;
+        } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+            IntegerStamp yStamp = (IntegerStamp) forY.stamp();
+            if (xStamp.upperBound() < yStamp.lowerBound()) {
+                return TriState.TRUE;
+            } else if (xStamp.lowerBound() >= yStamp.upperBound()) {
+                return TriState.FALSE;
+            }
+        }
+        return super.evaluate(constantReflection, forX, forY);
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return LogicConstantNode.contradiction(graph());
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
         }
         if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-            IntegerStamp xStamp = (IntegerStamp) x().stamp();
-            IntegerStamp yStamp = (IntegerStamp) y().stamp();
-            if (xStamp.upperBound() < yStamp.lowerBound()) {
-                return LogicConstantNode.tautology(graph());
-            } else if (xStamp.lowerBound() >= yStamp.upperBound()) {
-                return LogicConstantNode.contradiction(graph());
-            }
-            if (IntegerStamp.sameSign(xStamp, yStamp)) {
+            if (IntegerStamp.sameSign((IntegerStamp) x().stamp(), (IntegerStamp) y().stamp())) {
                 return graph().unique(new IntegerBelowThanNode(x(), y()));
             }
         }
-        return super.canonical(tool);
+        return this;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Thu Apr 24 10:44:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Thu Apr 24 10:44:12 2014 +0200
@@ -22,9 +22,9 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -32,7 +32,7 @@
  * expression "(x &amp; y) == 0", meaning that it will return true if (and only if) no bit is set in
  * both x and y.
  */
-public class IntegerTestNode extends BinaryOpLogicNode implements Canonicalizable {
+public class IntegerTestNode extends BinaryOpLogicNode {
 
     /**
      * Constructs a new Test instruction.
@@ -45,19 +45,19 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            return LogicConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph());
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            return TriState.get((forX.asConstant().asLong() & forY.asConstant().asLong()) == 0);
         }
         if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-            IntegerStamp xStamp = (IntegerStamp) x().stamp();
-            IntegerStamp yStamp = (IntegerStamp) y().stamp();
+            IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+            IntegerStamp yStamp = (IntegerStamp) forY.stamp();
             if ((xStamp.upMask() & yStamp.upMask()) == 0) {
-                return LogicConstantNode.tautology(graph());
+                return TriState.TRUE;
             } else if ((xStamp.downMask() & yStamp.downMask()) != 0) {
-                return LogicConstantNode.contradiction(graph());
+                return TriState.FALSE;
             }
         }
-        return this;
+        return TriState.UNKNOWN;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Thu Apr 24 10:44:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Thu Apr 24 10:44:12 2014 +0200
@@ -23,19 +23,21 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "==")
 public final class ObjectEqualsNode extends CompareNode implements Virtualizable {
 
     /**
      * Constructs a new object equality comparison node.
-     * 
+     *
      * @param x the instruction producing the first input to the instruction
      * @param y the instruction that produces the second input to this instruction
      */
@@ -56,21 +58,28 @@
     }
 
     @Override
+    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return TriState.TRUE;
+        } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
+            return TriState.FALSE;
+        } else {
+            return super.evaluate(constantReflection, forX, forY);
+        }
+    }
+
+    @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return LogicConstantNode.tautology(graph());
+        Node result = super.canonical(tool);
+        if (result != this) {
+            return result;
         }
-
         if (StampTool.isObjectAlwaysNull(x())) {
             return graph().unique(new IsNullNode(y()));
         } else if (StampTool.isObjectAlwaysNull(y())) {
             return graph().unique(new IsNullNode(x()));
         }
-        if (x().stamp().alwaysDistinct(y().stamp())) {
-            return LogicConstantNode.contradiction(graph());
-        }
-
-        return super.canonical(tool);
+        return this;
     }
 
     private void virtualizeNonVirtualComparison(State state, ValueNode other, VirtualizerTool tool) {