# HG changeset patch # User Miguel Garcia # Date 1402407332 -7200 # Node ID 8d0202b354fb91c05dca9b62111e71c28913078b # Parent fa04403d1cb56a78a87ada2a063aa956108de209 [inliner] de-duplicate parameters for callsites with duplicate arguments diff -r fa04403d1cb5 -r 8d0202b354fb graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java --- 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 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 rewireParamsForDuplicateArguments(Invoke invoke, ArrayList parameterUsages0) { + ArrayList parameterUsages = parameterUsages0; + ArrayList params = new ArrayList<>(); + List originalArgs = invoke.callTarget().arguments(); + List 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); }