changeset 7690:afa802ff433c

better computation of inlining relevance fix for removing interpreter api
author Christian Haeubl <haeubl@ssw.jku.at>
date Mon, 04 Feb 2013 13:43:36 +0100
parents ed51e7237e94
children 014092acf009
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java src/share/vm/runtime/arguments.cpp
diffstat 3 files changed, 67 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Mon Feb 04 10:53:24 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java	Mon Feb 04 13:43:36 2013 +0100
@@ -275,6 +275,7 @@
     }
 
     private class PropagateLoopFrequency extends PostOrderNodeIterator<LoopCount> {
+
         public PropagateLoopFrequency(FixedNode start) {
             super(start, new LoopCount(1d));
         }
@@ -287,6 +288,7 @@
     }
 
     private static class ComputeInliningRelevanceIterator extends ScopedPostOrderNodeIterator {
+
         private final HashMap<FixedNode, Scope> scopes;
         private double currentProbability;
         private double parentRelevance;
@@ -307,13 +309,13 @@
             if (scope.start instanceof LoopBeginNode) {
                 assert scope.parent != null;
                 double parentProbability = 0;
-                for (EndNode end: ((LoopBeginNode) scope.start).forwardEnds()) {
+                for (EndNode end : ((LoopBeginNode) scope.start).forwardEnds()) {
                     parentProbability += end.probability();
                 }
                 return parentProbability / scope.parent.minPathProbability;
             } else {
-               assert scope.parent == null;
-               return 1.0;
+                assert scope.parent == null;
+                return 1.0;
             }
         }
 
@@ -354,7 +356,7 @@
         private static HashMap<FixedNode, Scope> computeLowestPathProbabilities(Scope[] scopes) {
             HashMap<FixedNode, Scope> result = new HashMap<>();
 
-            for (Scope scope: scopes) {
+            for (Scope scope : scopes) {
                 double lowestPathProbability = computeLowestPathProbability(scope);
                 scope.minPathProbability = Math.max(EPSILON, lowestPathProbability);
                 result.put(scope.start, scope);
@@ -365,66 +367,86 @@
 
         private static double computeLowestPathProbability(Scope scope) {
             FixedNode scopeStart = scope.start;
-            Node current = scopeStart;
+            ArrayList<FixedNode> pathBeginNodes = new ArrayList<>();
+            pathBeginNodes.add(scopeStart);
             double minPathProbability = scopeStart.probability();
             boolean isLoopScope = scopeStart instanceof LoopBeginNode;
 
-            while (current != null) {
-                if (isLoopScope && current instanceof LoopExitNode && ((LoopBeginNode) scopeStart).loopExits().contains((LoopExitNode) current)) {
-                    return minPathProbability;
-                } else if (current instanceof LoopBeginNode && current != scopeStart) {
-                    current = getMaxProbabilityLoopExit((LoopBeginNode) current);
-                    if (((FixedNode) current).probability() < minPathProbability) {
-                        minPathProbability = ((FixedNode) current).probability();
+            do {
+                Node current = pathBeginNodes.remove(pathBeginNodes.size() - 1);
+                do {
+                    if (isLoopScope && current instanceof LoopExitNode && ((LoopBeginNode) scopeStart).loopExits().contains((LoopExitNode) current)) {
+                        return minPathProbability;
+                    } else if (current instanceof LoopBeginNode && current != scopeStart) {
+                        current = getMaxProbabilityLoopExit((LoopBeginNode) current, pathBeginNodes);
+                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
+                    } else if (current instanceof ControlSplitNode) {
+                        current = getMaxProbabilitySux((ControlSplitNode) current, pathBeginNodes);
+                        minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability);
+                    } else {
+                        assert current.successors().count() <= 1;
+                        current = current.successors().first();
                     }
-                } else if (current instanceof ControlSplitNode) {
-                    current = getMaxProbabilitySux((ControlSplitNode) current);
-                    if (((FixedNode) current).probability() < minPathProbability) {
-                        minPathProbability = ((FixedNode) current).probability();
-                    }
-                } else {
-                    assert current.successors().count() <= 1;
-                    current = current.successors().first();
-                }
-            }
+                } while (current != null);
+            } while (!pathBeginNodes.isEmpty());
 
             return minPathProbability;
         }
 
-        private static Node getMaxProbabilitySux(ControlSplitNode controlSplit) {
+        private static double getMinPathProbability(FixedNode current, double minPathProbability) {
+            if (current.probability() < minPathProbability) {
+                return current.probability();
+            }
+            return minPathProbability;
+        }
+
+        private static Node getMaxProbabilitySux(ControlSplitNode controlSplit, ArrayList<FixedNode> pathBeginNodes) {
             Node maxSux = null;
             double maxProbability = 0.0;
+            int pathBeginCount = pathBeginNodes.size();
 
-            // TODO (chaeubl): process recursively if we have multiple successors with same probability
             for (Node sux : controlSplit.successors()) {
                 double probability = controlSplit.probability((BeginNode) sux);
                 if (probability > maxProbability) {
                     maxProbability = probability;
                     maxSux = sux;
+                    truncate(pathBeginNodes, pathBeginCount);
+                } else if (probability == maxProbability) {
+                    pathBeginNodes.add((FixedNode) sux);
                 }
             }
 
             return maxSux;
         }
 
-        private static Node getMaxProbabilityLoopExit(LoopBeginNode loopBegin) {
+        private static Node getMaxProbabilityLoopExit(LoopBeginNode loopBegin, ArrayList<FixedNode> pathBeginNodes) {
             Node maxSux = null;
             double maxProbability = 0.0;
+            int pathBeginCount = pathBeginNodes.size();
 
-            // TODO (chaeubl): process recursively if we have multiple successors with same probability
-            for (LoopExitNode sux: loopBegin.loopExits()) {
+            for (LoopExitNode sux : loopBegin.loopExits()) {
                 double probability = sux.probability();
                 if (probability > maxProbability) {
                     maxProbability = probability;
                     maxSux = sux;
+                    truncate(pathBeginNodes, pathBeginCount);
+                } else if (probability == maxProbability) {
+                    pathBeginNodes.add(sux);
                 }
             }
 
             return maxSux;
         }
+
+        public static void truncate(ArrayList<FixedNode> pathBeginNodes, int pathBeginCount) {
+            for (int i = pathBeginNodes.size() - pathBeginCount; i > 0; i--) {
+                pathBeginNodes.remove(pathBeginNodes.size() - 1);
+            }
+        }
     }
 
     private static class Scope {
+
         public final FixedNode start;
         public final Scope parent;
         public double minPathProbability;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Feb 04 10:53:24 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java	Mon Feb 04 13:43:36 2013 +0100
@@ -191,10 +191,12 @@
 // return compilationComplexity(info) < maxSize;
 
             assert GraalOptions.ProbabilityAnalysis;
-            // TODO (chaeubl): invoked methods that are on important paths but not yet compiled ->
-// will be compiled anyways and it is likely that we are the only caller...
-            // might be useful to inline those methods but increases bootstrap time (maybe those
-// methods are also getting queued in the compilation queue concurrently)
+            /*
+             * TODO (chaeubl): invoked methods that are on important paths but not yet compiled ->
+             * will be compiled anyways and it is likely that we are the only caller... might be
+             * useful to inline those methods but increases bootstrap time (maybe those methods are
+             * also getting queued in the compilation queue concurrently)
+             */
 
             if (GraalOptions.AlwaysInlineIntrinsics && onlyIntrinsics(info)) {
                 return InliningUtil.logInlinedMethod(info, "intrinsic");
@@ -205,8 +207,10 @@
             int compiledCodeSize = compiledCodeSize(info);
             double relevance = info.invoke().inliningRelevance();
 
-            // as long as the compiled code size is small enough (or the method was not yet
-// compiled), we can do a pretty general inlining that suits most situations
+            /*
+             * as long as the compiled code size is small enough (or the method was not yet
+             * compiled), we can do a pretty general inlining that suits most situations
+             */
             if (compiledCodeSize < GraalOptions.SmallCompiledCodeSize) {
                 if (isTrivialInlining(bytecodeSize, complexity, compiledCodeSize)) {
                     return InliningUtil.logInlinedMethod(info, "trivial (bytecodes=%d, complexity=%d, codeSize=%d)", bytecodeSize, complexity, compiledCodeSize);
@@ -217,8 +221,10 @@
                 }
             }
 
-            // the normal inlining did not fit this invoke, so check if we have any reason why we
-// should still do the inlining
+            /*
+             * the normal inlining did not fit this invoke, so check if we have any reason why we
+             * should still do the inlining
+             */
             double probability = info.invoke().probability();
             int transferredValues = numberOfTransferredValues(info);
             int invokeUsages = countInvokeUsages(info);
@@ -281,8 +287,10 @@
         }
 
         private int countMoreSpecificArgumentInfo(InlineInfo info) {
-            // inlining invokes where the caller has very specific information about the passed
-// argument simplifies the callee
+            /*
+             * inlining invokes where the caller has very specific information about the passed
+             * argument simplifies the callee
+             */
             int moreSpecificArgumentInfo = 0;
             boolean isStatic = info.invoke().methodCallTarget().isStatic();
             int signatureOffset = isStatic ? 0 : 1;
--- a/src/share/vm/runtime/arguments.cpp	Mon Feb 04 10:53:24 2013 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Mon Feb 04 13:43:36 2013 +0100
@@ -2270,7 +2270,6 @@
           "com.oracle.graal.api.runtime",
           "com.oracle.graal.api.meta",
           "com.oracle.graal.api.code",
-          "com.oracle.graal.api.interpreter",
           "com.oracle.graal.hotspot",
           "com.oracle.graal.asm",
           "com.oracle.graal.alloc",