changeset 16071:8d0202b354fb

[inliner] de-duplicate parameters for callsites with duplicate arguments
author Miguel Garcia <miguel.m.garcia@oracle.com>
date Tue, 10 Jun 2014 15:35:32 +0200
parents fa04403d1cb5
children b6ab7e7fa0a5
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java
diffstat 1 files changed, 44 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java	Sat Jun 07 14:23:10 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java	Tue Jun 10 15:35:32 2014 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
 import com.oracle.graal.phases.common.DeadCodeEliminationPhase;
+import com.oracle.graal.phases.common.cfs.FlowUtil;
 import com.oracle.graal.phases.common.inlining.InliningUtil;
 import com.oracle.graal.phases.tiers.HighTierContext;
 
@@ -87,6 +88,7 @@
         try (Debug.Scope s = Debug.scope("InlineGraph", graph)) {
 
             ArrayList<Node> parameterUsages = replaceParamsWithMoreInformativeArguments(invoke, context);
+            parameterUsages = rewireParamsForDuplicateArguments(invoke, parameterUsages);
             if (parameterUsages != null && OptCanonicalizer.getValue()) {
                 assert !parameterUsages.isEmpty() : "The caller didn't have more information about arguments after all";
                 canonicalizer.applyIncremental(graph, context, parameterUsages);
@@ -103,6 +105,48 @@
         }
     }
 
+    /**
+     * This method detects duplicate arguments (therefore corresponding to different
+     * {@link ParameterNode}s) and updates the graph to make all of their usages refer to the first
+     * one of them.
+     *
+     * @return a (possibly updated) list of nodes for incremental canonicalization.
+     */
+    private ArrayList<Node> rewireParamsForDuplicateArguments(Invoke invoke, ArrayList<Node> parameterUsages0) {
+        ArrayList<Node> parameterUsages = parameterUsages0;
+        ArrayList<ParameterNode> params = new ArrayList<>();
+        List<ValueNode> originalArgs = invoke.callTarget().arguments();
+        List<ValueNode> argsInEffect = new ArrayList<>();
+        // some param-nodes might have been deleted by replaceParamsWithMoreInformativeArguments()
+        // that's why we obtain an up-to-date list
+        for (ParameterNode p : graph.getNodes(ParameterNode.class)) {
+            if (!FlowUtil.lacksUsages(p)) {
+                params.add(p);
+                argsInEffect.add(originalArgs.get(p.index()));
+            }
+        }
+        // argsInEffect and params paired by position
+        assert params.size() == argsInEffect.size();
+        int argIdx = 0;
+        for (ValueNode arg : argsInEffect) {
+            int firstOccurrrence = argsInEffect.indexOf(arg);
+            assert firstOccurrrence >= 0;
+            if (firstOccurrrence < argIdx) {
+                ParameterNode survivingParam = params.get(firstOccurrrence);
+                assert survivingParam.isAlive();
+                ParameterNode duplicateParam = params.get(argIdx);
+                assert duplicateParam.isAlive();
+                assert survivingParam != duplicateParam;
+                assert !isArgMoreInformativeThanParam(arg, survivingParam);
+                parameterUsages = trackParameterUsages(duplicateParam, parameterUsages);
+                // replaceFloating() deletes the duplicate param, unlike replaceAtUsages()
+                graph.replaceFloating(duplicateParam, survivingParam);
+            }
+            argIdx++;
+        }
+        return parameterUsages;
+    }
+
     private static boolean isArgMoreInformativeThanParam(ValueNode arg, ParameterNode param) {
         return arg.isConstant() || canStampBeImproved(arg, param);
     }