changeset 22916:102b099df9dd

Merge.
author Doug Simon <doug.simon@oracle.com>
date Sat, 31 Oct 2015 12:49:11 +0100
parents c5aa3f4aac72 (current diff) 3c00f45259b6 (diff)
children be55d92d4cb6
files
diffstat 17 files changed, 231 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTestBase.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTestBase.java	Sat Oct 31 12:49:11 2015 +0100
@@ -57,6 +57,7 @@
         testConditionalElimination(snippet, referenceSnippet, false);
     }
 
+    @SuppressWarnings("try")
     protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
         Debug.dump(graph, "Graph");
@@ -68,21 +69,30 @@
              */
             canonicalizer1.disableSimplification();
         }
-        canonicalizer1.apply(graph, context);
-        new ConvertDeoptimizeToGuardPhase().apply(graph, context);
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
-        new DominatorConditionalEliminationPhase(true).apply(graph, context);
-        canonicalizer.apply(graph, context);
-        canonicalizer.apply(graph, context);
-        new ConvertDeoptimizeToGuardPhase().apply(graph, context);
+        try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest", graph)) {
+            canonicalizer1.apply(graph, context);
+            new ConvertDeoptimizeToGuardPhase().apply(graph, context);
+            new DominatorConditionalEliminationPhase(true).apply(graph, context);
+            canonicalizer.apply(graph, context);
+            canonicalizer.apply(graph, context);
+            new ConvertDeoptimizeToGuardPhase().apply(graph, context);
+        } catch (Throwable t) {
+            Debug.handle(t);
+        }
         StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES);
-        new ConvertDeoptimizeToGuardPhase().apply(referenceGraph, context);
-        if (applyConditionalEliminationOnReference) {
-            new DominatorConditionalEliminationPhase(true).apply(referenceGraph, context);
-            canonicalizer.apply(referenceGraph, context);
-            canonicalizer.apply(referenceGraph, context);
-        } else {
-            canonicalizer.apply(referenceGraph, context);
+        try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest.ReferenceGraph", graph)) {
+
+            new ConvertDeoptimizeToGuardPhase().apply(referenceGraph, context);
+            if (applyConditionalEliminationOnReference) {
+                new DominatorConditionalEliminationPhase(true).apply(referenceGraph, context);
+                canonicalizer.apply(referenceGraph, context);
+                canonicalizer.apply(referenceGraph, context);
+            } else {
+                canonicalizer.apply(referenceGraph, context);
+            }
+        } catch (Throwable t) {
+            Debug.handle(t);
         }
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GuardEliminationCornerCasesTest.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GuardEliminationCornerCasesTest.java	Sat Oct 31 12:49:11 2015 +0100
@@ -94,7 +94,7 @@
         for (Node n : graph.getNodes()) {
             if (n instanceof GuardNode) {
                 GuardNode guardNode = (GuardNode) n;
-                LogicNode condition = guardNode.condition();
+                LogicNode condition = guardNode.getCondition();
                 if (condition instanceof InstanceOfNode) {
                     InstanceOfNode instanceOfNode = (InstanceOfNode) condition;
                     if (instanceOfNode.getValue() instanceof ValueProxy) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Sat Oct 31 12:49:11 2015 +0100
@@ -51,6 +51,25 @@
         return 0;
     }
 
+    @Test
+    public void testSubtractEqualsZeroLong() {
+        test("testSubtractEqualsZeroLongSnippet", "testSubtractEqualsZeroLongReference");
+    }
+
+    public static int testSubtractEqualsZeroLongReference(long a, long b) {
+        if (a == b) {
+            return 1;
+        }
+        return 0;
+    }
+
+    public static int testSubtractEqualsZeroLongSnippet(long a, long b) {
+        if (a - b == 0) {
+            return 1;
+        }
+        return 0;
+    }
+
     /**
      * Tests the canonicalization of (x >>> const) == 0 to x |test| (-1 << const).
      */
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Sat Oct 31 12:49:11 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,15 +35,16 @@
 import com.oracle.graal.nodes.ValuePhiNode;
 import com.oracle.graal.nodes.java.LoadFieldNode;
 import com.oracle.graal.nodes.java.StoreFieldNode;
+import com.oracle.graal.nodes.memory.ReadNode;
+import com.oracle.graal.nodes.spi.LoweringTool;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
+import com.oracle.graal.phases.common.LoweringPhase;
 import com.oracle.graal.phases.common.inlining.InliningPhase;
 import com.oracle.graal.phases.tiers.HighTierContext;
 import com.oracle.graal.virtual.phases.ea.EarlyReadEliminationPhase;
 
 public class EarlyReadEliminationTest extends GraalCompilerTest {
 
-    protected StructuredGraph graph;
-
     public static Object staticField;
 
     public static class TestObject {
@@ -87,8 +88,15 @@
 
     @Test
     public void testSimple() {
-        ValueNode result = getReturn("testSimpleSnippet").result();
-        assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty());
+        // Test without lowering.
+        ValueNode result = getReturn("testSimpleSnippet", false).result();
+        assertTrue(result.graph().getNodes().filter(LoadFieldNode.class).isEmpty());
+        assertTrue(result.isConstant());
+        assertDeepEquals(2, result.asJavaConstant().asInt());
+
+        // Test with lowering.
+        result = getReturn("testSimpleSnippet", true).result();
+        assertTrue(result.graph().getNodes().filter(ReadNode.class).isEmpty());
         assertTrue(result.isConstant());
         assertDeepEquals(2, result.asJavaConstant().asInt());
     }
@@ -103,7 +111,7 @@
 
     @Test
     public void testSimpleConflict() {
-        ValueNode result = getReturn("testSimpleConflictSnippet").result();
+        ValueNode result = getReturn("testSimpleConflictSnippet", false).result();
         assertFalse(result.isConstant());
         assertTrue(result instanceof LoadFieldNode);
     }
@@ -116,9 +124,9 @@
 
     @Test
     public void testParam() {
-        ValueNode result = getReturn("testParamSnippet").result();
-        assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty());
-        assertDeepEquals(graph.getParameter(1), result);
+        ValueNode result = getReturn("testParamSnippet", false).result();
+        assertTrue(result.graph().getNodes().filter(LoadFieldNode.class).isEmpty());
+        assertDeepEquals(result.graph().getParameter(1), result);
     }
 
     @SuppressWarnings("all")
@@ -130,9 +138,9 @@
 
     @Test
     public void testMaterialized() {
-        ValueNode result = getReturn("testMaterializedSnippet").result();
-        assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty());
-        assertDeepEquals(graph.getParameter(0), result);
+        ValueNode result = getReturn("testMaterializedSnippet", false).result();
+        assertTrue(result.graph().getNodes().filter(LoadFieldNode.class).isEmpty());
+        assertDeepEquals(result.graph().getParameter(0), result);
     }
 
     @SuppressWarnings("all")
@@ -146,9 +154,15 @@
 
     @Test
     public void testSimpleLoop() {
-        ValueNode result = getReturn("testSimpleLoopSnippet").result();
-        assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty());
-        assertDeepEquals(graph.getParameter(1), result);
+        // Test without lowering.
+        ValueNode result = getReturn("testSimpleLoopSnippet", false).result();
+        assertTrue(result.graph().getNodes().filter(LoadFieldNode.class).isEmpty());
+        assertDeepEquals(result.graph().getParameter(1), result);
+
+        // Now test with lowering.
+        result = getReturn("testSimpleLoopSnippet", true).result();
+        assertTrue(result.graph().getNodes().filter(ReadNode.class).isEmpty());
+        assertDeepEquals(result.graph().getParameter(1), result);
     }
 
     @SuppressWarnings("all")
@@ -164,8 +178,8 @@
 
     @Test
     public void testBadLoop() {
-        ValueNode result = getReturn("testBadLoopSnippet").result();
-        assertDeepEquals(0, graph.getNodes().filter(LoadFieldNode.class).count());
+        ValueNode result = getReturn("testBadLoopSnippet", false).result();
+        assertDeepEquals(0, result.graph().getNodes().filter(LoadFieldNode.class).count());
         assertTrue(result instanceof ProxyNode);
         assertTrue(((ProxyNode) result).value() instanceof ValuePhiNode);
     }
@@ -182,8 +196,8 @@
 
     @Test
     public void testBadLoop2() {
-        ValueNode result = getReturn("testBadLoop2Snippet").result();
-        assertDeepEquals(1, graph.getNodes().filter(LoadFieldNode.class).count());
+        ValueNode result = getReturn("testBadLoop2Snippet", false).result();
+        assertDeepEquals(1, result.graph().getNodes().filter(LoadFieldNode.class).count());
         assertTrue(result instanceof LoadFieldNode);
     }
 
@@ -199,7 +213,7 @@
 
     @Test
     public void testPhi() {
-        processMethod("testPhiSnippet");
+        StructuredGraph graph = processMethod("testPhiSnippet", false);
         assertTrue(graph.getNodes().filter(LoadFieldNode.class).isEmpty());
         List<ReturnNode> returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot();
         assertDeepEquals(2, returnNodes.size());
@@ -217,7 +231,7 @@
 
     @Test
     public void testSimpleStore() {
-        processMethod("testSimpleStoreSnippet");
+        StructuredGraph graph = processMethod("testSimpleStoreSnippet", false);
         assertDeepEquals(1, graph.getNodes().filter(StoreFieldNode.class).count());
     }
 
@@ -235,20 +249,24 @@
 
     @Test
     public void testValueProxy() {
-        processMethod("testValueProxySnippet");
+        StructuredGraph graph = processMethod("testValueProxySnippet", false);
         assertDeepEquals(2, graph.getNodes().filter(LoadFieldNode.class).count());
     }
 
-    ReturnNode getReturn(String snippet) {
-        processMethod(snippet);
+    ReturnNode getReturn(String snippet, boolean doLowering) {
+        StructuredGraph graph = processMethod(snippet, doLowering);
         assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count());
         return graph.getNodes(ReturnNode.TYPE).first();
     }
 
-    protected void processMethod(String snippet) {
-        graph = parseEager(getResolvedJavaMethod(snippet), AllowAssumptions.NO);
+    protected StructuredGraph processMethod(String snippet, boolean doLowering) {
+        StructuredGraph graph = parseEager(getResolvedJavaMethod(snippet), AllowAssumptions.NO);
         HighTierContext context = getDefaultHighTierContext();
         new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        if (doLowering) {
+            new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+        }
         new EarlyReadEliminationPhase(new CanonicalizerPhase()).apply(graph, context);
+        return graph;
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Sat Oct 31 12:49:11 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 
 import sun.misc.Unsafe;
 
+import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.extended.UnsafeLoadNode;
 import com.oracle.graal.nodes.java.LoadIndexedNode;
@@ -49,7 +50,7 @@
 
     @Test
     public void testIndexed1() {
-        processMethod("testIndexed1Snippet");
+        StructuredGraph graph = processMethod("testIndexed1Snippet", false);
         assertDeepEquals(0, graph.getNodes().filter(LoadIndexedNode.class).count());
     }
 
@@ -69,7 +70,7 @@
 
     @Test
     public void testIndexed2() {
-        processMethod("testIndexed2Snippet");
+        StructuredGraph graph = processMethod("testIndexed2Snippet", false);
         assertDeepEquals(3, graph.getNodes().filter(LoadIndexedNode.class).count());
         assertDeepEquals(7, graph.getNodes().filter(StoreIndexedNode.class).count());
     }
@@ -93,7 +94,7 @@
 
     @Test
     public void testIndexed3() {
-        processMethod("testIndexed3Snippet");
+        StructuredGraph graph = processMethod("testIndexed3Snippet", false);
         assertDeepEquals(3, graph.getNodes().filter(LoadIndexedNode.class).count());
     }
 
@@ -112,7 +113,7 @@
 
     @Test
     public void testIndexed4() {
-        processMethod("testIndexed4Snippet");
+        StructuredGraph graph = processMethod("testIndexed4Snippet", false);
         assertDeepEquals(3, graph.getNodes().filter(LoadIndexedNode.class).count());
     }
 
@@ -128,7 +129,7 @@
 
     @Test
     public void testUnsafe1() {
-        processMethod("testUnsafe1Snippet");
+        StructuredGraph graph = processMethod("testUnsafe1Snippet", false);
         assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count());
     }
 
@@ -141,7 +142,7 @@
 
     @Test
     public void testUnsafe2() {
-        processMethod("testUnsafe2Snippet");
+        StructuredGraph graph = processMethod("testUnsafe2Snippet", false);
         assertDeepEquals(3, graph.getNodes().filter(UnsafeLoadNode.class).count());
     }
 
@@ -157,7 +158,7 @@
 
     @Test
     public void testUnsafe3() {
-        processMethod("testUnsafe3Snippet");
+        StructuredGraph graph = processMethod("testUnsafe3Snippet", false);
         assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count());
     }
 
@@ -171,7 +172,7 @@
 
     @Test
     public void testUnsafe4() {
-        processMethod("testUnsafe4Snippet");
+        StructuredGraph graph = processMethod("testUnsafe4Snippet", false);
         assertDeepEquals(3, graph.getNodes().filter(UnsafeLoadNode.class).count());
     }
 
@@ -187,15 +188,16 @@
 
     @Test
     public void testUnsafe5() {
-        processMethod("testUnsafe5Snippet");
+        StructuredGraph graph = processMethod("testUnsafe5Snippet", false);
         assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count());
     }
 
     @Override
-    protected void processMethod(final String snippet) {
-        graph = parseEager(snippet, AllowAssumptions.NO);
+    protected StructuredGraph processMethod(final String snippet, boolean doLowering) {
+        StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
         HighTierContext context = getDefaultHighTierContext();
         new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
         new PartialEscapePhase(false, true, new CanonicalizerPhase(), null).apply(graph, context);
+        return graph;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Sat Oct 31 12:49:11 2015 +0100
@@ -37,7 +37,7 @@
 import com.oracle.graal.nodes.util.GraphUtil;
 
 @NodeInfo
-public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode {
+public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode, DeoptimizingGuard {
 
     public static final NodeClass<AbstractFixedGuardNode> TYPE = NodeClass.create(AbstractFixedGuardNode.class);
     @Input(InputType.Condition) protected LogicNode condition;
@@ -46,13 +46,18 @@
     protected JavaConstant speculation;
     protected boolean negated;
 
-    public LogicNode condition() {
+    public LogicNode getCondition() {
         return condition;
     }
 
-    public void setCondition(LogicNode x) {
+    public LogicNode condition() {
+        return getCondition();
+    }
+
+    public void setCondition(LogicNode x, boolean negated) {
         updateUsages(condition, x);
         condition = x;
+        this.negated = negated;
     }
 
     protected AbstractFixedGuardNode(NodeClass<? extends AbstractFixedGuardNode> c, LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, JavaConstant speculation,
@@ -94,8 +99,7 @@
     public void simplify(SimplifierTool tool) {
         while (condition instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition;
-            setCondition(negation.getValue());
-            negated = !negated;
+            setCondition(negation.getValue(), !negated);
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Sat Oct 31 12:49:11 2015 +0100
@@ -75,7 +75,7 @@
     @SuppressWarnings("deprecation")
     public LogicNode maybeCommuteInputs() {
         assert this instanceof BinaryCommutative;
-        if (x.isConstant() && !y.isConstant() || x.getId() > y.getId()) {
+        if (!y.isConstant() && x.getId() > y.getId()) {
             ValueNode tmp = x;
             x = y;
             y = tmp;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingGuard.java	Sat Oct 31 12:49:11 2015 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import jdk.vm.ci.meta.DeoptimizationAction;
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaConstant;
+
+import com.oracle.graal.graph.NodeInterface;
+
+/**
+ * Shared interface to capture core methods of {@link AbstractFixedGuardNode} and {@link GuardNode}.
+ *
+ */
+public interface DeoptimizingGuard extends NodeInterface {
+
+    LogicNode getCondition();
+
+    void setCondition(LogicNode x, boolean negated);
+
+    DeoptimizationReason getReason();
+
+    DeoptimizationAction getAction();
+
+    JavaConstant getSpeculation();
+
+    boolean isNegated();
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java	Sat Oct 31 12:49:11 2015 +0100
@@ -55,8 +55,8 @@
     public void simplify(SimplifierTool tool) {
         super.simplify(tool);
 
-        if (condition() instanceof LogicConstantNode) {
-            LogicConstantNode c = (LogicConstantNode) condition();
+        if (getCondition() instanceof LogicConstantNode) {
+            LogicConstantNode c = (LogicConstantNode) getCondition();
             if (c.getValue() == isNegated()) {
                 FixedNode currentNext = this.next();
                 if (currentNext != null) {
@@ -69,8 +69,8 @@
             }
             this.replaceAtUsages(null);
             graph().removeFixed(this);
-        } else if (condition() instanceof ShortCircuitOrNode) {
-            ShortCircuitOrNode shortCircuitOr = (ShortCircuitOrNode) condition();
+        } else if (getCondition() instanceof ShortCircuitOrNode) {
+            ShortCircuitOrNode shortCircuitOr = (ShortCircuitOrNode) getCondition();
             if (isNegated() && hasNoUsages()) {
                 graph().addAfterFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getY(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isYNegated())));
                 graph().replaceFixedWithFixed(this, graph().add(new FixedGuardNode(shortCircuitOr.getX(), getReason(), getAction(), getSpeculation(), !shortCircuitOr.isXNegated())));
@@ -90,7 +90,7 @@
              * case.
              */
             if (getAction() != DeoptimizationAction.None || getReason() != DeoptimizationReason.RuntimeConstraint) {
-                ValueNode guard = tool.createGuard(this, condition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode();
+                ValueNode guard = tool.createGuard(this, getCondition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode();
                 this.replaceAtUsages(guard);
                 ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode()));
                 graph().replaceFixedWithFixed(this, newAnchor);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Sat Oct 31 12:49:11 2015 +0100
@@ -50,7 +50,7 @@
  * control flow would have reached the guarded node (without taking exceptions into account).
  */
 @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}", allowedUsageTypes = {InputType.Guard})
-public class GuardNode extends FloatingAnchoredNode implements Canonicalizable, GuardingNode {
+public class GuardNode extends FloatingAnchoredNode implements Canonicalizable, GuardingNode, DeoptimizingGuard {
 
     public static final NodeClass<GuardNode> TYPE = NodeClass.create(GuardNode.class);
     @Input(InputType.Condition) protected LogicNode condition;
@@ -75,19 +75,25 @@
     /**
      * The instruction that produces the tested boolean value.
      */
-    public LogicNode condition() {
+    public LogicNode getCondition() {
         return condition;
     }
 
+    public void setCondition(LogicNode x, boolean negated) {
+        updateUsages(condition, x);
+        condition = x;
+        this.negated = negated;
+    }
+
     public boolean isNegated() {
         return negated;
     }
 
-    public DeoptimizationReason reason() {
+    public DeoptimizationReason getReason() {
         return reason;
     }
 
-    public DeoptimizationAction action() {
+    public DeoptimizationAction getAction() {
         return action;
     }
 
@@ -110,12 +116,12 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (condition() instanceof LogicNegationNode) {
-            LogicNegationNode negation = (LogicNegationNode) condition();
+        if (getCondition() instanceof LogicNegationNode) {
+            LogicNegationNode negation = (LogicNegationNode) getCondition();
             return new GuardNode(negation.getValue(), getAnchor(), reason, action, !negated, speculation);
         }
-        if (condition() instanceof LogicConstantNode) {
-            LogicConstantNode c = (LogicConstantNode) condition();
+        if (getCondition() instanceof LogicConstantNode) {
+            LogicConstantNode c = (LogicConstantNode) getCondition();
             if (c.getValue() != negated) {
                 return null;
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Sat Oct 31 12:49:11 2015 +0100
@@ -83,7 +83,7 @@
             if (currentNext.getGuard() == anchored) {
                 GraphUtil.removeFixedWithUnusedInputs(this);
                 return;
-            } else if (currentNext.getGuard() == null && anchored instanceof GuardNode && ((GuardNode) anchored).condition() instanceof IsNullNode) {
+            } else if (currentNext.getGuard() == null && anchored instanceof GuardNode && ((GuardNode) anchored).getCondition() instanceof IsNullNode) {
                 // coalesce null check guards into subsequent read/write
                 currentNext.setGuard((GuardingNode) anchored);
                 tool.addToWorkList(next());
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Sat Oct 31 12:49:11 2015 +0100
@@ -487,12 +487,12 @@
         }
 
         private GuardedStamp computeGuardedStamp(GuardNode guard) {
-            if (guard.condition() instanceof IntegerBelowNode) {
+            if (guard.getCondition() instanceof IntegerBelowNode) {
                 if (guard.isNegated()) {
                     // Not sure how to reason about negated guards
                     return null;
                 }
-                IntegerBelowNode below = (IntegerBelowNode) guard.condition();
+                IntegerBelowNode below = (IntegerBelowNode) guard.getCondition();
                 if (below.getX().getStackKind() == JavaKind.Int && below.getX().isConstant() && !below.getY().isConstant()) {
                     Stamp stamp = StampTool.unsignedCompare(below.getX().stamp(), below.getY().stamp());
                     if (stamp != null) {
@@ -543,8 +543,8 @@
             }
 
             GuardNode existingGuard = null;
-            if (guard.condition() instanceof IntegerBelowNode) {
-                IntegerBelowNode below = (IntegerBelowNode) guard.condition();
+            if (guard.getCondition() instanceof IntegerBelowNode) {
+                IntegerBelowNode below = (IntegerBelowNode) guard.getCondition();
                 IntegerStamp xStamp = (IntegerStamp) below.getX().stamp();
                 IntegerStamp yStamp = (IntegerStamp) below.getY().stamp();
                 GuardedStamp cstamp = state.valueConstraints.get(below.getX());
@@ -566,22 +566,22 @@
                         if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
                             // Proven true
                             existingGuard = cstamp.getGuard();
-                            Debug.log("existing guard %s %1s proves %1s", existingGuard, existingGuard.condition(), guard.condition());
+                            Debug.log("existing guard %s %1s proves %1s", existingGuard, existingGuard.getCondition(), guard.getCondition());
                         } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
                             // An earlier guard proves that this will always fail but it's probably
                             // not worth trying to use it.
                         }
                     }
                 }
-            } else if (guard.condition() instanceof IntegerEqualsNode && guard.isNegated()) {
-                IntegerEqualsNode equals = (IntegerEqualsNode) guard.condition();
+            } else if (guard.getCondition() instanceof IntegerEqualsNode && guard.isNegated()) {
+                IntegerEqualsNode equals = (IntegerEqualsNode) guard.getCondition();
                 GuardedStamp cstamp = state.valueConstraints.get(equals.getY());
                 if (cstamp != null && equals.getX().isConstant()) {
                     IntegerStamp stamp = (IntegerStamp) cstamp.getStamp();
                     if (!stamp.contains(equals.getX().asJavaConstant().asLong())) {
                         // x != n is true if n is outside the range of the stamp
                         existingGuard = cstamp.getGuard();
-                        Debug.log("existing guard %s %1s proves !%1s", existingGuard, existingGuard.condition(), guard.condition());
+                        Debug.log("existing guard %s %1s proves !%1s", existingGuard, existingGuard.getCondition(), guard.getCondition());
                     }
                 }
             }
@@ -595,7 +595,7 @@
         }
 
         private boolean tryReplaceWithExistingGuard(GuardNode guard) {
-            GuardingNode existingGuard = guard.isNegated() ? state.falseConditions.get(guard.condition()) : state.trueConditions.get(guard.condition());
+            GuardingNode existingGuard = guard.isNegated() ? state.falseConditions.get(guard.getCondition()) : state.trueConditions.get(guard.getCondition());
             if (existingGuard != null && existingGuard != guard) {
                 eliminateGuard(guard, existingGuard);
                 return true;
@@ -617,7 +617,7 @@
                     // information
                     Stamp result = conditional.getStamp().join(other.getStamp());
                     if (result == conditional.getStamp()) {
-                        Debug.log("%1s overrides existing value %1s", guard.condition(), other.getGuard().condition());
+                        Debug.log("%1s overrides existing value %1s", guard.getCondition(), other.getGuard().getCondition());
                         state.valueConstraints.put(conditional.getValue(), conditional);
                     } else if (result == other.getStamp()) {
                         // existing type constraint is best
@@ -879,7 +879,7 @@
             // to see if they can be deleted using type constraints.
             for (GuardNode guard : begin.guards().snapshot()) {
                 if (provers.contains(guard) || !(tryReplaceWithExistingGuard(guard) || testImpliedGuard(guard))) {
-                    registerCondition(!guard.isNegated(), guard.condition(), guard);
+                    registerCondition(!guard.isNegated(), guard.getCondition(), guard);
                 }
             }
             assert assertImpliedGuard(provers);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java	Sat Oct 31 12:49:11 2015 +0100
@@ -576,11 +576,11 @@
         }
 
         private void processGuard(GuardNode node, List<Runnable> undoOperations) {
-            if (!tryProofCondition(node.condition(), (guard, result) -> {
+            if (!tryProofCondition(node.getCondition(), (guard, result) -> {
                 if (result != node.isNegated()) {
                     node.replaceAndDelete(guard);
                 } else {
-                    DeoptimizeNode deopt = node.graph().add(new DeoptimizeNode(node.action(), node.reason(), node.getSpeculation()));
+                    DeoptimizeNode deopt = node.graph().add(new DeoptimizeNode(node.getAction(), node.getReason(), node.getSpeculation()));
                     AbstractBeginNode beginNode = (AbstractBeginNode) node.getAnchor();
                     FixedNode next = beginNode.next();
                     beginNode.setNext(deopt);
@@ -588,7 +588,7 @@
                 }
                 return true;
             })) {
-                registerNewCondition(node.condition(), node.isNegated(), node, undoOperations);
+                registerNewCondition(node.getCondition(), node.isNegated(), node, undoOperations);
             }
         }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Sat Oct 31 12:49:11 2015 +0100
@@ -173,7 +173,7 @@
                     PiNode piNode = (PiNode) guard;
                     guardNode = (GuardNode) piNode.getGuard();
                 }
-                LogicNode condition = guardNode.condition();
+                LogicNode condition = guardNode.getCondition();
                 guardNode.replaceAndDelete(fixedAccess);
                 if (condition.hasNoUsages()) {
                     GraphUtil.killWithUnusedFloatingInputs(condition);
@@ -184,8 +184,8 @@
 
         private void processGuard(Node node) {
             GuardNode guard = (GuardNode) node;
-            if (guard.isNegated() && guard.condition() instanceof IsNullNode && (guard.getSpeculation() == null || guard.getSpeculation().equals(JavaConstant.NULL_POINTER))) {
-                ValueNode obj = ((IsNullNode) guard.condition()).getValue();
+            if (guard.isNegated() && guard.getCondition() instanceof IsNullNode && (guard.getSpeculation() == null || guard.getSpeculation().equals(JavaConstant.NULL_POINTER))) {
+                ValueNode obj = ((IsNullNode) guard.getCondition()).getValue();
                 nullGuarded.put(obj, guard);
             }
         }
@@ -228,7 +228,7 @@
             AbstractBeginNode fastPath = graph.add(new BeginNode());
             @SuppressWarnings("deprecation")
             int debugId = useGuardIdAsDebugId ? guard.getId() : DeoptimizeNode.DEFAULT_DEBUG_ID;
-            DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason(), debugId, guard.getSpeculation(), null));
+            DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.getAction(), guard.getReason(), debugId, guard.getSpeculation(), null));
             AbstractBeginNode deoptBranch = BeginNode.begin(deopt);
             AbstractBeginNode trueSuccessor;
             AbstractBeginNode falseSuccessor;
@@ -240,7 +240,7 @@
                 trueSuccessor = fastPath;
                 falseSuccessor = deoptBranch;
             }
-            IfNode ifNode = graph.add(new IfNode(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0));
+            IfNode ifNode = graph.add(new IfNode(guard.getCondition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0));
             guard.replaceAndDelete(fastPath);
             insert(ifNode, fastPath);
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchorsPhase.java	Sat Oct 31 12:49:11 2015 +0100
@@ -107,14 +107,14 @@
         AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit);
         int successorCount = controlSplit.successors().count();
         for (GuardNode guard : successor.guards().snapshot()) {
-            if (guard.isDeleted() || guard.condition().getUsageCount() < successorCount) {
+            if (guard.isDeleted() || guard.getCondition().getUsageCount() < successorCount) {
                 continue;
             }
             List<GuardNode> otherGuards = new ArrayList<>(successorCount - 1);
             HashSet<Node> successorsWithoutGuards = new HashSet<>(controlSplit.successors().count());
             controlSplit.successors().snapshotTo(successorsWithoutGuards);
             successorsWithoutGuards.remove(guard.getAnchor());
-            for (GuardNode conditonGuard : guard.condition().usages().filter(GuardNode.class)) {
+            for (GuardNode conditonGuard : guard.getCondition().usages().filter(GuardNode.class)) {
                 if (conditonGuard != guard) {
                     AnchoringNode conditionGuardAnchor = conditonGuard.getAnchor();
                     if (conditionGuardAnchor.asNode().predecessor() == controlSplit && compatibleGuards(guard, conditonGuard)) {
@@ -127,7 +127,7 @@
             if (successorsWithoutGuards.isEmpty()) {
                 assert otherGuards.size() >= successorCount - 1;
                 AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit));
-                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.isNegated(), guard.getSpeculation()));
+                GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.getCondition(), anchor, guard.getReason(), guard.getAction(), guard.isNegated(), guard.getSpeculation()));
                 for (GuardNode otherGuard : otherGuards) {
                     otherGuard.replaceAndDelete(newGuard);
                 }
@@ -139,7 +139,7 @@
     }
 
     private static boolean compatibleGuards(GuardNode guard, GuardNode conditonGuard) {
-        return conditonGuard.isNegated() == guard.isNegated() && conditonGuard.action() == guard.action() && conditonGuard.reason() == guard.reason() &&
+        return conditonGuard.isNegated() == guard.isNegated() && conditonGuard.getAction() == guard.getAction() && conditonGuard.getReason() == guard.getReason() &&
                         conditonGuard.getSpeculation().equals(guard.getSpeculation());
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationBlockState.java	Sat Oct 31 12:49:11 2015 +0100
@@ -112,41 +112,6 @@
         }
     }
 
-    static class ReadCacheEntry extends CacheEntry<ValueNode> {
-
-        private final LocationIdentity location;
-
-        public ReadCacheEntry(ValueNode object, ValueNode offset, LocationIdentity location) {
-            super(object, offset);
-            this.location = location;
-        }
-
-        @Override
-        public CacheEntry<ValueNode> duplicateWithObject(ValueNode newObject) {
-            return new ReadCacheEntry(newObject, identity, location);
-        }
-
-        @Override
-        public boolean conflicts(LocationIdentity other) {
-            return location.equals(other);
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof ReadCacheEntry)) {
-                return false;
-            }
-
-            ReadCacheEntry other = (ReadCacheEntry) obj;
-            return this.location.equals(other.location) && super.equals(other);
-        }
-
-        @Override
-        public int hashCode() {
-            return location.hashCode() * 23 + super.hashCode();
-        }
-    }
-
     public ReadEliminationBlockState() {
         readCache = CollectionsFactory.newMap();
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Sat Oct 31 12:49:00 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java	Sat Oct 31 12:49:11 2015 +0100
@@ -55,11 +55,9 @@
 import com.oracle.graal.nodes.memory.MemoryCheckpoint;
 import com.oracle.graal.nodes.memory.ReadNode;
 import com.oracle.graal.nodes.memory.WriteNode;
-import com.oracle.graal.nodes.memory.address.OffsetAddressNode;
 import com.oracle.graal.nodes.util.GraphUtil;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
-import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.ReadCacheEntry;
 import com.oracle.graal.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry;
 
 public class ReadEliminationClosure extends EffectsClosure<ReadEliminationBlockState> {
@@ -106,46 +104,46 @@
             }
         } else if (node instanceof ReadNode) {
             ReadNode read = (ReadNode) node;
-            if (read.getAddress() instanceof OffsetAddressNode) {
-                OffsetAddressNode address = (OffsetAddressNode) read.getAddress();
-                if (address.getOffset().isConstant()) {
-                    ValueNode object = GraphUtil.unproxify(address.getBase());
-                    ReadCacheEntry identifier = new ReadCacheEntry(object, address.getOffset(), read.getLocationIdentity());
-                    ValueNode cachedValue = state.getCacheEntry(identifier);
-                    if (cachedValue != null && read.stamp().isCompatible(cachedValue.stamp())) {
-                        // Anchor guard if it is not fixed and different from cachedValue's guard
-                        if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
-                            if (!(cachedValue instanceof GuardedNode) || ((GuardedNode) cachedValue).getGuard() != read.getGuard()) {
-                                effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read);
-                            }
+            if (read.getLocationIdentity().isSingle()) {
+                ValueNode object = GraphUtil.unproxify(read.getAddress());
+                LoadCacheEntry identifier = new LoadCacheEntry(object, read.getLocationIdentity());
+                ValueNode cachedValue = state.getCacheEntry(identifier);
+                if (cachedValue != null && read.stamp().isCompatible(cachedValue.stamp())) {
+                    // Anchor guard if it is not fixed and different from cachedValue's guard such
+                    // that it gets preserved.
+                    if (read.getGuard() != null && !(read.getGuard() instanceof FixedNode)) {
+                        if (!(cachedValue instanceof GuardedNode) || ((GuardedNode) cachedValue).getGuard() != read.getGuard()) {
+                            effects.addFixedNodeBefore(new ValueAnchorNode((ValueNode) read.getGuard()), read);
                         }
                     }
+                    effects.replaceAtUsages(read, cachedValue);
+                    addScalarAlias(read, cachedValue);
+                    deleted = true;
+                } else {
+                    state.addCacheEntry(identifier, read);
                 }
             }
         } else if (node instanceof WriteNode) {
             WriteNode write = (WriteNode) node;
-            if (write.getAddress() instanceof OffsetAddressNode) {
-                OffsetAddressNode address = (OffsetAddressNode) write.getAddress();
-                if (address.getOffset().isConstant()) {
-                    ValueNode object = GraphUtil.unproxify(address.getBase());
-                    ReadCacheEntry identifier = new ReadCacheEntry(object, address.getOffset(), write.getLocationIdentity());
-                    ValueNode cachedValue = state.getCacheEntry(identifier);
+            if (write.getLocationIdentity().isSingle()) {
+                ValueNode object = GraphUtil.unproxify(write.getAddress());
+                LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity());
+                ValueNode cachedValue = state.getCacheEntry(identifier);
 
-                    ValueNode value = getScalarAlias(write.value());
-                    if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
-                        effects.deleteNode(write);
-                        deleted = true;
-                    }
-                    processIdentity(state, write.getLocationIdentity());
-                    state.addCacheEntry(identifier, value);
-                } else {
-                    processIdentity(state, write.getLocationIdentity());
+                ValueNode value = getScalarAlias(write.value());
+                if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
+                    effects.deleteNode(write);
+                    deleted = true;
                 }
+                processIdentity(state, write.getLocationIdentity());
+                state.addCacheEntry(identifier, value);
+            } else {
+                processIdentity(state, write.getLocationIdentity());
             }
         } else if (node instanceof UnsafeAccessNode) {
             if (node instanceof UnsafeLoadNode) {
                 UnsafeLoadNode load = (UnsafeLoadNode) node;
-                if (load.offset().isConstant() && !load.getLocationIdentity().equals(LocationIdentity.any())) {
+                if (load.getLocationIdentity().isSingle()) {
                     ValueNode object = GraphUtil.unproxify(load.object());
                     UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, load.offset(), load.getLocationIdentity());
                     ValueNode cachedValue = state.getCacheEntry(identifier);
@@ -160,7 +158,7 @@
             } else {
                 assert node instanceof UnsafeStoreNode;
                 UnsafeStoreNode write = (UnsafeStoreNode) node;
-                if (write.offset().isConstant() && !write.getLocationIdentity().equals(LocationIdentity.any())) {
+                if (write.getLocationIdentity().isSingle()) {
                     ValueNode object = GraphUtil.unproxify(write.object());
                     UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getLocationIdentity());
                     ValueNode cachedValue = state.getCacheEntry(identifier);