Mercurial > hg > graal-jvmci-8
diff graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java @ 9049:6d376d09880b
Make CanonicalizerPhase reentrant.
author | Roland Schatz <roland.schatz@oracle.com> |
---|---|
date | Fri, 12 Apr 2013 13:50:45 +0200 |
parents | 961ad124cb21 |
children | 908cac5f443c |
line wrap: on
line diff
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Apr 12 13:49:29 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Fri Apr 12 13:50:45 2013 +0200 @@ -36,8 +36,9 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; -public class CanonicalizerPhase extends Phase { +public class CanonicalizerPhase extends BasePhase<PhaseContext> { private static final int MAX_ITERATION_PER_NODE = 10; private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes"); @@ -47,155 +48,163 @@ private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes"); public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits"); - private final int newNodesMark; - private final Assumptions assumptions; - private final MetaAccessProvider runtime; - private final CustomCanonicalizer customCanonicalizer; - private final Iterable<Node> initWorkingSet; - - private NodeWorkList workList; - private Tool tool; - private List<Node> snapshotTemp; - public interface CustomCanonicalizer { ValueNode canonicalize(Node node); } - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions) { - this(runtime, assumptions, null, 0, null); - } - - /** - * @param runtime - * @param assumptions - * @param workingSet the initial working set of nodes on which the canonicalizer works, should - * be an auto-grow node bitmap - * @param customCanonicalizer - */ - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) { - this(runtime, assumptions, workingSet, 0, customCanonicalizer); - } - - /** - * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by this - * mark are processed otherwise all nodes in the graph are processed - */ - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { - this(runtime, assumptions, null, newNodesMark, customCanonicalizer); - } - - public CanonicalizerPhase(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { - this.newNodesMark = newNodesMark; - this.assumptions = assumptions; - this.runtime = runtime; - this.customCanonicalizer = customCanonicalizer; - this.initWorkingSet = workingSet; - this.snapshotTemp = new ArrayList<>(); - } - @Override - protected void run(StructuredGraph graph) { - if (initWorkingSet == null) { - workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE); - } else { - workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE); - workList.addAll(initWorkingSet); - } - if (newNodesMark > 0) { - workList.addAll(graph.getNewNodes(newNodesMark)); - } - tool = new Tool(workList, runtime, assumptions); - processWorkSet(graph); - } - - private void processWorkSet(StructuredGraph graph) { - graph.trackInputChange(new InputChangedListener() { - - @Override - public void inputChanged(Node node) { - workList.addAgain(node); - } - }); - - for (Node n : workList) { - processNode(n, graph); - } - - graph.stopTrackingInputChange(); + protected void run(StructuredGraph graph, PhaseContext context) { + new Instance(context.getRuntime(), context.getAssumptions()).run(graph); } - private void processNode(Node node, StructuredGraph graph) { - if (node.isAlive()) { - METRIC_PROCESSED_NODES.increment(); + public static class Instance extends Phase { + + private final int newNodesMark; + private final Assumptions assumptions; + private final MetaAccessProvider runtime; + private final CustomCanonicalizer customCanonicalizer; + private final Iterable<Node> initWorkingSet; + + private NodeWorkList workList; + private Tool tool; + private List<Node> snapshotTemp; + + public Instance(MetaAccessProvider runtime, Assumptions assumptions) { + this(runtime, assumptions, null, 0, null); + } - if (tryGlobalValueNumbering(node, graph)) { - return; + /** + * @param runtime + * @param assumptions + * @param workingSet the initial working set of nodes on which the canonicalizer works, + * should be an auto-grow node bitmap + * @param customCanonicalizer + */ + public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, CustomCanonicalizer customCanonicalizer) { + this(runtime, assumptions, workingSet, 0, customCanonicalizer); + } + + /** + * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by + * this mark are processed otherwise all nodes in the graph are processed + */ + public Instance(MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + this(runtime, assumptions, null, newNodesMark, customCanonicalizer); + } + + public Instance(MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, CustomCanonicalizer customCanonicalizer) { + super("Canonicalizer"); + this.newNodesMark = newNodesMark; + this.assumptions = assumptions; + this.runtime = runtime; + this.customCanonicalizer = customCanonicalizer; + this.initWorkingSet = workingSet; + this.snapshotTemp = new ArrayList<>(); + } + + @Override + protected void run(StructuredGraph graph) { + if (initWorkingSet == null) { + workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE); + } else { + workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE); + workList.addAll(initWorkingSet); } - int mark = graph.getMark(); - if (!tryKillUnused(node)) { - node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); - if (!tryCanonicalize(node, graph)) { - tryInferStamp(node, graph); - } else { - for (Node in : snapshotTemp) { - if (in.isAlive() && in.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(in); + if (newNodesMark > 0) { + workList.addAll(graph.getNewNodes(newNodesMark)); + } + tool = new Tool(workList, runtime, assumptions); + processWorkSet(graph); + } + + private void processWorkSet(StructuredGraph graph) { + graph.trackInputChange(new InputChangedListener() { + + @Override + public void inputChanged(Node node) { + workList.addAgain(node); + } + }); + + for (Node n : workList) { + processNode(n, graph); + } + + graph.stopTrackingInputChange(); + } + + private void processNode(Node node, StructuredGraph graph) { + if (node.isAlive()) { + METRIC_PROCESSED_NODES.increment(); + + if (tryGlobalValueNumbering(node, graph)) { + return; + } + int mark = graph.getMark(); + if (!tryKillUnused(node)) { + node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp); + if (!tryCanonicalize(node, graph)) { + tryInferStamp(node, graph); + } else { + for (Node in : snapshotTemp) { + if (in.isAlive() && in.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(in); + } } } + snapshotTemp.clear(); } - snapshotTemp.clear(); - } - for (Node newNode : graph.getNewNodes(mark)) { - workList.add(newNode); + for (Node newNode : graph.getNewNodes(mark)) { + workList.add(newNode); + } } } - } - private static boolean tryKillUnused(Node node) { - if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(node); - return true; - } - return false; - } - - public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) { - if (node.getNodeClass().valueNumberable()) { - Node newNode = graph.findDuplicate(node); - if (newNode != null) { - assert !(node instanceof FixedNode || newNode instanceof FixedNode); - node.replaceAtUsages(newNode); - node.safeDelete(); - METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment(); - Debug.log("GVN applied and new node is %1s", newNode); + private static boolean tryKillUnused(Node node) { + if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(node); return true; } + return false; } - return false; - } - public boolean tryCanonicalize(final Node node, final StructuredGraph graph) { - boolean result = baseTryCanonicalize(node, graph); - if (!result && customCanonicalizer != null) { - ValueNode canonical = customCanonicalizer.canonicalize(node); - if (canonical == node && customCanonicalizer != null) { - canonical = customCanonicalizer.canonicalize(node); + public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) { + if (node.getNodeClass().valueNumberable()) { + Node newNode = graph.findDuplicate(node); + if (newNode != null) { + assert !(node instanceof FixedNode || newNode instanceof FixedNode); + node.replaceAtUsages(newNode); + node.safeDelete(); + METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment(); + Debug.log("GVN applied and new node is %1s", newNode); + return true; + } } - result = performReplacement(node, graph, canonical); + return false; } - return result; - } - public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) { - if (node instanceof Canonicalizable) { - assert !(node instanceof Simplifiable); - METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); - return Debug.scope("CanonicalizeNode", node, new Callable<Boolean>() { + public boolean tryCanonicalize(final Node node, final StructuredGraph graph) { + boolean result = baseTryCanonicalize(node, graph); + if (!result && customCanonicalizer != null) { + ValueNode canonical = customCanonicalizer.canonicalize(node); + if (canonical == node && customCanonicalizer != null) { + canonical = customCanonicalizer.canonicalize(node); + } + result = performReplacement(node, graph, canonical); + } + return result; + } - public Boolean call() { - ValueNode canonical = ((Canonicalizable) node).canonical(tool); + public boolean baseTryCanonicalize(final Node node, final StructuredGraph graph) { + if (node instanceof Canonicalizable) { + assert !(node instanceof Simplifiable); + METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); + return Debug.scope("CanonicalizeNode", node, new Callable<Boolean>() { + + public Boolean call() { + ValueNode canonical = ((Canonicalizable) node).canonical(tool); // @formatter:off // cases: original node: // |Floating|Fixed-unconnected|Fixed-connected| @@ -211,137 +220,139 @@ // X: must not happen (checked with assertions) // @formatter:on - return performReplacement(node, graph, canonical); - } - }); - } else if (node instanceof Simplifiable) { - Debug.log("Canonicalizer: simplifying %s", node); - METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); - Debug.scope("SimplifyNode", node, new Runnable() { + return performReplacement(node, graph, canonical); + } + }); + } else if (node instanceof Simplifiable) { + Debug.log("Canonicalizer: simplifying %s", node); + METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); + Debug.scope("SimplifyNode", node, new Runnable() { - public void run() { - ((Simplifiable) node).simplify(tool); - } - }); + public void run() { + ((Simplifiable) node).simplify(tool); + } + }); + } + return node.isDeleted(); } - return node.isDeleted(); - } - private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) { - if (canonical == node) { - Debug.log("Canonicalizer: work on %s", node); - return false; - } else { - Debug.log("Canonicalizer: replacing %s with %s", node, canonical); - METRIC_CANONICALIZED_NODES.increment(); - if (node instanceof FloatingNode) { - if (canonical == null) { - // case 1 - graph.removeFloating((FloatingNode) node); + private boolean performReplacement(final Node node, final StructuredGraph graph, ValueNode canonical) { + if (canonical == node) { + Debug.log("Canonicalizer: work on %s", node); + return false; + } else { + Debug.log("Canonicalizer: replacing %s with %s", node, canonical); + METRIC_CANONICALIZED_NODES.increment(); + if (node instanceof FloatingNode) { + if (canonical == null) { + // case 1 + graph.removeFloating((FloatingNode) node); + } else { + // case 2 + assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + + " : replacement should be floating or fixed and connected"; + graph.replaceFloating((FloatingNode) node, canonical); + } } else { - // case 2 - assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical + - " : replacement should be floating or fixed and connected"; - graph.replaceFloating((FloatingNode) node, canonical); - } - } else { - assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; - FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; + assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; + FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; - // When removing a fixed node, new canonicalization opportunities for its successor - // may arise - assert fixedWithNext.next() != null; - tool.addToWorkList(fixedWithNext.next()); + // When removing a fixed node, new canonicalization opportunities for its +// successor + // may arise + assert fixedWithNext.next() != null; + tool.addToWorkList(fixedWithNext.next()); - if (canonical == null) { - // case 3 - graph.removeFixed(fixedWithNext); - } else if (canonical instanceof FloatingNode) { - // case 4 - graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); - } else { - assert canonical instanceof FixedNode; - if (canonical.predecessor() == null) { - assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; - // case 5 - graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + if (canonical == null) { + // case 3 + graph.removeFixed(fixedWithNext); + } else if (canonical instanceof FloatingNode) { + // case 4 + graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); } else { - assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; - // case 6 - node.replaceAtUsages(canonical); - graph.removeFixed(fixedWithNext); + assert canonical instanceof FixedNode; + if (canonical.predecessor() == null) { + assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; + // case 5 + graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + } else { + assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; + // case 6 + node.replaceAtUsages(canonical); + graph.removeFixed(fixedWithNext); + } } } + return true; } - return true; } - } - /** - * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that - * the stamp has changed), re-queues the node's usages . If the stamp has changed then this - * method also checks if the stamp now describes a constant integer value, in which case the - * node is replaced with a constant. - */ - private void tryInferStamp(Node node, StructuredGraph graph) { - if (node.isAlive() && node instanceof ValueNode) { - ValueNode valueNode = (ValueNode) node; - METRIC_INFER_STAMP_CALLED.increment(); - if (valueNode.inferStamp()) { - METRIC_STAMP_CHANGED.increment(); - if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) { - ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph); - Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement); - valueNode.replaceAtUsages(replacement); - } else { - for (Node usage : valueNode.usages()) { - workList.addAgain(usage); + /** + * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means + * that the stamp has changed), re-queues the node's usages . If the stamp has changed then + * this method also checks if the stamp now describes a constant integer value, in which + * case the node is replaced with a constant. + */ + private void tryInferStamp(Node node, StructuredGraph graph) { + if (node.isAlive() && node instanceof ValueNode) { + ValueNode valueNode = (ValueNode) node; + METRIC_INFER_STAMP_CALLED.increment(); + if (valueNode.inferStamp()) { + METRIC_STAMP_CHANGED.increment(); + if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) { + ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph); + Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement); + valueNode.replaceAtUsages(replacement); + } else { + for (Node usage : valueNode.usages()) { + workList.addAgain(usage); + } } } } } - } - private static final class Tool implements SimplifierTool { + private static final class Tool implements SimplifierTool { - private final NodeWorkList nodeWorkSet; - private final MetaAccessProvider runtime; - private final Assumptions assumptions; + private final NodeWorkList nodeWorkSet; + private final MetaAccessProvider runtime; + private final Assumptions assumptions; - public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) { - this.nodeWorkSet = nodeWorkSet; - this.runtime = runtime; - this.assumptions = assumptions; - } + public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, Assumptions assumptions) { + this.nodeWorkSet = nodeWorkSet; + this.runtime = runtime; + this.assumptions = assumptions; + } - @Override - public void deleteBranch(FixedNode branch) { - branch.predecessor().replaceFirstSuccessor(branch, null); - GraphUtil.killCFG(branch); - } + @Override + public void deleteBranch(FixedNode branch) { + branch.predecessor().replaceFirstSuccessor(branch, null); + GraphUtil.killCFG(branch); + } - /** - * @return an object that can be used for recording assumptions or {@code null} if - * assumptions are not allowed in the current context. - */ - @Override - public Assumptions assumptions() { - return assumptions; - } + /** + * @return an object that can be used for recording assumptions or {@code null} if + * assumptions are not allowed in the current context. + */ + @Override + public Assumptions assumptions() { + return assumptions; + } - @Override - public MetaAccessProvider runtime() { - return runtime; - } + @Override + public MetaAccessProvider runtime() { + return runtime; + } - @Override - public void addToWorkList(Node node) { - nodeWorkSet.addAgain(node); - } + @Override + public void addToWorkList(Node node) { + nodeWorkSet.addAgain(node); + } - @Override - public void removeIfUnused(Node node) { - tryKillUnused(node); + @Override + public void removeIfUnused(Node node) { + tryKillUnused(node); + } } } }