# HG changeset patch # User Lukas Stadler # Date 1337697090 -7200 # Node ID 3f6496caa1a4f5491692fa658082a929c7c4cdb3 # Parent 0364a2a874b8df328b52c18285bb8da48d4440cb# Parent b26a95cf8e3d68242cd1dacd9a660ae72bd56c18 Merge diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue May 22 16:31:30 2012 +0200 @@ -169,13 +169,8 @@ if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } - if (GraalOptions.OptGVN) { - new GlobalValueNumberingPhase().apply(graph); - } - int mark = graph.getMark(); new LoweringPhase(runtime, assumptions).apply(graph); - new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph); if (GraalOptions.CullFrameStates) { new CullFrameStatesPhase().apply(graph); @@ -201,9 +196,6 @@ if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } - if (GraalOptions.OptGVN) { - new GlobalValueNumberingPhase().apply(graph); - } new DeadCodeEliminationPhase().apply(graph); plan.runPhases(PhasePosition.MID_LEVEL, graph); diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Tue May 22 16:31:30 2012 +0200 @@ -22,52 +22,86 @@ */ package com.oracle.graal.compiler.phases; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Graph.InputChangedListener; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; public class CanonicalizerPhase extends Phase { private static final int MAX_ITERATION_PER_NODE = 10; private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes"); private static final DebugMetric METRIC_CANONICALIZATION_CONSIDERED_NODES = Debug.metric("CanonicalizationConsideredNodes"); private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes"); + public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits"); - private int newNodesMark; + private final int newNodesMark; private final CiTarget target; private final CiAssumptions assumptions; private final RiRuntime runtime; private final IsImmutablePredicate immutabilityPredicate; + private final Iterable initWorkingSet; + + private NodeWorkList workList; + private Tool tool; public CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions) { - this(target, runtime, assumptions, -1, null); + this(target, runtime, assumptions, null, 0, null); } /** - * @param newNodesMark if non-negative, then only the {@linkplain Graph#getNewNodes(int) new nodes} specified by + * @param target + * @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 immutabilityPredicate + */ + public CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions, Iterable workingSet, IsImmutablePredicate immutabilityPredicate) { + this(target, runtime, assumptions, workingSet, 0, immutabilityPredicate); + } + + /** + * @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(CiTarget target, RiRuntime runtime, CiAssumptions assumptions, int newNodesMark, IsImmutablePredicate immutabilityPredicate) { + this(target, runtime, assumptions, null, newNodesMark, immutabilityPredicate); + } + + private CanonicalizerPhase(CiTarget target, RiRuntime runtime, CiAssumptions assumptions, Iterable workingSet, int newNodesMark, IsImmutablePredicate immutabilityPredicate) { this.newNodesMark = newNodesMark; this.target = target; this.assumptions = assumptions; this.runtime = runtime; this.immutabilityPredicate = immutabilityPredicate; + this.initWorkingSet = workingSet; } @Override protected void run(StructuredGraph graph) { - boolean newNodes = newNodesMark >= 0; - NodeWorkList nodeWorkList = graph.createNodeWorkList(!newNodes, MAX_ITERATION_PER_NODE); - if (newNodes) { - nodeWorkList.addAll(graph.getNewNodes(newNodesMark)); + if (initWorkingSet == null) { + workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE); + if (newNodesMark > 0) { + workList.addAll(graph.getNewNodes(newNodesMark)); + } + } else { + workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE); + workList.addAll(initWorkingSet); } + tool = new Tool(workList, runtime, target, assumptions, immutabilityPredicate); + processWorkSet(graph); - canonicalize(graph, nodeWorkList, runtime, target, assumptions, immutabilityPredicate); + while (graph.getUsagesDroppedNodesCount() > 0) { + for (Node n : graph.getAndCleanUsagesDroppedNodes()) { + if (!n.isDeleted() && n.usages().size() == 0 && GraphUtil.isFloatingNode().apply(n)) { + n.safeDelete(); + } + } + } } public interface IsImmutablePredicate { @@ -78,15 +112,56 @@ boolean apply(CiConstant constant); } - public static void canonicalize(StructuredGraph graph, NodeWorkList nodeWorkList, RiRuntime runtime, CiTarget target, CiAssumptions assumptions, IsImmutablePredicate immutabilityPredicate) { - graph.trackInputChange(nodeWorkList); - Tool tool = new Tool(nodeWorkList, runtime, target, assumptions, immutabilityPredicate); - for (Node node : nodeWorkList) { + 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 n, StructuredGraph graph) { + if (n.isAlive()) { METRIC_PROCESSED_NODES.increment(); - if (node instanceof Canonicalizable) { - METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); - int mark = graph.getMark(); - ValueNode canonical = ((Canonicalizable) node).canonical(tool); + + if (tryGlobalValueNumbering(n, graph)) { + return; + } + int mark = graph.getMark(); + tryCanonicalize(n, graph, tool); + + for (Node node : graph.getNewNodes(mark)) { + workList.add(node); + } + } + } + + public static boolean tryGlobalValueNumbering(Node n, StructuredGraph graph) { + if (n.getNodeClass().valueNumberable()) { + Node newNode = graph.findDuplicate(n); + if (newNode != null) { + assert !(n instanceof FixedNode || newNode instanceof FixedNode); + n.replaceAtUsages(newNode); + n.safeDelete(); + METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment(); + Debug.log("GVN applied and new node is %1s", newNode); + return true; + } + } + return false; + } + + public static void tryCanonicalize(Node node, StructuredGraph graph, SimplifierTool tool) { + if (node instanceof Canonicalizable) { + METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); + ValueNode canonical = ((Canonicalizable) node).canonical(tool); // cases: original node: // |Floating|Fixed-unconnected|Fixed-connected| // -------------------------------------------- @@ -99,72 +174,62 @@ // Fixed-connected| 2 | X | 6 | // -------------------------------------------- // X: must not happen (checked with assertions) - if (canonical == node) { - Debug.log("Canonicalizer: work on %s", node); - } else { - Debug.log("Canonicalizer: replacing %s with %s", node, canonical); + if (canonical == node) { + Debug.log("Canonicalizer: work on %s", node); + } 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 : node + " -> " + canonical + - " : replacement should be floating or fixed and connected"; - graph.replaceFloating((FloatingNode) node, canonical); - } + METRIC_CANONICALIZED_NODES.increment(); + if (node instanceof FloatingNode) { + if (canonical == null) { + // case 1 + graph.removeFloating((FloatingNode) node); } else { - assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; - if (canonical == null) { - // case 3 - graph.removeFixed((FixedWithNextNode) node); - } else if (canonical instanceof FloatingNode) { - // case 4 - graph.replaceFixedWithFloating((FixedWithNextNode) node, (FloatingNode) canonical); + // case 2 + assert !(canonical instanceof FixedNode) || canonical.predecessor() != null : 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() + ")"; + if (canonical == null) { + // case 3 + graph.removeFixed((FixedWithNextNode) node); + } else if (canonical instanceof FloatingNode) { + // case 4 + graph.replaceFixedWithFloating((FixedWithNextNode) node, (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((FixedWithNextNode) node, (FixedWithNextNode) 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((FixedWithNextNode) node, (FixedWithNextNode) canonical); - } else { - assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; - // case 6 - node.replaceAtUsages(canonical); - graph.removeFixed((FixedWithNextNode) node); - } + assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; + // case 6 + node.replaceAtUsages(canonical); + graph.removeFixed((FixedWithNextNode) node); } } - nodeWorkList.addAll(graph.getNewNodes(mark)); - } - } else if (node instanceof Simplifiable) { - Debug.log("Canonicalizer: simplifying %s", node); - METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); - ((Simplifiable) node).simplify(tool); - } - } - graph.stopTrackingInputChange(); - while (graph.getUsagesDroppedNodesCount() > 0) { - for (Node n : graph.getAndCleanUsagesDroppedNodes()) { - if (!n.isDeleted() && n.usages().size() == 0 && GraphUtil.isFloatingNode().apply(n)) { - n.safeDelete(); } } + } else if (node instanceof Simplifiable) { + Debug.log("Canonicalizer: simplifying %s", node); + METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); + ((Simplifiable) node).simplify(tool); } } private static final class Tool implements SimplifierTool { - private final NodeWorkList nodeWorkList; + private final NodeWorkList nodeWorkSet; private final RiRuntime runtime; private final CiTarget target; private final CiAssumptions assumptions; private final IsImmutablePredicate immutabilityPredicate; - public Tool(NodeWorkList nodeWorkList, RiRuntime runtime, CiTarget target, CiAssumptions assumptions, IsImmutablePredicate immutabilityPredicate) { - this.nodeWorkList = nodeWorkList; + public Tool(NodeWorkList nodeWorkSet, RiRuntime runtime, CiTarget target, CiAssumptions assumptions, IsImmutablePredicate immutabilityPredicate) { + this.nodeWorkSet = nodeWorkSet; this.runtime = runtime; this.target = target; this.assumptions = assumptions; @@ -200,7 +265,7 @@ @Override public void addToWorkList(Node node) { - nodeWorkList.add(node); + nodeWorkSet.add(node); } @Override diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java Tue May 22 16:31:30 2012 +0200 @@ -153,6 +153,16 @@ } else { floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), getLocationForRead(readNode), readNode.stamp(), readNode.dependencies())); } + ValueAnchorNode anchor = null; + for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) { + if (anchor == null) { + anchor = graph.add(new ValueAnchorNode()); + } + anchor.addAnchoredValue(guard); + } + if (anchor != null) { + graph.addAfterFixed(readNode, anchor); + } graph.replaceFixedWithFloating(readNode, floatingRead); } diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Tue May 22 16:31:30 2012 +0200 @@ -24,6 +24,7 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.cri.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; @@ -84,10 +85,13 @@ protected void run(final StructuredGraph graph) { // Step 1: repeatedly lower fixed nodes until no new ones are created NodeBitMap processed = graph.createNodeBitMap(); + int i = 0; while (true) { int mark = graph.getMark(); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, true); processBlock(cfg.getStartBlock(), graph.createNodeBitMap(), processed, null); + Debug.dump(graph, "Lowering iteration %d", i++); + new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph); if (graph.getNewNodes(mark).filter(FixedNode.class).isEmpty()) { break; @@ -151,7 +155,7 @@ } } - if (parentAnchor == null) { + if (parentAnchor == null && GraalOptions.OptEliminateGuards) { for (GuardNode guard : anchor.usages().filter(GuardNode.class)) { activeGuards.clear(guard); } @@ -178,8 +182,10 @@ } } GuardNode newGuard = guardAnchor.graph().unique(new GuardNode((BooleanNode) condition, guardAnchor, deoptReason, action, negated, leafGraphId)); - activeGuards.grow(); - activeGuards.mark(newGuard); + if (GraalOptions.OptEliminateGuards) { + activeGuards.grow(); + activeGuards.mark(newGuard); + } return newGuard; } }; diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java Tue May 22 16:31:30 2012 +0200 @@ -25,17 +25,18 @@ import java.io.*; import java.util.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.compiler.schedule.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Graph.InputChangedListener; import com.oracle.graal.graph.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.types.*; import com.oracle.graal.nodes.spi.types.TypeCanonicalizable.Result; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; public class PropagateTypeCachePhase extends Phase { @@ -45,7 +46,6 @@ private final RiRuntime runtime; private final CiAssumptions assumptions; - private NodeWorkList changedNodes; private StructuredGraph currentGraph; private SchedulePhase schedule; @@ -109,20 +109,30 @@ } } - changedNodes = graph.createNodeWorkList(false, 10); schedule = new SchedulePhase(); schedule.apply(graph); + final NodeBitMap changedNodes = graph.createNodeBitMap(true); + graph.trackInputChange(new InputChangedListener() { + @Override + public void inputChanged(Node node) { + changedNodes.mark(node); + } + }); + new Iterator().apply(schedule.getCFG().getStartBlock()); + graph.stopTrackingInputChange(); + Debug.dump(graph, "After PropagateType iteration"); if (changes > 0) { // totalChanges += changes; // out.println(graph.method() + ": " + changes + " changes"); } - CanonicalizerPhase.canonicalize(graph, changedNodes, runtime, target, assumptions, null); + new CanonicalizerPhase(target, runtime, assumptions, changedNodes, null).apply(graph); + // outputGraph(graph); } @@ -232,7 +242,6 @@ assert node instanceof FixedWithNextNode; currentGraph.replaceFixed((FixedWithNextNode) node, replacement); } - changedNodes.addAll(replacement.usages()); } } if (node.isAlive() && node instanceof TypeFeedbackProvider) { diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Tue May 22 16:31:30 2012 +0200 @@ -960,7 +960,7 @@ assert localCount == args.length : "snippet argument count mismatch"; snippetCopy.addDuplicates(snippetGraph.getNodes(), replacements); if (!replacements.isEmpty()) { - new CanonicalizerPhase(null, runtime, null, -1, immutabilityPredicate).apply(snippetCopy); + new CanonicalizerPhase(null, runtime, null, 0, immutabilityPredicate).apply(snippetCopy); } // Explode all loops in the snippet if requested diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Tue May 22 16:31:30 2012 +0200 @@ -48,7 +48,7 @@ private GraphEventLog eventLog; ArrayList usagesDropped = new ArrayList<>(); - NodeWorkList inputChanged; + InputChangedListener inputChanged; private final HashMap cachedNodes = new HashMap<>(); private static final class CacheEntry { @@ -159,8 +159,12 @@ return result; } - public void trackInputChange(NodeWorkList worklist) { - this.inputChanged = worklist; + public interface InputChangedListener { + void inputChanged(Node node); + } + + public void trackInputChange(InputChangedListener inputChangedListener) { + this.inputChanged = inputChangedListener; } public void stopTrackingInputChange() { @@ -386,7 +390,11 @@ } public NodeBitMap createNodeBitMap() { - return new NodeBitMap(this); + return createNodeBitMap(false); + } + + public NodeBitMap createNodeBitMap(boolean autoGrow) { + return new NodeBitMap(this, autoGrow); } public NodeMap createNodeMap() { diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Tue May 22 16:31:30 2012 +0200 @@ -25,6 +25,7 @@ import java.lang.annotation.*; import java.util.*; +import com.oracle.graal.graph.Graph.InputChangedListener; import com.oracle.graal.graph.NodeClass.*; @@ -191,9 +192,9 @@ assert assertTrue(result, "not found in usages, old input: %s", oldInput); } if (newInput != null) { - NodeWorkList inputChanged = graph.inputChanged; + InputChangedListener inputChanged = graph.inputChanged; if (inputChanged != null) { - inputChanged.addAgain(this); + inputChanged.inputChanged(this); } newInput.usages.add(this); } @@ -251,9 +252,9 @@ boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); assert assertTrue(result, "not found in inputs, usage: %s", usage); if (other != null) { - NodeWorkList inputChanged = graph.inputChanged; + InputChangedListener inputChanged = graph.inputChanged; if (inputChanged != null) { - inputChanged.addAgain(usage); + inputChanged.inputChanged(usage); } other.usages.add(usage); } diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Tue May 22 16:31:30 2012 +0200 @@ -22,18 +22,22 @@ */ package com.oracle.graal.graph; -import java.util.Collection; -import java.util.Iterator; +import java.util.*; public final class NodeBitMap implements Iterable{ - + private final boolean autoGrow; private final BitMap bitMap; private final Graph graph; public NodeBitMap(Graph graph) { + this(graph, false); + } + + public NodeBitMap(Graph graph, boolean autoGrow) { this.graph = graph; + this.autoGrow = autoGrow; bitMap = new BitMap(graph.nodeIdCount()); } @@ -63,6 +67,9 @@ } public boolean isMarked(Node node) { + if (autoGrow && isNew(node)) { + return false; + } assert check(node); return bitMap.get(node.id()); } @@ -72,11 +79,17 @@ } public void mark(Node node) { + if (autoGrow && isNew(node)) { + grow(); + } assert check(node); bitMap.set(node.id()); } public void clear(Node node) { + if (autoGrow && isNew(node)) { + return; + } assert check(node); bitMap.clear(node.id()); } @@ -105,7 +118,7 @@ return bitMap.toBinaryString(); } - public void markAll(Collection nodes) { + public void markAll(Iterable nodes) { for (Node node : nodes) { mark(node); } diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Tue May 22 16:31:30 2012 +0200 @@ -43,6 +43,9 @@ public FilteredNodeIterable filter(NodePredicate predicate) { return new FilteredNodeIterable<>(this).and(predicate); } + public FilteredNodeIterable nonNull() { + return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull()); + } public List snapshot() { ArrayList list = new ArrayList<>(); for (T n : this) { diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Tue May 22 16:31:30 2012 +0200 @@ -289,7 +289,6 @@ ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.array(), StructuredGraph.INVALID_GRAPH_ID); graph.replaceFixedWithFixed(arrayLengthNode, safeReadArrayLength); - safeReadArrayLength.lower(tool); } else if (n instanceof LoadFieldNode) { LoadFieldNode field = (LoadFieldNode) n; int displacement = ((HotSpotField) field.field()).offset(); @@ -389,9 +388,6 @@ if (elementKind == CiKind.Object && !value.isNullConstant()) { graph.addAfterFixed(memoryWrite, graph.add(new ArrayWriteBarrier(array, arrayLocation))); } - if (checkcast != null) { - checkcast.lower(tool); - } } else if (n instanceof UnsafeLoadNode) { UnsafeLoadNode load = (UnsafeLoadNode) n; assert load.kind() != CiKind.Illegal; @@ -471,12 +467,12 @@ return safeRead(array.graph(), CiKind.Int, array, config.arrayLengthOffset, StampFactory.positiveInt(), leafGraphId); } - private Node createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) { - SafeReadNode arrayLength = safeReadArrayLength(n.array(), n.leafGraphId()); - Node guard = tool.createGuard(n.graph().unique(new IntegerBelowThanNode(n.index(), arrayLength)), RiDeoptReason.BoundsCheckException, RiDeoptAction.InvalidateReprofile, n.leafGraphId()); + private static Node createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) { + StructuredGraph graph = (StructuredGraph) n.graph(); + ArrayLengthNode arrayLength = graph.add(new ArrayLengthNode(n.array())); + Node guard = tool.createGuard(graph.unique(new IntegerBelowThanNode(n.index(), arrayLength)), RiDeoptReason.BoundsCheckException, RiDeoptAction.InvalidateReprofile, n.leafGraphId()); - ((StructuredGraph) n.graph()).addBeforeFixed(n, arrayLength); - arrayLength.lower(tool); + graph.addBeforeFixed(n, arrayLength); return guard; } diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedNode.java Tue May 22 16:31:30 2012 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.type.*; public abstract class FixedNode extends ValueNode { @@ -32,6 +33,10 @@ super(stamp); } + public FixedNode(Stamp stamp, Node... dependencies) { + super(stamp, dependencies); + } + public double probability() { return probability; } diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedWithNextNode.java Tue May 22 16:31:30 2012 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.type.*; /** @@ -41,4 +42,8 @@ public FixedWithNextNode(Stamp stamp) { super(stamp); } + + public FixedWithNextNode(Stamp stamp, Node... dependencies) { + super(stamp, dependencies); + } } diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Tue May 22 16:31:30 2012 +0200 @@ -72,7 +72,10 @@ CiConstant constantIndex = index.asConstant(); if (constantIndex != null && constantIndex.kind.stackKind().isInt()) { long constantIndexLong = constantIndex.asInt(); - if (indexScalingEnabled && tool.target() != null) { + if (indexScalingEnabled) { + if (tool.target() == null) { + return this; + } constantIndexLong *= tool.target().sizeInBytes(getValueKind()); } constantIndexLong += displacement(); diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java Tue May 22 16:31:30 2012 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.max.cri.ci.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.max.cri.ci.*; /** * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph. @@ -35,15 +35,8 @@ public final class ValueAnchorNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable, Node.IterableNodeType { - @Input private ValueNode object; - - public ValueNode object() { - return object; - } - - public ValueAnchorNode(ValueNode object) { - super(StampFactory.illegal()); - this.object = object; + public ValueAnchorNode(ValueNode... values) { + super(StampFactory.illegal(), values); } @Override @@ -51,23 +44,36 @@ // Nothing to emit, since this node is used for structural purposes only. } + public void addAnchoredValue(ValueNode value) { + this.dependencies().add(value); + } + @Override public ValueNode canonical(CanonicalizerTool tool) { - if (object == null) { - return null; - } - if (object instanceof ConstantNode) { + if (this.predecessor() instanceof ValueAnchorNode) { + // transfer values and remove + ValueAnchorNode previousAnchor = (ValueAnchorNode) this.predecessor(); + for (Node node : dependencies().nonNull()) { + previousAnchor.dependencies().add(node); + } return null; } - if (object instanceof IntegerDivNode || object instanceof IntegerRemNode) { - if (((ArithmeticNode) object).y().isConstant()) { - CiConstant constant = ((ArithmeticNode) object).y().asConstant(); - assert constant.kind == object.kind() : constant.kind + " != " + object.kind(); - if (constant.asLong() != 0) { - return null; + for (Node node : dependencies().nonNull()) { + if (node instanceof ConstantNode) { + continue; + } + if (node instanceof IntegerDivNode || node instanceof IntegerRemNode) { + ArithmeticNode arithmeticNode = (ArithmeticNode) node; + if (arithmeticNode.y().isConstant()) { + CiConstant constant = arithmeticNode.y().asConstant(); + assert constant.kind == arithmeticNode.kind() : constant.kind + " != " + arithmeticNode.kind(); + if (constant.asLong() != 0) { + continue; + } } } + return this; // still necessary } - return this; + return null; // no node which require an anchor found } } diff -r 0364a2a874b8 -r 3f6496caa1a4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Tue May 22 16:19:02 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Tue May 22 16:31:30 2012 +0200 @@ -74,10 +74,15 @@ public ValueNode canonical(CanonicalizerTool tool) { assert object() != null : this; - RiResolvedType objectDeclaredType = object().declaredType(); - if (objectDeclaredType != null && targetClass != null && objectDeclaredType.isSubtypeOf(targetClass)) { - // we don't have to check for null types here because they will also pass the checkcast. - return object(); + if (targetClass != null) { + RiResolvedType objectType = object().exactType(); + if (objectType == null) { + objectType = object().declaredType(); + } + if (objectType != null && objectType.isSubtypeOf(targetClass)) { + // we don't have to check for null types here because they will also pass the checkcast. + return object(); + } } CiConstant constant = object().asConstant();