Mercurial > hg > truffle
diff graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java @ 5005:c2ebd3d559f7
fixed probabilities when polymorphic inlining is used
author | Christian Haeubl <christian.haeubl@oracle.com> |
---|---|
date | Thu, 01 Mar 2012 15:18:32 -0800 |
parents | 5e6f1026a63e |
children | 836e4fce33ab |
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java Thu Mar 01 15:58:46 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/InliningUtil.java Thu Mar 01 15:18:32 2012 -0800 @@ -214,19 +214,19 @@ public final List<RiResolvedMethod> concretes; public final RiResolvedType[] types; public final int[] typesToConcretes; - public final double[] branchProbabilities; + public final double[] typeProbabilities; public final double notRecordedTypeProbability; public MultiTypeGuardInlineInfo(Invoke invoke, double weight, int level, List<RiResolvedMethod> concretes, RiResolvedType[] types, - int[] typesToConcretes, double[] branchProbabilities, double notRecordedTypeProbability) { + int[] typesToConcretes, double[] typeProbabilities, double notRecordedTypeProbability) { super(invoke, weight, level); assert concretes.size() > 0 && concretes.size() <= types.length : "must have at least one method but no more than types methods"; - assert types.length == typesToConcretes.length && types.length == branchProbabilities.length : "array length must match"; + assert types.length == typesToConcretes.length && types.length == typeProbabilities.length : "array length must match"; this.concretes = concretes; this.types = types; this.typesToConcretes = typesToConcretes; - this.branchProbabilities = branchProbabilities; + this.typeProbabilities = typeProbabilities; this.notRecordedTypeProbability = notRecordedTypeProbability; } @@ -291,14 +291,22 @@ // create one separate block for each invoked method BeginNode[] calleeEntryNodes = new BeginNode[numberOfMethods]; for (int i = 0; i < numberOfMethods; i++) { - int predecessors = getPredecessorCount(i); - calleeEntryNodes[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, predecessors, true); + int predecessors = 0; + double probability = 0; + for (int j = 0; j < typesToConcretes.length; j++) { + if (typesToConcretes[j] == i) { + predecessors++; + probability += typeProbabilities[j]; + } + } + + calleeEntryNodes[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, predecessors, invoke.probability() * probability, true); } // create the successor for an unknown type FixedNode unknownTypeNode; if (shouldFallbackToInvoke()) { - unknownTypeNode = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, 1, false); + unknownTypeNode = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, 1, notRecordedTypeProbability, false); } else { unknownTypeNode = graph.add(new DeoptimizeNode(DeoptAction.InvalidateReprofile)); } @@ -382,17 +390,19 @@ private FixedNode createDispatchOnType(StructuredGraph graph, ReadHubNode objectClassNode, BeginNode[] calleeEntryNodes, FixedNode unknownTypeSux) { assert types.length > 1; - // TODO (ch) set probabilities for all created fixed nodes... int lastIndex = types.length - 1; - FixedNode nextNode = createTypeCheck(graph, objectClassNode, types[lastIndex], calleeEntryNodes[typesToConcretes[lastIndex]], unknownTypeSux, branchProbabilities[lastIndex]); + double[] branchProbabilities = convertTypeToBranchProbabilities(typeProbabilities, notRecordedTypeProbability); + double nodeProbability = typeProbabilities[lastIndex]; + IfNode nextNode = createTypeCheck(graph, objectClassNode, types[lastIndex], calleeEntryNodes[typesToConcretes[lastIndex]], unknownTypeSux, branchProbabilities[lastIndex], invoke.probability() * nodeProbability); for (int i = lastIndex - 1; i >= 0; i--) { - nextNode = createTypeCheck(graph, objectClassNode, types[i], calleeEntryNodes[typesToConcretes[i]], nextNode, branchProbabilities[i]); + nodeProbability += typeProbabilities[i]; + nextNode = createTypeCheck(graph, objectClassNode, types[i], calleeEntryNodes[typesToConcretes[i]], nextNode, branchProbabilities[i], invoke.probability() * nodeProbability); } return nextNode; } - private static FixedNode createTypeCheck(StructuredGraph graph, ReadHubNode objectClassNode, RiResolvedType type, BeginNode tsux, FixedNode nextNode, double tsuxProbability) { + private static IfNode createTypeCheck(StructuredGraph graph, ReadHubNode objectClassNode, RiResolvedType type, BeginNode tsux, FixedNode nextNode, double tsuxProbability, double probability) { IfNode result; IsTypeNode isTypeNode = graph.unique(new IsTypeNode(objectClassNode, type)); if (tsux instanceof MergeNode) { @@ -402,45 +412,46 @@ } else { result = graph.add(new IfNode(isTypeNode, tsux, nextNode, tsuxProbability)); } + result.setProbability(probability); return result; } - private int getPredecessorCount(int concreteMethodIndex) { - if (concretes.size() == types.length) { - return 1; - } else { - int count = 0; - for (int i = 0; i < typesToConcretes.length; i++) { - if (typesToConcretes[i] == concreteMethodIndex) { - count++; - } - } - return count; + private static double[] convertTypeToBranchProbabilities(double[] typeProbabilities, double notRecordedTypeProbability) { + double[] result = new double[typeProbabilities.length]; + double total = notRecordedTypeProbability; + for (int i = typeProbabilities.length - 1; i >= 0; i--) { + total += typeProbabilities[i]; + result[i] = typeProbabilities[i] / total; } + assert total > 0.99 && total < 1.01; + return result; } private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, - MergeNode exceptionMerge, PhiNode exceptionObjectPhi, int predecessors, boolean useForInlining) { - Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining); - // TODO (ch) set probabilities + MergeNode exceptionMerge, PhiNode exceptionObjectPhi, int predecessors, double probability, boolean useForInlining) { + Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining, probability); BeginNode calleeEntryNode = graph.add(predecessors > 1 ? new MergeNode() : new BeginNode()); calleeEntryNode.setNext(duplicatedInvoke.node()); + calleeEntryNode.setProbability(probability); EndNode endNode = graph.add(new EndNode()); - // TODO (ch) set probability + endNode.setProbability(probability); + duplicatedInvoke.setNext(endNode); returnMerge.addForwardEnd(endNode); + if (returnValuePhi != null) { returnValuePhi.addInput(duplicatedInvoke.node()); } return calleeEntryNode; } - private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining) { + private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining, double probability) { Invoke result = (Invoke) invoke.node().copyWithInputs(); Node callTarget = result.callTarget().copyWithInputs(); result.node().replaceFirstInput(result.callTarget(), callTarget); result.setUseForInlining(useForInlining); + result.setProbability(probability); CiKind kind = invoke.node().kind(); if (!kind.isVoid()) { @@ -644,7 +655,6 @@ } if (canInline) { - convertTypeToBranchProbabilities(probabilities, notRecordedTypeProbability); return new MultiTypeGuardInlineInfo(invoke, totalWeight, level, concreteMethods, types, typesToConcretes, probabilities, notRecordedTypeProbability); } else { Debug.log("not inlining %s because it is a polymorphic method call and at least one invoked method cannot be inlined", methodName(targetMethod, invoke)); @@ -672,17 +682,6 @@ return checkCast; } - private static void convertTypeToBranchProbabilities(double[] typeProbabilities, double notRecordedTypeProbability) { - // avoid branches with 0.0/1.0 probability - double total = Math.max(1E-10, notRecordedTypeProbability); - - for (int i = typeProbabilities.length - 1; i >= 0; i--) { - total += typeProbabilities[i]; - typeProbabilities[i] = typeProbabilities[i] / total; - } - assert total > 0.99 && total < 1.01; - } - private static boolean checkInvokeConditions(Invoke invoke) { if (invoke.stateAfter() == null) { Debug.log("not inlining %s because the invoke has no after state", methodName(invoke.callTarget().targetMethod(), invoke));