Mercurial > hg > graal-compiler
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; }