# HG changeset patch # User Thomas Wuerthinger # Date 1429789047 -7200 # Node ID 56668f0816f75a9eb4be16edf700598379e11251 # Parent a11325faa4d9aa0adb85ed451c9925d9195f6600# Parent 00b66fc966b1050f9451911ff6072aca5c272d5d Merge. diff -r a11325faa4d9 -r 56668f0816f7 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Thu Apr 23 13:37:11 2015 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Thu Apr 23 13:37:27 2015 +0200 @@ -402,7 +402,7 @@ } } - @MatchRule("(Write Narrow=narrow location value)") + @MatchRule("(Write object location Narrow=narrow)") public ComplexMatchResult writeNarrow(WriteNode root, NarrowNode narrow) { return builder -> { LIRKind writeKind = getLIRGeneratorTool().getLIRKind(root.value().stamp()); diff -r a11325faa4d9 -r 56668f0816f7 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/FrequencyEncoder.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/FrequencyEncoder.java Thu Apr 23 13:37:11 2015 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/util/FrequencyEncoder.java Thu Apr 23 13:37:27 2015 +0200 @@ -46,6 +46,7 @@ } protected final Map> map; + protected boolean containsNull; /** * Creates an encoder that uses object identity. @@ -69,17 +70,17 @@ * Adds an object to the array. */ public void addObject(T object) { + if (object == null) { + containsNull = true; + return; + } + Entry entry = map.get(object); if (entry == null) { entry = new Entry<>(object); map.put(object, entry); } - if (object == null) { - /* null must get index 0, so sort it up. */ - entry.frequency = Integer.MAX_VALUE; - } else { - entry.frequency++; - } + entry.frequency++; } /** @@ -87,6 +88,10 @@ * {@link #addObject(Object) added} before. */ public int getIndex(Object object) { + if (object == null) { + assert containsNull; + return 0; + } Entry entry = map.get(object); assert entry != null && entry.index >= 0; return entry.index; @@ -96,7 +101,7 @@ * Returns the number of distinct objects that have been added, i.e., the length of the array. */ public int getLength() { - return map.size(); + return map.size() + (containsNull ? 1 : 0); } /** @@ -104,14 +109,21 @@ * correct length}. */ public T[] encodeAll(T[] allObjects) { - assert allObjects.length == map.size(); + assert allObjects.length == getLength(); List> sortedEntries = new ArrayList<>(map.values()); sortedEntries.sort((e1, e2) -> -Integer.compare(e1.frequency, e2.frequency)); + + int offset = 0; + if (containsNull) { + allObjects[0] = null; + offset = 1; + } for (int i = 0; i < sortedEntries.size(); i++) { Entry entry = sortedEntries.get(i); - entry.index = i; - allObjects[i] = entry.object; - assert entry.object != null || entry.index == 0; + int index = i + offset; + entry.index = index; + allObjects[index] = entry.object; + assert entry.object != null; } return allObjects; } diff -r a11325faa4d9 -r 56668f0816f7 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Thu Apr 23 13:37:11 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Thu Apr 23 13:37:27 2015 +0200 @@ -31,6 +31,8 @@ import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; import com.oracle.graal.lir.phases.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.StructuredGraph.*; import com.oracle.graal.options.*; import com.oracle.graal.options.DerivedOptionValue.OptionSupplier; import com.oracle.graal.phases.*; @@ -104,10 +106,34 @@ PhaseSuite suite = new PhaseSuite<>(); GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins); suite.appendPhase(new GraphBuilderPhase(config)); + assert appendGraphEncoderTest(suite); return suite; } /** + * When assertions are enabled, we encode and decode every parsed graph, to ensure that the + * encoding and decoding process work correctly. The decoding performs canonicalization during + * decoding, so the decoded graph can be different than the encoded graph - we cannot check them + * for equality here. However, the encoder {@link GraphEncoder#verifyEncoding verifies the + * encoding itself}, i.e., performs a decoding without canoncialization and checks the graphs + * for equality. + */ + private boolean appendGraphEncoderTest(PhaseSuite suite) { + suite.appendPhase(new BasePhase() { + @Override + protected void run(StructuredGraph graph, HighTierContext context) { + EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); + + SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(context.getMetaAccess(), context.getConstantReflection(), context.getStampProvider(), !ImmutableCode.getValue(), + runtime.getTarget().arch); + StructuredGraph targetGraph = new StructuredGraph(graph.method(), AllowAssumptions.YES); + graphDecoder.decode(targetGraph, encodedGraph); + } + }); + return true; + } + + /** * Modifies the {@link GraphBuilderConfiguration} to build extra * {@linkplain DebugInfoMode#Simple debug info} if the VM * {@linkplain CompilerToVM#shouldDebugNonSafepoints() requests} it. diff -r a11325faa4d9 -r 56668f0816f7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Thu Apr 23 13:37:11 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Thu Apr 23 13:37:27 2015 +0200 @@ -303,7 +303,6 @@ */ FixedNode detectLoopsStart = startNode.predecessor() != null ? (FixedNode) startNode.predecessor() : startNode; cleanupGraph(methodScope, start); - Debug.dump(methodScope.graph, "Before loop detection"); detectLoops(methodScope.graph, detectLoopsStart); } } @@ -1020,7 +1019,6 @@ } } - Debug.dump(currentGraph, "After loops detected"); insertLoopEnds(currentGraph, startInstruction); } @@ -1145,7 +1143,6 @@ protected void cleanupGraph(MethodScope methodScope, Graph.Mark start) { assert verifyEdges(methodScope); - Debug.dump(methodScope.graph, "Before removing redundant merges"); for (Node node : methodScope.graph.getNewNodes(start)) { if (node instanceof MergeNode) { MergeNode mergeNode = (MergeNode) node; @@ -1155,7 +1152,6 @@ } } - Debug.dump(methodScope.graph, "Before removing redundant begins"); for (Node node : methodScope.graph.getNewNodes(start)) { if (node instanceof BeginNode || node instanceof KillingBeginNode) { if (!(node.predecessor() instanceof ControlSplitNode) && node.hasNoUsages()) { @@ -1165,7 +1161,6 @@ } } - Debug.dump(methodScope.graph, "Before removing unused non-fixed nodes"); for (Node node : methodScope.graph.getNewNodes(start)) { if (!(node instanceof FixedNode) && node.hasNoUsages()) { GraphUtil.killCFG(node); diff -r a11325faa4d9 -r 56668f0816f7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Thu Apr 23 13:37:11 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Thu Apr 23 13:37:27 2015 +0200 @@ -70,9 +70,11 @@ if (constant != null) { return constant; } - PhiNode phi = asPhi(metaAccess, constantReflection, forObject); - if (phi != null) { - return phi; + if (tool.allUsagesAvailable()) { + PhiNode phi = asPhi(metaAccess, constantReflection, forObject); + if (phi != null) { + return phi; + } } } if (!isStatic() && forObject.isNullConstant()) { diff -r a11325faa4d9 -r 56668f0816f7 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Thu Apr 23 13:37:11 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Thu Apr 23 13:37:27 2015 +0200 @@ -238,14 +238,28 @@ * */ public static void normalizeLoops(StructuredGraph graph) { + boolean loopRemoved = false; for (LoopBeginNode begin : graph.getNodes(LoopBeginNode.TYPE)) { if (begin.loopEnds().isEmpty()) { assert begin.forwardEndCount() == 1; graph.reduceDegenerateLoopBegin(begin); + loopRemoved = true; } else { normalizeLoopBegin(begin); } } + + if (loopRemoved) { + /* + * Removing a degenerated loop can make non-loop phi functions unnecessary. Therefore, + * we re-check all phi functions and remove redundant ones. + */ + for (Node node : graph.getNodes()) { + if (node instanceof PhiNode) { + checkRedundantPhi((PhiNode) node); + } + } + } } private static void normalizeLoopBegin(LoopBeginNode begin) {