changeset 16206:2a1f3a8f76f1

handle Canonicalizable.Unary/Binary in CanonicalizerPhase and EquationalReasoner
author Lukas Stadler <lukas.stadler@oracle.com>
date Wed, 25 Jun 2014 11:20:50 +0200
parents d078a3239653
children df6f2365b153
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java
diffstat 6 files changed, 142 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Jun 25 10:58:42 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Jun 25 11:20:50 2014 +0200
@@ -28,6 +28,8 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.GraphEvent.NodeEvent;
 import com.oracle.graal.graph.Node.ValueNumberable;
+import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.graph.iterators.*;
 
 /**
@@ -279,6 +281,22 @@
         return add(node);
     }
 
+    public <T extends Node> T addOrUniqueWithInputs(T node) {
+        NodeClassIterator iterator = node.inputs().iterator();
+        while (iterator.hasNext()) {
+            Position pos = iterator.nextPosition();
+            Node input = pos.get(node);
+            if (input != null && !input.isAlive()) {
+                assert !input.isDeleted();
+                pos.initialize(node, addOrUniqueWithInputs(input));
+            }
+        }
+        if (node.getNodeClass().valueNumberable()) {
+            return uniqueHelper(node, true);
+        }
+        return add(node);
+    }
+
     private <T extends Node> T addHelper(T node) {
         node.initialize(this);
         return node;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Jun 25 10:58:42 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Jun 25 11:20:50 2014 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.graph.Node.Successor;
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graph.spi.Canonicalizable.CanonicalizeMethod;
 
 /**
  * Metadata for every {@link Node} type. The metadata includes:
@@ -102,7 +103,7 @@
     /**
      * Determines if this node type implements {@link Canonicalizable}.
      */
-    private final boolean isCanonicalizable;
+    private final CanonicalizeMethod canonicalizeMethod;
 
     /**
      * Determines if this node type implements {@link Simplifiable}.
@@ -116,7 +117,18 @@
     public NodeClass(Class<?> clazz, CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) {
         super(clazz);
         assert NODE_CLASS.isAssignableFrom(clazz);
-        this.isCanonicalizable = Canonicalizable.class.isAssignableFrom(clazz);
+        if (Canonicalizable.Unary.class.isAssignableFrom(clazz)) {
+            assert !Canonicalizable.Binary.class.isAssignableFrom(clazz) && !Canonicalizable.class.isAssignableFrom(clazz) : clazz;
+            this.canonicalizeMethod = CanonicalizeMethod.UNARY;
+        } else if (Canonicalizable.Binary.class.isAssignableFrom(clazz)) {
+            assert !Canonicalizable.class.isAssignableFrom(clazz) : clazz;
+            this.canonicalizeMethod = CanonicalizeMethod.BINARY;
+        } else if (Canonicalizable.class.isAssignableFrom(clazz)) {
+            this.canonicalizeMethod = CanonicalizeMethod.BASE;
+        } else {
+            this.canonicalizeMethod = null;
+        }
+
         this.isSimplifiable = Simplifiable.class.isAssignableFrom(clazz);
 
         FieldScanner scanner = new FieldScanner(calcOffset);
@@ -249,8 +261,8 @@
     /**
      * Determines if this node type implements {@link Canonicalizable}.
      */
-    public boolean isCanonicalizable() {
-        return isCanonicalizable;
+    public CanonicalizeMethod getCanonicalizeMethod() {
+        return canonicalizeMethod;
     }
 
     /**
@@ -377,6 +389,10 @@
             node.getNodeClass().set(node, this, value);
         }
 
+        void initialize(Node node, Node value) {
+            node.getNodeClass().initializePosition(node, this, value);
+        }
+
         public boolean isValidFor(Node node, Node from) {
             return node.getNodeClass().isValid(this, from.getNodeClass());
         }
@@ -1066,6 +1082,20 @@
         }
     }
 
+    public void initializePosition(Node node, Position pos, Node x) {
+        long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
+        if (pos.getSubIndex() == NOT_ITERABLE) {
+            assert x == null || fieldTypes.get((pos.isInput() ? inputOffsets : successorOffsets)[pos.getIndex()]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")";
+            putNode(node, offset, x);
+        } else {
+            NodeList<Node> list = getNodeList(node, offset);
+            while (list.size() <= pos.getSubIndex()) {
+                list.add(null);
+            }
+            list.initialize(pos.getSubIndex(), x);
+        }
+    }
+
     public NodeClassIterable getInputIterable(final Node node) {
         assert getClazz().isInstance(node);
         return new NodeClassIterable() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Jun 25 10:58:42 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Jun 25 11:20:50 2014 +0200
@@ -136,6 +136,12 @@
         return oldValue;
     }
 
+    void initialize(int index, T node) {
+        incModCount();
+        assert index < size();
+        nodes[index] = node;
+    }
+
     void copy(NodeList<T> other) {
         incModCount();
         nodes = Arrays.copyOf(other.nodes, other.size);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java	Wed Jun 25 10:58:42 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java	Wed Jun 25 11:20:50 2014 +0200
@@ -26,6 +26,12 @@
 
 public interface Canonicalizable {
 
+    public enum CanonicalizeMethod {
+        BASE,
+        UNARY,
+        BINARY
+    }
+
     Node canonical(CanonicalizerTool tool);
 
     public interface Unary<T extends Node> {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Jun 25 10:58:42 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Jun 25 11:20:50 2014 +0200
@@ -24,12 +24,15 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.Graph.NodeChangedListener;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graph.spi.Canonicalizable.Binary;
+import com.oracle.graal.graph.spi.Canonicalizable.Unary;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.util.*;
@@ -229,11 +232,50 @@
             return result;
         }
 
+        private static AutoCloseable getCanonicalizeableContractAssertion(Node node) {
+            boolean needsAssertion = false;
+            assert (needsAssertion = true) == true;
+            if (needsAssertion) {
+                Mark mark = node.graph().getMark();
+                return () -> {
+                    assert mark.equals(node.graph().getMark()) : "new node created while canonicalizing " + node.getClass().getSimpleName() + " " + node + ": " +
+                                    node.graph().getNewNodes(mark).snapshot();
+                };
+            } else {
+                return new AutoCloseable() {
+                    public void close() throws Exception {
+                        // nothing to do
+                    }
+                };
+            }
+        }
+
         public boolean baseTryCanonicalize(final Node node, NodeClass nodeClass) {
-            if (nodeClass.isCanonicalizable()) {
+            if (nodeClass.getCanonicalizeMethod() != null) {
                 METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
                 try (Scope s = Debug.scope("CanonicalizeNode", node)) {
-                    Node canonical = node.canonical(tool);
+                    Node canonical;
+                    switch (nodeClass.getCanonicalizeMethod()) {
+                        case BASE:
+                            canonical = node.canonical(tool);
+                            break;
+                        case UNARY:
+                            try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) {
+                                @SuppressWarnings("unchecked")
+                                Canonicalizable.Unary<Node> unary = (Unary<Node>) node;
+                                canonical = unary.canonical(tool, unary.getValue());
+                            }
+                            break;
+                        case BINARY:
+                            try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) {
+                                @SuppressWarnings("unchecked")
+                                Canonicalizable.Binary<Node> binary = (Binary<Node>) node;
+                                canonical = binary.canonical(tool, binary.getX(), binary.getY());
+                            }
+                            break;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere("unexpected CanonicalizeMethod");
+                    }
                     if (performReplacement(node, canonical)) {
                         return true;
                     }
@@ -271,14 +313,19 @@
 //                                         --------------------------------------------
 //       X: must not happen (checked with assertions)
 // @formatter:on
-        private boolean performReplacement(final Node node, Node canonical) {
-            if (canonical == node) {
+        private boolean performReplacement(final Node node, Node newCanonical) {
+            if (newCanonical == node) {
                 Debug.log("Canonicalizer: work on %1s", node);
                 return false;
             } else {
+                Node canonical = newCanonical;
                 Debug.log("Canonicalizer: replacing %1s with %1s", node, canonical);
                 METRIC_CANONICALIZED_NODES.increment();
                 StructuredGraph graph = (StructuredGraph) node.graph();
+                if (canonical != null && !canonical.isAlive()) {
+                    assert !canonical.isDeleted();
+                    canonical = graph.addOrUniqueWithInputs(canonical);
+                }
                 if (node instanceof FloatingNode) {
                     if (canonical == null) {
                         // case 1
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Wed Jun 25 10:58:42 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Wed Jun 25 11:20:50 2014 +0200
@@ -27,10 +27,12 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graph.spi.Canonicalizable.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -332,10 +334,32 @@
         }
         FlowUtil.inferStampAndCheck(changed);
         added.add(changed);
-        ValueNode canon = (ValueNode) changed.canonical(tool);
+
+        Node canon;
+        switch (changed.getNodeClass().getCanonicalizeMethod()) {
+            case BASE:
+                canon = changed.canonical(tool);
+                break;
+            case UNARY:
+                @SuppressWarnings("unchecked")
+                Canonicalizable.Unary<Node> unary = (Unary<Node>) changed;
+                canon = unary.canonical(tool, unary.getValue());
+                break;
+            case BINARY:
+                @SuppressWarnings("unchecked")
+                Canonicalizable.Binary<Node> binary = (Binary<Node>) changed;
+                canon = binary.canonical(tool, binary.getX(), binary.getY());
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("unexpected CanonicalizeMethod");
+        }
+        if (canon != null && !canon.isAlive()) {
+            assert !canon.isDeleted();
+            canon = graph.addOrUniqueWithInputs(canon);
+        }
         // might be already in `added`, no problem adding it again.
-        added.add(canon);
-        rememberSubstitution(f, canon);
+        added.add((ValueNode) canon);
+        rememberSubstitution(f, (ValueNode) canon);
         return canon;
     }