changeset 3040:5e70ffd361fb

Merge
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Mon, 20 Jun 2011 19:22:01 +0200
parents 546dc7e1b184 (current diff) 82898994df70 (diff)
children 5e8f82715790
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java
diffstat 19 files changed, 366 insertions(+), 134 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalOptions.java	Mon Jun 20 19:22:01 2011 +0200
@@ -36,6 +36,9 @@
     private static final boolean ____ = false;
     // Checkstyle: resume
 
+
+    public static boolean Lower                              = true;
+
     // inlining settings
     public static boolean Inline                             = true;
     public static boolean CacheGraphs                        = ____;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Jun 20 19:22:01 2011 +0200
@@ -407,20 +407,7 @@
 
     @Override
     public void visitGuardNode(GuardNode x) {
-        FrameState state = lastState;
-        assert state != null : "deoptimize instruction always needs a state";
-
-        if (deoptimizationStubs == null) {
-            deoptimizationStubs = new ArrayList<DeoptimizationStub>();
-        }
-
-        DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state);
-        deoptimizationStubs.add(stub);
-
-        emitCompare(x.node());
-        //emitBranch(x.node(), stub.label)
-        throw new RuntimeException();
-        //lir.branch(x.condition.negate(), stub.label, stub.info);
+        emitGuardComp(x.node());
     }
 
 
@@ -460,28 +447,38 @@
 
     @Override
     public void visitIf(If x) {
-        emitCompare(x.compare());
-        emitBranch(x.compare(), getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()));
+        Condition cond = emitBooleanBranch(x.compare());
+        emitBranch(x.compare(), cond, getLIRBlock(x.trueSuccessor()), getLIRBlock(x.falseSuccessor()));
         assert x.defaultSuccessor() == x.falseSuccessor() : "wrong destination above";
         LIRBlock block = getLIRBlock(x.defaultSuccessor());
         assert block != null : x;
         lir.jump(block);
     }
 
-    public void emitBranch(Compare compare, LIRBlock trueSuccessor, LIRBlock falseSucc) {
-        Condition cond = compare.condition();
-        if (compare.x().kind.isFloat() || compare.x().kind.isDouble()) {
-            LIRBlock unorderedSuccBlock = falseSucc;
-            if (compare.unorderedIsTrue()) {
-                unorderedSuccBlock = trueSuccessor;
+    public void emitBranch(BooleanNode n, Condition cond, LIRBlock trueSuccessor, LIRBlock falseSucc) {
+        if (n instanceof Compare) {
+            Compare compare = (Compare) n;
+            if (compare.x().kind.isFloat() || compare.x().kind.isDouble()) {
+                LIRBlock unorderedSuccBlock = falseSucc;
+                if (compare.unorderedIsTrue()) {
+                    unorderedSuccBlock = trueSuccessor;
+                }
+                lir.branch(cond, trueSuccessor, unorderedSuccBlock);
+                return;
             }
-            lir.branch(cond, trueSuccessor, unorderedSuccBlock);
+        }
+        lir.branch(cond, trueSuccessor);
+    }
+
+    public Condition emitBooleanBranch(BooleanNode node) {
+        if (node instanceof Compare) {
+            return emitCompare((Compare) node);
         } else {
-            lir.branch(cond, trueSuccessor);
+            throw Util.unimplemented();
         }
     }
 
-    public void emitCompare(Compare compare) {
+    public Condition emitCompare(Compare compare) {
         CiKind kind = compare.x().kind;
 
         Condition cond = compare.condition();
@@ -512,6 +509,7 @@
         CiValue left = xin.result();
         CiValue right = yin.result();
         lir.cmp(cond, left, right);
+        return cond;
     }
 
     @Override
@@ -707,11 +705,11 @@
 
     @Override
     public void visitFixedGuard(FixedGuard fixedGuard) {
-        Node comp = fixedGuard.node();
+        BooleanNode comp = fixedGuard.node();
         emitGuardComp(comp);
     }
 
-    public void emitGuardComp(Node comp) {
+    public void emitGuardComp(BooleanNode comp) {
         if (comp instanceof IsNonNull) {
             IsNonNull x = (IsNonNull) comp;
             CiValue value = load(x.object());
@@ -724,6 +722,19 @@
             XirArgument clazz = toXirArgument(x.type().getEncoding(Representation.ObjectHub));
             XirSnippet typeCheck = xir.genTypeCheck(site(x), toXirArgument(x.object()), clazz, x.type());
             emitXir(typeCheck, x, info, compilation.method, false);
+        } else {
+            FrameState state = lastState;
+            assert state != null : "deoptimize instruction always needs a state";
+
+            if (deoptimizationStubs == null) {
+                deoptimizationStubs = new ArrayList<DeoptimizationStub>();
+            }
+
+            DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state);
+            deoptimizationStubs.add(stub);
+
+            Condition cond = emitBooleanBranch(comp);
+            lir.branch(cond.negate(), stub.label, stub.info);
         }
     }
 
@@ -1434,14 +1445,17 @@
 
     @Override
     public void visitMemoryRead(MemoryRead memRead) {
-        if (memRead.guard() != null) {
-            emitGuardComp(memRead.guard());
-        }
         lir.move(new CiAddress(memRead.valueKind(), load(memRead.location()), memRead.displacement()), createResultVariable(memRead), memRead.valueKind());
     }
 
 
     @Override
+    public void visitMemoryWrite(MemoryWrite memWrite) {
+        lir.move(load(memWrite.location()), new CiAddress(memWrite.valueKind(), load(memWrite.location()), memWrite.displacement()), memWrite.valueKind());
+    }
+
+
+    @Override
     public void visitLoopEnd(LoopEnd x) {
         setNoResult(x);
         moveToPhi(x.loopBegin(), x.loopBegin().endCount());
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Mon Jun 20 19:22:01 2011 +0200
@@ -104,7 +104,9 @@
 
         new LoopPhase().apply(graph);
 
-        new LoweringPhase(compilation.runtime).apply(graph);
+        if (GraalOptions.Lower) {
+            new LoweringPhase(compilation.runtime).apply(graph);
+        }
 
         IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true);
         schedule.apply(graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Anchor.java	Mon Jun 20 19:22:01 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
+import java.util.*;
+
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
@@ -52,6 +54,42 @@
         out.print("anchor ").print(next());
     }
 
+    public Iterable<GuardNode> happensAfterGuards() {
+        final Iterator<Node> usages = this.usages().iterator();
+        return new Iterable<GuardNode>() {
+            public Iterator<GuardNode> iterator() {
+                return new Iterator<GuardNode>() {
+                    private GuardNode next;
+                    @Override
+                    public boolean hasNext() {
+                        if (next == null) {
+                            while (usages.hasNext()) {
+                                Node cur = usages.next();
+                                if (cur instanceof GuardNode) {
+                                    next = ((GuardNode) cur);
+                                    break;
+                                }
+                            }
+                        }
+                        return next != null;
+                    }
+
+                    @Override
+                    public GuardNode next() {
+                        GuardNode result = next;
+                        next = null;
+                        return result;
+                    }
+
+                    @Override
+                    public void remove() {
+                        throw new IllegalStateException();
+                    }
+                };
+            }
+        };
+    }
+
     @Override
     public Node copy(Graph into) {
         return new Anchor(into);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BooleanNode.java	Mon Jun 20 19:22:01 2011 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class BooleanNode extends FloatingNode {
+
+    public BooleanNode(CiKind kind, int inputCount, int successorCount, Graph graph) {
+        super(kind, inputCount, successorCount, graph);
+    }
+
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java	Mon Jun 20 19:22:01 2011 +0200
@@ -34,7 +34,7 @@
  * into variants that do not materialize the value (CompareIf, CompareGuard...)
  *
  */
-public final class Compare extends FloatingNode {
+public final class Compare extends BooleanNode {
 
     private static final int INPUT_COUNT = 2;
     private static final int INPUT_X = 0;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Mon Jun 20 19:22:01 2011 +0200
@@ -36,12 +36,12 @@
     /**
      * The instruction that produces the object tested against null.
      */
-     public FloatingNode node() {
-        return (FloatingNode) inputs().get(super.inputCount() + INPUT_NODE);
+     public BooleanNode node() {
+        return (BooleanNode) inputs().get(super.inputCount() + INPUT_NODE);
     }
 
-    public FloatingNode setNode(FloatingNode n) {
-        return (FloatingNode) inputs().set(super.inputCount() + INPUT_NODE, n);
+    public void setNode(BooleanNode n) {
+        inputs().set(super.inputCount() + INPUT_NODE, n);
     }
 
     public FixedGuard(Graph graph) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java	Mon Jun 20 19:22:01 2011 +0200
@@ -27,21 +27,30 @@
 import com.sun.cri.ci.*;
 
 
-public final class GuardNode extends Instruction {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_NODE = 0;
+public final class GuardNode extends FloatingNode {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_ANCHOR = 0;
+    private static final int INPUT_NODE = 1;
 
     private static final int SUCCESSOR_COUNT = 0;
 
+    public FixedNode anchor() {
+        return (FixedNode) inputs().get(super.inputCount() + INPUT_ANCHOR);
+    }
+
+    public void setAnchor(FixedNode anchor) {
+        inputs().set(super.inputCount() + INPUT_ANCHOR, anchor);
+    }
+
     /**
      * The instruction that produces the object tested against null.
      */
-     public Compare node() {
-        return (Compare) inputs().get(super.inputCount() + INPUT_NODE);
+    public BooleanNode node() {
+        return (BooleanNode) inputs().get(super.inputCount() + INPUT_NODE);
     }
 
-    public Compare setNode(Compare n) {
-        return (Compare) inputs().set(super.inputCount() + INPUT_NODE, n);
+    public void setNode(BooleanNode n) {
+        inputs().set(super.inputCount() + INPUT_NODE, n);
     }
 
     public GuardNode(Graph graph) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Mon Jun 20 19:22:01 2011 +0200
@@ -50,17 +50,17 @@
     /**
      * The instruction that produces the first input to this comparison.
      */
-     public Compare compare() {
-        return (Compare) inputs().get(super.inputCount() + INPUT_COMPARE);
+     public BooleanNode compare() {
+        return (BooleanNode) inputs().get(super.inputCount() + INPUT_COMPARE);
     }
 
-    public Value setCompare(Compare n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_COMPARE, n);
+    public void setCompare(BooleanNode n) {
+        inputs().set(super.inputCount() + INPUT_COMPARE, n);
     }
 
-    public If(Compare compare, Graph graph) {
+    public If(BooleanNode condition, Graph graph) {
         super(CiKind.Illegal, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        setCompare(compare);
+        setCompare(condition);
     }
 
     /**
@@ -96,11 +96,7 @@
     @Override
     public void print(LogStream out) {
         out.print("if ").
-        print(compare().x()).
-        print(' ').
-        print(compare().condition().operator).
-        print(' ').
-        print(compare().y()).
+        print(compare()).
         print(" then ").
         print(trueSuccessor()).
         print(" else ").
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java	Mon Jun 20 19:22:01 2011 +0200
@@ -32,7 +32,7 @@
 /**
  * The {@code NullCheck} class represents an explicit null check instruction.
  */
-public final class IsNonNull extends FloatingNode {
+public final class IsNonNull extends BooleanNode {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_OBJECT = 0;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java	Mon Jun 20 19:22:01 2011 +0200
@@ -34,7 +34,7 @@
 /**
  * The {@code TypeCheck} class represents an explicit type check instruction.
  */
-public final class IsType extends FloatingNode {
+public final class IsType extends BooleanNode {
 
     private static final int INPUT_COUNT = 1;
     private static final int INPUT_OBJECT = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryAccess.java	Mon Jun 20 19:22:01 2011 +0200
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class MemoryAccess extends Instruction {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_NODE = 0;
+    private static final int INPUT_GUARD = 1;
+
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private int displacement;
+    private CiKind valueKind;
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public Value location() {
+        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
+    }
+
+    public Value setLocation(Value n) {
+        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
+    }
+
+    /**
+     * The instruction that produces the object tested against null.
+     */
+     public GuardNode guard() {
+        return (GuardNode) inputs().get(super.inputCount() + INPUT_GUARD);
+    }
+
+    public void setGuard(GuardNode n) {
+        inputs().set(super.inputCount() + INPUT_GUARD, n);
+    }
+
+    public int displacement() {
+        return displacement;
+    }
+
+    public CiKind valueKind() {
+        return valueKind;
+    }
+
+    public MemoryAccess(CiKind kind, int displacement, int inputCount, int successorCount, Graph graph) {
+        super(kind.stackKind(), INPUT_COUNT + inputCount, SUCCESSOR_COUNT + successorCount, graph);
+        this.displacement = displacement;
+        this.valueKind = kind;
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem read from ").print(location());
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryRead.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryRead.java	Mon Jun 20 19:22:01 2011 +0200
@@ -27,50 +27,13 @@
 import com.sun.cri.ci.*;
 
 
-public final class MemoryRead extends Instruction {
-    private static final int INPUT_COUNT = 2;
-    private static final int INPUT_NODE = 0;
-    private static final int INPUT_GUARD = 1;
-
+public final class MemoryRead extends MemoryAccess {
+    private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
-    private int displacement;
-    private CiKind valueKind;
-
-    /**
-     * The instruction that produces the object tested against null.
-     */
-     public Value location() {
-        return (Value) inputs().get(super.inputCount() + INPUT_NODE);
-    }
-
-    public Value setLocation(Value n) {
-        return (Value) inputs().set(super.inputCount() + INPUT_NODE, n);
-    }
-
-    /**
-     * The instruction that produces the object tested against null.
-     */
-     public FloatingNode guard() {
-        return (FloatingNode) inputs().get(super.inputCount() + INPUT_GUARD);
-    }
-
-    public FloatingNode setGuard(FloatingNode n) {
-        return (FloatingNode) inputs().set(super.inputCount() + INPUT_GUARD, n);
-    }
-
-    public int displacement() {
-        return displacement;
-    }
-
-    public CiKind valueKind() {
-        return valueKind;
-    }
 
     public MemoryRead(CiKind kind, int displacement, Graph graph) {
-        super(kind.stackKind(), INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        this.displacement = displacement;
-        this.valueKind = kind;
+        super(kind, displacement, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MemoryWrite.java	Mon Jun 20 19:22:01 2011 +0200
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011, 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.max.graal.compiler.ir;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class MemoryWrite extends MemoryAccess {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public void setValue(Value v) {
+        inputs().set(super.inputCount() + INPUT_VALUE, v);
+    }
+
+    public MemoryWrite(CiKind kind, Value value, int displacement, Graph graph) {
+        super(kind, displacement, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setValue(value);
+    }
+
+    @Override
+    public void accept(ValueVisitor v) {
+        v.visitMemoryWrite(this);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("mem write to ").print(location()).print(" with value").print(value());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new MemoryWrite(super.kind, null, displacement(), into);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreField.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/StoreField.java	Mon Jun 20 19:22:01 2011 +0200
@@ -23,6 +23,8 @@
 package com.oracle.max.graal.compiler.ir;
 
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.phases.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -76,6 +78,15 @@
         v.visitStoreField(this);
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(java.lang.Class<T> clazz) {
+        if (clazz == LoweringOp.class) {
+            return (T) LoweringPhase.DELEGATE_TO_RUNTIME;
+        }
+        return null;
+    };
+
     @Override
     public void print(LogStream out) {
         out.print(object()).
@@ -89,7 +100,6 @@
 
     @Override
     public Node copy(Graph into) {
-        StoreField x = new StoreField(null, field, null, into);
-        return x;
+        return new StoreField(null, field, null, into);
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Mon Jun 20 19:22:01 2011 +0200
@@ -154,28 +154,6 @@
     }
 
     /**
-     * Compute the value number of this Instruction. Local and global value numbering
-     * optimizations use a hash map, and the value number provides a hash code.
-     * If the instruction cannot be value numbered, then this method should return
-     * {@code 0}.
-     * @return the hashcode of this instruction
-     */
-    public int valueNumber() {
-        return 0;
-    }
-
-    /**
-     * Checks that this instruction is equal to another instruction for the purposes
-     * of value numbering.
-     * @param i the other instruction
-     * @return {@code true} if this instruction is equivalent to the specified
-     * instruction w.r.t. value numbering
-     */
-    public boolean valueEqual(Node i) {
-        return false;
-    }
-
-    /**
      * This method supports the visitor pattern by accepting a visitor and calling the
      * appropriate {@code visit()} method.
      *
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java	Mon Jun 20 19:22:01 2011 +0200
@@ -52,6 +52,7 @@
     public abstract void visitLogic(Logic i);
     public abstract void visitLookupSwitch(LookupSwitch i);
     public abstract void visitMemoryRead(MemoryRead i);
+    public abstract void visitMemoryWrite(MemoryWrite i);
     public abstract void visitMonitorAddress(MonitorAddress monitorAddress);
     public abstract void visitMonitorEnter(MonitorEnter i);
     public abstract void visitMonitorExit(MonitorExit i);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoweringPhase.java	Mon Jun 20 19:22:01 2011 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.schedule.*;
-import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
@@ -50,28 +49,57 @@
         s.apply(graph);
 
         for (Block b : s.getBlocks()) {
-            //final Node firstNode = b.firstNode();
+            final Node[] firstNodeValue = new Node[]{b.firstNode()};
 
             final CiLoweringTool loweringTool = new CiLoweringTool() {
                 @Override
                 public Node getGuardAnchor() {
-                    throw Util.unimplemented();
-//                    if (!(firstNode instanceof Anchor) && !(firstNode instanceof Merge)) {
-//                        Anchor a = new Anchor(graph);
-//                        assert firstNode.predecessors().size() == 1;
-//                        Node pred = firstNode.predecessors().get(0);
-//                        int predIndex = firstNode.predecessorsIndex().get(0);
-//                        a.successors().setAndClear(Instruction.SUCCESSOR_NEXT, pred, predIndex);
-//                        pred.successors().set(predIndex, a);
-//                        return a;
-//                    }
-//                    return firstNode;
+                    Node firstNode = firstNodeValue[0];
+                    if (firstNode == firstNode.graph().start()) {
+                        Anchor a = new Anchor(graph);
+                        a.setNext((FixedNode) firstNode.graph().start().start());
+                        firstNode.graph().start().setStart(a);
+                        firstNodeValue[0] = a;
+                        return a;
+                    } else if (firstNode instanceof Merge) {
+                        Merge merge = (Merge) firstNode;
+                        Anchor a = new Anchor(graph);
+                        a.setNext(merge.next());
+                        merge.setNext(a);
+                        firstNodeValue[0] = a;
+                        return a;
+                    } else if (!(firstNode instanceof Anchor)) {
+                        Anchor a = new Anchor(graph);
+                        assert firstNode.predecessors().size() == 1 : firstNode;
+                        Node pred = firstNode.predecessors().get(0);
+                        int predIndex = pred.successors().indexOf(firstNode);
+                        pred.successors().set(predIndex, a);
+                        a.setNext((FixedNode) firstNode);
+                        firstNodeValue[0] = a;
+                        return a;
+                    }
+                    return firstNode;
                 }
 
                 @Override
                 public RiRuntime getRuntime() {
                     return runtime;
                 }
+
+                @Override
+                public Node createGuard(Node condition) {
+                    Anchor anchor = (Anchor) getGuardAnchor();
+                    for (GuardNode guard : anchor.happensAfterGuards()) {
+                        if (guard.node().valueEqual(condition)) {
+                            condition.delete();
+                            return guard;
+                        }
+                    }
+                    GuardNode newGuard = new GuardNode(graph);
+                    newGuard.setAnchor(anchor);
+                    newGuard.setNode((BooleanNode) condition);
+                    return newGuard;
+                }
             };
 
             for (final Node n : b.getInstructions()) {
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Mon Jun 20 19:06:35 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Mon Jun 20 19:22:01 2011 +0200
@@ -251,10 +251,23 @@
             int displacement = ((HotSpotField) field.field()).offset();
             assert field.kind != CiKind.Illegal;
             MemoryRead memoryRead = new MemoryRead(field.field().kind(), displacement, graph);
-            memoryRead.setGuard(new IsNonNull(field.object(), graph));
+            memoryRead.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
             memoryRead.setNext(field.next());
             memoryRead.setLocation(field.object());
             return memoryRead;
+        } else if (n instanceof StoreField) {
+            return null;
+//            StoreField field = (StoreField) n;
+//            if (field.isVolatile()) {
+//                return null;
+//            }
+//            Graph graph = field.graph();
+//            int displacement = ((HotSpotField) field.field()).offset();
+//            MemoryWrite memoryWrite = new MemoryWrite(field.field().kind(), field.value(), displacement, graph);
+//            memoryWrite.setGuard((GuardNode) tool.createGuard(new IsNonNull(field.object(), graph)));
+//            memoryWrite.setNext(field.next());
+//            memoryWrite.setLocation(field.object());
+//            return memoryWrite;
         }
         return null;
     }