# HG changeset patch # User Lukas Stadler # Date 1308324635 -7200 # Node ID 681a227c332b676f68148a6e7f275c222fda4355 # Parent 5ee0f57bb18cfb586fa76b02d702f91735f5cbc9 better inlining logic, DCE removes If with constant comparison diff -r 5ee0f57bb18c -r 681a227c332b graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java Fri Jun 17 14:58:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java Fri Jun 17 17:30:35 2011 +0200 @@ -162,6 +162,7 @@ */ public Boolean foldCondition(CiConstant lt, CiConstant rt, RiRuntime runtime) { switch (lt.kind) { + case Boolean: case Int: { int x = lt.asInt(); int y = rt.asInt(); diff -r 5ee0f57bb18c -r 681a227c332b graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Fri Jun 17 14:58:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java Fri Jun 17 17:30:35 2011 +0200 @@ -29,6 +29,7 @@ import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; public class DeadCodeEliminationPhase extends Phase { @@ -46,8 +47,25 @@ // remove chained Merges for (Merge merge : graph.getNodes(Merge.class)) { if (merge.endCount() == 1 && merge.usages().size() == 0 && !(merge instanceof LoopEnd) && !(merge instanceof LoopBegin)) { - merge.endAt(0).replace(merge.next()); + FixedNode next = merge.next(); + EndNode endNode = merge.endAt(0); merge.delete(); + endNode.replace(next); + } + } + // remove if nodes with constant-value comparison + for (If ifNode : graph.getNodes(If.class)) { + Compare compare = ifNode.compare(); + if (compare.x().isConstant() && compare.y().isConstant()) { + CiConstant constX = compare.x().asConstant(); + CiConstant constY = compare.y().asConstant(); + Boolean result = compare.condition().foldCondition(constX, constY, GraalCompilation.compilation().runtime); + if (result != null) { + Node actualSuccessor = result ? ifNode.trueSuccessor() : ifNode.falseSuccessor(); + ifNode.replace(actualSuccessor); + } else { + TTY.println("if not removed %s %s %s (%s %s)", constX, compare.condition(), constY, constX.kind, constY.kind); + } } } diff -r 5ee0f57bb18c -r 681a227c332b graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Jun 17 14:58:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java Fri Jun 17 17:30:35 2011 +0200 @@ -66,44 +66,47 @@ inliningSize = compilation.method.codeSize(); for (int iterations = 0; iterations < GraalOptions.MaximumInlineLevel; iterations++) { for (Invoke invoke : graph.getNodes(Invoke.class)) { - RiTypeProfile profile = compilation.method.typeProfile(invoke.bci); - if (!checkInliningConditions(invoke)) { + RiMethod parent = parentMethod.get(invoke); + if (parent == null) { + parent = compilation.method; + } + RiTypeProfile profile = parent.typeProfile(invoke.bci); + if (!checkInvokeConditions(invoke)) { continue; } if (invoke.target.canBeStaticallyBound()) { - if (checkInliningConditions(invoke.target, iterations, invoke, profile, ratio)) { + if (checkTargetConditions(invoke.target, iterations) && checkSizeConditions(invoke.target, invoke, profile, ratio)) { addToQueue(invoke, invoke.target); } } else { RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target); - if (concrete != null && concrete.isResolved() && checkInliningConditions(concrete, iterations, invoke, profile, ratio)) { - if (trace) { - String targetName = CiUtil.format("%H.%n(%p):%r", invoke.target, false); - String concreteName = CiUtil.format("%H.%n(%p):%r", concrete, false); - TTY.println("recording concrete method assumption: %s -> %s", targetName, concreteName); - } - compilation.assumptions.recordConcreteMethod(invoke.target, concrete); - addToQueue(invoke, concrete); - } else if (profile != null && profile.probabilities != null && profile.probabilities.length > 0 && profile.morphism == 1) { - if (!GraalOptions.InlineWithTypeCheck) { - continue; + if (concrete != null) { + if (checkTargetConditions(concrete, iterations) && checkSizeConditions(concrete, invoke, profile, ratio)) { + if (trace) { + String targetName = CiUtil.format("%H.%n(%p):%r", invoke.target, false); + String concreteName = CiUtil.format("%H.%n(%p):%r", concrete, false); + TTY.println("recording concrete method assumption: %s -> %s", targetName, concreteName); + } + compilation.assumptions.recordConcreteMethod(invoke.target, concrete); + addToQueue(invoke, concrete); } - // type check and inlining... - concrete = profile.types[0].resolveMethodImpl(invoke.target); - if (concrete != null && concrete.isResolved() && checkInliningConditions(concrete, iterations, invoke, profile, ratio)) { - IsType isType = new IsType(invoke.receiver(), profile.types[0], compilation.graph); - FixedGuard guard = new FixedGuard(graph); - guard.setNode(isType); - assert invoke.predecessors().size() == 1; - invoke.predecessors().get(0).successors().replace(invoke, guard); - guard.setNext(invoke); + } else if (profile != null && profile.probabilities != null && profile.probabilities.length > 0 && profile.morphism == 1) { + if (GraalOptions.InlineWithTypeCheck) { + // type check and inlining... + concrete = profile.types[0].resolveMethodImpl(invoke.target); + if (concrete != null && checkTargetConditions(concrete, iterations) && checkSizeConditions(concrete, invoke, profile, ratio)) { + IsType isType = new IsType(invoke.receiver(), profile.types[0], compilation.graph); + FixedGuard guard = new FixedGuard(graph); + guard.setNode(isType); + assert invoke.predecessors().size() == 1; + invoke.predecessors().get(0).successors().replace(invoke, guard); + guard.setNext(invoke); - if (trace) { - TTY.println("inlining with type check, type probability: %5.3f", profile.probabilities[0]); + if (trace) { + TTY.println("inlining with type check, type probability: %5.3f", profile.probabilities[0]); + } + addToQueue(invoke, concrete); } - addToQueue(invoke, concrete); -// System.out.println("inlining with type check " + profile.probabilities[0] + " " + profile.morphism + " " + profile.count); -// System.out.println(invoke.target + " -> " + concrete + " (" + profile.types[0] + ")"); } } } @@ -153,67 +156,100 @@ } } - private boolean checkInliningConditions(Invoke invoke) { - String name = !trace ? null : invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false); + private String methodName(RiMethod method) { + return CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.codeSize() + " bytes)"; + } + private String methodName(RiMethod method, Invoke invoke) { + if (invoke != null) { + RiMethod parent = parentMethod.get(invoke); + if (parent == null) { + parent = compilation.method; + } + return parent.name() + "@" + invoke.bci + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.codeSize() + " bytes)"; + } else { + return CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.codeSize() + " bytes)"; + } + } + + private boolean checkInvokeConditions(Invoke invoke) { if (invoke.stateAfter() == null) { if (trace) { - TTY.println("not inlining %s because the invoke has no after state", name); + TTY.println("not inlining %s because the invoke has no after state", methodName(invoke.target, invoke)); } return false; } if (invoke.stateAfter().locksSize() > 0) { if (trace) { - TTY.println("not inlining %s because of locks", name); + TTY.println("not inlining %s because of locks", methodName(invoke.target, invoke)); } return false; } if (!invoke.target.isResolved()) { if (trace) { - TTY.println("not inlining %s because the invoke target is unresolved", name); + TTY.println("not inlining %s because the invoke target is unresolved", methodName(invoke.target, invoke)); } return false; } if (invoke.predecessors().size() == 0) { if (trace) { - TTY.println("not inlining %s because the invoke is dead code", name); + TTY.println("not inlining %s because the invoke is dead code", methodName(invoke.target, invoke)); } return false; } if (invoke.stateAfter() == null) { if (trace) { - TTY.println("not inlining %s because of missing frame state", name); + TTY.println("not inlining %s because of missing frame state", methodName(invoke.target, invoke)); } } return true; } - private boolean checkInliningConditions(RiMethod method, int iterations, Invoke invoke, RiTypeProfile profile, float adjustedRatio) { - String name = !trace ? null : CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.codeSize() + " bytes)"; + private boolean checkTargetConditions(RiMethod method, int iterations) { + if (!method.isResolved()) { + if (trace) { + TTY.println("not inlining %s because it is unresolved", methodName(method)); + } + return false; + } if (Modifier.isNative(method.accessFlags())) { if (trace) { - TTY.println("not inlining %s because it is a native method", name); + TTY.println("not inlining %s because it is a native method", methodName(method)); } return false; } if (Modifier.isAbstract(method.accessFlags())) { if (trace) { - TTY.println("not inlining %s because it is an abstract method", name); + TTY.println("not inlining %s because it is an abstract method", methodName(method)); } return false; } if (!method.holder().isInitialized()) { if (trace) { - TTY.println("not inlining %s because of non-initialized class", name); + TTY.println("not inlining %s because of non-initialized class", methodName(method)); } return false; } if (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel) { if (trace) { - TTY.println("not inlining %s because of recursive inlining limit", name); + TTY.println("not inlining %s because of recursive inlining limit", methodName(method)); } return false; } + return true; + } + + private boolean checkStaticSizeConditions(RiMethod method, Invoke invoke) { + if (method.codeSize() > GraalOptions.MaximumInlineSize) { + if (trace) { + TTY.println("not inlining %s because of code size (size: %d, max size: %d)", methodName(method, invoke), method.codeSize(), GraalOptions.MaximumInlineSize); + } + return false; + } + return true; + } + + private boolean checkSizeConditions(RiMethod method, Invoke invoke, RiTypeProfile profile, float adjustedRatio) { int maximumSize = GraalOptions.MaximumTrivialSize; float ratio = 0; if (profile != null && profile.count > 0) { @@ -230,15 +266,17 @@ } if (method.codeSize() > maximumSize) { if (trace) { - TTY.println("not inlining %s because of code size (size: %d, max size: %d, ratio %5.3f)", name, method.codeSize(), maximumSize, ratio); + TTY.println("not inlining %s because of code size (size: %d, max size: %d, ratio %5.3f, %s)", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile); } return false; } + if (trace) { + TTY.println("inlining %s (size: %d, max size: %d, ratio %5.3f, %s)", methodName(method, invoke), method.codeSize(), maximumSize, ratio, profile); + } return true; } private void inlineMethod(Invoke invoke, RiMethod method) { - String name = !trace ? null : invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.codeSize() + " bytes)"; FrameState stateAfter = invoke.stateAfter(); Instruction exceptionEdge = invoke.exceptionEdge(); @@ -246,12 +284,12 @@ Object stored = GraphBuilderPhase.cachedGraphs.get(method); if (stored != null) { if (trace) { - TTY.println("Reusing graph for %s, locals: %d, stack: %d", name, method.maxLocals(), method.maxStackSize()); + TTY.println("Reusing graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize()); } graph = (CompilerGraph) stored; } else { if (trace) { - TTY.println("Building graph for %s, locals: %d, stack: %d", name, method.maxLocals(), method.maxStackSize()); + TTY.println("Building graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize()); } graph = new CompilerGraph(null); new GraphBuilderPhase(compilation, method, true, true).apply(graph); @@ -299,7 +337,7 @@ } if (trace) { - TTY.println("inlining %s: %d frame states, %d nodes", name, frameStates.size(), nodes.size()); + TTY.println("inlining %s: %d frame states, %d nodes", methodName(method), frameStates.size(), nodes.size()); } assert invoke.successors().get(0) != null : invoke; diff -r 5ee0f57bb18c -r 681a227c332b graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java Fri Jun 17 14:58:03 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotMethodResolvedImpl.java Fri Jun 17 17:30:35 2011 +0200 @@ -24,6 +24,7 @@ import java.lang.reflect.*; +import com.oracle.max.graal.compiler.debug.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -202,4 +203,19 @@ public int branchProbability(int bci) { return compiler.getVMEntries().RiMethod_branchProbability(this, bci); } + + public void dumpProfile() { + TTY.println("profile info for %s", this); + TTY.println("canBeStaticallyBound: " + canBeStaticallyBound()); + TTY.println("invocationCount: " + invocationCount()); + for (int i = 0; i < codeSize(); i++) { + if (branchProbability(i) != -1) { + TTY.println("branchProbability@%d: %d", i, branchProbability(i)); + } + RiTypeProfile profile = typeProfile(i); + if (profile != null && profile.count > 0) { + TTY.println("profile@%d: count: %d, morphism: %d", i, profile.count, profile.morphism); + } + } + } } diff -r 5ee0f57bb18c -r 681a227c332b src/share/vm/graal/graalVMEntries.cpp --- a/src/share/vm/graal/graalVMEntries.cpp Fri Jun 17 14:58:03 2011 +0200 +++ b/src/share/vm/graal/graalVMEntries.cpp Fri Jun 17 17:30:35 2011 +0200 @@ -235,10 +235,10 @@ jfloat probability = -1; - if (!method_data->is_mature()) return -1; + if (method_data == NULL || !method_data->is_mature()) return -1; ciProfileData* data = method_data->bci_to_data(bci); - if (!data->is_JumpData()) return -1; + if (data == NULL || !data->is_JumpData()) return -1; // get taken and not taken values int taken = data->as_JumpData()->taken();