changeset 11749:a27fcd670725

SnippetTemplate: use FloatingReadPhase to store MemoryMap at ReturnNodes in order to connect the snippet graph properly when inlining it
author Bernhard Urban <bernhard.urban@jku.at>
date Sat, 21 Sep 2013 08:19:19 +0200
parents db8cf3957e5b
children bf7f09417f76
files graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java
diffstat 2 files changed, 70 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Thu Sep 19 21:53:20 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Sat Sep 21 08:19:19 2013 +0200
@@ -206,7 +206,7 @@
         }
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) {
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
@@ -238,7 +238,7 @@
         }
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) {
             assert newNode instanceof PhiNode;
             assert oldNode == instanceOf;
             newNode.inferStamp();
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Thu Sep 19 21:53:20 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Sat Sep 21 08:19:19 2013 +0200
@@ -34,7 +34,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.StructuredGraph.*;
+import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
@@ -532,13 +532,16 @@
         }
 
         new DeadCodeEliminationPhase().apply(snippetCopy);
+        new CanonicalizerPhase(true).apply(snippetCopy, context);
 
         assert checkAllVarargPlaceholdersAreDeleted(parameterCount, placeholders);
 
+        new FloatingReadPhase(false).apply(snippetCopy);
+        this.memoryMap = null;
+
         this.snippet = snippetCopy;
         ReturnNode retNode = null;
         StartNode entryPointNode = snippet.start();
-
         nodes = new ArrayList<>(snippet.getNodeCount());
         for (Node node : snippet.getNodes()) {
             if (node == entryPointNode || node == entryPointNode.stateAfter()) {
@@ -547,9 +550,15 @@
                 nodes.add(node);
                 if (node instanceof ReturnNode) {
                     retNode = (ReturnNode) node;
+                    for (MemoryState memstate : retNode.usages().filter(MemoryState.class).snapshot()) {
+                        this.memoryMap = memstate.getMemoryMap();
+                        memstate.safeDelete();
+                    }
+                    assert snippet.getNodes().filter(ReturnNode.class).count() == 1;
                 }
             }
         }
+        assert !containsMemoryState(snippet);
 
         this.sideEffectNodes = curSideEffectNodes;
         this.deoptNodes = curDeoptNodes;
@@ -560,6 +569,10 @@
         this.instantiationTimer = Debug.timer("SnippetInstantiationTime[" + method.getName() + "]");
     }
 
+    private static boolean containsMemoryState(StructuredGraph snippet) {
+        return snippet.getNodes().filter(MemoryState.class).count() > 0;
+    }
+
     private static boolean checkAllVarargPlaceholdersAreDeleted(int parameterCount, ConstantNode[] placeholders) {
         for (int i = 0; i < parameterCount; i++) {
             if (placeholders[i] != null) {
@@ -633,6 +646,11 @@
     private final ArrayList<Node> nodes;
 
     /**
+     * mapping of killing locations to memory checkpoints (nodes).
+     */
+    private MemoryMap memoryMap;
+
+    /**
      * Gets the instantiation-time bindings to this template's parameters.
      * 
      * @return the map that will be used to bind arguments to parameters when inlining this template
@@ -724,7 +742,7 @@
         /**
          * Replaces all usages of {@code oldNode} with direct or indirect usages of {@code newNode}.
          */
-        void replace(ValueNode oldNode, ValueNode newNode);
+        void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap);
     }
 
     /**
@@ -734,11 +752,51 @@
     public static final UsageReplacer DEFAULT_REPLACER = new UsageReplacer() {
 
         @Override
-        public void replace(ValueNode oldNode, ValueNode newNode) {
+        public void replace(ValueNode oldNode, ValueNode newNode, MemoryMap mmap) {
             oldNode.replaceAtUsages(newNode);
+            if (mmap == null || newNode == null) {
+                return;
+            }
+            for (Node usage : newNode.usages().snapshot()) {
+                if (usage instanceof FloatingReadNode && ((FloatingReadNode) usage).lastLocationAccess() == newNode) {
+                    // TODO: add graph state for FloatingReadPhase
+                    assert newNode.graph().getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal();
+
+                    // lastLocationAccess points into the snippet graph. find a proper
+                    // MemoryCheckPoint inside the snippet graph
+                    FloatingReadNode frn = (FloatingReadNode) usage;
+                    Node newlla = mmap.getLastLocationAccess(frn.location().getLocationIdentity());
+
+                    assert newlla != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)";
+                    frn.setLastLocationAccess(newlla);
+                }
+            }
         }
     };
 
+    private class DuplicateMapper implements MemoryMap {
+
+        Map<Node, Node> duplicates;
+        StartNode replaceeStart;
+
+        public DuplicateMapper(Map<Node, Node> duplicates, StartNode replaceeStart) {
+            this.duplicates = duplicates;
+            this.replaceeStart = replaceeStart;
+        }
+
+        @Override
+        public Node getLastLocationAccess(LocationIdentity locationIdentity) {
+            assert memoryMap != null : "no memory map stored for this snippet graph (snippet doesn't have a ReturnNode?)";
+            Node lastLocationAccess = memoryMap.getLastLocationAccess(locationIdentity);
+            assert lastLocationAccess != null;
+            if (lastLocationAccess instanceof StartNode) {
+                return replaceeStart;
+            } else {
+                return duplicates.get(lastLocationAccess);
+            }
+        }
+    }
+
     /**
      * Replaces a given fixed node with this specialized snippet.
      * 
@@ -756,6 +814,7 @@
             FixedNode firstCFGNode = entryPointNode.next();
             StructuredGraph replaceeGraph = replacee.graph();
             IdentityHashMap<Node, Node> replacements = bind(replaceeGraph, runtime, args);
+            replacements.put(entryPointNode, replaceeGraph.start());
             Map<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements);
             Debug.dump(replaceeGraph, "After inlining snippet %s", snippet.method());
 
@@ -801,12 +860,12 @@
                     returnValue = (ValueNode) duplicates.get(returnNode.result());
                 }
                 Node returnDuplicate = duplicates.get(returnNode);
+                MemoryMap mmap = new DuplicateMapper(duplicates, replaceeGraph.start());
                 if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
-                    replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor());
+                    replacer.replace(replacee, (ValueNode) returnDuplicate.predecessor(), mmap);
                 } else {
                     assert returnValue != null || replacee.usages().isEmpty() : this + " " + returnValue + " " + returnNode + " " + replacee.usages();
-                    replacer.replace(replacee, returnValue);
-
+                    replacer.replace(replacee, returnValue, mmap);
                 }
                 if (returnDuplicate.isAlive()) {
                     returnDuplicate.clearInputs();
@@ -850,6 +909,7 @@
             FixedNode firstCFGNode = entryPointNode.next();
             StructuredGraph replaceeGraph = replacee.graph();
             IdentityHashMap<Node, Node> replacements = bind(replaceeGraph, runtime, args);
+            replacements.put(entryPointNode, replaceeGraph.start());
             Map<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, snippet, snippet.getNodeCount(), replacements);
             Debug.dump(replaceeGraph, "After inlining snippet %s", snippetCopy.method());
 
@@ -881,7 +941,7 @@
                 returnValue = (ValueNode) duplicates.get(returnNode.result());
             }
             assert returnValue != null || replacee.usages().isEmpty();
-            replacer.replace(replacee, returnValue);
+            replacer.replace(replacee, returnValue, new DuplicateMapper(duplicates, replaceeGraph.start()));
 
             Node returnDuplicate = duplicates.get(returnNode);
             if (returnDuplicate.isAlive()) {