changeset 6589:341f34427e09

Merge.
author Doug Simon <doug.simon@oracle.com>
date Mon, 29 Oct 2012 17:22:25 +0100
parents b89b5038ad7e (current diff) 795df1687282 (diff)
children dc5eec61daba
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CheckCastEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeCheckCastEliminationPhase.java
diffstat 7 files changed, 462 insertions(+), 462 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Oct 29 17:12:47 2012 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Oct 29 17:22:25 2012 +0100
@@ -165,7 +165,7 @@
         Debug.dump(graph, "Graph");
 //        TypeSystemTest.outputGraph(graph);
         new CanonicalizerPhase(null, runtime(), null).apply(graph);
-        new CheckCastEliminationPhase().apply(graph);
+        new ConditionalEliminationPhase().apply(graph);
         new CanonicalizerPhase(null, runtime(), null).apply(graph);
         StructuredGraph referenceGraph = parse(referenceSnippet);
         assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Oct 29 17:12:47 2012 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Oct 29 17:22:25 2012 +0100
@@ -190,7 +190,7 @@
             StructuredGraph graph = parse(snippet);
             Debug.dump(graph, "Graph");
             new CanonicalizerPhase(null, runtime(), null).apply(graph);
-            new CheckCastEliminationPhase().apply(graph);
+            new ConditionalEliminationPhase().apply(graph);
             new CanonicalizerPhase(null, runtime(), null).apply(graph);
             new GlobalValueNumberingPhase().apply(graph);
             StructuredGraph referenceGraph = parse(referenceSnippet);
@@ -254,7 +254,7 @@
             StructuredGraph graph = parse(snippet);
             Debug.dump(graph, "Graph");
             new CanonicalizerPhase(null, runtime(), null).apply(graph);
-            new CheckCastEliminationPhase().apply(graph);
+            new ConditionalEliminationPhase().apply(graph);
             new CanonicalizerPhase(null, runtime(), null).apply(graph);
             Debug.dump(graph, "Graph");
             Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Oct 29 17:12:47 2012 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Oct 29 17:22:25 2012 +0100
@@ -134,7 +134,7 @@
             }
 
             if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) {
-                new IterativeCheckCastEliminationPhase(target, runtime, assumptions).apply(graph);
+                new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph);
             }
         }
 
@@ -191,7 +191,7 @@
         }
 
         if (GraalOptions.CheckCastElimination && GraalOptions.OptCanonicalizer) {
-            new IterativeCheckCastEliminationPhase(target, runtime, assumptions).apply(graph);
+            new IterativeConditionalEliminationPhase(target, runtime, assumptions).apply(graph);
         }
 
         plan.runPhases(PhasePosition.MID_LEVEL, graph);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CheckCastEliminationPhase.java	Mon Oct 29 17:12:47 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,384 +0,0 @@
-/*
- * Copyright (c) 2012, 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.phases.common;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.graph.*;
-
-public class CheckCastEliminationPhase extends Phase {
-
-    private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered");
-    private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered");
-    private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved");
-    private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved");
-    private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved");
-    private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved");
-    private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced");
-
-    private StructuredGraph graph;
-
-    @Override
-    protected void run(StructuredGraph inputGraph) {
-        graph = inputGraph;
-        new EliminateCheckCasts(graph.start(), new State()).apply();
-    }
-
-    public static class State implements MergeableState<State> {
-
-        private IdentityHashMap<ValueNode, ResolvedJavaType> knownTypes;
-        private HashSet<ValueNode> knownNotNull;
-        private HashSet<ValueNode> knownNull;
-        private IdentityHashMap<BooleanNode, ValueNode> trueConditions;
-        private IdentityHashMap<BooleanNode, ValueNode> falseConditions;
-
-        public State() {
-            this.knownTypes = new IdentityHashMap<>();
-            this.knownNotNull = new HashSet<>();
-            this.knownNull = new HashSet<>();
-            this.trueConditions = new IdentityHashMap<>();
-            this.falseConditions = new IdentityHashMap<>();
-        }
-
-        public State(State other) {
-            this.knownTypes = new IdentityHashMap<>(other.knownTypes);
-            this.knownNotNull = new HashSet<>(other.knownNotNull);
-            this.knownNull = new HashSet<>(other.knownNull);
-            this.trueConditions = new IdentityHashMap<>(other.trueConditions);
-            this.falseConditions = new IdentityHashMap<>(other.falseConditions);
-        }
-
-        @Override
-        public boolean merge(MergeNode merge, List<State> withStates) {
-            IdentityHashMap<ValueNode, ResolvedJavaType> newKnownTypes = new IdentityHashMap<>();
-            HashSet<ValueNode> newKnownNotNull = new HashSet<>();
-            HashSet<ValueNode> newKnownNull = new HashSet<>();
-            IdentityHashMap<BooleanNode, ValueNode> newTrueConditions = new IdentityHashMap<>();
-            IdentityHashMap<BooleanNode, ValueNode> newFalseConditions = new IdentityHashMap<>();
-
-            for (Map.Entry<ValueNode, ResolvedJavaType> entry : knownTypes.entrySet()) {
-                ValueNode node = entry.getKey();
-                ResolvedJavaType type = entry.getValue();
-
-                for (State other : withStates) {
-                    ResolvedJavaType otherType = other.getNodeType(node);
-                    type = widen(type, otherType);
-                    if (type == null) {
-                        break;
-                    }
-                }
-                if (type == null && type != node.objectStamp().type()) {
-                    newKnownTypes.put(node, type);
-                }
-            }
-            for (ValueNode node : knownNotNull) {
-                boolean notNull = true;
-                for (State other : withStates) {
-                    if (!other.knownNotNull.contains(node)) {
-                        notNull = false;
-                        break;
-                    }
-                }
-                if (notNull) {
-                    newKnownNotNull.add(node);
-                }
-            }
-            for (ValueNode node : knownNull) {
-                boolean nul = true;
-                for (State other : withStates) {
-                    if (!other.knownNull.contains(node)) {
-                        nul = false;
-                        break;
-                    }
-                }
-                if (nul) {
-                    newKnownNull.add(node);
-                }
-            }
-            for (Map.Entry<BooleanNode, ValueNode> entry : trueConditions.entrySet()) {
-                BooleanNode check = entry.getKey();
-                ValueNode guard = entry.getValue();
-
-                for (State other : withStates) {
-                    ValueNode otherGuard = other.trueConditions.get(check);
-                    if (otherGuard == null) {
-                        guard = null;
-                        break;
-                    }
-                    if (otherGuard != guard) {
-                        guard = merge;
-                    }
-                }
-                if (guard != null) {
-                    newTrueConditions.put(check, guard);
-                }
-            }
-            for (Map.Entry<BooleanNode, ValueNode> entry : falseConditions.entrySet()) {
-                BooleanNode check = entry.getKey();
-                ValueNode guard = entry.getValue();
-
-                for (State other : withStates) {
-                    ValueNode otherGuard = other.falseConditions.get(check);
-                    if (otherGuard == null) {
-                        guard = null;
-                        break;
-                    }
-                    if (otherGuard != guard) {
-                        guard = merge;
-                    }
-                }
-                if (guard != null) {
-                    newFalseConditions.put(check, guard);
-                }
-            }
-
-            /*
-            // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values)
-            if (!(merge instanceof LoopBeginNode)) {
-                for (PhiNode phi : merge.phis()) {
-                    if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) {
-                        ValueNode firstValue = phi.valueAt(0);
-                        ResolvedJavaType type = getNodeType(firstValue);
-                        boolean notNull = knownNotNull.contains(firstValue);
-                        boolean nul = knownNull.contains(firstValue);
-
-                        for (int i = 0; i < withStates.size(); i++) {
-                            State otherState = withStates.get(i);
-                            ValueNode value = phi.valueAt(i + 1);
-                            ResolvedJavaType otherType = otherState.getNodeType(value);
-                            type = widen(type, otherType);
-                            notNull &= otherState.knownNotNull.contains(value);
-                            nul &= otherState.knownNull.contains(value);
-                        }
-                        if (type == null && type != phi.declaredType()) {
-                            newKnownTypes.put(phi, type);
-                        }
-                        if (notNull) {
-                            newKnownNotNull.add(phi);
-                        }
-                        if (nul) {
-                            newKnownNull.add(phi);
-                        }
-                    }
-                }
-            }
-            */
-            this.knownTypes = newKnownTypes;
-            this.knownNotNull = newKnownNotNull;
-            this.knownNull = newKnownNull;
-            this.trueConditions = newTrueConditions;
-            this.falseConditions = newFalseConditions;
-            return true;
-        }
-
-        public ResolvedJavaType getNodeType(ValueNode node) {
-            ResolvedJavaType result = knownTypes.get(node);
-            return result == null ? node.objectStamp().type() : result;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<State> loopEndStates) {
-        }
-
-        @Override
-        public void afterSplit(FixedNode node) {
-        }
-
-        @Override
-        public State clone() {
-            return new State(this);
-        }
-    }
-
-    public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) {
-        if (a == null || b == null) {
-            return null;
-        } else if (a == b) {
-            return a;
-        } else {
-            return a.findLeastCommonAncestor(b);
-        }
-    }
-
-    public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) {
-        if (a == null) {
-            return b;
-        } else if (b == null) {
-            return a;
-        } else if (a == b) {
-            return a;
-        } else if (a.isSubtypeOf(b)) {
-            return a;
-        } else if (b.isSubtypeOf(a)) {
-            return b;
-        } else {
-            return a;
-        }
-    }
-
-    public class EliminateCheckCasts extends PostOrderNodeIterator<State> {
-        private BeginNode lastBegin = null;
-
-        public EliminateCheckCasts(FixedNode start, State initialState) {
-            super(start, initialState);
-        }
-
-        @Override
-        protected void node(FixedNode node) {
-            if (node instanceof BeginNode) {
-                BeginNode begin = (BeginNode) node;
-                lastBegin = begin;
-                Node pred = node.predecessor();
-                if (pred != null && pred instanceof IfNode) {
-                    IfNode ifNode = (IfNode) pred;
-                    if (!(ifNode.condition() instanceof ConstantNode)) {
-                        boolean isTrue = (node == ifNode.trueSuccessor());
-                        if (isTrue) {
-                            state.trueConditions.put(ifNode.condition(), begin);
-                        } else {
-                            state.falseConditions.put(ifNode.condition(), begin);
-                        }
-                    }
-                    if (ifNode.condition() instanceof InstanceOfNode) {
-                        InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
-                        if ((node == ifNode.trueSuccessor())) {
-                            ValueNode object = instanceOf.object();
-                            state.knownNotNull.add(object);
-                            state.knownTypes.put(object, tighten(instanceOf.targetClass(), state.getNodeType(object)));
-                            metricInstanceOfRegistered.increment();
-                        }
-                    } else if (ifNode.condition() instanceof IsNullNode) {
-                        IsNullNode nullCheck = (IsNullNode) ifNode.condition();
-                        boolean isNull = (node == ifNode.trueSuccessor());
-                        if (isNull) {
-                            state.knownNull.add(nullCheck.object());
-                        } else {
-                            state.knownNotNull.add(nullCheck.object());
-                        }
-                        metricNullCheckRegistered.increment();
-                    }
-                }
-                for (GuardNode guard : begin.guards().snapshot()) {
-                    BooleanNode condition = guard.condition();
-                    ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition);
-                    if (existingGuards != null) {
-                        guard.replaceAtUsages(existingGuards);
-                        GraphUtil.killWithUnusedFloatingInputs(guard);
-                        metricGuardsReplaced.increment();
-                    } else {
-                        boolean removeCheck = false;
-                        if (condition instanceof IsNullNode) {
-                            IsNullNode isNull = (IsNullNode) condition;
-                            if (guard.negated() && state.knownNotNull.contains(isNull.object())) {
-                                removeCheck = true;
-                            } else if (!guard.negated() && state.knownNull.contains(isNull.object())) {
-                                removeCheck = true;
-                            }
-                            if (removeCheck) {
-                                metricNullCheckGuardRemoved.increment();
-                            }
-                        }
-                        if (removeCheck) {
-                            guard.replaceAtUsages(begin);
-                            GraphUtil.killWithUnusedFloatingInputs(guard);
-                        } else {
-                            if (guard.negated()) {
-                                state.falseConditions.put(condition, guard);
-                            } else {
-                                state.trueConditions.put(condition, guard);
-                            }
-                        }
-                    }
-                }
-            } else if (node instanceof CheckCastNode) {
-                CheckCastNode checkCast = (CheckCastNode) node;
-                ResolvedJavaType type = state.getNodeType(checkCast.object());
-                if (checkCast.targetClass() != null && type != null && type.isSubtypeOf(checkCast.targetClass())) {
-                    PiNode piNode;
-                    boolean nonNull = state.knownNotNull.contains(checkCast.object());
-                    piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type)));
-                    checkCast.replaceAtUsages(piNode);
-                    graph.removeFixed(checkCast);
-                    metricCheckCastRemoved.increment();
-                }
-            } else if (node instanceof IfNode) {
-                IfNode ifNode = (IfNode) node;
-                BooleanNode replaceWith = null;
-                BooleanNode compare = ifNode.condition();
-
-                if (state.trueConditions.containsKey(compare)) {
-                    replaceWith = ConstantNode.forBoolean(true, graph);
-                } else if (state.falseConditions.containsKey(compare)) {
-                    replaceWith = ConstantNode.forBoolean(false, graph);
-                } else {
-                    if (compare instanceof InstanceOfNode) {
-                        InstanceOfNode instanceOf = (InstanceOfNode) compare;
-                        ValueNode object = instanceOf.object();
-                        if (state.knownNull.contains(object)) {
-                            replaceWith = ConstantNode.forBoolean(false, graph);
-                        } else if (state.knownNotNull.contains(object)) {
-                            ResolvedJavaType type = state.getNodeType(object);
-                            if (type != null && type.isSubtypeOf(instanceOf.targetClass())) {
-                                replaceWith = ConstantNode.forBoolean(true, graph);
-                            }
-                        }
-                        if (replaceWith != null) {
-                            metricInstanceOfRemoved.increment();
-                        }
-                    } else if (compare instanceof IsNullNode) {
-                        IsNullNode isNull = (IsNullNode) compare;
-                        ValueNode object = isNull.object();
-                        if (state.knownNull.contains(object)) {
-                            replaceWith = ConstantNode.forBoolean(true, graph);
-                        } else if (state.knownNotNull.contains(object)) {
-                            replaceWith = ConstantNode.forBoolean(false, graph);
-                        }
-                        if (replaceWith != null) {
-                            metricNullCheckRemoved.increment();
-                        }
-                    }
-                }
-                if (replaceWith != null) {
-                    ifNode.setCondition(replaceWith);
-                    if (compare.usages().isEmpty()) {
-                        GraphUtil.killWithUnusedFloatingInputs(compare);
-                    }
-                }
-            }
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Oct 29 17:22:25 2012 +0100
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2012, 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.phases.common;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
+
+public class ConditionalEliminationPhase extends Phase {
+
+    private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered");
+    private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered");
+    private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved");
+    private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved");
+    private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved");
+    private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved");
+    private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced");
+
+    private StructuredGraph graph;
+
+    @Override
+    protected void run(StructuredGraph inputGraph) {
+        graph = inputGraph;
+        new ConditionalElimination(graph.start(), new State()).apply();
+    }
+
+    public static class State implements MergeableState<State> {
+
+        private IdentityHashMap<ValueNode, ResolvedJavaType> knownTypes;
+        private HashSet<ValueNode> knownNotNull;
+        private HashSet<ValueNode> knownNull;
+        private IdentityHashMap<BooleanNode, ValueNode> trueConditions;
+        private IdentityHashMap<BooleanNode, ValueNode> falseConditions;
+
+        public State() {
+            this.knownTypes = new IdentityHashMap<>();
+            this.knownNotNull = new HashSet<>();
+            this.knownNull = new HashSet<>();
+            this.trueConditions = new IdentityHashMap<>();
+            this.falseConditions = new IdentityHashMap<>();
+        }
+
+        public State(State other) {
+            this.knownTypes = new IdentityHashMap<>(other.knownTypes);
+            this.knownNotNull = new HashSet<>(other.knownNotNull);
+            this.knownNull = new HashSet<>(other.knownNull);
+            this.trueConditions = new IdentityHashMap<>(other.trueConditions);
+            this.falseConditions = new IdentityHashMap<>(other.falseConditions);
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<State> withStates) {
+            IdentityHashMap<ValueNode, ResolvedJavaType> newKnownTypes = new IdentityHashMap<>();
+            HashSet<ValueNode> newKnownNotNull = new HashSet<>();
+            HashSet<ValueNode> newKnownNull = new HashSet<>();
+            IdentityHashMap<BooleanNode, ValueNode> newTrueConditions = new IdentityHashMap<>();
+            IdentityHashMap<BooleanNode, ValueNode> newFalseConditions = new IdentityHashMap<>();
+
+            for (Map.Entry<ValueNode, ResolvedJavaType> entry : knownTypes.entrySet()) {
+                ValueNode node = entry.getKey();
+                ResolvedJavaType type = entry.getValue();
+
+                for (State other : withStates) {
+                    ResolvedJavaType otherType = other.getNodeType(node);
+                    type = widen(type, otherType);
+                    if (type == null) {
+                        break;
+                    }
+                }
+                if (type == null && type != node.objectStamp().type()) {
+                    newKnownTypes.put(node, type);
+                }
+            }
+            for (ValueNode node : knownNotNull) {
+                boolean notNull = true;
+                for (State other : withStates) {
+                    if (!other.knownNotNull.contains(node)) {
+                        notNull = false;
+                        break;
+                    }
+                }
+                if (notNull) {
+                    newKnownNotNull.add(node);
+                }
+            }
+            for (ValueNode node : knownNull) {
+                boolean isNull = true;
+                for (State other : withStates) {
+                    if (!other.knownNull.contains(node)) {
+                        isNull = false;
+                        break;
+                    }
+                }
+                if (isNull) {
+                    newKnownNull.add(node);
+                }
+            }
+            for (Map.Entry<BooleanNode, ValueNode> entry : trueConditions.entrySet()) {
+                BooleanNode check = entry.getKey();
+                ValueNode guard = entry.getValue();
+
+                for (State other : withStates) {
+                    ValueNode otherGuard = other.trueConditions.get(check);
+                    if (otherGuard == null) {
+                        guard = null;
+                        break;
+                    }
+                    if (otherGuard != guard) {
+                        guard = merge;
+                    }
+                }
+                if (guard != null) {
+                    newTrueConditions.put(check, guard);
+                }
+            }
+            for (Map.Entry<BooleanNode, ValueNode> entry : falseConditions.entrySet()) {
+                BooleanNode check = entry.getKey();
+                ValueNode guard = entry.getValue();
+
+                for (State other : withStates) {
+                    ValueNode otherGuard = other.falseConditions.get(check);
+                    if (otherGuard == null) {
+                        guard = null;
+                        break;
+                    }
+                    if (otherGuard != guard) {
+                        guard = merge;
+                    }
+                }
+                if (guard != null) {
+                    newFalseConditions.put(check, guard);
+                }
+            }
+
+            // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values)
+            if (!(merge instanceof LoopBeginNode)) {
+                for (PhiNode phi : merge.phis()) {
+                    if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) {
+                        ValueNode firstValue = phi.valueAt(0);
+                        ResolvedJavaType type = getNodeType(firstValue);
+                        boolean notNull = knownNotNull.contains(firstValue);
+                        boolean isNull = knownNull.contains(firstValue);
+
+                        for (int i = 0; i < withStates.size(); i++) {
+                            State otherState = withStates.get(i);
+                            ValueNode value = phi.valueAt(i + 1);
+                            ResolvedJavaType otherType = otherState.getNodeType(value);
+                            type = widen(type, otherType);
+                            notNull &= otherState.knownNotNull.contains(value);
+                            isNull &= otherState.knownNull.contains(value);
+                        }
+                        if (type != null) {
+                            newKnownTypes.put(phi, type);
+                        }
+                        if (notNull) {
+                            newKnownNotNull.add(phi);
+                        }
+                        if (isNull) {
+                            newKnownNull.add(phi);
+                        }
+                    }
+                }
+            }
+
+            this.knownTypes = newKnownTypes;
+            this.knownNotNull = newKnownNotNull;
+            this.knownNull = newKnownNull;
+            this.trueConditions = newTrueConditions;
+            this.falseConditions = newFalseConditions;
+            return true;
+        }
+
+        public ResolvedJavaType getNodeType(ValueNode node) {
+            ResolvedJavaType result = knownTypes.get(node);
+            return result == null ? node.objectStamp().type() : result;
+        }
+
+        @Override
+        public void loopBegin(LoopBeginNode loopBegin) {
+        }
+
+        @Override
+        public void loopEnds(LoopBeginNode loopBegin, List<State> loopEndStates) {
+        }
+
+        @Override
+        public void afterSplit(FixedNode node) {
+        }
+
+        @Override
+        public State clone() {
+            return new State(this);
+        }
+    }
+
+    public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) {
+        if (a == null || b == null) {
+            return null;
+        } else if (a == b) {
+            return a;
+        } else {
+            return a.findLeastCommonAncestor(b);
+        }
+    }
+
+    public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) {
+        if (a == null) {
+            return b;
+        } else if (b == null) {
+            return a;
+        } else if (a == b) {
+            return a;
+        } else if (a.isSubtypeOf(b)) {
+            return a;
+        } else if (b.isSubtypeOf(a)) {
+            return b;
+        } else {
+            return a;
+        }
+    }
+
+    public class ConditionalElimination extends PostOrderNodeIterator<State> {
+        private BeginNode lastBegin = null;
+
+        public ConditionalElimination(FixedNode start, State initialState) {
+            super(start, initialState);
+        }
+
+        @Override
+        protected void node(FixedNode node) {
+            if (node instanceof BeginNode) {
+                BeginNode begin = (BeginNode) node;
+                lastBegin = begin;
+                Node pred = node.predecessor();
+                if (pred != null && pred instanceof IfNode) {
+                    IfNode ifNode = (IfNode) pred;
+                    if (!(ifNode.condition() instanceof ConstantNode)) {
+                        boolean isTrue = (node == ifNode.trueSuccessor());
+                        if (isTrue) {
+                            state.trueConditions.put(ifNode.condition(), begin);
+                        } else {
+                            state.falseConditions.put(ifNode.condition(), begin);
+                        }
+                    }
+                    if (ifNode.condition() instanceof InstanceOfNode) {
+                        InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
+                        if ((node == ifNode.trueSuccessor())) {
+                            ValueNode object = instanceOf.object();
+                            state.knownNotNull.add(object);
+                            state.knownTypes.put(object, tighten(instanceOf.targetClass(), state.getNodeType(object)));
+                            metricInstanceOfRegistered.increment();
+                        }
+                    } else if (ifNode.condition() instanceof IsNullNode) {
+                        IsNullNode nullCheck = (IsNullNode) ifNode.condition();
+                        boolean isNull = (node == ifNode.trueSuccessor());
+                        if (isNull) {
+                            state.knownNull.add(nullCheck.object());
+                        } else {
+                            state.knownNotNull.add(nullCheck.object());
+                        }
+                        metricNullCheckRegistered.increment();
+                    }
+                }
+                for (GuardNode guard : begin.guards().snapshot()) {
+                    BooleanNode condition = guard.condition();
+                    ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition);
+                    if (existingGuards != null) {
+                        guard.replaceAtUsages(existingGuards);
+                        GraphUtil.killWithUnusedFloatingInputs(guard);
+                        metricGuardsReplaced.increment();
+                    } else {
+                        boolean removeCheck = false;
+                        if (condition instanceof IsNullNode) {
+                            IsNullNode isNull = (IsNullNode) condition;
+                            if (guard.negated() && state.knownNotNull.contains(isNull.object())) {
+                                removeCheck = true;
+                            } else if (!guard.negated() && state.knownNull.contains(isNull.object())) {
+                                removeCheck = true;
+                            }
+                            if (removeCheck) {
+                                metricNullCheckGuardRemoved.increment();
+                            }
+                        }
+                        if (removeCheck) {
+                            guard.replaceAtUsages(begin);
+                            GraphUtil.killWithUnusedFloatingInputs(guard);
+                        } else {
+                            if (guard.negated()) {
+                                state.falseConditions.put(condition, guard);
+                            } else {
+                                state.trueConditions.put(condition, guard);
+                            }
+                        }
+                    }
+                }
+            } else if (node instanceof CheckCastNode) {
+                CheckCastNode checkCast = (CheckCastNode) node;
+                ResolvedJavaType type = state.getNodeType(checkCast.object());
+                if (checkCast.targetClass() != null && type != null && type.isSubtypeOf(checkCast.targetClass())) {
+                    PiNode piNode;
+                    boolean nonNull = state.knownNotNull.contains(checkCast.object());
+                    piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type)));
+                    checkCast.replaceAtUsages(piNode);
+                    graph.removeFixed(checkCast);
+                    metricCheckCastRemoved.increment();
+                }
+            } else if (node instanceof IfNode) {
+                IfNode ifNode = (IfNode) node;
+                BooleanNode replaceWith = null;
+                BooleanNode compare = ifNode.condition();
+
+                if (state.trueConditions.containsKey(compare)) {
+                    replaceWith = ConstantNode.forBoolean(true, graph);
+                } else if (state.falseConditions.containsKey(compare)) {
+                    replaceWith = ConstantNode.forBoolean(false, graph);
+                } else {
+                    if (compare instanceof InstanceOfNode) {
+                        InstanceOfNode instanceOf = (InstanceOfNode) compare;
+                        ValueNode object = instanceOf.object();
+                        if (state.knownNull.contains(object)) {
+                            replaceWith = ConstantNode.forBoolean(false, graph);
+                        } else if (state.knownNotNull.contains(object)) {
+                            ResolvedJavaType type = state.getNodeType(object);
+                            if (type != null && type.isSubtypeOf(instanceOf.targetClass())) {
+                                replaceWith = ConstantNode.forBoolean(true, graph);
+                            }
+                        }
+                        if (replaceWith != null) {
+                            metricInstanceOfRemoved.increment();
+                        }
+                    } else if (compare instanceof IsNullNode) {
+                        IsNullNode isNull = (IsNullNode) compare;
+                        ValueNode object = isNull.object();
+                        if (state.knownNull.contains(object)) {
+                            replaceWith = ConstantNode.forBoolean(true, graph);
+                        } else if (state.knownNotNull.contains(object)) {
+                            replaceWith = ConstantNode.forBoolean(false, graph);
+                        }
+                        if (replaceWith != null) {
+                            metricNullCheckRemoved.increment();
+                        }
+                    }
+                }
+                if (replaceWith != null) {
+                    ifNode.setCondition(replaceWith);
+                    if (compare.usages().isEmpty()) {
+                        GraphUtil.killWithUnusedFloatingInputs(compare);
+                    }
+                }
+            }
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeCheckCastEliminationPhase.java	Mon Oct 29 17:12:47 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2012, 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.phases.common;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.Graph.InputChangedListener;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-
-
-public class IterativeCheckCastEliminationPhase extends Phase {
-    private final TargetDescription target;
-    private final MetaAccessProvider runtime;
-    private final Assumptions assumptions;
-
-    public IterativeCheckCastEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
-        this.target = target;
-        this.runtime = runtime;
-        this.assumptions = assumptions;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        Set<Node> canonicalizationRoots = new HashSet<>();
-        CheckCastEliminationPhase eliminate = new CheckCastEliminationPhase();
-        Listener listener = new Listener(canonicalizationRoots);
-        while (true) {
-            graph.trackInputChange(listener);
-            eliminate.apply(graph);
-            graph.stopTrackingInputChange();
-            if (canonicalizationRoots.isEmpty()) {
-                break;
-            }
-            new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph);
-            canonicalizationRoots.clear();
-        }
-    }
-
-    private static class Listener implements InputChangedListener {
-        private final Set<Node> canonicalizationRoots;
-        public Listener(Set<Node> canonicalizationRoots) {
-            this.canonicalizationRoots = canonicalizationRoots;
-        }
-        @Override
-        public void inputChanged(Node node) {
-            canonicalizationRoots.add(node);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Oct 29 17:22:25 2012 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012, 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.phases.common;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Graph.InputChangedListener;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+
+
+public class IterativeConditionalEliminationPhase extends Phase {
+    private final TargetDescription target;
+    private final MetaAccessProvider runtime;
+    private final Assumptions assumptions;
+
+    public IterativeConditionalEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
+        this.target = target;
+        this.runtime = runtime;
+        this.assumptions = assumptions;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        Set<Node> canonicalizationRoots = new HashSet<>();
+        ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase();
+        Listener listener = new Listener(canonicalizationRoots);
+        while (true) {
+            graph.trackInputChange(listener);
+            eliminate.apply(graph);
+            graph.stopTrackingInputChange();
+            if (canonicalizationRoots.isEmpty()) {
+                break;
+            }
+            new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph);
+            canonicalizationRoots.clear();
+        }
+    }
+
+    private static class Listener implements InputChangedListener {
+        private final Set<Node> canonicalizationRoots;
+        public Listener(Set<Node> canonicalizationRoots) {
+            this.canonicalizationRoots = canonicalizationRoots;
+        }
+        @Override
+        public void inputChanged(Node node) {
+            canonicalizationRoots.add(node);
+        }
+    }
+}