# HG changeset patch # User Christian Wimmer # Date 1429733136 25200 # Node ID 71af9afd7ff67d91518449fe101b0db79dafb47e # Parent 266eef1c29e049440b5cb0c7f6913dd6a4a7762f Test the GraphDecoder by encoding and decoding every graph after parsing; fix bugs found by that testing diff -r 266eef1c29e0 -r 71af9afd7ff6 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 Wed Apr 22 11:38:25 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Wed Apr 22 13:05:36 2015 -0700 @@ -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 266eef1c29e0 -r 71af9afd7ff6 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 Wed Apr 22 11:38:25 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Wed Apr 22 13:05:36 2015 -0700 @@ -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 266eef1c29e0 -r 71af9afd7ff6 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 Wed Apr 22 11:38:25 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Wed Apr 22 13:05:36 2015 -0700 @@ -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 266eef1c29e0 -r 71af9afd7ff6 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 Wed Apr 22 11:38:25 2015 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Wed Apr 22 13:05:36 2015 -0700 @@ -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) {