changeset 19719:7241e6dfcafd

Merge.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 09 Mar 2015 15:04:08 +0100
parents d30a0545ddc2 (diff) dc7189b2bb5f (current diff)
children 79a472b4f024
files
diffstat 109 files changed, 2261 insertions(+), 386 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Mon Mar 09 15:04:08 2015 +0100
@@ -25,7 +25,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 
 /**
  * This profile object represents the type profile at a specific BCI. The precision of the supplied
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ProfilingInfo.java	Mon Mar 09 15:04:08 2015 +0100
@@ -31,34 +31,6 @@
 public interface ProfilingInfo {
 
     /**
-     * Represents the three possibilities that an exception was seen at a specific BCI.
-     */
-    public enum TriState {
-        TRUE,
-        FALSE,
-        UNKNOWN;
-
-        public static TriState get(boolean value) {
-            return value ? TRUE : FALSE;
-        }
-
-        /**
-         * This is optimistic about {@link #UNKNOWN} (it prefers known values over {@link #UNKNOWN})
-         * and pesimistic about known (it perfers {@link #TRUE} over {@link #FALSE}).
-         */
-        public static TriState merge(TriState a, TriState b) {
-            if (a == TRUE || b == TRUE) {
-                return TRUE;
-            }
-            if (a == FALSE || b == FALSE) {
-                return FALSE;
-            }
-            assert a == UNKNOWN && b == UNKNOWN;
-            return UNKNOWN;
-        }
-    }
-
-    /**
      * Returns the length of the bytecodes associated with this profile.
      */
     int getCodeSize();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/TriState.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 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.api.meta;
+
+/**
+ * Represents the three possibilities that an exception was seen at a specific BCI.
+ */
+public enum TriState {
+    TRUE,
+    FALSE,
+    UNKNOWN;
+
+    public static TriState get(boolean value) {
+        return value ? TRUE : FALSE;
+    }
+
+    /**
+     * This is optimistic about {@link #UNKNOWN} (it prefers known values over {@link #UNKNOWN}) and
+     * pesimistic about known (it perfers {@link #TRUE} over {@link #FALSE}).
+     */
+    public static TriState merge(TriState a, TriState b) {
+        if (a == TRUE || b == TRUE) {
+            return TRUE;
+        }
+        if (a == FALSE || b == FALSE) {
+            return FALSE;
+        }
+        assert a == UNKNOWN && b == UNKNOWN;
+        return UNKNOWN;
+    }
+
+    public boolean isTrue() {
+        return this == TRUE;
+    }
+
+    public boolean isFalse() {
+        return this == FALSE;
+    }
+
+    public boolean isUnknown() {
+        return this == UNKNOWN;
+    }
+
+    public boolean isKnown() {
+        return this != UNKNOWN;
+    }
+
+    public boolean toBoolean() {
+        if (isTrue()) {
+            return true;
+        } else if (isFalse()) {
+            return false;
+        } else {
+            throw new IllegalStateException("Cannot convert to boolean, TriState is in an unknown state");
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java	Mon Mar 09 15:04:08 2015 +0100
@@ -135,4 +135,13 @@
         }
         return newStamp;
     }
+
+    public boolean neverDistinct(Stamp other) {
+        Constant constant = this.asConstant();
+        if (constant != null) {
+            Constant otherConstant = other.asConstant();
+            return otherConstant != null && constant.equals(otherConstant);
+        }
+        return false;
+    }
 }
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/StampFactory.java	Mon Mar 09 15:04:08 2015 +0100
@@ -37,6 +37,8 @@
     private static final Stamp objectAlwaysNullStamp = new ObjectStamp(null, false, false, true);
     private static final Stamp nodeIntrinsicStamp = new ObjectStamp(null, false, false, false);
     private static final Stamp positiveInt = forInteger(Kind.Int, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
+    private static final Stamp booleanTrue = forInteger(Kind.Boolean, -1, -1, 1, 1);
+    private static final Stamp booleanFalse = forInteger(Kind.Boolean, 0, 0, 0, 0);
 
     private static void setCache(Kind kind, Stamp stamp) {
         stampCache[kind.ordinal()] = stamp;
@@ -80,6 +82,14 @@
         }
     }
 
+    public static Stamp tautology() {
+        return booleanTrue;
+    }
+
+    public static Stamp contradiction() {
+        return booleanFalse;
+    }
+
     /**
      * Return a stamp for a Java kind, as it would be represented on the bytecode stack.
      */
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -307,8 +307,8 @@
     private void processMethod(final String snippet) {
         graph = parseEager(snippet, AllowAssumptions.NO);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context);
     }
 
     private void compareGraphs(final String snippet, final String referenceSnippet) {
@@ -318,9 +318,9 @@
     private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) {
         graph = parseEager(snippet, AllowAssumptions.NO);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
         canonicalizer.apply(graph, context);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
         if (loopPeeling) {
             new LoopPeelingPhase().apply(graph);
         }
@@ -332,9 +332,9 @@
         canonicalizer.apply(graph, context);
 
         StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(referenceGraph, context);
+        new InliningPhase(new CanonicalizerPhase()).apply(referenceGraph, context);
         new DeadCodeEliminationPhase().apply(referenceGraph);
-        new CanonicalizerPhase(true).apply(referenceGraph, context);
+        new CanonicalizerPhase().apply(referenceGraph, context);
 
         assertEquals(referenceGraph, graph, excludeVirtual, true);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -36,7 +36,7 @@
 
     private StructuredGraph getCanonicalizedGraph(String name) {
         StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         return graph;
     }
 
@@ -53,7 +53,7 @@
             StructuredGraph graph = parseEager("canonicalCompare" + i, AllowAssumptions.NO);
             assertEquals(referenceGraph, graph);
         }
-        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders()));
         for (int i = 1; i < 4; i++) {
             StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * 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.graal.compiler.test;
-
-import org.junit.*;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.tiers.*;
-
-/**
- * Collection of tests for {@link com.oracle.graal.phases.common.ConditionalEliminationPhase}
- * including those that triggered bugs in this phase.
- */
-public class ConditionalEliminationTest extends GraalCompilerTest {
-
-    public static Object field;
-
-    static class Entry {
-
-        final String name;
-
-        public Entry(String name) {
-            this.name = name;
-        }
-    }
-
-    static class EntryWithNext extends Entry {
-
-        public EntryWithNext(String name, Entry next) {
-            super(name);
-            this.next = next;
-        }
-
-        final Entry next;
-    }
-
-    public static Entry search(Entry start, String name, Entry alternative) {
-        Entry current = start;
-        do {
-            while (current instanceof EntryWithNext) {
-                if (name != null && current.name == name) {
-                    current = null;
-                } else {
-                    Entry next = ((EntryWithNext) current).next;
-                    current = next;
-                }
-            }
-
-            if (current != null) {
-                if (current.name.equals(name)) {
-                    return current;
-                }
-            }
-            if (current == alternative) {
-                return null;
-            }
-            current = alternative;
-
-        } while (true);
-    }
-
-    public static int testRedundantComparesSnippet(int[] array) {
-        if (array == null) {
-            return 0;
-        }
-        return array[0] + array[1] + array[2] + array[3];
-    }
-
-    @Test
-    public void testRedundantCompares() {
-        StructuredGraph graph = parseEager("testRedundantComparesSnippet", AllowAssumptions.YES);
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-        PhaseContext context = new PhaseContext(getProviders());
-
-        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
-        canonicalizer.apply(graph, context);
-        new FloatingReadPhase().apply(graph);
-        new ConditionalEliminationPhase().apply(graph, context);
-        canonicalizer.apply(graph, context);
-
-        assertDeepEquals(1, graph.getNodes().filter(GuardNode.class).count());
-    }
-
-    public static String testInstanceOfCheckCastSnippet(Object e) {
-        if (e instanceof Entry) {
-            return ((Entry) e).name;
-        }
-        return null;
-    }
-
-    @Test
-    @Ignore
-    public void testInstanceOfCheckCastLowered() {
-        StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet", AllowAssumptions.YES);
-
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-        PhaseContext context = new PhaseContext(getProviders());
-
-        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
-        canonicalizer.apply(graph, context);
-        new ConditionalEliminationPhase().apply(graph, context);
-        canonicalizer.apply(graph, context);
-
-        assertDeepEquals(0, graph.getNodes().filter(GuardNode.class).count());
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest1.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.directives.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase {
+
+    private static final String REFERENCE_SNIPPET = "referenceSnippet";
+
+    @SuppressWarnings("all")
+    public static int referenceSnippet(int a) {
+        if (a == 0) {
+            return 1;
+        }
+        return 0;
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet", REFERENCE_SNIPPET);
+    }
+
+    @SuppressWarnings("all")
+    public static int test1Snippet(int a) {
+        if (a == 0) {
+            if (a == 5) {
+                return 100;
+            }
+            if (a > 100) {
+                if (a == 0) {
+                    return 200;
+                }
+            }
+            if (a != 2) {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet", REFERENCE_SNIPPET);
+    }
+
+    @SuppressWarnings("all")
+    public static int test2Snippet(int a) {
+        if (a == 0) {
+            if (a > 100) {
+                if (a == 0) {
+                    return 200;
+                }
+            }
+            if (a != 2) {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    @Test
+    public void test3() {
+        test("test3Snippet", REFERENCE_SNIPPET);
+    }
+
+    @SuppressWarnings("all")
+    public static int test3Snippet(int a) {
+        if (a == 0) {
+            if (a < 1) {
+                if (a < 2) {
+                    if (a < 3) {
+                        if (a > -1) {
+                            if (a > -2) {
+                                if (a > -3) {
+                                    if (a == 1) {
+                                        return 42;
+                                    } else {
+                                        return 1;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return 0;
+    }
+
+    @SuppressWarnings("all")
+    public static int test4Snippet(int a, int b) {
+        if (b < 1) {
+            GraalDirectives.controlFlowAnchor();
+            if (b < 0) {
+                return 1;
+            }
+        }
+        return 0;
+    }
+
+    @Test
+    public void test4() {
+        test("test4Snippet", "test4Snippet");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest2.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,130 @@
+/*
+ * 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.graal.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase {
+
+    public static Object field;
+
+    static class Entry {
+
+        final String name;
+
+        public Entry(String name) {
+            this.name = name;
+        }
+    }
+
+    static class EntryWithNext extends Entry {
+
+        public EntryWithNext(String name, Entry next) {
+            super(name);
+            this.next = next;
+        }
+
+        final Entry next;
+    }
+
+    public static Entry search(Entry start, String name, Entry alternative) {
+        Entry current = start;
+        do {
+            while (current instanceof EntryWithNext) {
+                if (name != null && current.name == name) {
+                    current = null;
+                } else {
+                    Entry next = ((EntryWithNext) current).next;
+                    current = next;
+                }
+            }
+
+            if (current != null) {
+                if (current.name.equals(name)) {
+                    return current;
+                }
+            }
+            if (current == alternative) {
+                return null;
+            }
+            current = alternative;
+
+        } while (true);
+    }
+
+    public static int testRedundantComparesSnippet(int[] array) {
+        if (array == null) {
+            return 0;
+        }
+        return array[0] + array[1] + array[2] + array[3];
+    }
+
+    @Test
+    public void testRedundantCompares() {
+        StructuredGraph graph = parseEager("testRedundantComparesSnippet", AllowAssumptions.YES);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+        PhaseContext context = new PhaseContext(getProviders());
+
+        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+        canonicalizer.apply(graph, context);
+        new FloatingReadPhase().apply(graph);
+        new DominatorConditionalEliminationPhase(true).apply(graph, context);
+        canonicalizer.apply(graph, context);
+
+        assertDeepEquals(1, graph.getNodes().filter(GuardNode.class).count());
+    }
+
+    public static String testInstanceOfCheckCastSnippet(Object e) {
+        if (e instanceof Entry) {
+            return ((Entry) e).name;
+        }
+        return null;
+    }
+
+    @Test
+    public void testInstanceOfCheckCastLowered() {
+        StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet", AllowAssumptions.YES);
+
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+        PhaseContext context = new PhaseContext(getProviders());
+
+        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+        canonicalizer.apply(graph, context);
+        new DominatorConditionalEliminationPhase(true).apply(graph, context);
+        canonicalizer.apply(graph, context);
+
+        assertDeepEquals(0, graph.getNodes().filter(GuardNode.class).count());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest3.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTest3 extends ConditionalEliminationTestBase {
+
+    private static final String REFERENCE_SNIPPET = "referenceSnippet";
+
+    @SuppressWarnings("all")
+    public static int referenceSnippet(int a, int b) {
+        int sum = 0;
+        outer: for (int i = 0;; ++i) {
+            if (b > 100) {
+                inner: for (int j = 0;; ++j) {
+                    ++sum;
+                    if (sum == 100) {
+                        break inner;
+                    }
+                    if (sum == 1000 && b < 1000) {
+                        break outer;
+                    }
+                }
+            }
+        }
+        return sum;
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet", REFERENCE_SNIPPET);
+    }
+
+    @SuppressWarnings("all")
+    public static int test1Snippet(int a, int b) {
+        int sum = 0;
+        outer: for (int i = 0;; ++i) {
+            if (b > 100) {
+                inner: for (int j = 0;; ++j) {
+                    ++sum;
+                    if (sum == 100) {
+                        break inner;
+                    }
+                    if (sum == 1000 && b < 1000) {
+                        break outer;
+                    }
+                }
+            }
+        }
+        if (b >= 1000) {
+            return 5;
+        }
+        return sum;
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet", REFERENCE_SNIPPET);
+    }
+
+    @SuppressWarnings("all")
+    public static int test2Snippet(int a, int b) {
+        int sum = 0;
+        outer: for (int i = 0;; ++i) {
+            if (b > 100) {
+                inner: for (int j = 0;; ++j) {
+                    ++sum;
+                    if (sum == 100) {
+                        break inner;
+                    }
+                    if (sum == 1000 && b < 1000) {
+                        break outer;
+                    }
+                }
+                if (sum != 100) {
+                    return 42;
+                }
+            }
+        }
+        return sum;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest4.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTest4 extends ConditionalEliminationTestBase {
+
+    @SuppressWarnings("all")
+    public static int reference1Snippet(int a, int b) {
+        if (a > b) {
+            return 1;
+        }
+        return 2;
+    }
+
+    @SuppressWarnings("all")
+    public static int test1Snippet(int a, int b) {
+        if (a > b) {
+            if (a > b) {
+                return 1;
+            }
+        }
+        return 2;
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet", "reference1Snippet");
+    }
+
+    @SuppressWarnings("all")
+    public static int reference2Snippet(int a, int b) {
+        if (a < b) {
+            return 1;
+        }
+        return 2;
+    }
+
+    @SuppressWarnings("all")
+    public static int test2Snippet(int a, int b) {
+        if (a < b) {
+            if (a < b) {
+                return 1;
+            }
+        }
+        return 2;
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet", "reference2Snippet");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest5.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase {
+
+    interface A {
+    }
+
+    interface B extends A {
+    }
+
+    @SuppressWarnings("all")
+    public static int reference1Snippet(A a, B b) {
+        if (a instanceof B) {
+            return 1;
+        }
+        return 2;
+    }
+
+    @SuppressWarnings("all")
+    public static int test1Snippet(A a, B b) {
+        if (a instanceof B) {
+            if (a instanceof A) {
+                return 1;
+            }
+        }
+        return 2;
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet", "reference1Snippet");
+    }
+
+    @SuppressWarnings("all")
+    public static int reference2Snippet(A a, B b) {
+        if (a instanceof B) {
+            return 1;
+        }
+        return 2;
+    }
+
+    @SuppressWarnings("all")
+    public static int test2Snippet(A a, B b) {
+        if (a instanceof B) {
+            B newVal = (B) a;
+            if (newVal != null) {
+                return 1;
+            }
+        }
+        return 2;
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet", "reference2Snippet");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest6.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTest6 extends ConditionalEliminationTestBase {
+
+    public static final A constA = new A();
+    public static final B constB = new B();
+
+    static class A {
+    }
+
+    static class B {
+    }
+
+    @SuppressWarnings("all")
+    public static B reference1Snippet(Object a, B b) {
+        if (a == constA) {
+            return b;
+        }
+        return null;
+    }
+
+    @SuppressWarnings("all")
+    public static B test1Snippet(Object a, B b) {
+        if (a == constA) {
+            if (a == null) {
+                return null;
+            } else {
+                return b;
+            }
+        }
+        return null;
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet", "reference1Snippet");
+    }
+
+    @SuppressWarnings("all")
+    public static B test2Snippet(Object a, B b) {
+        if (a == constA) {
+            if (a == constB) {
+                return null;
+            } else {
+                return b;
+            }
+        }
+        return null;
+    }
+
+    @Test
+    public void test2() {
+        test("test2Snippet", "reference1Snippet");
+    }
+
+    @SuppressWarnings("all")
+    public static B test3Snippet(Object a, B b) {
+        if (a == constA) {
+            if (a == b) {
+                return null;
+            } else {
+                return b;
+            }
+        }
+        return null;
+    }
+
+    @Test
+    public void test3() {
+        test("test3Snippet", "reference1Snippet");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest7.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTest7 extends ConditionalEliminationTestBase {
+
+    @SuppressWarnings("all")
+    public static int test1Snippet(int a, Object b) {
+        int sum = 0;
+        for (int j = 0;; ++j) {
+            ++sum;
+            if (b instanceof String) {
+                if (sum == 100) {
+                    break;
+                }
+            }
+        }
+        String s = (String) b;
+        return s.length() + sum;
+    }
+
+    @Test
+    public void test1() {
+        // One loop exit is skipped.
+        testProxies("test1Snippet", 1);
+    }
+
+    @SuppressWarnings("all")
+    public static int test2Snippet(int a, Object b) {
+        int sum = 0;
+        for (int j = 0;; ++j) {
+            ++sum;
+            if (b instanceof String) {
+                break;
+            }
+        }
+        String s = (String) b;
+        return s.length() + sum;
+    }
+
+    @Test
+    public void test2() {
+        // The loop exit is the anchor => no proxy necessary.
+        testProxies("test2Snippet", 0);
+    }
+
+    @SuppressWarnings("all")
+    public static int test3Snippet(int a, Object b) {
+        int sum = a;
+        outer: while (true) {
+            sum++;
+            while (sum++ != 20) {
+                while (sum++ != 30) {
+                    while (sum++ != 40) {
+                        while (sum++ != 50) {
+                            if (b instanceof String) {
+                                break outer;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        String s = (String) b;
+        return s.length() + sum;
+    }
+
+    @Test
+    public void test3() {
+        // The break skips over 4 other loops.
+        testProxies("test3Snippet", 4);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest8.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTest8 extends ConditionalEliminationTestBase {
+
+    private static double value;
+
+    @SuppressWarnings("all")
+    public static int test1Snippet(int a, Object b) {
+        double sum = 0;
+        if (!(b instanceof String)) {
+            return 42;
+        }
+        for (int j = 0; j < a; ++j) {
+            sum += value;
+        }
+        return ((String) b).length();
+    }
+
+    @Test
+    public void test1() {
+        // One loop exit is skipped, because the condition dominates also the loop begin.
+        testProxies("test1Snippet", 0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest9.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.directives.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTest9 extends ConditionalEliminationTestBase {
+
+    private static final String REFERENCE_SNIPPET = "referenceSnippet";
+
+    @SuppressWarnings("all")
+    public static int referenceSnippet(int a) {
+        if (a == 0) {
+            GraalDirectives.deoptimize();
+        }
+        return 0;
+    }
+
+    @Test
+    public void test1() {
+        test("test1Snippet", REFERENCE_SNIPPET);
+    }
+
+    @SuppressWarnings("all")
+    public static int test1Snippet(int a) {
+        if (a == 0) {
+            if (a == 0) {
+                GraalDirectives.deoptimize();
+            }
+            if (a == 0) {
+                GraalDirectives.deoptimize();
+            }
+        }
+        return 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTestBase.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
+
+/**
+ * Collection of tests for
+ * {@link com.oracle.graal.phases.common.DominatorConditionalEliminationPhase} including those that
+ * triggered bugs in this phase.
+ */
+public class ConditionalEliminationTestBase extends GraalCompilerTest {
+
+    protected void test(String snippet, String referenceSnippet) {
+        StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
+        Debug.dump(graph, "Graph");
+        PhaseContext context = new PhaseContext(getProviders());
+        CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase();
+        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);
+        StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES);
+        canonicalizer.apply(referenceGraph, context);
+        assertEquals(referenceGraph, graph);
+    }
+
+    public void testProxies(String snippet, int expectedProxiesCreated) {
+        StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
+        PhaseContext context = new PhaseContext(getProviders());
+        CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase();
+        canonicalizer1.disableSimplification();
+        canonicalizer1.apply(graph, context);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+        canonicalizer.apply(graph, context);
+
+        int baseProxyCount = graph.getNodes().filter(ProxyNode.class).count();
+        new DominatorConditionalEliminationPhase(true).apply(graph, context);
+        canonicalizer.apply(graph, context);
+        new SchedulePhase().apply(graph, context);
+        int actualProxiesCreated = graph.getNodes().filter(ProxyNode.class).count() - baseProxyCount;
+        Assert.assertEquals(expectedProxiesCreated, actualProxiesCreated);
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -83,8 +83,8 @@
         try (Scope s = Debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) {
             StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
             HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-            new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-            new CanonicalizerPhase(true).apply(graph, context);
+            new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+            new CanonicalizerPhase().apply(graph, context);
             Debug.dump(graph, "Graph");
             StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES);
             Debug.dump(referenceGraph, "ReferenceGraph");
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -110,7 +110,7 @@
         try (Scope s = Debug.scope("NestedCheckCastsTest", graph)) {
             Debug.dump(graph, "After parsing: " + snippet);
             Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count());
-            new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+            new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
             Assert.assertEquals(afterCanon, graph.getNodes().filter(CheckCastNode.class).count());
             return graph;
         } catch (Throwable e) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -70,8 +70,8 @@
         GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault();
         new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), conf, OptimisticOptimizations.ALL).apply(graph);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         return graph;
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -60,7 +60,7 @@
 
             StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
             PhaseContext context = new PhaseContext(getProviders());
-            new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+            new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
             new FloatingReadPhase().apply(graph);
 
             ReturnNode returnNode = null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GuardEliminationCornerCasesTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015, 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.compiler.test;
+
+import org.junit.*;
+
+import com.oracle.graal.api.directives.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
+
+public class GuardEliminationCornerCasesTest extends GraalCompilerTest {
+
+    static class A {
+
+    }
+
+    static class B extends A {
+
+    }
+
+    static class C extends B {
+
+    }
+
+    static class D extends C {
+
+    }
+
+    @SuppressWarnings({"static-method", "unused"})
+    private int testMethod(Object a) {
+        if (a instanceof A) {
+            if (a instanceof C) {
+                if (a instanceof B) {
+                    B b = (B) a;
+                    if (b instanceof C) {
+                        return 1;
+                    } else {
+                        GraalDirectives.deoptimize();
+                    }
+                }
+            } else {
+                GraalDirectives.deoptimize();
+            }
+        }
+        return 0;
+    }
+
+    @Test
+    public void testFloatingGuards() {
+        HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
+        StructuredGraph graph = parseEager("testMethod", AllowAssumptions.YES);
+        new ConvertDeoptimizeToGuardPhase().apply(graph, context);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+        Debug.dump(graph, "after parsing");
+
+        GuardNode myGuardNode = null;
+        for (Node n : graph.getNodes()) {
+            if (n instanceof GuardNode) {
+                GuardNode guardNode = (GuardNode) n;
+                LogicNode condition = guardNode.condition();
+                if (condition instanceof InstanceOfNode) {
+                    InstanceOfNode instanceOfNode = (InstanceOfNode) condition;
+                    if (instanceOfNode.getValue() instanceof ValueProxy) {
+                        myGuardNode = guardNode;
+                        break;
+                    }
+                }
+            }
+        }
+
+        AbstractBeginNode myBegin = (AbstractBeginNode) myGuardNode.getAnchor();
+        AbstractBeginNode prevBegin = BeginNode.prevBegin((FixedNode) myBegin.predecessor());
+        myGuardNode.setAnchor(prevBegin);
+
+        Debug.dump(graph, "after manual modification");
+        graph.reverseUsageOrder();
+        new ConditionalEliminationPhase().apply(graph);
+        new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST).apply(graph);
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -182,13 +182,13 @@
     private void testCombinedIf(String snippet, int count) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
         PhaseContext context = new PhaseContext(getProviders());
-        new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+        new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
         new FloatingReadPhase().apply(graph);
         MidTierContext midContext = new MidTierContext(getProviders(), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null);
         new GuardLoweringPhase().apply(graph, midContext);
-        new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext);
+        new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext);
         new ValueAnchorCleanupPhase().apply(graph);
-        new CanonicalizerPhase(true).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         assertDeepEquals(count, graph.getNodes().filter(IfNode.class).count());
     }
 
@@ -200,7 +200,7 @@
             n.replaceFirstInput(param, constant);
         }
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) {
             fs.replaceFirstInput(param, null);
             param.safeDelete();
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IntegerEqualsCanonicalizerTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -114,7 +114,7 @@
 
     private StructuredGraph getCanonicalizedGraph(String snippet) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
-        new CanonicalizerPhase(false).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         for (FrameState state : graph.getNodes(FrameState.TYPE).snapshot()) {
             state.replaceAtUsages(null);
             state.safeDelete();
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -67,8 +67,8 @@
             hints.put(invoke, 1000d);
         }
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, context);
+        new InliningPhase(hints, new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -78,8 +78,8 @@
         }
 
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, context);
+        new InliningPhase(hints, new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
         StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.NO);
         assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -62,7 +62,7 @@
         test("testSynchronizedSnippet", new A(), new A());
 
         StructuredGraph graph = getGraph("testSynchronizedSnippet");
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         new LockEliminationPhase().apply(graph);
         assertDeepEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count());
         assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
@@ -80,7 +80,7 @@
         test("testSynchronizedMethodSnippet", new A());
 
         StructuredGraph graph = getGraph("testSynchronizedMethodSnippet");
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         new LockEliminationPhase().apply(graph);
         assertDeepEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count());
         assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
@@ -90,11 +90,11 @@
         ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
         StructuredGraph graph = parseEager(method, AllowAssumptions.YES);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new CanonicalizerPhase(true).apply(graph, context);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
-        new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+        new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
         new ValueAnchorCleanupPhase().apply(graph);
         new LockEliminationPhase().apply(graph);
         return graph;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LongNodeChainTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LongNodeChainTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -77,7 +77,7 @@
             new SchedulePhase(s).apply(graph);
         }
 
-        new CanonicalizerPhase(false).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         JavaConstant asConstant = (JavaConstant) returnNode.result().asConstant();
         Assert.assertEquals(N + 1, asConstant.asInt());
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -134,8 +134,8 @@
             ((StateSplit) stateSplit).setStateAfter(null);
         }
 
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
-        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders()));
         try (Scope s = Debug.scope("Test", new DebugDumpScope("Test:" + snippet))) {
             assertEquals(referenceGraph, graph);
         } catch (Throwable e) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -600,7 +600,7 @@
         try (Scope d = Debug.scope("FloatingReadTest", graph)) {
             try (OverrideScope s = OptionValue.override(OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false)) {
                 HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-                CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+                CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
                 canonicalizer.apply(graph, context);
                 if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     new InliningPhase(canonicalizer).apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MergeCanonicalizerTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -58,8 +58,8 @@
 
     private void testReturnCount(String snippet, int returnCount) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         Debug.dump(graph, "Graph");
         assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count());
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -97,8 +97,8 @@
             hints.put(invoke, 1000d);
         }
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, context);
+        new InliningPhase(hints, new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ProfilingInfoTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -27,7 +27,6 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 
 /**
  * Tests profiling information provided by the runtime.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -93,7 +93,7 @@
     private StructuredGraph compileTestSnippet(final String snippet) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
         PhaseContext context = new PhaseContext(getProviders());
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
         new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
         canonicalizer.apply(graph, context);
         new PushThroughPiPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushThroughIfTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -63,15 +63,15 @@
             fs.replaceAtUsages(null);
             GraphUtil.killWithUnusedFloatingInputs(fs);
         }
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
 
         StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES);
         for (FrameState fs : referenceGraph.getNodes(FrameState.TYPE).snapshot()) {
             fs.replaceAtUsages(null);
             GraphUtil.killWithUnusedFloatingInputs(fs);
         }
-        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders()));
         assertEquals(referenceGraph, graph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -83,7 +83,7 @@
             // structure changes significantly
             StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
             PhaseContext context = new PhaseContext(getProviders());
-            CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+            CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
             new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
             new FloatingReadPhase().apply(graph);
             new OptimizeGuardAnchorsPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -244,9 +244,9 @@
 
     private <T extends Node & IterableNodeType> void test(String test, String ref) {
         StructuredGraph testGraph = parseEager(test, AllowAssumptions.NO);
-        new CanonicalizerPhase(true).apply(testGraph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(testGraph, new PhaseContext(getProviders()));
         StructuredGraph refGraph = parseEager(ref, AllowAssumptions.NO);
-        new CanonicalizerPhase(true).apply(refGraph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(refGraph, new PhaseContext(getProviders()));
         assertEquals(testGraph, refGraph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -133,7 +133,7 @@
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
         Debug.dump(graph, "Graph");
         PhaseContext context = new PhaseContext(getProviders());
-        new CanonicalizerPhase(true).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -110,7 +110,7 @@
 
     private void testZeroReturn(String methodName) {
         StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         new DeadCodeEliminationPhase().apply(graph);
         assertConstantReturn(graph, 0);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -89,7 +89,7 @@
         // No debug scope to reduce console noise for @Test(expected = ...) tests
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -178,11 +178,11 @@
          * reference graph.
          */
         new ConditionalEliminationPhase().apply(graph, new PhaseContext(getProviders()));
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         // a second canonicalizer is needed to process nested MaterializeNodes
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO);
-        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders()));
         assertEquals(referenceGraph, graph);
     }
 
@@ -230,8 +230,8 @@
 
     private <T extends Node> void testHelper(String snippet, Class<T> clazz) {
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         Debug.dump(graph, "Graph " + snippet);
         Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -53,7 +53,7 @@
     public void test1() {
         final ResolvedJavaMethod javaMethod = getResolvedJavaMethod("testMethod");
         final StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.NO);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         new DeadCodeEliminationPhase().apply(graph);
 
         for (ConstantNode node : ConstantNode.getConstantNodes(graph)) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EATestBase.java	Mon Mar 09 15:04:08 2015 +0100
@@ -154,10 +154,10 @@
             new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), GraphBuilderConfiguration.getEagerDefault(),
                             OptimisticOptimizations.ALL).apply(graph);
             context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-            new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+            new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
             new DeadCodeEliminationPhase().apply(graph);
-            new CanonicalizerPhase(true).apply(graph, context);
-            new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(true), null).apply(graph, context);
+            new CanonicalizerPhase().apply(graph, context);
+            new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null).apply(graph, context);
             returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot();
         } catch (Throwable e) {
             throw Debug.handle(e);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -42,7 +42,7 @@
     protected void processMethod(final String snippet) {
         graph = parseEager(getResolvedJavaMethod(snippet), AllowAssumptions.NO);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new EarlyReadEliminationPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        new EarlyReadEliminationPhase(new CanonicalizerPhase()).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -308,8 +308,8 @@
     @Test
     public void testFullyUnrolledLoop() {
         prepareGraph("testFullyUnrolledLoopSnippet", false);
-        new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
+        new LoopFullUnrollPhase(new CanonicalizerPhase()).apply(graph, context);
+        new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context);
         Assert.assertEquals(1, returnNodes.size());
         Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode);
         CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit();
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -86,6 +86,6 @@
     private void processMethod(final String snippet) {
         graph = parseEager(snippet, AllowAssumptions.YES);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new IterativeInliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new IterativeInliningPhase(new CanonicalizerPhase()).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -246,7 +246,7 @@
     protected void processMethod(final String snippet) {
         graph = parseEager(snippet, AllowAssumptions.NO);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new PartialEscapePhase(false, true, new CanonicalizerPhase(true), null).apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        new PartialEscapePhase(false, true, new CanonicalizerPhase(), null).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -181,7 +181,7 @@
             merge.setStateAfter(null);
         }
         new DeadCodeEliminationPhase().apply(graph);
-        new CanonicalizerPhase(true).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         try {
             Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", graph.getNodes().filter(NewInstanceNode.class).isEmpty());
             Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", graph.getNodes().filter(NewArrayNode.class).isEmpty());
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PoorMansEATest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -61,9 +61,9 @@
         try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) {
             StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
             HighTierContext highTierContext = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-            new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
+            new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext);
             PhaseContext context = new PhaseContext(getProviders());
-            new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+            new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
 
             // remove framestates in order to trigger the simplification.
             cleanup: for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) {
@@ -75,7 +75,7 @@
                     }
                 }
             }
-            new CanonicalizerPhase(true).apply(graph, context);
+            new CanonicalizerPhase().apply(graph, context);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -236,10 +236,10 @@
             PhaseSuite<HighTierContext> graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getFullDebugDefault()) : getDefaultGraphBuilderSuite();
             HighTierContext context = new HighTierContext(getProviders(), null, graphBuilderSuite, OptimisticOptimizations.ALL);
             Debug.dump(graph, "Graph");
-            new CanonicalizerPhase(true).apply(graph, context);
-            new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+            new CanonicalizerPhase().apply(graph, context);
+            new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
             Debug.dump(graph, "Graph");
-            new CanonicalizerPhase(true).apply(graph, context);
+            new CanonicalizerPhase().apply(graph, context);
             new DeadCodeEliminationPhase().apply(graph);
             return graph;
         } catch (Throwable e) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Mar 09 15:04:08 2015 +0100
@@ -32,7 +32,6 @@
 import com.oracle.graal.api.code.CompilationResult.ConstantReference;
 import com.oracle.graal.api.code.CompilationResult.DataPatch;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.LIRGenerationPhase.LIRGenerationContext;
 import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Mon Mar 09 15:04:08 2015 +0100
@@ -62,7 +62,7 @@
                    "Thread - aggregate by qualified name and thread", type = OptionType.Debug)
     public static final OptionValue<String> DebugValueSummary = new OptionValue<>("Name");
     @Option(help = "Omit reporting 0-value metrics", type = OptionType.Debug)
-    public static final OptionValue<Boolean> SuppressZeroDebugValues = new OptionValue<>(false);
+    public static final OptionValue<Boolean> SuppressZeroDebugValues = new OptionValue<>(true);
     @Option(help = "Send Graal IR to dump handlers on error", type = OptionType.Debug)
     public static final OptionValue<Boolean> DumpOnError = new OptionValue<>(false);
     @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug)
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Mon Mar 09 15:04:08 2015 +0100
@@ -46,7 +46,10 @@
     }
 
     public HighTier() {
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+        if (ImmutableCode.getValue()) {
+            canonicalizer.disableReadCanonicalization();
+        }
 
         if (OptCanonicalizer.getValue()) {
             appendPhase(canonicalizer);
@@ -61,7 +64,7 @@
 
                 if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
                     appendPhase(canonicalizer);
-                    appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
+                    appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false));
                 }
             }
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Mon Mar 09 15:04:08 2015 +0100
@@ -43,7 +43,10 @@
     }
 
     public LowTier() {
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+        if (ImmutableCode.getValue()) {
+            canonicalizer.disableReadCanonicalization();
+        }
 
         if (Options.ProfileCompiledMethods.getValue()) {
             appendPhase(new ProfileCompiledMethodsPhase());
@@ -57,7 +60,7 @@
 
         /* Cleanup IsNull checks resulting from MID_TIER/LOW_TIER lowering and ExpandLogic phase. */
         if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
-            appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
+            appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false));
             /* Canonicalizer may create some new ShortCircuitOrNodes so clean them up. */
             appendPhase(new ExpandLogicPhase());
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Mon Mar 09 15:04:08 2015 +0100
@@ -34,7 +34,10 @@
 public class MidTier extends PhaseSuite<MidTierContext> {
 
     public MidTier() {
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+        if (ImmutableCode.getValue()) {
+            canonicalizer.disableReadCanonicalization();
+        }
 
         if (OptPushThroughPi.getValue()) {
             appendPhase(new PushThroughPiPhase());
@@ -64,7 +67,7 @@
         }
 
         if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
-            appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
+            appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false));
         }
 
         if (OptEliminatePartiallyRedundantGuards.getValue()) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Mar 09 15:04:08 2015 +0100
@@ -891,6 +891,16 @@
         }
     }
 
+    /**
+     * Reverses the usage orders of all nodes. This is used for debugging to make sure an unorthodox
+     * usage order does not trigger bugs in the compiler.
+     */
+    public void reverseUsageOrder() {
+        for (Node n : getNodes()) {
+            n.reverseUsageOrder();
+        }
+    }
+
     public boolean isFrozen() {
         return isFrozen;
     }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Mar 09 15:04:08 2015 +0100
@@ -346,6 +346,24 @@
     }
 
     /**
+     * Checks whether this node has usages.
+     */
+    public final boolean hasUsages() {
+        return this.usage0 != null;
+    }
+
+    void reverseUsageOrder() {
+        List<Node> snapshot = this.usages().snapshot();
+        for (Node n : snapshot) {
+            this.removeUsage(n);
+        }
+        Collections.reverse(snapshot);
+        for (Node n : snapshot) {
+            this.addUsage(n);
+        }
+    }
+
+    /**
      * Adds a given node to this node's {@linkplain #usages() usages}.
      *
      * @param node the node to add
@@ -424,15 +442,6 @@
         return false;
     }
 
-    private void clearUsages() {
-        incUsageModCount();
-        maybeNotifyZeroUsages(this);
-        usage0 = null;
-        usage1 = null;
-        extraUsages = NO_NODES;
-        extraUsagesCount = 0;
-    }
-
     public final Node predecessor() {
         return predecessor;
     }
@@ -551,17 +560,27 @@
         return true;
     }
 
-    public void replaceAtUsages(Node other) {
+    public final void replaceAtUsages(Node other) {
+        replaceAtUsages(other, null);
+    }
+
+    public final void replaceAtUsages(Node other, Predicate<Node> filter) {
         assert checkReplaceWith(other);
-        for (Node usage : usages()) {
-            boolean result = usage.getNodeClass().getInputEdges().replaceFirst(usage, this, other);
-            assert assertTrue(result, "not found in inputs, usage: %s", usage);
-            if (other != null) {
-                maybeNotifyInputChanged(usage);
-                other.addUsage(usage);
+        int i = 0;
+        while (i < this.getUsageCount()) {
+            Node usage = this.getUsageAt(i);
+            if (filter == null || filter.test(usage)) {
+                boolean result = usage.getNodeClass().getInputEdges().replaceFirst(usage, this, other);
+                assert assertTrue(result, "not found in inputs, usage: %s", usage);
+                if (other != null) {
+                    maybeNotifyInputChanged(usage);
+                    other.addUsage(usage);
+                }
+                this.movUsageFromEndTo(i);
+            } else {
+                ++i;
             }
         }
-        clearUsages();
     }
 
     public Node getUsageAt(int index) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -248,10 +248,11 @@
             HighTierContext highContext = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
             MidTierContext midContext = new MidTierContext(getProviders(), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null);
             new NodeIntrinsificationPhase(getProviders(), getSnippetReflection()).apply(graph);
-            new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase(true)).apply(graph, highContext);
-            new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext);
+            new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext);
+            new CanonicalizerPhase().apply(graph, highContext);
+            new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext);
             new GuardLoweringPhase().apply(graph, midContext);
-            new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext);
+            new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext);
             new WriteBarrierAdditionPhase(config).apply(graph);
             Debug.dump(graph, "After Write Barrier Addition");
 
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -628,14 +628,14 @@
         try (Scope d = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) {
             final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
             HighTierContext highTierContext = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-            new InliningPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext);
+            new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext);
 
             MidTierContext midTierContext = new MidTierContext(getProviders(), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null);
 
-            new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext);
+            new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext);
             new GuardLoweringPhase().apply(graph, midTierContext);
             new LoopSafepointInsertionPhase().apply(graph);
-            new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, highTierContext);
+            new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, highTierContext);
 
             new WriteBarrierAdditionPhase(config).apply(graph);
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java	Mon Mar 09 15:04:08 2015 +0100
@@ -34,7 +34,6 @@
 import java.util.jar.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Mon Mar 09 15:04:08 2015 +0100
@@ -33,7 +33,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaMethodProfile.ProfiledMethod;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.HotSpotMethodDataAccessor.Tag;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodDataAccessor.java	Mon Mar 09 15:04:08 2015 +0100
@@ -25,7 +25,6 @@
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.hotspot.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethodImpl.java	Mon Mar 09 15:04:08 2015 +0100
@@ -33,7 +33,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.debug.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/HotSpotNativeFunctionInterface.java	Mon Mar 09 15:04:08 2015 +0100
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Mon Mar 09 15:04:08 2015 +0100
@@ -31,7 +31,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.hotspot.meta.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -77,9 +77,9 @@
         // the canonicalization before loop unrolling is needed to propagate the length into
         // additions, etc.
         PhaseContext context = new PhaseContext(tool.getMetaAccess(), tool.getConstantReflection(), tool.getLowerer(), tool.getReplacements(), tool.getStampProvider());
-        new CanonicalizerPhase(true).apply(snippetGraph, context);
-        new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(snippetGraph, context);
-        new CanonicalizerPhase(true).apply(snippetGraph, context);
+        new CanonicalizerPhase().apply(snippetGraph, context);
+        new LoopFullUnrollPhase(new CanonicalizerPhase()).apply(snippetGraph, context);
+        new CanonicalizerPhase().apply(snippetGraph, context);
     }
 
     @Override
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java	Mon Mar 09 15:04:08 2015 +0100
@@ -31,7 +31,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Mar 09 15:04:08 2015 +0100
@@ -34,7 +34,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.common.*;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NestedLoop_EA.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/NestedLoop_EA.java	Mon Mar 09 15:04:08 2015 +0100
@@ -26,7 +26,6 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.jtt.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.virtual.*;
@@ -41,7 +40,7 @@
     protected Suites createSuites() {
         Suites suites = super.createSuites();
         ListIterator<BasePhase<? super HighTierContext>> position = suites.getHighTier().findPhase(PartialEscapePhase.class);
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!GraalOptions.ImmutableCode.getValue());
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
         // incremental canonicalizer of PEA is missing some important canonicalization (TODO?)
         position.add(canonicalizer);
         position.add(new PartialEscapePhase(true, canonicalizer));
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/LoopPhiCanonicalizerTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -62,7 +62,7 @@
 
         PhaseContext context = new PhaseContext(getProviders());
         Assert.assertEquals(5, graph.getNodes().filter(loopPhis).count());
-        new CanonicalizerPhase(false).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         Assert.assertEquals(2, graph.getNodes().filter(loopPhis).count());
 
         test("loopSnippet");
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -94,10 +94,19 @@
     }
 
     public void removeProxies() {
-        for (ProxyNode vpn : proxies().snapshot()) {
-            // can not use graph.replaceFloating because vpn.value may be null during killCFG
-            vpn.replaceAtUsages(vpn.value());
-            vpn.safeDelete();
+        if (this.hasUsages()) {
+            outer: while (true) {
+                for (ProxyNode vpn : proxies().snapshot()) {
+                    ValueNode value = vpn.value();
+                    vpn.replaceAtUsages(value);
+                    vpn.safeDelete();
+                    if (value == this) {
+                        // Guard proxy could have this input as value.
+                        continue outer;
+                    }
+                }
+                break;
+            }
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
@@ -83,4 +85,10 @@
         }
         return this;
     }
+
+    public abstract Stamp getSucceedingStampForX(boolean negated);
+
+    public abstract Stamp getSucceedingStampForY(boolean negated);
+
+    public abstract TriState tryFold(Stamp xStamp, Stamp yStamp);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -76,6 +76,9 @@
                 return new ValueAnchorNode(null);
             }
         }
+        if (this.hasNoUsages()) {
+            return null;
+        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -41,11 +41,6 @@
         this.values = new NodeInputList<>(this);
     }
 
-    public GuardPhiNode(AbstractMergeNode merge, ValueNode[] values) {
-        super(TYPE, StampFactory.forVoid(), merge);
-        this.values = new NodeInputList<>(this, values);
-    }
-
     @Override
     public NodeInputList<ValueNode> values() {
         return values;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -43,6 +43,11 @@
     public void generate(NodeLIRBuilderTool generator) {
     }
 
+    public void setValue(GuardingNode newValue) {
+        this.updateUsages(value.asNode(), newValue.asNode());
+        this.value = newValue;
+    }
+
     @Override
     public ValueNode value() {
         return value.asNode();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
@@ -1133,4 +1132,8 @@
     public AbstractBeginNode getPrimarySuccessor() {
         return this.trueSuccessor();
     }
+
+    public AbstractBeginNode getSuccessor(boolean result) {
+        return result ? this.trueSuccessor() : this.falseSuccessor();
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Mar 09 15:04:08 2015 +0100
@@ -324,7 +324,7 @@
         if (node instanceof AbstractBeginNode) {
             ((AbstractBeginNode) node).prepareDelete();
         }
-        assert node.hasNoUsages() : node + " " + node.usages();
+        assert node.hasNoUsages() : node + " " + node.usages().count() + ", " + node.usages().first();
         GraphUtil.unlinkFixedNode(node);
         node.safeDelete();
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
@@ -46,4 +48,8 @@
     @Override
     public void generate(NodeLIRBuilderTool gen) {
     }
+
+    public abstract Stamp getSucceedingStampForValue(boolean negated);
+
+    public abstract TriState tryFold(Stamp valueStamp);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -58,9 +58,11 @@
         if (result != this) {
             return result;
         }
-        if (forX.stamp() instanceof FloatStamp && forY.stamp() instanceof FloatStamp) {
-            FloatStamp xStamp = (FloatStamp) forX.stamp();
-            FloatStamp yStamp = (FloatStamp) forY.stamp();
+        Stamp xStampGeneric = forX.stamp();
+        Stamp yStampGeneric = forY.stamp();
+        if (xStampGeneric instanceof FloatStamp && yStampGeneric instanceof FloatStamp) {
+            FloatStamp xStamp = (FloatStamp) xStampGeneric;
+            FloatStamp yStamp = (FloatStamp) yStampGeneric;
             if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && xStamp.isNonNaN() && yStamp.isNonNaN()) {
                 return LogicConstantNode.tautology();
             } else if (xStamp.alwaysDistinct(yStamp)) {
@@ -79,4 +81,34 @@
         }
         throw GraalInternalError.shouldNotReachHere();
     }
+
+    @Override
+    public Stamp getSucceedingStampForX(boolean negated) {
+        if (!negated) {
+            return getX().stamp().join(getY().stamp());
+        }
+        return null;
+    }
+
+    @Override
+    public Stamp getSucceedingStampForY(boolean negated) {
+        if (!negated) {
+            return getX().stamp().join(getY().stamp());
+        }
+        return null;
+    }
+
+    @Override
+    public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
+        if (xStampGeneric instanceof FloatStamp && yStampGeneric instanceof FloatStamp) {
+            FloatStamp xStamp = (FloatStamp) xStampGeneric;
+            FloatStamp yStamp = (FloatStamp) yStampGeneric;
+            if (xStamp.alwaysDistinct(yStamp)) {
+                return TriState.FALSE;
+            } else if (xStamp.neverDistinct(yStamp)) {
+                return TriState.TRUE;
+            }
+        }
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -72,4 +72,19 @@
         }
         throw GraalInternalError.shouldNotReachHere();
     }
+
+    @Override
+    public Stamp getSucceedingStampForX(boolean negated) {
+        return null;
+    }
+
+    @Override
+    public Stamp getSucceedingStampForY(boolean negated) {
+        return null;
+    }
+
+    @Override
+    public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
@@ -92,4 +93,97 @@
     protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
         return new IntegerBelowNode(newX, newY);
     }
+
+    @Override
+    public Stamp getSucceedingStampForX(boolean negated) {
+        Stamp xStampGeneric = getX().stamp();
+        Stamp yStampGeneric = getY().stamp();
+        if (xStampGeneric instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+            int bits = xStamp.getBits();
+            if (yStampGeneric instanceof IntegerStamp) {
+                IntegerStamp yStamp = (IntegerStamp) yStampGeneric;
+                assert yStamp.getBits() == bits;
+                if (negated) {
+                    // x >= y
+                    if (xStamp.isPositive() && yStamp.isPositive()) {
+                        long xLowerBound = xStamp.lowerBound();
+                        long yLowerBound = yStamp.lowerBound();
+                        if (yLowerBound > xLowerBound) {
+                            return new IntegerStamp(bits, yLowerBound, xStamp.upperBound(), xStamp.downMask(), xStamp.upMask());
+                        }
+                    }
+                } else {
+                    // x < y
+                    if (yStamp.isPositive()) {
+                        // x >= 0 && x < y
+                        long xUpperBound = xStamp.upperBound();
+                        long yUpperBound = yStamp.upperBound();
+                        if (yUpperBound <= xUpperBound || !xStamp.isPositive()) {
+                            if (yUpperBound != 0) {
+                                yUpperBound--;
+                            }
+                            return new IntegerStamp(bits, Math.max(0, xStamp.lowerBound()), Math.min(xUpperBound, yUpperBound), xStamp.downMask(), xStamp.upMask());
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Stamp getSucceedingStampForY(boolean negated) {
+        Stamp xStampGeneric = getX().stamp();
+        Stamp yStampGeneric = getY().stamp();
+        if (xStampGeneric instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+            int bits = xStamp.getBits();
+            if (yStampGeneric instanceof IntegerStamp) {
+                IntegerStamp yStamp = (IntegerStamp) yStampGeneric;
+                assert yStamp.getBits() == bits;
+                if (negated) {
+                    // y <= x
+                    if (xStamp.isPositive()) {
+                        long xUpperBound = xStamp.upperBound();
+                        long yUpperBound = yStamp.upperBound();
+                        if (xUpperBound < yUpperBound || !yStamp.isPositive()) {
+                            return new IntegerStamp(bits, Math.max(0, yStamp.lowerBound()), Math.min(xUpperBound, yUpperBound), yStamp.downMask(), yStamp.upMask());
+                        }
+                    }
+                } else {
+                    // y > x
+                    if (xStamp.isPositive() && yStamp.isPositive()) {
+                        long xLowerBound = xStamp.lowerBound();
+                        long yLowerBound = yStamp.lowerBound();
+                        if (xLowerBound >= yLowerBound) {
+                            if (xLowerBound != CodeUtil.maxValue(bits)) {
+                                xLowerBound++;
+                            }
+                            return new IntegerStamp(bits, xLowerBound, yStamp.upperBound(), yStamp.downMask(), yStamp.upMask());
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
+        if (xStampGeneric instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+            if (yStampGeneric instanceof IntegerStamp) {
+                IntegerStamp yStamp = (IntegerStamp) yStampGeneric;
+                if (yStamp.isPositive()) {
+                    if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
+                        return TriState.TRUE;
+                    } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
+                        return TriState.FALSE;
+                    }
+                }
+            }
+        }
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -154,4 +154,34 @@
         }
         return super.canonicalizeSymmetricConstant(tool, constant, nonConstant, mirrored);
     }
+
+    @Override
+    public Stamp getSucceedingStampForX(boolean negated) {
+        if (!negated) {
+            return getX().stamp().join(getY().stamp());
+        }
+        return null;
+    }
+
+    @Override
+    public Stamp getSucceedingStampForY(boolean negated) {
+        if (!negated) {
+            return getX().stamp().join(getY().stamp());
+        }
+        return null;
+    }
+
+    @Override
+    public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
+        if (xStampGeneric instanceof IntegerStamp && yStampGeneric instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+            IntegerStamp yStamp = (IntegerStamp) yStampGeneric;
+            if (xStamp.alwaysDistinct(yStamp)) {
+                return TriState.FALSE;
+            } else if (xStamp.neverDistinct(yStamp)) {
+                return TriState.TRUE;
+            }
+        }
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
@@ -114,4 +115,85 @@
         }
         throw GraalInternalError.shouldNotReachHere();
     }
+
+    @Override
+    public Stamp getSucceedingStampForX(boolean negated) {
+        Stamp xStampGeneric = getX().stamp();
+        Stamp yStampGeneric = getY().stamp();
+        if (xStampGeneric instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+            int bits = xStamp.getBits();
+            if (yStampGeneric instanceof IntegerStamp) {
+                IntegerStamp yStamp = (IntegerStamp) yStampGeneric;
+                assert yStamp.getBits() == bits;
+                if (negated) {
+                    // x >= y
+                    long xLowerBound = xStamp.lowerBound();
+                    long yLowerBound = yStamp.lowerBound();
+                    if (yLowerBound > xLowerBound) {
+                        return new IntegerStamp(bits, yLowerBound, xStamp.upperBound(), xStamp.downMask(), xStamp.upMask());
+                    }
+                } else {
+                    // x < y
+                    long xUpperBound = xStamp.upperBound();
+                    long yUpperBound = yStamp.upperBound();
+                    if (yUpperBound <= xUpperBound) {
+                        if (yUpperBound != CodeUtil.minValue(bits)) {
+                            yUpperBound--;
+                        }
+                        return new IntegerStamp(bits, xStamp.lowerBound(), yUpperBound, xStamp.downMask(), xStamp.upMask());
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Stamp getSucceedingStampForY(boolean negated) {
+        Stamp xStampGeneric = getX().stamp();
+        Stamp yStampGeneric = getY().stamp();
+        if (xStampGeneric instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+            int bits = xStamp.getBits();
+            if (yStampGeneric instanceof IntegerStamp) {
+                IntegerStamp yStamp = (IntegerStamp) yStampGeneric;
+                assert yStamp.getBits() == bits;
+                if (negated) {
+                    // y <= x
+                    long xUpperBound = xStamp.upperBound();
+                    long yUpperBound = yStamp.upperBound();
+                    if (xUpperBound < yUpperBound) {
+                        return new IntegerStamp(bits, yStamp.lowerBound(), xUpperBound, yStamp.downMask(), yStamp.upMask());
+                    }
+                } else {
+                    // y > x
+                    long xLowerBound = xStamp.lowerBound();
+                    long yLowerBound = yStamp.lowerBound();
+                    if (xLowerBound >= yLowerBound) {
+                        if (xLowerBound != CodeUtil.maxValue(bits)) {
+                            xLowerBound++;
+                        }
+                        return new IntegerStamp(bits, xLowerBound, yStamp.upperBound(), yStamp.downMask(), yStamp.upMask());
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
+        if (xStampGeneric instanceof IntegerStamp && yStampGeneric instanceof IntegerStamp) {
+            IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+            IntegerStamp yStamp = (IntegerStamp) yStampGeneric;
+            if (xStamp.upperBound() < yStamp.lowerBound()) {
+                return TriState.TRUE;
+            }
+            if (xStamp.lowerBound() >= yStamp.upperBound()) {
+                return TriState.FALSE;
+            }
+        }
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative;
@@ -58,4 +59,20 @@
         }
         return this;
     }
+
+    @Override
+    public Stamp getSucceedingStampForX(boolean negated) {
+        return null;
+    }
+
+    @Override
+    public Stamp getSucceedingStampForY(boolean negated) {
+        return null;
+    }
+
+    @Override
+    public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
+        System.out.println("try fold with " + xStampGeneric + " and " + yStampGeneric);
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -86,4 +87,22 @@
 
     @NodeIntrinsic
     public static native IsNullNode isNull(Object object);
+
+    @Override
+    public Stamp getSucceedingStampForValue(boolean negated) {
+        return negated ? StampFactory.objectNonNull() : StampFactory.alwaysNull();
+    }
+
+    @Override
+    public TriState tryFold(Stamp valueStamp) {
+        if (valueStamp instanceof ObjectStamp) {
+            ObjectStamp objectStamp = (ObjectStamp) valueStamp;
+            if (objectStamp.alwaysNull()) {
+                return TriState.TRUE;
+            } else if (objectStamp.nonNull()) {
+                return TriState.FALSE;
+            }
+        }
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/PointerEqualsNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/PointerEqualsNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
@@ -73,4 +74,42 @@
     protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
         return new PointerEqualsNode(newX, newY);
     }
+
+    @Override
+    public Stamp getSucceedingStampForX(boolean negated) {
+        if (!negated) {
+            Stamp xStamp = getX().stamp();
+            Stamp newStamp = xStamp.join(getY().stamp());
+            if (!newStamp.equals(xStamp)) {
+                return newStamp;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public Stamp getSucceedingStampForY(boolean negated) {
+        if (!negated) {
+            Stamp yStamp = getY().stamp();
+            Stamp newStamp = yStamp.join(getX().stamp());
+            if (!newStamp.equals(yStamp)) {
+                return newStamp;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
+        if (xStampGeneric instanceof ObjectStamp && yStampGeneric instanceof ObjectStamp) {
+            ObjectStamp xStamp = (ObjectStamp) xStampGeneric;
+            ObjectStamp yStamp = (ObjectStamp) yStampGeneric;
+            if (xStamp.alwaysDistinct(yStamp)) {
+                return TriState.FALSE;
+            } else if (xStamp.neverDistinct(yStamp)) {
+                return TriState.TRUE;
+            }
+        }
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java	Mon Mar 09 15:04:08 2015 +0100
@@ -124,10 +124,15 @@
         @Override
         public FixedNode next() {
             FixedNode result = cur;
-            if (cur == getEndNode()) {
+            if (result instanceof FixedWithNextNode) {
+                FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) result;
+                FixedNode next = fixedWithNextNode.next();
+                if (next instanceof AbstractBeginNode) {
+                    next = null;
+                }
+                cur = next;
+            } else {
                 cur = null;
-            } else {
-                cur = ((FixedWithNextNode) cur).next();
             }
             assert !(cur instanceof AbstractBeginNode);
             return result;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Mon Mar 09 15:04:08 2015 +0100
@@ -318,7 +318,7 @@
         }
     }
 
-    private void computePostdominators() {
+    public void computePostdominators() {
         outer: for (Block block : postOrder()) {
             if (block.isLoopEnd()) {
                 // We do not want the loop header registered as the postdominator of the loop end.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -28,7 +28,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -239,4 +238,17 @@
     public ValueNode getOriginalNode() {
         return object;
     }
+
+    public TriState tryFold(Stamp testStamp) {
+        if (testStamp instanceof ObjectStamp) {
+            ObjectStamp objectStamp = (ObjectStamp) testStamp;
+            ResolvedJavaType objectType = objectStamp.type();
+            if (objectType != null && type.isAssignableFrom(objectType)) {
+                return TriState.TRUE;
+            } else if (objectStamp.alwaysNull()) {
+                return TriState.TRUE;
+            }
+        }
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -160,4 +160,43 @@
             tool.replaceWithValue(LogicConstantNode.forBoolean(type().isAssignableFrom(state.getVirtualObject().type()), graph()));
         }
     }
+
+    @Override
+    public Stamp getSucceedingStampForValue(boolean negated) {
+        if (negated) {
+            return null;
+        } else {
+            return StampFactory.declaredTrustedNonNull(type);
+        }
+    }
+
+    @Override
+    public TriState tryFold(Stamp valueStamp) {
+        if (valueStamp instanceof ObjectStamp) {
+            ObjectStamp objectStamp = (ObjectStamp) valueStamp;
+            if (objectStamp.alwaysNull()) {
+                return TriState.FALSE;
+            }
+
+            ResolvedJavaType objectType = objectStamp.type();
+            if (objectType != null) {
+                ResolvedJavaType instanceofType = type;
+                if (instanceofType.isAssignableFrom(objectType)) {
+                    if (objectStamp.nonNull()) {
+                        return TriState.TRUE;
+                    }
+                } else {
+                    if (objectStamp.isExactType()) {
+                        return TriState.FALSE;
+                    } else {
+                        boolean superType = objectType.isAssignableFrom(instanceofType);
+                        if (!superType && !objectType.isInterface() && !instanceofType.isInterface()) {
+                            return TriState.FALSE;
+                        }
+                    }
+                }
+            }
+        }
+        return TriState.UNKNOWN;
+    }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Mon Mar 09 15:04:08 2015 +0100
@@ -49,36 +49,23 @@
     private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes");
     private static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
 
-    private final boolean canonicalizeReads;
-    private final CustomCanonicalizer customCanonicalizer;
-
-    public abstract static class CustomCanonicalizer {
+    private boolean canonicalizeReads = true;
+    private boolean simplify = true;
 
-        public Node canonicalize(Node node) {
-            return node;
-        }
-
-        @SuppressWarnings("unused")
-        public void simplify(Node node, SimplifierTool tool) {
-        }
+    public CanonicalizerPhase() {
     }
 
-    public CanonicalizerPhase(boolean canonicalizeReads) {
-        this(canonicalizeReads, null);
+    public void disableReadCanonicalization() {
+        canonicalizeReads = false;
     }
 
-    public CanonicalizerPhase(boolean canonicalizeReads, CustomCanonicalizer customCanonicalizer) {
-        this.canonicalizeReads = canonicalizeReads;
-        this.customCanonicalizer = customCanonicalizer;
-    }
-
-    public boolean getCanonicalizeReads() {
-        return canonicalizeReads;
+    public void disableSimplification() {
+        simplify = false;
     }
 
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
-        new Instance(context, canonicalizeReads, customCanonicalizer).run(graph);
+        new Instance(context).run(graph);
     }
 
     /**
@@ -90,7 +77,7 @@
     }
 
     public void applyIncremental(StructuredGraph graph, PhaseContext context, Mark newNodesMark, boolean dumpGraph) {
-        new Instance(context, canonicalizeReads, newNodesMark, customCanonicalizer).apply(graph, dumpGraph);
+        new Instance(context, newNodesMark).apply(graph, dumpGraph);
     }
 
     /**
@@ -102,7 +89,7 @@
     }
 
     public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<? extends Node> workingSet, boolean dumpGraph) {
-        new Instance(context, canonicalizeReads, workingSet, customCanonicalizer).apply(graph, dumpGraph);
+        new Instance(context, workingSet).apply(graph, dumpGraph);
     }
 
     public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<? extends Node> workingSet, Mark newNodesMark) {
@@ -110,38 +97,34 @@
     }
 
     public void applyIncremental(StructuredGraph graph, PhaseContext context, Iterable<? extends Node> workingSet, Mark newNodesMark, boolean dumpGraph) {
-        new Instance(context, canonicalizeReads, workingSet, newNodesMark, customCanonicalizer).apply(graph, dumpGraph);
+        new Instance(context, workingSet, newNodesMark).apply(graph, dumpGraph);
     }
 
-    private static final class Instance extends Phase {
+    private final class Instance extends Phase {
 
         private final Mark newNodesMark;
         private final PhaseContext context;
-        private final CustomCanonicalizer customCanonicalizer;
         private final Iterable<? extends Node> initWorkingSet;
-        private final boolean canonicalizeReads;
 
         private NodeWorkList workList;
         private Tool tool;
 
-        private Instance(PhaseContext context, boolean canonicalizeReads, CustomCanonicalizer customCanonicalizer) {
-            this(context, canonicalizeReads, null, null, customCanonicalizer);
+        private Instance(PhaseContext context) {
+            this(context, null, null);
         }
 
-        private Instance(PhaseContext context, boolean canonicalizeReads, Iterable<? extends Node> workingSet, CustomCanonicalizer customCanonicalizer) {
-            this(context, canonicalizeReads, workingSet, null, customCanonicalizer);
+        private Instance(PhaseContext context, Iterable<? extends Node> workingSet) {
+            this(context, workingSet, null);
         }
 
-        private Instance(PhaseContext context, boolean canonicalizeReads, Mark newNodesMark, CustomCanonicalizer customCanonicalizer) {
-            this(context, canonicalizeReads, null, newNodesMark, customCanonicalizer);
+        private Instance(PhaseContext context, Mark newNodesMark) {
+            this(context, null, newNodesMark);
         }
 
-        private Instance(PhaseContext context, boolean canonicalizeReads, Iterable<? extends Node> workingSet, Mark newNodesMark, CustomCanonicalizer customCanonicalizer) {
+        private Instance(PhaseContext context, Iterable<? extends Node> workingSet, Mark newNodesMark) {
             super("Canonicalizer");
             this.newNodesMark = newNodesMark;
             this.context = context;
-            this.canonicalizeReads = canonicalizeReads;
-            this.customCanonicalizer = customCanonicalizer;
             this.initWorkingSet = workingSet;
         }
 
@@ -214,7 +197,7 @@
             }
         }
 
-        public static boolean tryGlobalValueNumbering(Node node, NodeClass<?> nodeClass) {
+        public boolean tryGlobalValueNumbering(Node node, NodeClass<?> nodeClass) {
             if (nodeClass.valueNumberable() && !nodeClass.isLeafNode()) {
                 Node newNode = node.graph().findDuplicate(node);
                 if (newNode != null) {
@@ -229,19 +212,7 @@
             return false;
         }
 
-        public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) {
-            if (customCanonicalizer != null) {
-                Node canonical = customCanonicalizer.canonicalize(node);
-                if (performReplacement(node, canonical)) {
-                    return true;
-                } else {
-                    customCanonicalizer.simplify(node, tool);
-                }
-            }
-            return baseTryCanonicalize(node, nodeClass);
-        }
-
-        private static AutoCloseable getCanonicalizeableContractAssertion(Node node) {
+        private AutoCloseable getCanonicalizeableContractAssertion(Node node) {
             boolean needsAssertion = false;
             assert (needsAssertion = true) == true;
             if (needsAssertion) {
@@ -255,7 +226,7 @@
             }
         }
 
-        public boolean baseTryCanonicalize(final Node node, NodeClass<?> nodeClass) {
+        public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) {
             if (nodeClass.isCanonicalizable()) {
                 METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
                 try (Scope s = Debug.scope("CanonicalizeNode", node)) {
@@ -274,7 +245,7 @@
                 }
             }
 
-            if (nodeClass.isSimplifiable()) {
+            if (nodeClass.isSimplifiable() && simplify) {
                 Debug.log(3, "Canonicalizer: simplifying %s", node);
                 METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
                 try (Scope s = Debug.scope("SimplifyNode", node)) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Mar 09 15:04:08 2015 +0100
@@ -778,6 +778,8 @@
             ResolvedJavaType type = state.getNodeType(object);
             if (isNull || (type != null && checkCast.type().isAssignableFrom(type))) {
                 boolean nonNull = state.isNonNull(object);
+                // if (true)
+                // throw new RuntimeException(checkCast.toString());
                 GuardingNode replacementAnchor = null;
                 if (nonNull) {
                     replacementAnchor = searchAnchor(GraphUtil.unproxify(object), type);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java	Mon Mar 09 15:04:08 2015 +0100
@@ -0,0 +1,472 @@
+/*
+ * Copyright (c) 2015, 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.phases.common;
+
+import static com.oracle.graal.api.meta.DeoptimizationAction.*;
+import static com.oracle.graal.api.meta.DeoptimizationReason.*;
+
+import java.util.*;
+import java.util.function.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.schedule.*;
+
+public class DominatorConditionalEliminationPhase extends Phase {
+
+    private static final DebugMetric metricStampsRegistered = Debug.metric("StampsRegistered");
+    private static final DebugMetric metricStampsFound = Debug.metric("StampsFound");
+    private final boolean fullSchedule;
+
+    public DominatorConditionalEliminationPhase(boolean fullSchedule) {
+        this.fullSchedule = fullSchedule;
+    }
+
+    private static final class InfoElement {
+        private Stamp stamp;
+        private ValueNode guard;
+
+        public InfoElement(Stamp stamp, ValueNode guard) {
+            this.stamp = stamp;
+            this.guard = guard;
+        }
+
+        public Stamp getStamp() {
+            return stamp;
+        }
+
+        public ValueNode getGuard() {
+            return guard;
+        }
+    }
+
+    private static final class Info {
+        private ArrayList<InfoElement> infos;
+
+        public Info() {
+            infos = new ArrayList<>();
+        }
+
+        public Iterable<InfoElement> getElements() {
+            return infos;
+        }
+
+        public void pushElement(InfoElement element) {
+            infos.add(element);
+        }
+
+        public void popElement() {
+            infos.remove(infos.size() - 1);
+        }
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+
+        Function<Block, Iterable<? extends Node>> blockToNodes;
+        Function<Node, Block> nodeToBlock;
+        Block startBlock;
+
+        if (fullSchedule) {
+            SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST);
+            schedule.apply(graph);
+            ControlFlowGraph cfg = schedule.getCFG();
+            cfg.computePostdominators();
+            blockToNodes = b -> schedule.getBlockToNodesMap().get(b);
+            nodeToBlock = n -> schedule.getNodeToBlockMap().get(n);
+            startBlock = cfg.getStartBlock();
+        } else {
+            ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, true);
+            cfg.computePostdominators();
+            blockToNodes = b -> b.getNodes();
+            nodeToBlock = n -> cfg.blockFor(n);
+            startBlock = cfg.getStartBlock();
+        }
+
+        Instance instance = new Instance(graph, blockToNodes, nodeToBlock);
+        instance.processBlock(startBlock);
+    }
+
+    private static class Instance {
+
+        private final NodeMap<Info> map;
+        private final Stack<LoopExitNode> loopExits;
+        private final Function<Block, Iterable<? extends Node>> blockToNodes;
+        private final Function<Node, Block> nodeToBlock;
+
+        public Instance(StructuredGraph graph, Function<Block, Iterable<? extends Node>> blockToNodes, Function<Node, Block> nodeToBlock) {
+            map = graph.createNodeMap();
+            loopExits = new Stack<>();
+            this.blockToNodes = blockToNodes;
+            this.nodeToBlock = nodeToBlock;
+        }
+
+        private void processBlock(Block block) {
+
+            List<Runnable> undoOperations = new ArrayList<>();
+
+            if (preprocess(block, undoOperations)) {
+
+                // Process always reached block first.
+                Block postdominator = block.getPostdominator();
+                if (postdominator != null && postdominator.getDominator() == block) {
+                    processBlock(postdominator);
+                }
+
+                // Now go for the other dominators.
+                for (Block dominated : block.getDominated()) {
+                    if (dominated != postdominator) {
+                        assert dominated.getDominator() == block;
+                        processBlock(dominated);
+                    }
+                }
+
+                postprocess(undoOperations);
+            }
+        }
+
+        private static void postprocess(List<Runnable> undoOperations) {
+            for (Runnable r : undoOperations) {
+                r.run();
+            }
+        }
+
+        private boolean preprocess(Block block, List<Runnable> undoOperations) {
+            AbstractBeginNode beginNode = block.getBeginNode();
+            if (beginNode.isAlive() || (beginNode instanceof MergeNode && beginNode.next().isAlive())) {
+                if (beginNode instanceof LoopExitNode) {
+                    LoopExitNode loopExitNode = (LoopExitNode) beginNode;
+                    this.loopExits.push(loopExitNode);
+                    undoOperations.add(() -> loopExits.pop());
+                }
+                for (Node n : blockToNodes.apply(block)) {
+                    if (n.isAlive()) {
+                        processNode(n, undoOperations);
+                    }
+                }
+                return true;
+            } else {
+                // Control flow has been deleted by previous eliminations.
+                return false;
+            }
+        }
+
+        private void processNode(Node node, List<Runnable> undoOperations) {
+            if (node instanceof AbstractBeginNode) {
+                processAbstractBegin((AbstractBeginNode) node, undoOperations);
+            } else if (node instanceof FixedGuardNode) {
+                processFixedGuard((FixedGuardNode) node, undoOperations);
+            } else if (node instanceof GuardNode) {
+                processGuard((GuardNode) node, undoOperations);
+            } else if (node instanceof CheckCastNode) {
+                processCheckCast((CheckCastNode) node);
+            } else if (node instanceof ConditionAnchorNode) {
+                processConditionAnchor((ConditionAnchorNode) node);
+            } else if (node instanceof IfNode) {
+                processIf((IfNode) node);
+            } else {
+                return;
+            }
+        }
+
+        private void processCheckCast(CheckCastNode node) {
+            tryProofCondition(node, (guard, result) -> {
+                if (result) {
+                    PiNode piNode = node.graph().unique(new PiNode(node.object(), node.stamp(), guard));
+                    node.replaceAtUsages(piNode);
+                    GraphUtil.unlinkFixedNode(node);
+                    node.safeDelete();
+                } else {
+                    DeoptimizeNode deopt = node.graph().add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
+                    node.replaceAtPredecessor(deopt);
+                    GraphUtil.killCFG(node);
+                }
+            });
+        }
+
+        private void processIf(IfNode node) {
+            tryProofCondition(node.condition(), (guard, result) -> {
+                AbstractBeginNode survivingSuccessor = node.getSuccessor(result);
+                survivingSuccessor.replaceAtUsages(InputType.Guard, guard);
+                survivingSuccessor.replaceAtPredecessor(null);
+                node.replaceAtPredecessor(survivingSuccessor);
+                GraphUtil.killCFG(node);
+            });
+        }
+
+        private void registerNewCondition(LogicNode condition, boolean negated, ValueNode guard, List<Runnable> undoOperations) {
+            if (condition instanceof UnaryOpLogicNode) {
+                UnaryOpLogicNode unaryLogicNode = (UnaryOpLogicNode) condition;
+                Stamp newStamp = unaryLogicNode.getSucceedingStampForValue(negated);
+                registerNewStamp(unaryLogicNode.getValue(), newStamp, guard, undoOperations);
+            } else if (condition instanceof BinaryOpLogicNode) {
+                BinaryOpLogicNode binaryOpLogicNode = (BinaryOpLogicNode) condition;
+                ValueNode x = binaryOpLogicNode.getX();
+                if (!x.isConstant()) {
+                    Stamp newStampX = binaryOpLogicNode.getSucceedingStampForX(negated);
+                    registerNewStamp(x, newStampX, guard, undoOperations);
+                }
+
+                ValueNode y = binaryOpLogicNode.getY();
+                if (!y.isConstant()) {
+                    Stamp newStampY = binaryOpLogicNode.getSucceedingStampForY(negated);
+                    registerNewStamp(y, newStampY, guard, undoOperations);
+                }
+                registerCondition(condition, negated, guard, undoOperations);
+            }
+        }
+
+        private void registerCondition(LogicNode condition, boolean negated, ValueNode guard, List<Runnable> undoOperations) {
+            this.registerNewStamp(condition, negated ? StampFactory.contradiction() : StampFactory.tautology(), guard, undoOperations);
+        }
+
+        private Iterable<InfoElement> getInfoElements(ValueNode proxiedValue) {
+            ValueNode value = GraphUtil.unproxify(proxiedValue);
+            Info info = map.get(value);
+            if (info == null) {
+                return Collections.emptyList();
+            } else {
+                return info.getElements();
+            }
+        }
+
+        private boolean rewireGuards(ValueNode guard, boolean result, BiConsumer<ValueNode, Boolean> rewireGuardFunction) {
+            assert guard instanceof GuardingNode;
+            metricStampsFound.increment();
+            ValueNode proxiedGuard = proxyGuard(guard);
+            rewireGuardFunction.accept(proxiedGuard, result);
+            return true;
+        }
+
+        private ValueNode proxyGuard(ValueNode guard) {
+            ValueNode proxiedGuard = guard;
+            if (!this.loopExits.isEmpty()) {
+                while (proxiedGuard instanceof GuardProxyNode) {
+                    proxiedGuard = ((GuardProxyNode) proxiedGuard).value();
+                }
+                Block guardBlock = nodeToBlock.apply(proxiedGuard);
+                assert guardBlock != null;
+                for (int i = 0; i < loopExits.size(); ++i) {
+                    LoopExitNode loopExitNode = loopExits.get(i);
+                    Block loopExitBlock = nodeToBlock.apply(loopExitNode);
+                    if (guardBlock != loopExitBlock && AbstractControlFlowGraph.dominates(guardBlock, loopExitBlock)) {
+                        Block loopBeginBlock = nodeToBlock.apply(loopExitNode.loopBegin());
+                        if (!AbstractControlFlowGraph.dominates(guardBlock, loopBeginBlock) || guardBlock == loopBeginBlock) {
+                            proxiedGuard = proxiedGuard.graph().unique(new GuardProxyNode((GuardingNode) proxiedGuard, loopExitNode));
+                        }
+                    }
+                }
+            }
+            return proxiedGuard;
+        }
+
+        private boolean tryProofCondition(Node node, BiConsumer<ValueNode, Boolean> rewireGuardFunction) {
+            if (node instanceof UnaryOpLogicNode) {
+                UnaryOpLogicNode unaryLogicNode = (UnaryOpLogicNode) node;
+                ValueNode value = unaryLogicNode.getValue();
+                for (InfoElement infoElement : getInfoElements(value)) {
+                    Stamp stamp = infoElement.getStamp();
+                    TriState result = unaryLogicNode.tryFold(stamp);
+                    if (result.isKnown()) {
+                        return rewireGuards(infoElement.getGuard(), result.toBoolean(), rewireGuardFunction);
+                    }
+                }
+            } else if (node instanceof BinaryOpLogicNode) {
+                BinaryOpLogicNode binaryOpLogicNode = (BinaryOpLogicNode) node;
+                for (InfoElement infoElement : getInfoElements(binaryOpLogicNode)) {
+                    if (infoElement.getStamp().equals(StampFactory.contradiction())) {
+                        return rewireGuards(infoElement.getGuard(), false, rewireGuardFunction);
+                    } else if (infoElement.getStamp().equals(StampFactory.tautology())) {
+                        return rewireGuards(infoElement.getGuard(), true, rewireGuardFunction);
+                    }
+                }
+
+                ValueNode x = binaryOpLogicNode.getX();
+                ValueNode y = binaryOpLogicNode.getY();
+                for (InfoElement infoElement : getInfoElements(x)) {
+                    TriState result = binaryOpLogicNode.tryFold(infoElement.getStamp(), y.stamp());
+                    if (result.isKnown()) {
+                        return rewireGuards(infoElement.getGuard(), result.toBoolean(), rewireGuardFunction);
+                    }
+                }
+
+                for (InfoElement infoElement : getInfoElements(y)) {
+                    TriState result = binaryOpLogicNode.tryFold(x.stamp(), infoElement.getStamp());
+                    if (result.isKnown()) {
+                        return rewireGuards(infoElement.getGuard(), result.toBoolean(), rewireGuardFunction);
+                    }
+                }
+            } else if (node instanceof CheckCastNode) {
+                CheckCastNode checkCastNode = (CheckCastNode) node;
+                for (InfoElement infoElement : getInfoElements(checkCastNode.object())) {
+                    TriState result = checkCastNode.tryFold(infoElement.getStamp());
+                    if (result.isKnown()) {
+                        return rewireGuards(infoElement.getGuard(), result.toBoolean(), rewireGuardFunction);
+                    }
+                }
+            } else if (node instanceof ShortCircuitOrNode) {
+                final ShortCircuitOrNode shortCircuitOrNode = (ShortCircuitOrNode) node;
+                if (this.loopExits.isEmpty()) {
+                    tryProofCondition(shortCircuitOrNode.getX(), (guard, result) -> {
+                        if (result == !shortCircuitOrNode.isXNegated()) {
+                            rewireGuards(guard, result, rewireGuardFunction);
+                        } else {
+                            tryProofCondition(shortCircuitOrNode.getY(), (innerGuard, innerResult) -> {
+                                if (innerGuard == guard) {
+                                    rewireGuards(guard, shortCircuitOrNode.isYNegated() ? !innerResult : innerResult, rewireGuardFunction);
+                                }
+                            });
+                        }
+                    });
+                }
+            }
+
+            return false;
+        }
+
+        private void registerNewStamp(ValueNode proxiedValue, Stamp newStamp, ValueNode guard, List<Runnable> undoOperations) {
+            if (newStamp != null) {
+                ValueNode value = GraphUtil.unproxify(proxiedValue);
+                Info info = map.get(value);
+                if (info == null) {
+                    info = new Info();
+                    map.set(value, info);
+                }
+                metricStampsRegistered.increment();
+                final Info finalInfo = info;
+                finalInfo.pushElement(new InfoElement(newStamp, guard));
+                undoOperations.add(() -> finalInfo.popElement());
+            }
+        }
+
+        private void processConditionAnchor(ConditionAnchorNode node) {
+            tryProofCondition(node.condition(), (guard, result) -> {
+                if (result == node.isNegated()) {
+                    node.replaceAtUsages(guard);
+                    GraphUtil.unlinkFixedNode(node);
+                    GraphUtil.killWithUnusedFloatingInputs(node);
+                } else {
+                    ValueAnchorNode valueAnchor = node.graph().add(new ValueAnchorNode(null));
+                    node.replaceAtUsages(valueAnchor);
+                    node.graph().replaceFixedWithFixed(node, valueAnchor);
+                }
+            });
+        }
+
+        private void processGuard(GuardNode node, List<Runnable> undoOperations) {
+            if (!tryProofCondition(node.condition(), (guard, result) -> {
+                if (result != node.isNegated()) {
+                    node.replaceAndDelete(guard);
+                } else {
+                    DeoptimizeNode deopt = node.graph().add(new DeoptimizeNode(node.action(), node.reason()));
+                    Block block = nodeToBlock.apply(node);
+                    FixedNode next = block.getBeginNode().next();
+                    block.getBeginNode().setNext(deopt);
+                    GraphUtil.killCFG(next);
+                }
+            })) {
+                registerNewCondition(node.condition(), node.isNegated(), node, undoOperations);
+            }
+        }
+
+        private void processFixedGuard(FixedGuardNode node, List<Runnable> undoOperations) {
+            if (!tryProofCondition(node.condition(), (guard, result) -> {
+                if (result != node.isNegated()) {
+                    node.replaceAtUsages(guard);
+                    GraphUtil.unlinkFixedNode(node);
+                    GraphUtil.killWithUnusedFloatingInputs(node);
+                } else {
+                    DeoptimizeNode deopt = node.graph().add(new DeoptimizeNode(node.getAction(), node.getReason()));
+                    deopt.setStateBefore(node.stateBefore());
+                    node.replaceAtPredecessor(deopt);
+                    GraphUtil.killCFG(node);
+                }
+            })) {
+                registerNewCondition(node.condition(), node.isNegated(), node, undoOperations);
+            }
+        }
+
+        private void processAbstractBegin(AbstractBeginNode beginNode, List<Runnable> undoOperations) {
+            Node predecessor = beginNode.predecessor();
+            if (predecessor instanceof IfNode) {
+                IfNode ifNode = (IfNode) predecessor;
+                boolean negated = (ifNode.falseSuccessor() == beginNode);
+                LogicNode condition = ifNode.condition();
+                registerNewCondition(condition, negated, beginNode, undoOperations);
+            } else if (predecessor instanceof TypeSwitchNode) {
+                TypeSwitchNode typeSwitch = (TypeSwitchNode) predecessor;
+                processTypeSwitch(beginNode, undoOperations, predecessor, typeSwitch);
+            } else if (predecessor instanceof IntegerSwitchNode) {
+                IntegerSwitchNode integerSwitchNode = (IntegerSwitchNode) predecessor;
+                processIntegerSwitch(beginNode, undoOperations, predecessor, integerSwitchNode);
+            }
+        }
+
+        private void processIntegerSwitch(AbstractBeginNode beginNode, List<Runnable> undoOperations, Node predecessor, IntegerSwitchNode integerSwitchNode) {
+            Stamp stamp = null;
+            for (int i = 0; i < integerSwitchNode.keyCount(); i++) {
+                if (integerSwitchNode.keySuccessor(i) == predecessor) {
+                    if (stamp == null) {
+                        stamp = StampFactory.forConstant(integerSwitchNode.keyAt(i));
+                    } else {
+                        stamp = stamp.meet(StampFactory.forConstant(integerSwitchNode.keyAt(i)));
+                    }
+                }
+            }
+
+            if (stamp != null) {
+                registerNewStamp(integerSwitchNode.value(), stamp, beginNode, undoOperations);
+            }
+        }
+
+        private void processTypeSwitch(AbstractBeginNode beginNode, List<Runnable> undoOperations, Node predecessor, TypeSwitchNode typeSwitch) {
+            ValueNode hub = typeSwitch.value();
+            if (hub instanceof LoadHubNode) {
+                LoadHubNode loadHub = (LoadHubNode) hub;
+                Stamp stamp = null;
+                for (int i = 0; i < typeSwitch.keyCount(); i++) {
+                    if (typeSwitch.keySuccessor(i) == predecessor) {
+                        if (stamp == null) {
+                            stamp = StampFactory.exactNonNull(typeSwitch.typeAt(i));
+                        } else {
+                            stamp = stamp.meet(StampFactory.exactNonNull(typeSwitch.typeAt(i)));
+                        }
+                    }
+                }
+                if (stamp != null) {
+                    registerNewStamp(loadHub.getValue(), stamp, beginNode, undoOperations);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java	Mon Mar 09 15:04:08 2015 +0100
@@ -38,19 +38,20 @@
     private static final int MAX_ITERATIONS = 256;
 
     private final CanonicalizerPhase canonicalizer;
+    private final boolean fullSchedule;
 
-    public IterativeConditionalEliminationPhase(CanonicalizerPhase canonicalizer) {
+    public IterativeConditionalEliminationPhase(CanonicalizerPhase canonicalizer, boolean fullSchedule) {
         this.canonicalizer = canonicalizer;
+        this.fullSchedule = fullSchedule;
     }
 
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
-        ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase();
-        HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NODE_ADDED);
+        HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NODE_ADDED).exclude(ZERO_USAGES);
         int count = 0;
         while (true) {
             try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
-                eliminate.apply(graph);
+                new DominatorConditionalEliminationPhase(fullSchedule).apply(graph);
             }
             if (listener.getNodes().isEmpty()) {
                 break;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Mon Mar 09 15:04:08 2015 +0100
@@ -278,7 +278,10 @@
                 metricInliningTailDuplication.increment();
                 Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities);
                 PhaseContext phaseContext = new PhaseContext(providers);
-                CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue());
+                CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+                if (ImmutableCode.getValue()) {
+                    canonicalizer.disableReadCanonicalization();
+                }
                 TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, phaseContext, canonicalizer);
             }
         }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Mar 09 15:04:08 2015 +0100
@@ -75,8 +75,6 @@
         LATEST_OUT_OF_LOOPS
     }
 
-    static int created;
-
     private class LocationSet {
         private LocationIdentity firstLocation;
         private List<LocationIdentity> list;
@@ -305,6 +303,7 @@
     private BlockMap<LocationSet> blockToKillSet;
     private final SchedulingStrategy selectedStrategy;
     private boolean scheduleConstants;
+    private NodeMap<Block> nodeToBlockMap;
 
     public SchedulePhase() {
         this(OptScheduleOutOfLoops.getValue() ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST);
@@ -358,6 +357,11 @@
                 for (PhiNode phi : mergeNode.phis()) {
                     nodeToBlock.set(phi, b);
                 }
+            } else if (beginNode instanceof LoopExitNode) {
+                LoopExitNode loopExitNode = (LoopExitNode) beginNode;
+                for (ProxyNode proxy : loopExitNode.proxies()) {
+                    nodeToBlock.set(proxy, b);
+                }
             }
         }
 
@@ -378,7 +382,7 @@
                 if (visited.isMarked(phi)) {
                     for (int i = 0; i < loopBegin.getLoopEndCount(); ++i) {
                         Node node = phi.valueAt(i + loopBegin.forwardEndCount());
-                        if (!visited.isMarked(node)) {
+                        if (node != null && !visited.isMarked(node)) {
                             stack.push(node);
                             processStack(blockToNodes, nodeToBlock, visited, stack);
                         }
@@ -406,6 +410,7 @@
         }
 
         this.blockToNodesMap = blockToNodes;
+        this.nodeToBlockMap = nodeToBlock;
     }
 
     private static void addNode(BlockMap<List<ValueNode>> blockToNodes, Block b, ValueNode endNode) {
@@ -430,7 +435,9 @@
                     AbstractMergeNode merge = phiNode.merge();
                     for (int i = 0; i < merge.forwardEndCount(); ++i) {
                         Node input = phiNode.valueAt(i);
-                        stack.push(input);
+                        if (input != null) {
+                            stack.push(input);
+                        }
                     }
                 } else {
                     for (Node input : current.inputs()) {
@@ -561,6 +568,10 @@
         return blockToNodesMap;
     }
 
+    public NodeMap<Block> getNodeToBlockMap() {
+        return this.nodeToBlockMap;
+    }
+
     /**
      * Gets the nodes in a given block.
      */
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ArraysSubstitutionsTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -332,8 +332,8 @@
     public void testCanonicalLength() {
         StructuredGraph graph = parseEager("testCanonicalLengthSnippet", AllowAssumptions.NO);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
 
         Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0);
     }
@@ -348,8 +348,8 @@
     public void testCanonicalEqual() {
         StructuredGraph graph = parseEager("testCanonicalEqualSnippet", AllowAssumptions.NO);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
 
         Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1);
     }
@@ -362,10 +362,10 @@
     public void testVirtualEqual() {
         StructuredGraph graph = parseEager("testVirtualEqualSnippet", AllowAssumptions.NO);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
-        new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+        new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
 
         Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 1);
     }
@@ -380,10 +380,10 @@
     public void testVirtualNotEqual() {
         StructuredGraph graph = parseEager("testVirtualNotEqualSnippet", AllowAssumptions.NO);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
-        new PartialEscapePhase(false, new CanonicalizerPhase(false)).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
+        new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
 
         Assert.assertTrue(graph.getNodes(ReturnNode.TYPE).first().result().asJavaConstant().asLong() == 0);
     }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -249,7 +249,7 @@
     private ValueNode parseAndInline(String name, Class<? extends ValueNode> expectedClass) {
         StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE);
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
         canonicalizer.apply(graph, context);
         new InliningPhase(canonicalizer).apply(graph, context);
         canonicalizer.apply(graph, context);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/EdgesTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -116,8 +116,8 @@
         ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method);
         StructuredGraph g = parseProfiled(javaMethod, AllowAssumptions.NO);
         HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
-        new InliningPhase(new InlineMethodSubstitutionsPolicy(), new CanonicalizerPhase(true)).apply(g, context);
-        new CanonicalizerPhase(false).apply(g, context);
+        new InliningPhase(new InlineMethodSubstitutionsPolicy(), new CanonicalizerPhase()).apply(g, context);
+        new CanonicalizerPhase().apply(g, context);
         Assert.assertTrue(g.getNodes().filter(CheckCastNode.class).isEmpty());
     }
 
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MethodSubstitutionTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -52,9 +52,9 @@
             StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
             HighTierContext context = new HighTierContext(getProviders(), null, getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL);
             Debug.dump(graph, "Graph");
-            new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+            new InliningPhase(new CanonicalizerPhase()).apply(graph, context);
             Debug.dump(graph, "Graph");
-            new CanonicalizerPhase(true).apply(graph, context);
+            new CanonicalizerPhase().apply(graph, context);
             new DeadCodeEliminationPhase().apply(graph);
 
             assertNotInGraph(graph, Invoke.class);
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -403,7 +403,7 @@
         HighTierContext context = new HighTierContext(getProviders(), null, null, OptimisticOptimizations.ALL);
 
         StructuredGraph graph = parseEager(snippetName, AllowAssumptions.YES);
-        new CanonicalizerPhase(false).apply(graph, context);
+        new CanonicalizerPhase().apply(graph, context);
         Assert.assertEquals(expectedWordCasts, graph.getNodes().filter(WordCastNode.class).count());
     }
 
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/TypeCheckTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/TypeCheckTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -25,7 +25,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.*;
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Mar 09 15:04:08 2015 +0100
@@ -287,7 +287,7 @@
         // Do deferred intrinsification of node intrinsics
 
         nodeIntrinsificationPhase.apply(specializedSnippet);
-        new CanonicalizerPhase(true).apply(specializedSnippet, new PhaseContext(providers));
+        new CanonicalizerPhase().apply(specializedSnippet, new PhaseContext(providers));
         NodeIntrinsificationVerificationPhase.verify(specializedSnippet);
     }
 
@@ -627,7 +627,7 @@
                 afterParsing(graph);
 
                 if (OptCanonicalizer.getValue()) {
-                    new CanonicalizerPhase(true).apply(graph, new PhaseContext(replacements.providers));
+                    new CanonicalizerPhase().apply(graph, new PhaseContext(replacements.providers));
                 }
             } catch (Throwable e) {
                 throw Debug.handle(e);
@@ -659,7 +659,7 @@
          */
         protected void afterInline(StructuredGraph caller, StructuredGraph callee, Object beforeInlineData) {
             if (OptCanonicalizer.getValue()) {
-                new CanonicalizerPhase(true).apply(caller, new PhaseContext(replacements.providers));
+                new CanonicalizerPhase().apply(caller, new PhaseContext(replacements.providers));
             }
         }
 
@@ -670,7 +670,7 @@
             replacements.nodeIntrinsificationPhase.apply(graph);
             new DeadCodeEliminationPhase(Optional).apply(graph);
             if (OptCanonicalizer.getValue()) {
-                new CanonicalizerPhase(true).apply(graph, new PhaseContext(replacements.providers));
+                new CanonicalizerPhase().apply(graph, new PhaseContext(replacements.providers));
             }
         }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Mon Mar 09 15:04:08 2015 +0100
@@ -670,8 +670,8 @@
                 if (loopBegin != null) {
                     LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin);
                     Mark mark = snippetCopy.getMark();
-                    LoopTransformations.fullUnroll(loop, phaseContext, new CanonicalizerPhase(true));
-                    new CanonicalizerPhase(true).applyIncremental(snippetCopy, phaseContext, mark);
+                    LoopTransformations.fullUnroll(loop, phaseContext, new CanonicalizerPhase());
+                    new CanonicalizerPhase().applyIncremental(snippetCopy, phaseContext, mark);
                     loop.deleteUnusedNodes();
                 }
                 GraphUtil.removeFixedWithUnusedInputs(explodeLoop);
@@ -686,7 +686,7 @@
         }
         snippetCopy.setGuardsStage(guardsStage);
         try (Scope s = Debug.scope("LoweringSnippetTemplate", snippetCopy)) {
-            new LoweringPhase(new CanonicalizerPhase(true), args.cacheKey.loweringStage).apply(snippetCopy, phaseContext);
+            new LoweringPhase(new CanonicalizerPhase(), args.cacheKey.loweringStage).apply(snippetCopy, phaseContext);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Mon Mar 09 15:04:08 2015 +0100
@@ -142,7 +142,7 @@
             }
         }
         try (Scope s = Debug.scope("LoweringSnippetTemplate", replacementGraph)) {
-            new LoweringPhase(new CanonicalizerPhase(true), tool.getLoweringStage()).apply(replacementGraph, c);
+            new LoweringPhase(new CanonicalizerPhase(), tool.getLoweringStage()).apply(replacementGraph, c);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java	Mon Mar 09 15:04:08 2015 +0100
@@ -100,7 +100,7 @@
             frameState.replaceAtUsages(null);
             frameState.safeDelete();
         }
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders()));
+        new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders()));
         new DeadCodeEliminationPhase().apply(graph);
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Mon Mar 09 15:04:08 2015 +0100
@@ -85,7 +85,7 @@
 
     public PartialEvaluator(Providers providers, GraphBuilderConfiguration configForRoot, TruffleCache truffleCache, SnippetReflectionProvider snippetReflection) {
         this.providers = providers;
-        this.canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue());
+        this.canonicalizer = new CanonicalizerPhase();
         this.snippetReflection = snippetReflection;
         this.truffleCache = truffleCache;
         this.callDirectMethod = providers.getMetaAccess().lookupJavaMethod(OptimizedCallTarget.getCallDirectMethod());
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Mon Mar 09 14:22:15 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Mon Mar 09 15:04:08 2015 +0100
@@ -65,7 +65,7 @@
 
                 Map<Invoke, Double> hints = PEAInliningHints.getValue() ? PartialEscapePhase.getHints(graph) : null;
 
-                InliningPhase inlining = new InliningPhase(hints, new CanonicalizerPhase(true));
+                InliningPhase inlining = new InliningPhase(hints, new CanonicalizerPhase());
                 inlining.setMaxMethodsPerInlining(simple ? 1 : Integer.MAX_VALUE);
                 inlining.apply(graph, context);
                 progress |= inlining.getInliningCount() > 0;
@@ -74,7 +74,7 @@
 
                 if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
                     canonicalizer.apply(graph, context);
-                    new IterativeConditionalEliminationPhase(canonicalizer).apply(graph, context);
+                    new IterativeConditionalEliminationPhase(canonicalizer, false).apply(graph, context);
                 }
                 if (!progress) {
                     break;