changeset 10814:8b0c8fbbfa1c

make early read elimination work on read/write nodes (in addition to load/store)
author Lukas Stadler <lukas.stadler@jku.at>
date Thu, 18 Jul 2013 17:18:13 +0200
parents 3d6bd17da6e1
children 825d37fcdc9e f3697f17f671
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java
diffstat 3 files changed, 117 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Thu Jul 18 17:16:16 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Thu Jul 18 17:18:13 2013 +0200
@@ -29,6 +29,7 @@
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.virtual.phases.ea.*;
 
 public class MidTier extends PhaseSuite<MidTierContext> {
 
@@ -45,6 +46,10 @@
         appendPhase(new ValueAnchorCleanupPhase());
         appendPhase(new LockEliminationPhase());
 
+        if (OptReadElimination.getValue()) {
+            appendPhase(new EarlyReadEliminationPhase(canonicalizer));
+        }
+
         if (OptFloatingReads.getValue()) {
             IncrementalCanonicalizerPhase<MidTierContext> incCanonicalizer = new IncrementalCanonicalizerPhase<>();
             incCanonicalizer.appendPhase(new FloatingReadPhase());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Thu Jul 18 17:16:16 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Thu Jul 18 17:18:13 2013 +0200
@@ -26,21 +26,24 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 
 public class ReadEliminationBlockState extends EffectsBlockState<ReadEliminationBlockState> {
 
-    final HashMap<ReadCacheEntry, ValueNode> readCache;
+    final HashMap<CacheEntry<?>, ValueNode> readCache;
 
-    static class ReadCacheEntry {
+    abstract static class CacheEntry<T> {
 
-        public final ResolvedJavaField identity;
         public final ValueNode object;
+        public final T identity;
 
-        public ReadCacheEntry(ResolvedJavaField identity, ValueNode object) {
+        public CacheEntry(ValueNode object, T identity) {
+            this.object = object;
             this.identity = identity;
-            this.object = object;
         }
 
+        public abstract CacheEntry<T> duplicateWithObject(ValueNode newObject);
+
         @Override
         public int hashCode() {
             int result = 31 + ((identity == null) ? 0 : identity.hashCode());
@@ -49,7 +52,7 @@
 
         @Override
         public boolean equals(Object obj) {
-            ReadCacheEntry other = (ReadCacheEntry) obj;
+            CacheEntry<?> other = (CacheEntry<?>) obj;
             return identity == other.identity && object == other.object;
         }
 
@@ -57,6 +60,42 @@
         public String toString() {
             return object + ":" + identity;
         }
+
+        public abstract boolean conflicts(LocationIdentity other);
+    }
+
+    static class LoadCacheEntry extends CacheEntry<ResolvedJavaField> {
+
+        public LoadCacheEntry(ValueNode object, ResolvedJavaField identity) {
+            super(object, identity);
+        }
+
+        @Override
+        public CacheEntry<ResolvedJavaField> duplicateWithObject(ValueNode newObject) {
+            return new LoadCacheEntry(newObject, identity);
+        }
+
+        @Override
+        public boolean conflicts(LocationIdentity other) {
+            return identity == other;
+        }
+    }
+
+    static class ReadCacheEntry extends CacheEntry<LocationNode> {
+
+        public ReadCacheEntry(ValueNode object, LocationNode identity) {
+            super(object, identity);
+        }
+
+        @Override
+        public CacheEntry<LocationNode> duplicateWithObject(ValueNode newObject) {
+            return new ReadCacheEntry(newObject, identity);
+        }
+
+        @Override
+        public boolean conflicts(LocationIdentity other) {
+            return identity.getLocationIdentity() == other;
+        }
     }
 
     public ReadEliminationBlockState() {
@@ -81,29 +120,29 @@
         return super.equivalentTo(other);
     }
 
-    public void addReadCache(ValueNode object, ResolvedJavaField identity, ValueNode value) {
-        readCache.put(new ReadCacheEntry(identity, object), value);
+    public void addCacheEntry(CacheEntry<?> identifier, ValueNode value) {
+        readCache.put(identifier, value);
     }
 
-    public ValueNode getReadCache(ValueNode object, ResolvedJavaField identity) {
-        return readCache.get(new ReadCacheEntry(identity, object));
+    public ValueNode getCacheEntry(CacheEntry<?> identifier) {
+        return readCache.get(identifier);
     }
 
     public void killReadCache() {
         readCache.clear();
     }
 
-    public void killReadCache(ResolvedJavaField identity) {
-        Iterator<Map.Entry<ReadCacheEntry, ValueNode>> iter = readCache.entrySet().iterator();
+    public void killReadCache(LocationIdentity identity) {
+        Iterator<Map.Entry<CacheEntry<?>, ValueNode>> iter = readCache.entrySet().iterator();
         while (iter.hasNext()) {
-            Map.Entry<ReadCacheEntry, ValueNode> entry = iter.next();
-            if (entry.getKey().identity == identity) {
+            Map.Entry<CacheEntry<?>, ValueNode> entry = iter.next();
+            if (entry.getKey().conflicts(identity)) {
                 iter.remove();
             }
         }
     }
 
-    public Map<ReadCacheEntry, ValueNode> getReadCache() {
+    public Map<CacheEntry<?>, ValueNode> getReadCache() {
         return readCache;
     }
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Thu Jul 18 17:16:16 2013 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Thu Jul 18 17:18:13 2013 +0200
@@ -35,7 +35,9 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.ReadCacheEntry;
+import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
 
 public class ReadEliminationClosure extends EffectsClosure<ReadEliminationBlockState> {
 
@@ -54,28 +56,59 @@
         if (node instanceof LoadFieldNode) {
             LoadFieldNode load = (LoadFieldNode) node;
             ValueNode object = GraphUtil.unproxify(load.object());
-            ValueNode cachedValue = state.getReadCache(object, load.field());
+            LoadCacheEntry identifier = new LoadCacheEntry(object, load.field());
+            ValueNode cachedValue = state.getCacheEntry(identifier);
             if (cachedValue != null) {
                 effects.replaceAtUsages(load, cachedValue);
                 state.addScalarAlias(load, cachedValue);
                 deleted = true;
             } else {
-                state.addReadCache(object, load.field(), load);
+                state.addCacheEntry(identifier, load);
             }
         } else if (node instanceof StoreFieldNode) {
             StoreFieldNode store = (StoreFieldNode) node;
             ValueNode object = GraphUtil.unproxify(store.object());
-            ValueNode cachedValue = state.getReadCache(object, store.field());
+            LoadCacheEntry identifier = new LoadCacheEntry(object, store.field());
+            ValueNode cachedValue = state.getCacheEntry(identifier);
 
-            if (state.getScalarAlias(store.value()) == cachedValue) {
+            ValueNode value = state.getScalarAlias(store.value());
+            if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
                 effects.deleteFixedNode(store);
                 deleted = true;
             }
-            state.killReadCache(store.field());
-            state.addReadCache(object, store.field(), store.value());
+            state.killReadCache((LocationIdentity) store.field());
+            state.addCacheEntry(identifier, value);
+        } else if (node instanceof ReadNode) {
+            ReadNode read = (ReadNode) node;
+            if (read.location() instanceof ConstantLocationNode) {
+                ValueNode object = GraphUtil.unproxify(read.object());
+                ReadCacheEntry identifier = new ReadCacheEntry(object, read.location());
+                ValueNode cachedValue = state.getCacheEntry(identifier);
+                if (cachedValue != null) {
+                    effects.replaceAtUsages(read, cachedValue);
+                    state.addScalarAlias(read, cachedValue);
+                    deleted = true;
+                } else {
+                    state.addCacheEntry(identifier, read);
+                }
+            }
+        } else if (node instanceof WriteNode) {
+            WriteNode write = (WriteNode) node;
+            if (write.location() instanceof ConstantLocationNode) {
+                ValueNode object = GraphUtil.unproxify(write.object());
+                ReadCacheEntry identifier = new ReadCacheEntry(object, write.location());
+                ValueNode cachedValue = state.getCacheEntry(identifier);
+
+                ValueNode value = state.getScalarAlias(write.value());
+                if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
+                    effects.deleteFixedNode(write);
+                    deleted = true;
+                }
+                state.killReadCache(write.location().getLocationIdentity());
+                state.addCacheEntry(identifier, value);
+            }
         } else if (node instanceof MemoryCheckpoint.Single) {
-            LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity();
-            processIdentity(state, identity);
+            processIdentity(state, ((MemoryCheckpoint.Single) node).getLocationIdentity());
         } else if (node instanceof MemoryCheckpoint.Multi) {
             for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) {
                 processIdentity(state, identity);
@@ -85,18 +118,18 @@
     }
 
     private static void processIdentity(ReadEliminationBlockState state, LocationIdentity identity) {
-        if (identity instanceof ResolvedJavaField) {
-            state.killReadCache((ResolvedJavaField) identity);
-        } else if (identity == ANY_LOCATION) {
+        if (identity == ANY_LOCATION) {
             state.killReadCache();
+            return;
         }
+        state.killReadCache(identity);
     }
 
     @Override
     protected void processLoopExit(LoopExitNode exitNode, ReadEliminationBlockState initialState, ReadEliminationBlockState exitState, GraphEffectList effects) {
-        for (Map.Entry<ReadCacheEntry, ValueNode> entry : exitState.getReadCache().entrySet()) {
+        for (Map.Entry<CacheEntry<?>, ValueNode> entry : exitState.getReadCache().entrySet()) {
             if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) {
-                ProxyNode proxy = new ProxyNode(exitState.getReadCache(entry.getKey().object, entry.getKey().identity), exitNode, PhiType.Value, null);
+                ProxyNode proxy = new ProxyNode(exitState.getCacheEntry(entry.getKey()), exitNode, PhiType.Value, null);
                 effects.addFloatingNode(proxy, "readCacheProxy");
                 entry.setValue(proxy);
             }
@@ -138,8 +171,8 @@
         }
 
         private void mergeReadCache(List<ReadEliminationBlockState> states) {
-            for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
-                ReadCacheEntry key = entry.getKey();
+            for (Map.Entry<CacheEntry<?>, ValueNode> entry : states.get(0).readCache.entrySet()) {
+                CacheEntry<?> key = entry.getKey();
                 ValueNode value = entry.getValue();
                 boolean phi = false;
                 for (int i = 1; i < states.size(); i++) {
@@ -157,18 +190,18 @@
                     PhiNode phiNode = getCachedPhi(entry, value.kind());
                     mergeEffects.addFloatingNode(phiNode, "mergeReadCache");
                     for (int i = 0; i < states.size(); i++) {
-                        afterMergeEffects.addPhiInput(phiNode, states.get(i).getReadCache(key.object, key.identity));
+                        afterMergeEffects.addPhiInput(phiNode, states.get(i).getCacheEntry(key));
                     }
-                    newState.readCache.put(key, phiNode);
+                    newState.addCacheEntry(key, phiNode);
                 } else if (value != null) {
-                    newState.readCache.put(key, value);
+                    newState.addCacheEntry(key, value);
                 }
             }
             for (PhiNode phi : merge.phis()) {
                 if (phi.kind() == Kind.Object) {
-                    for (Map.Entry<ReadCacheEntry, ValueNode> entry : states.get(0).readCache.entrySet()) {
+                    for (Map.Entry<CacheEntry<?>, ValueNode> entry : states.get(0).readCache.entrySet()) {
                         if (entry.getKey().object == phi.valueAt(0)) {
-                            mergeReadCachePhi(phi, entry.getKey().identity, states);
+                            mergeReadCachePhi(phi, entry.getKey(), states);
                         }
                     }
 
@@ -176,22 +209,23 @@
             }
         }
 
-        private void mergeReadCachePhi(PhiNode phi, ResolvedJavaField identity, List<ReadEliminationBlockState> states) {
+        private void mergeReadCachePhi(PhiNode phi, CacheEntry<?> identifier, List<ReadEliminationBlockState> states) {
             ValueNode[] values = new ValueNode[phi.valueCount()];
             for (int i = 0; i < phi.valueCount(); i++) {
-                ValueNode value = states.get(i).getReadCache(phi.valueAt(i), identity);
+                ValueNode value = states.get(i).getCacheEntry(identifier.duplicateWithObject(phi.valueAt(i)));
                 if (value == null) {
                     return;
                 }
                 values[i] = value;
             }
 
-            PhiNode phiNode = getCachedPhi(new ReadCacheEntry(identity, phi), values[0].kind());
+            CacheEntry<?> newIdentifier = identifier.duplicateWithObject(phi);
+            PhiNode phiNode = getCachedPhi(newIdentifier, values[0].kind());
             mergeEffects.addFloatingNode(phiNode, "mergeReadCachePhi");
             for (int i = 0; i < values.length; i++) {
                 afterMergeEffects.addPhiInput(phiNode, values[i]);
             }
-            newState.readCache.put(new ReadCacheEntry(identity, phi), phiNode);
+            newState.addCacheEntry(newIdentifier, phiNode);
         }
     }
 }