# HG changeset patch # User Gilles Duboscq # Date 1340289397 -7200 # Node ID 494332f39ee8fda0f5c1a5dbaff9fd99e2483101 # Parent 776366f3a41aa37ca73989c21146334208386c92# Parent 17639f600cda407fe923013a5a510b79b5094e8c Merge diff -r 17639f600cda -r 494332f39ee8 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 Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Jun 21 16:36:37 2012 +0200 @@ -134,7 +134,6 @@ if (GraalOptions.Inline && !plan.isPhaseDisabled(InliningPhase.class)) { new InliningPhase(target, runtime, null, assumptions, cache, plan, optimisticOpts).apply(graph); - new DeadCodeEliminationPhase().apply(graph); new PhiStampPhase().apply(graph); if (GraalOptions.PropagateTypes) { @@ -153,19 +152,17 @@ plan.runPhases(PhasePosition.HIGH_LEVEL, graph); + if (GraalOptions.FullUnroll) { + new LoopFullUnrollPhase().apply(graph); + } + if (GraalOptions.EscapeAnalysis && !plan.isPhaseDisabled(EscapeAnalysisPhase.class)) { new EscapeAnalysisPhase(target, runtime, assumptions, cache, plan, optimisticOpts).apply(graph); new PhiStampPhase().apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); - } } - if (GraalOptions.OptLoops) { - if (GraalOptions.OptLoopTransform) { - new LoopTransformPhase().apply(graph); - } + if (GraalOptions.OptLoopTransform) { + new LoopTransformHighPhase().apply(graph); } - new RemoveValueProxyPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } @@ -191,15 +188,26 @@ new CheckCastEliminationPhase().apply(graph); } + if (GraalOptions.OptLoopTransform) { + new LoopTransformLowPhase().apply(graph); + } + new RemoveValueProxyPhase().apply(graph); if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions).apply(graph); } - new DeadCodeEliminationPhase().apply(graph); + if (GraalOptions.CheckCastElimination) { + new CheckCastEliminationPhase().apply(graph); + } + plan.runPhases(PhasePosition.MID_LEVEL, graph); plan.runPhases(PhasePosition.LOW_LEVEL, graph); + new DeadCodeEliminationPhase().apply(graph); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + } // Add safepoints to loops if (GraalOptions.GenLoopSafepoints) { new LoopSafepointInsertionPhase().apply(graph); diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Thu Jun 21 16:36:37 2012 +0200 @@ -200,7 +200,6 @@ public static boolean OptReadElimination = true; public static boolean OptGVN = true; public static boolean OptCanonicalizer = true; - public static boolean OptLoops = true; public static boolean ScheduleOutOfLoops = true; public static boolean OptReorderLoops = true; public static boolean OptEliminateGuards = true; @@ -209,6 +208,11 @@ public static boolean OptLoopTransform = true; public static boolean OptSafepointElimination = true; + // Loops + public static boolean ReassociateInvariants = true; + public static boolean FullUnroll = true; + public static int FullUnrollMaxNodes = 250; // TODO (gd) tune + /** * Insert a counter in the method prologue to track the most frequently called methods that were compiled by Graal. */ diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Thu Jun 21 16:36:37 2012 +0200 @@ -153,7 +153,7 @@ } else if (value != null) { Debug.metric("StateVariables").increment(); Value operand = nodeOperands.get(value); - assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand; + assert operand != null && (operand instanceof Variable || operand instanceof Constant) : operand + " for " + value; return operand; } else { diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/CountedLoopInfo.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/CountedLoopInfo.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/CountedLoopInfo.java Thu Jun 21 16:36:37 2012 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.compiler.loop; +import com.oracle.graal.compiler.loop.InductionVariable.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -29,14 +30,17 @@ private final LoopEx loop; private InductionVariable iv; private ValueNode end; + private boolean oneOff; - CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end) { + CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end, boolean oneOff) { this.loop = loop; this.iv = iv; this.end = end; + this.oneOff = oneOff; } public ValueNode maxTripCountNode() { + //TODO (gd) stuarte and respect oneOff return IntegerArithmeticNode.div(IntegerArithmeticNode.sub(end, iv.initNode()), iv.strideNode()); } @@ -45,7 +49,9 @@ } public long constantMaxTripCount() { - return (((ConstantNode) end).asConstant().asLong() - iv.constantInit()) / iv.constantStride(); + long off = oneOff ? iv.direction() == Direction.Up ? 1 : -1 : 0; + long max = (((ConstantNode) end).asConstant().asLong() + off - iv.constantInit()) / iv.constantStride(); + return Math.max(0, max); } public boolean isExactTripCount() { @@ -66,4 +72,9 @@ assert isExactTripCount(); return constantMaxTripCount(); } + + @Override + public String toString() { + return "iv=" + iv + " until " + end + (oneOff ? iv.direction() == Direction.Up ? "+1" : "-1" : ""); + } } diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java Thu Jun 21 16:36:37 2012 +0200 @@ -22,9 +22,14 @@ */ package com.oracle.graal.compiler.loop; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; public class LoopEx { private final Loop lirLoop; @@ -105,6 +110,32 @@ @Override public String toString() { - return isCounted() ? "Counted" : "" + "Loop (depth=" + lirLoop().depth + ") " + loopBegin(); + return (isCounted() ? "CountedLoop [" + counted() + "] " : "Loop ") + "(depth=" + lirLoop().depth + ") " + loopBegin(); + } + + private class InvariantPredicate extends NodePredicate { + @Override + public boolean apply(Node n) { + return isOutsideLoop(n); + } + } + + public void reassociateInvariants() { + InvariantPredicate invariant = new InvariantPredicate(); + StructuredGraph graph = (StructuredGraph) loopBegin().graph(); + for (BinaryNode binary : whole().nodes().filter(BinaryNode.class)) { + if (!BinaryNode.canTryReassociate(binary)) { + continue; + } + BinaryNode result = BinaryNode.reassociate(binary, invariant); + if (result != binary) { + Debug.log(CodeUtil.format("%H::%n", Debug.contextLookup(ResolvedJavaMethod.class)) + " : Reassociated %s into %s", binary, result); + graph.replaceFloating(binary, result); + } + } + } + + public void setCounted(CountedLoopInfo countedLoopInfo) { + counted = countedLoopInfo; } } diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java Thu Jun 21 16:36:37 2012 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.PhiNode.*; import com.oracle.graal.nodes.util.*; @@ -235,8 +236,8 @@ newExitMerge.addForwardEnd(end); } - for (PhiNode phi : loopBegin.phis().snapshot()) { - PhiNode firstPhi = graph.add(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), newExitMerge) : new PhiNode(phi.type(), newExitMerge)); + for (final PhiNode phi : loopBegin.phis().snapshot()) { + final PhiNode firstPhi = graph.add(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), newExitMerge) : new PhiNode(phi.type(), newExitMerge)); for (EndNode end : newExitMerge.forwardEnds()) { LoopEndNode loopEnd = reverseEnds.get(end); ValueNode prim = prim(phi.valueAt(loopEnd)); @@ -245,7 +246,15 @@ } ValueNode initializer = firstPhi; if (duplicateState != null) { - duplicateState.replaceFirstInput(phi, firstPhi); // fix the merge's state after + // fix the merge's state after + duplicateState.applyToNonVirtual(new NodeClosure() { + @Override + public void apply(Node from, ValueNode node) { + if (node == phi) { + from.replaceFirstInput(phi, firstPhi); + } + } + }); } mergedInitializers.put(phi, initializer); } diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopPolicies.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopPolicies.java Thu Jun 21 16:36:37 2012 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.loop; + +import com.oracle.graal.compiler.*; +import com.oracle.graal.nodes.*; + + +public abstract class LoopPolicies { + private LoopPolicies() { + // does not need to be instantiated + } + + // TODO (gd) change when inversion is available + public static boolean shouldPeel(LoopEx loop) { + LoopBeginNode loopBegin = loop.loopBegin(); + double entryProbability = loopBegin.forwardEnd().probability(); + return entryProbability > GraalOptions.MinimumPeelProbability && loop.size() + loopBegin.graph().getNodeCount() < GraalOptions.MaximumDesiredSize; + } + + public static boolean shouldFullUnroll(LoopEx loop) { + if (!loop.isCounted() || !loop.counted().isConstantMaxTripCount()) { + return false; + } + long exactTrips = loop.counted().constantMaxTripCount(); + int maxNodes = Math.min(GraalOptions.FullUnrollMaxNodes, GraalOptions.MaximumDesiredSize - loop.loopBegin().graph().getNodeCount()); + return loop.size() * exactTrips <= maxNodes; + } +} diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformations.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformations.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformations.java Thu Jun 21 16:36:37 2012 +0200 @@ -27,6 +27,10 @@ public abstract class LoopTransformations { + private LoopTransformations() { + // does not need to be instantiated + } + public static void invert(LoopEx loop, FixedNode point) { LoopFragmentInsideBefore head = loop.insideBefore(point); LoopFragmentInsideBefore duplicate = head.duplicate(); diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java Thu Jun 21 16:36:37 2012 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.compiler.loop; import java.util.*; +import java.util.concurrent.*; import com.oracle.graal.compiler.loop.InductionVariable.*; import com.oracle.graal.debug.*; @@ -35,8 +36,14 @@ private Map lirLoopToEx = new IdentityHashMap<>(); private Map loopBeginToEx = new IdentityHashMap<>(); - public LoopsData(StructuredGraph graph) { - ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, false); + public LoopsData(final StructuredGraph graph) { + + ControlFlowGraph cfg = Debug.scope("ControlFlowGraph", new Callable() { + @Override + public ControlFlowGraph call() throws Exception { + return ControlFlowGraph.compute(graph, true, true, true, false); + } + }); for (Loop lirLoop : cfg.getLoops()) { LoopEx ex = new LoopEx(lirLoop, this); lirLoopToEx.put(lirLoop, ex); @@ -139,8 +146,7 @@ break; default: throw GraalInternalError.shouldNotReachHere(); } - // TODO (gd) - Debug.log("absorb %b %s", oneOff, limit); + loop.setCounted(new CountedLoopInfo(loop, iv, limit, oneOff)); } } } diff -r 17639f600cda -r 494332f39ee8 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 Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Thu Jun 21 16:36:37 2012 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.phases; -import java.util.concurrent.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; @@ -164,14 +162,12 @@ return false; } - public static void tryCanonicalize(final Node node, StructuredGraph graph, final SimplifierTool tool) { + public static void tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) { if (node instanceof Canonicalizable) { METRIC_CANONICALIZATION_CONSIDERED_NODES.increment(); - ValueNode canonical = Debug.scope("CanonicalizeNode", node, new Callable() { - public ValueNode call() throws Exception { - return ((Canonicalizable) node).canonical(tool); - } - }); + Debug.scope("CanonicalizeNode", node, new Runnable() { + public void run() { + ValueNode canonical = ((Canonicalizable) node).canonical(tool); // cases: original node: // |Floating|Fixed-unconnected|Fixed-connected| // -------------------------------------------- @@ -184,45 +180,47 @@ // 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); - - METRIC_CANONICALIZED_NODES.increment(); - if (node instanceof FloatingNode) { - if (canonical == null) { - // case 1 - graph.removeFloating((FloatingNode) node); + if (canonical == node) { + Debug.log("Canonicalizer: work on %s", 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); - } - } 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); + 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); + } } else { - assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; - // case 6 - node.replaceAtUsages(canonical); - graph.removeFixed((FixedWithNextNode) node); + 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.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; + // case 6 + node.replaceAtUsages(canonical); + graph.removeFixed((FixedWithNextNode) node); + } + } } } } - } + }); } else if (node instanceof Simplifiable) { Debug.log("Canonicalizer: simplifying %s", node); METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment(); diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InliningPhase.java Thu Jun 21 16:36:37 2012 +0200 @@ -91,12 +91,17 @@ } while (!inlineCandidates.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) { - final InlineInfo info = inlineCandidates.remove(); + InlineInfo candidate = inlineCandidates.remove(); + if (!candidate.invoke.node().isAlive()) { + continue; + } + // refresh infos + final InlineInfo info = InliningUtil.getInlineInfo(candidate.invoke, candidate.level, runtime, assumptions, this, optimisticOpts); boolean inline = Debug.scope("InliningDecisions", new Callable() { @Override public Boolean call() throws Exception { - return info.invoke.node().isAlive() && inliningPolicy.isWorthInlining(graph, info); + return info != null && inliningPolicy.isWorthInlining(graph, info); } }); diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java Thu Jun 21 16:36:37 2012 +0200 @@ -29,7 +29,7 @@ public class InsertStateAfterPlaceholderPhase extends Phase { - private static class PlaceholderNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, LIRLowerable { + private static class PlaceholderNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, LIRLowerable, Canonicalizable { public PlaceholderNode() { super(StampFactory.forVoid()); } @@ -43,6 +43,14 @@ public boolean hasSideEffect() { return false; } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (stateAfter() == null) { + return null; + } + return this; + } } @Override diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopFullUnrollPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopFullUnrollPhase.java Thu Jun 21 16:36:37 2012 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.phases; + +import com.oracle.graal.compiler.loop.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; + + +public class LoopFullUnrollPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + if (graph.hasLoops()) { + while (true) { + final LoopsData dataCounted = new LoopsData(graph); + dataCounted.detectedCountedLoops(); + for (final LoopEx loop : dataCounted.countedLoops()) { + if (LoopPolicies.shouldFullUnroll(loop)) { + Debug.log("FullUnroll %s", loop); + LoopTransformations.fullUnroll(loop); + Debug.dump(graph, "After fullUnroll %s", loop); + continue; + } + } + break; + } + } + } + +} diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformHighPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformHighPhase.java Thu Jun 21 16:36:37 2012 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.phases; + +import com.oracle.graal.compiler.loop.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; + +public class LoopTransformHighPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + if (graph.hasLoops()) { + LoopsData data = new LoopsData(graph); + for (LoopEx loop : data.outterFirst()) { + if (LoopPolicies.shouldPeel(loop)) { + Debug.log("Peeling %s", loop); + LoopTransformations.peel(loop); + Debug.dump(graph, "After peeling %s", loop); + } + } + } + } +} diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformLowPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformLowPhase.java Thu Jun 21 16:36:37 2012 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.phases; + +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.loop.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; + +public class LoopTransformLowPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + if (graph.hasLoops()) { + if (GraalOptions.ReassociateInvariants) { + final LoopsData dataReassociate = new LoopsData(graph); + Debug.scope("ReassociateInvariants", new Runnable() { + @Override + public void run() { + for (LoopEx loop : dataReassociate.loops()) { + loop.reassociateInvariants(); + } + } + }); + } + } + } +} diff -r 17639f600cda -r 494332f39ee8 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 Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Thu Jun 21 16:36:37 2012 +0200 @@ -95,7 +95,7 @@ if (graph.getNewNodes(mark).filter(FixedNode.class).isEmpty()) { break; } - graph.verify(); + assert graph.verify(); processed.grow(); } diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java Thu Jun 21 16:36:37 2012 +0200 @@ -137,13 +137,18 @@ Value base = operand(object); Value index = Value.IllegalValue; int scale = 1; - long displacement = location.displacement(); + int displacement = location.displacement(); if (isConstant(base)) { - if (!asConstant(base).isNull()) { - displacement += asConstant(base).asLong(); + if (asConstant(base).isNull()) { + base = Value.IllegalValue; + } else if (asConstant(base).kind != Kind.Object) { + long newDisplacement = displacement + asConstant(base).asLong(); + if (NumUtil.isInt(newDisplacement)) { + displacement = (int) newDisplacement; + base = Value.IllegalValue; + } } - base = Value.IllegalValue; } if (location instanceof IndexedLocationNode) { @@ -157,7 +162,7 @@ long newDisplacement = displacement + asConstant(index).asLong() * scale; // only use the constant index if the resulting displacement fits into a 32 bit offset if (NumUtil.isInt(newDisplacement)) { - displacement = newDisplacement; + displacement = (int) newDisplacement; index = Value.IllegalValue; } else { // create a temporary variable for the index, the pointer load cannot handle a constant index @@ -168,7 +173,7 @@ } } - return new Address(location.getValueKind(), base, index, Address.Scale.fromInt(scale), (int) displacement); + return new Address(location.getValueKind(), base, index, Address.Scale.fromInt(scale), displacement); } @Override diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctFilteredNodeIterable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/DistinctFilteredNodeIterable.java Thu Jun 21 16:36:37 2012 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph.iterators; + +import java.util.*; + +import com.oracle.graal.graph.*; + + +public class DistinctFilteredNodeIterable extends FilteredNodeIterable { + + public DistinctFilteredNodeIterable(NodeIterable nodeIterable) { + super(nodeIterable); + } + + @Override + public DistinctFilteredNodeIterable distinct() { + return this; + } + + @Override + public Iterator iterator() { + return new DistinctPredicatedProxyNodeIterator<>(until, nodeIterable.iterator(), predicate); + } +} diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java Thu Jun 21 16:36:37 2012 +0200 @@ -27,10 +27,9 @@ import com.oracle.graal.graph.*; public class FilteredNodeIterable extends AbstractNodeIterable { - private final NodeIterable nodeIterable; - private NodePredicate predicate = NodePredicates.alwaysTrue(); - private NodePredicate until = NodePredicates.isNull(); - private boolean distinct; + protected final NodeIterable nodeIterable; + protected NodePredicate predicate = NodePredicates.alwaysTrue(); + protected NodePredicate until = NodePredicates.isNull(); public FilteredNodeIterable(NodeIterable nodeIterable) { this.nodeIterable = nodeIterable; } @@ -58,18 +57,15 @@ return this; } @Override - public FilteredNodeIterable distinct() { - distinct = true; - return this; + public DistinctFilteredNodeIterable distinct() { + DistinctFilteredNodeIterable distinct = new DistinctFilteredNodeIterable<>(nodeIterable); + distinct.predicate = predicate; + distinct.until = until; + return distinct; } @Override public Iterator iterator() { - final Iterator iterator = nodeIterable.iterator(); - if (distinct) { - return new DistinctPredicatedProxyNodeIterator<>(until, iterator, predicate); - } else { - return new PredicatedProxyNodeIterator<>(until, iterator, predicate); - } + return new PredicatedProxyNodeIterator<>(until, nodeIterable.iterator(), predicate); } @SuppressWarnings("unchecked") diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Thu Jun 21 16:36:37 2012 +0200 @@ -34,7 +34,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.phases.*; import com.oracle.graal.cri.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; @@ -385,7 +384,6 @@ SnippetTemplate template = cache.get(key); Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, arguments); template.instantiate(runtime, checkcast, checkcast, arguments); - new DeadCodeEliminationPhase().apply(graph); } private static HotSpotKlassOop[] createHints(TypeCheckHints hints) { diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Thu Jun 21 16:36:37 2012 +0200 @@ -201,7 +201,6 @@ SnippetTemplate template = cache.get(key); Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); template.instantiate(runtime, tlabAllocateNode, tlabAllocateNode, arguments); - new DeadCodeEliminationPhase().apply(graph); } @SuppressWarnings("unused") @@ -219,7 +218,6 @@ SnippetTemplate template = cache.get(key); Debug.log("Lowering initialize in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); template.instantiate(runtime, initializeNode, initializeNode, arguments); - new DeadCodeEliminationPhase().apply(graph); } } } diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java Thu Jun 21 16:36:37 2012 +0200 @@ -392,10 +392,13 @@ @Override public void applyToNonVirtual(NodeClosure< ? super ValueNode> closure) { for (ValueNode value : values.nonNull()) { - closure.apply(value); + closure.apply(this, value); } for (VirtualObjectState state : virtualObjectMappings) { state.applyToNonVirtual(closure); } + if (outerFrameState() != null) { + outerFrameState().applyToNonVirtual(closure); + } } } diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Thu Jun 21 16:36:37 2012 +0200 @@ -173,7 +173,7 @@ } public boolean hasLoops() { - return getNodes(LoopBeginNode.class).iterator().hasNext(); + return getNodes(LoopBeginNode.class).isNotEmpty(); } public void removeFloating(FloatingNode node) { diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/VirtualState.java Thu Jun 21 16:36:37 2012 +0200 @@ -31,7 +31,7 @@ public abstract class VirtualState extends Node { public interface NodeClosure { - void apply(T node); + void apply(Node usage, T node); } public abstract VirtualState duplicateWithVirtualState(); diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Thu Jun 21 16:36:37 2012 +0200 @@ -77,6 +77,9 @@ } else if (x().integerStamp().lowerBound() >= y().integerStamp().upperBound()) { return ConstantNode.forBoolean(false, graph()); } + if (x().integerStamp().lowerBound() >= 0 && y().integerStamp().lowerBound() >= 0) { + return graph().unique(new IntegerBelowThanNode(x(), y())); + } return super.canonical(tool); } } diff -r 17639f600cda -r 494332f39ee8 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 Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Thu Jun 21 16:36:37 2012 +0200 @@ -69,8 +69,8 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { Constant constantIndex = index.asConstant(); - if (constantIndex != null && constantIndex.kind.stackKind().isInt()) { - long constantIndexLong = constantIndex.asInt(); + if (constantIndex != null) { + long constantIndexLong = constantIndex.asLong(); if (indexScalingEnabled) { if (tool.target() == null) { return this; diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectState.java Thu Jun 21 16:36:37 2012 +0200 @@ -69,7 +69,7 @@ @Override public void applyToNonVirtual(NodeClosure< ? super ValueNode> closure) { for (ValueNode value : fieldValues) { - closure.apply(value); + closure.apply(this, value); } } } diff -r 17639f600cda -r 494332f39ee8 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Thu Jun 21 10:52:23 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Thu Jun 21 16:36:37 2012 +0200 @@ -458,7 +458,10 @@ if (replacee instanceof FixedNode) { GraphUtil.killCFG((FixedNode) replacee); } else { - replacee.safeDelete(); + GraphUtil.killWithUnusedFloatingInputs(replacee); + } + if (anchor != replacee) { + GraphUtil.killCFG(anchor); } Debug.dump(replaceeGraph, "After lowering %s with %s", replacee, this);