changeset 18940:2ad82c6147f1

Temporarily remove FlowSensitiveReductionPhase.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 23 Jan 2015 22:13:55 +0100
parents 732748092bae
children c943ba97b2a7
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Evidence.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Histogram.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Witness.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java
diffstat 22 files changed, 4 insertions(+), 5696 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Fri Jan 23 22:00:55 2015 +0100
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Fri Jan 23 22:13:55 2015 +0100
@@ -232,10 +232,6 @@
     @Option(help = "Comma separated list of register that the allocation is limited to.", type = OptionType.Debug)
     public static final OptionValue<String> RegisterPressure = new OptionValue<>(null);
 
-    // Code generator settings
-    @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> FlowSensitiveReduction = new OptionValue<>(false);
-
     @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSenReduTest.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,392 +0,0 @@
-/*
- * Copyright (c) 2011, 2014, 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 java.util.*;
-
-import org.junit.*;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.cfs.*;
-import com.oracle.graal.phases.tiers.*;
-
-/**
- * Tests whether {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} actually
- * performs some graph rewritings that it's supposed to perform.
- */
-public class FlowSenReduTest extends GraalCompilerTest {
-
-    /*
-     * A previous instanceof makes redundant a follow-up checkcast.
-     */
-    public Object redundantCheckCastSnippet(Number o) {
-        Integer z = null;
-        if (o instanceof Integer) {
-            z = (Integer) o; // this CheckCastNode will be removed
-        }
-        return z;
-    }
-
-    static final Integer i7 = new Integer(7);
-
-    @Test
-    public void redundantCheckCastTest() {
-        assertDeepEquals(i7, redundantCheckCastSnippet(i7));
-        StructuredGraph result = afterFlowSensitiveReduce("redundantCheckCastSnippet");
-        nodeCountEquals(result, CheckCastNode.class, 0);
-        nodeCountEquals(result, InstanceOfNode.class, 1);
-    }
-
-    @SuppressWarnings("unused")
-    public boolean redundantInstanceOfSnippet01(Object o) {
-        if (o != null) {
-            Integer x = (Integer) o;
-            return (o instanceof Number); // this InstanceOfNode will be removed
-        }
-        return false;
-    }
-
-    @Test
-    public void redundantInstanceOfTest01() {
-        String snippet = "redundantInstanceOfSnippet01";
-        assertDeepEquals(true, redundantInstanceOfSnippet01(i7));
-        nodeCountEquals(afterFlowSensitiveReduce(snippet), InstanceOfNode.class, 1);
-    }
-
-    /*
-     * The combination of (previous) non-null-check and checkcast make redundant an instanceof.
-     */
-    @SuppressWarnings("unused")
-    public Object redundantInstanceOfSnippet02(Object o) {
-        Integer x = (Integer) o;
-        if (o != null) {
-            if (o instanceof Number) { // this InstanceOfNode will be removed
-                return o;
-            }
-        }
-        return null;
-    }
-
-    @Test
-    public void redundantInstanceOfTest02() {
-        String snippet = "redundantInstanceOfSnippet02";
-        assertDeepEquals(i7, redundantInstanceOfSnippet02(i7));
-        int ioAfter = getNodes(afterFlowSensitiveReduce(snippet), InstanceOfNode.class).size();
-        assertDeepEquals(ioAfter, 1);
-    }
-
-    /*
-     * Once an exact-type has been inferred (due to instanceof final-class) a callsite is
-     * devirtualized.
-     */
-    public int devirtualizationSnippet(Object x, Object y) {
-        boolean c = x instanceof Integer;
-        if (c && x == y) {
-            Number z = (Number) y; // this CheckCastNode will be removed
-            return z.intValue(); // devirtualized into InvokeSpecial on Integer.intValue()
-        }
-        return 0;
-    }
-
-    @Test
-    public void devirtualizationTest() {
-        String snippet = "devirtualizationSnippet";
-        assertDeepEquals(i7, devirtualizationSnippet(i7, i7));
-        nodeCountEquals(afterFlowSensitiveReduce(snippet), CheckCastNode.class, 0);
-
-        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
-        assertDeepEquals(0, graph.getNodes().filter(CheckCastNode.class).count());
-
-        List<InvokeNode> invokeNodes = getNodes(afterFlowSensitiveReduce(snippet), InvokeNode.class);
-        assertDeepEquals(1, invokeNodes.size());
-
-        MethodCallTargetNode target = (MethodCallTargetNode) invokeNodes.get(0).callTarget();
-        assertDeepEquals(MethodCallTargetNode.InvokeKind.Special, target.invokeKind());
-        assertDeepEquals("HotSpotMethod<Integer.intValue()>", target.targetMethod().toString());
-    }
-
-    /*
-     * At the return statement, the returned value has been inferred to have type j.l.Number. The
-     * instanceof is deemed to always evaluate to false. The interplay with tail-duplication is also
-     * taken into account (resulting in two return statements, each with "false" as input).
-     */
-    @SuppressWarnings("unused")
-    public boolean t5Snippet(Object o, boolean b) {
-        Number z;
-        if (b) {
-            z = (Number) o; // tail duplication of return stmt, which becomes "return false"
-        } else {
-            z = (Integer) o; // tail duplication of return stmt, which becomes "return false"
-        }
-        return o instanceof String; // unreachable
-    }
-
-    @Test
-    public void t5a() {
-        String snippet = "t5Snippet";
-        assertDeepEquals(false, t5Snippet(null, true));
-        StructuredGraph resultGraph = canonicalize(afterFlowSensitiveReduce(snippet));
-        nodeCountEquals(resultGraph, ReturnNode.class, 2);
-
-        List<ReturnNode> returnNodes = getNodes(resultGraph, ReturnNode.class);
-        Iterator<ReturnNode> iter = returnNodes.iterator();
-
-        ConstantNode c1 = (ConstantNode) iter.next().result();
-        ConstantNode c2 = (ConstantNode) iter.next().result();
-
-        assertDeepEquals(c1, c2);
-        assertDeepEquals(0, c1.asJavaConstant().asInt());
-    }
-
-    @Test
-    public void t5b() {
-        String snippet = "t5Snippet";
-        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
-        canonicalize(graph);
-        nodeCountEquals(graph, InstanceOfNode.class, 2);
-    }
-
-    public boolean t6Snippet(Object x, Object y) {
-        if (!(x instanceof String)) {
-            return false;
-        }
-        if (!(y instanceof Number)) {
-            return false;
-        }
-        return x == y; // two known-not-to-conform reference values can't be ==
-    }
-
-    // TODO: two known-not-to-conform reference values can't be ==
-    // but baseCaseObjectEqualsNode doesn't check that as of now.
-    public void t6() {
-        String snippet = "t6Snippet";
-        // visualize(snippet);
-        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
-        canonicalize(graph);
-        nodeCountEquals(graph, ObjectEqualsNode.class, 0);
-    }
-
-    /*
-     * A previous instanceof check causes a follow-up instanceof to be deemed unsatisfiable,
-     * resulting in constant-substitution at that usage.
-     */
-    public Object t7Snippet(Object o) {
-        if (o instanceof Number) {
-            if (o instanceof String) { // condition amounts to false
-                return o; // made unreachable
-            }
-        }
-        return null;
-    }
-
-    @Test
-    public void t7() {
-        String snippet = "t7Snippet";
-        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
-        graph = dce(canonicalize(graph));
-        // TODO how to simplify IfNode(false)
-        assertDeepEquals(1, getNodes(graph, InstanceOfNode.class).size());
-
-        List<ReturnNode> returnNodes = getNodes(graph, ReturnNode.class);
-        assertDeepEquals(2, returnNodes.size());
-        Iterator<ReturnNode> iter = returnNodes.iterator();
-
-        ConstantNode c1 = (ConstantNode) iter.next().result();
-        ConstantNode c2 = (ConstantNode) iter.next().result();
-
-        assertDeepEquals(c1, c2);
-        Assert.assertTrue(c1.isNullConstant());
-    }
-
-    /*
-     * During FlowSensitiveReduction, an unreachable branch doesn't contribute to the merged state.
-     * The resulting ("non-polluted") more precise inferred type after the merge allows
-     * devirtualizing a callsite.
-     */
-    public int devirtualizationSnippet02(Number o) {
-        if (o instanceof Integer) {
-            Number z = o;
-            if (o instanceof Long) {
-                z = o;
-            }
-            /*
-             * devirtualized into InvokeSpecial on Integer.intValue() ie the inferred-type is not
-             * polluted with values from the unreachable branch.
-             */
-            return z.intValue();
-        }
-        return 0;
-    }
-
-    @Test
-    public void devirtualizationTest02() {
-        String snippet = "devirtualizationSnippet02";
-        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
-
-        assertDeepEquals(1, getNodes(graph, InvokeNode.class).size());
-
-        List<InvokeNode> invokeNodes = getNodes(graph, InvokeNode.class);
-        assertDeepEquals(1, invokeNodes.size());
-
-        MethodCallTargetNode target = (MethodCallTargetNode) invokeNodes.get(0).callTarget();
-        assertDeepEquals(MethodCallTargetNode.InvokeKind.Special, target.invokeKind());
-        assertDeepEquals("HotSpotMethod<Integer.intValue()>", target.targetMethod().toString());
-    }
-
-    /*
-     * TODO ClassCastException known to fail --- either Deopt or throw ObjectGetClassNode The latter
-     * might lead to direct jump to EH if present.
-     */
-    @SuppressWarnings("unused")
-    public int t9Snippet(Object o) {
-        try {
-            if (o instanceof Number) {
-                String s = (String) o;
-                /*
-                 * make a long story short: replace the above with throw new ClassCastException (ok,
-                 * actual type of o unknown).
-                 */
-                return 1;
-            }
-        } catch (ClassCastException e) {
-            return 2;
-        }
-        return 3;
-    }
-
-    /*
-     * "Partial evaluation" via canonicalization of an expression (in the last return statement) one
-     * of whose leaf sub-expressions was determined to be constant.
-     */
-    @SuppressWarnings("unused")
-    public Object partialEvalSnippet01(Object o, boolean b) {
-        if (o == null) {
-            return o; // turned into "return null;"
-        } else {
-            Number z;
-            if (b) {
-                z = (Number) o;
-            } else {
-                z = (Integer) o;
-            }
-            return o instanceof String ? this : null; // turned into "return null;"
-        }
-    }
-
-    @Test
-    public void partialEvalTest01() {
-        String snippet = "partialEvalSnippet01";
-
-        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
-        canonicalize(graph);
-        dce(graph);
-
-        List<ReturnNode> returnNodes = getNodes(graph, ReturnNode.class);
-        assertDeepEquals(2, returnNodes.size());
-        Iterator<ReturnNode> iter = returnNodes.iterator();
-
-        ValueNode c1 = GraphUtil.unproxify(iter.next().result());
-        ValueNode c2 = GraphUtil.unproxify(iter.next().result());
-        assert !iter.hasNext();
-
-        Assert.assertTrue(c1.isNullConstant());
-        Assert.assertTrue(c2.isNullConstant());
-    }
-
-    public static class C {
-        public int f;
-    }
-
-    /*
-     * A previous (assumed successful) instanceof check is reused later on to remove a checkcast.
-     */
-    public void deduplicateInstanceOfSnippet(Object o) {
-        ((C) o).f = ((C) o).f; // boils down to a single instanceof test
-    }
-
-    @Test
-    public void deduplicateInstanceOfTest() {
-        String snippet = "deduplicateInstanceOfSnippet";
-        StructuredGraph graph = afterFlowSensitiveReduce(snippet);
-        List<InstanceOfNode> ioNodes = getNodes(graph, InstanceOfNode.class);
-        assertDeepEquals(1, ioNodes.size());
-
-    }
-
-    // ---------------------------------------------
-    // ----------------- UTILITIES -----------------
-    // ---------------------------------------------
-
-    private PhaseContext getPhaseContext() {
-        return new PhaseContext(getProviders(), null);
-    }
-
-    private static StructuredGraph dce(StructuredGraph graph) {
-        new DeadCodeEliminationPhase().apply(graph);
-        return graph;
-    }
-
-    private StructuredGraph canonicalize(StructuredGraph graph) {
-        new CanonicalizerPhase(true).apply(graph, getPhaseContext());
-        return graph;
-    }
-
-    private StructuredGraph flowSensitiveReduce(StructuredGraph graph) {
-        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, getPhaseContext());
-        return graph;
-    }
-
-    public static <N extends Node> List<N> getNodes(StructuredGraph graph, Class<N> nodeClass) {
-        return graph.getNodes().filter(nodeClass).snapshot();
-    }
-
-    public <N extends Node> void nodeCountEquals(StructuredGraph graph, Class<N> nodeClass, int expected) {
-        assertDeepEquals(expected, getNodes(graph, nodeClass).size());
-    }
-
-    public StructuredGraph afterFlowSensitiveReduce(String snippet) {
-        StructuredGraph before = canonicalize(parseEager(snippet));
-        // visualize(before, snippet + "-before");
-        StructuredGraph result = flowSensitiveReduce(before);
-        // visualize(result, snippet + "-after");
-        return result;
-    }
-
-    public StructuredGraph visualize(StructuredGraph graph, String title) {
-        DebugConfig debugConfig = DebugScope.getConfig();
-        DebugConfig fixedConfig = Debug.fixedConfig(0, Debug.DEFAULT_LOG_LEVEL, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output());
-        try (DebugConfigScope s = Debug.setConfig(fixedConfig)) {
-            Debug.dump(graph, title);
-
-            return graph;
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FlowSensitiveReductionTest.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,289 +0,0 @@
-/*
- * Copyright (c) 2011, 2014, 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 static com.oracle.graal.nodes.ConstantNode.*;
-import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.cfs.*;
-import com.oracle.graal.phases.tiers.*;
-
-/**
- * Collection of tests for {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase}
- * including those that triggered bugs in this phase.
- */
-public class FlowSensitiveReductionTest 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);
-    }
-
-    /**
-     * This test presents a code pattern that triggered a bug where a (non-eliminated) checkcast
-     * caused an enclosing instanceof (for the same object and target type) to be incorrectly
-     * eliminated.
-     */
-    @Test
-    public void testReanchoringIssue() {
-        Entry end = new Entry("end");
-        EntryWithNext e1 = new EntryWithNext("e1", end);
-        EntryWithNext e2 = new EntryWithNext("e2", e1);
-
-        test("search", e2, "e3", new Entry("e4"));
-    }
-
-    @SuppressWarnings("unused")
-    public static int testNullnessSnippet(Object a, Object b) {
-        if (a == null) {
-            if (a == b) {
-                if (b == null) {
-                    return 1;
-                } else {
-                    return -2;
-                }
-            } else {
-                if (b == null) {
-                    return -3;
-                } else {
-                    return 4;
-                }
-            }
-        } else {
-            if (a == b) {
-                if (b == null) {
-                    return -5;
-                } else {
-                    return 6;
-                }
-            } else {
-                if (b == null) {
-                    return 7;
-                } else {
-                    return 8;
-                }
-            }
-        }
-    }
-
-    @Test
-    public void testNullness() {
-        test("testNullnessSnippet", null, null);
-        test("testNullnessSnippet", null, new Object());
-        test("testNullnessSnippet", new Object(), null);
-        test("testNullnessSnippet", new Object(), new Object());
-
-        StructuredGraph graph = parseEager("testNullnessSnippet");
-        PhaseContext context = new PhaseContext(getProviders(), null);
-        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, context);
-        for (ConstantNode constant : getConstantNodes(graph)) {
-            assertTrue("unexpected constant: " + constant, constant.isNullConstant() || constant.asJavaConstant().asInt() > 0);
-        }
-    }
-
-    @SuppressWarnings("unused")
-    public static int testDisjunctionSnippet(Object a) {
-        try {
-            if (a instanceof Integer) {
-                if (a == null) {
-                    return -1;
-                } else {
-                    return 2;
-                }
-            } else {
-                return 3;
-            }
-        } finally {
-            field = null;
-        }
-    }
-
-    @Test
-    public void testDisjunction() {
-        StructuredGraph graph = parseEager("testDisjunctionSnippet");
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        IfNode ifNode = (IfNode) graph.start().next();
-        InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
-        IsNullNode x = graph.unique(new IsNullNode(graph.getParameter(0)));
-        InstanceOfNode y = instanceOf;
-        ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY));
-        LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction));
-        ifNode.setCondition(negation);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), null));
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-        for (ConstantNode constant : getConstantNodes(graph)) {
-            assertTrue("unexpected constant: " + constant, constant.isNullConstant() || constant.asJavaConstant().asInt() > 0);
-        }
-    }
-
-    public static int testInvokeSnippet(Number n) {
-        if (n instanceof Integer) {
-            return n.intValue();
-        } else {
-            return 1;
-        }
-    }
-
-    @Test
-    public void testInvoke() {
-        test("testInvokeSnippet", new Integer(16));
-        StructuredGraph graph = parseEager("testInvokeSnippet");
-        PhaseContext context = new PhaseContext(getProviders(), null);
-        new CanonicalizerPhase(true).apply(graph, context);
-        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
-
-        InvokeNode invoke = graph.getNodes().filter(InvokeNode.class).first();
-        assertDeepEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind());
-    }
-
-    public static void testTypeMergingSnippet(Object o, boolean b) {
-        if (b) {
-            if (!(o instanceof Double)) {
-                return;
-            }
-        } else {
-            if (!(o instanceof Integer)) {
-                return;
-            }
-        }
-
-        /*
-         * For this test the conditional elimination has to correctly merge the type information it
-         * has about o, so that it can remove the check on Number.
-         */
-        if (!(o instanceof Number)) {
-            field = o;
-        }
-    }
-
-    @Test
-    public void testTypeMerging() {
-        StructuredGraph graph = parseEager("testTypeMergingSnippet");
-        PhaseContext context = new PhaseContext(getProviders(), null);
-        new CanonicalizerPhase(true).apply(graph, context);
-        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-
-        assertDeepEquals(0, graph.getNodes().filter(StoreFieldNode.class).count());
-    }
-
-    public static String testInstanceOfCheckCastSnippet(Object e) {
-        if (e instanceof Entry) {
-            return ((Entry) e).name;
-        }
-        return null;
-    }
-
-    @Test
-    public void testInstanceOfCheckCast() {
-        StructuredGraph graph = parseEager("testInstanceOfCheckCastSnippet");
-        PhaseContext context = new PhaseContext(getProviders(), null);
-        new CanonicalizerPhase(true).apply(graph, context);
-        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
-        new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), null));
-
-        assertDeepEquals(0, graph.getNodes().filter(CheckCastNode.class).count());
-    }
-
-    public static int testDuplicateNullChecksSnippet(Object a) {
-        if (a == null) {
-            return 2;
-        }
-        try {
-            return ((Integer) a).intValue();
-        } catch (ClassCastException e) {
-            return 0;
-        }
-    }
-
-    @Test
-    @Ignore
-    public void testDuplicateNullChecks() {
-        // This tests whether explicit null checks properly eliminate later null guards. Currently
-        // it's failing.
-        StructuredGraph graph = parseEager("testDuplicateNullChecksSnippet");
-        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-        PhaseContext context = new PhaseContext(getProviders(), null);
-
-        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
-        canonicalizer.apply(graph, context);
-        new FloatingReadPhase().apply(graph);
-        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
-        canonicalizer.apply(graph, context);
-
-        assertDeepEquals(1, graph.getNodes().filter(GuardNode.class).count());
-    }
-
-}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Fri Jan 23 22:00:55 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Fri Jan 23 22:13:55 2015 +0100
@@ -28,7 +28,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.tiers.*;
 
 /**
@@ -104,28 +103,6 @@
         }
     }
 
-    @Test
-    public void test4() {
-        test("test4Snippet", "referenceSnippet2");
-    }
-
-    public static int test4Snippet(int a, int b) {
-        if (a > b) {
-            if (a <= b) {
-                return 3;
-            } else {
-                return 1;
-            }
-        } else {
-            return 2;
-        }
-    }
-
-    @Test
-    public void test5() {
-        test("test5Snippet", "referenceSnippet3");
-    }
-
     public static int referenceSnippet3(int a, int b) {
         if (a == b) {
             return 1;
@@ -134,18 +111,6 @@
         }
     }
 
-    public static int test5Snippet(int a, int b) {
-        if (a == b) {
-            if (a != b) {
-                return 3;
-            } else {
-                return 1;
-            }
-        } else {
-            return 2;
-        }
-    }
-
     @Test(expected = AssertionError.class)
     public void test6() {
         test("test6Snippet", "referenceSnippet3");
@@ -169,7 +134,6 @@
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
         PhaseContext context = new PhaseContext(getProviders(), assumptions);
-        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         StructuredGraph referenceGraph = parseEager(referenceSnippet);
         assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Fri Jan 23 22:00:55 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Fri Jan 23 22:13:55 2015 +0100
@@ -34,7 +34,6 @@
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -45,30 +44,6 @@
 public class TypeSystemTest extends GraalCompilerTest {
 
     @Test
-    public void test1() {
-        testHelper("test1Snippet", CheckCastNode.class);
-    }
-
-    public static int test1Snippet(Object a) {
-        if (a instanceof Boolean) {
-            return ((Boolean) a).booleanValue() ? 0 : 1;
-        }
-        return 1;
-    }
-
-    @Test
-    public void test2() {
-        testHelper("test2Snippet", CheckCastNode.class);
-    }
-
-    public static int test2Snippet(Object a) {
-        if (a instanceof Integer) {
-            return ((Number) a).intValue();
-        }
-        return 1;
-    }
-
-    @Test
     public void test3() {
         test("test3Snippet", "referenceSnippet3");
     }
@@ -258,7 +233,6 @@
         StructuredGraph graph = parseEager(snippet);
         Assumptions assumptions = new Assumptions(false);
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
-        new FlowSensitiveReductionPhase(getMetaAccess()).apply(graph, new PhaseContext(getProviders(), assumptions));
         new CanonicalizerPhase(true).apply(graph, new PhaseContext(getProviders(), assumptions));
         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/src/com/oracle/graal/compiler/phases/HighTier.java	Fri Jan 23 22:00:55 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Fri Jan 23 22:13:55 2015 +0100
@@ -31,7 +31,6 @@
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.common.inlining.*;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.virtual.phases.ea.*;
@@ -60,14 +59,9 @@
                 appendPhase(new InliningPhase(canonicalizer));
                 appendPhase(new DeadCodeEliminationPhase(Optional));
 
-                boolean reduceOrEliminate = FlowSensitiveReduction.getValue() || ConditionalElimination.getValue();
-                if (reduceOrEliminate && OptCanonicalizer.getValue()) {
+                if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
                     appendPhase(canonicalizer);
-                    if (FlowSensitiveReduction.getValue()) {
-                        appendPhase(new IterativeFlowSensitiveReductionPhase(canonicalizer));
-                    } else {
-                        appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
-                    }
+                    appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
                 }
             }
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,233 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.graph.*;
-import com.oracle.graal.phases.tiers.*;
-
-/**
- * <p>
- * For readability purposes the code realizing control-flow-sensitive reductions is chopped into
- * several classes in an inheritance hierarchy, this class being their common ancestor. That way,
- * many dependencies can be ruled out immediately (e.g., private members of a class aren't needed by
- * other classes). The whole thing is reminiscent of trait-based patterns, minus their
- * disadvantages.
- * </p>
- *
- * <p>
- * This class makes available little more than a few fields and a few utility methods used
- * throughout the remaining components making up control-flow sensitive reductions.
- * </p>
- *
- * <p>
- * The laundry-list of all flow-sensitive reductions is summarized in
- * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction}
- * </p>
- *
- */
-public abstract class BaseReduction extends SinglePassNodeIterator<State> {
-
-    protected static final DebugMetric metricCheckCastRemoved = Debug.metric("FSR-CheckCastRemoved");
-    protected static final DebugMetric metricGuardingPiNodeRemoved = Debug.metric("FSR-GuardingPiNodeRemoved");
-    protected static final DebugMetric metricFixedGuardNodeRemoved = Debug.metric("FSR-FixedGuardNodeRemoved");
-    protected static final DebugMetric metricMethodResolved = Debug.metric("FSR-MethodResolved");
-    protected static final DebugMetric metricUnconditionalDeoptInserted = Debug.metric("FSR-UnconditionalDeoptInserted");
-
-    /**
-     * <p>
-     * Upon visiting a {@link com.oracle.graal.nodes.FixedNode FixedNode} in
-     * {@link #node(com.oracle.graal.nodes.FixedNode)}, an impossible path may be detected. We'd
-     * like to insert an unconditional deoptimizing node as a hint for Dead Code Elimination to kill
-     * that branch. However that can't be made on the go (a
-     * {@link com.oracle.graal.nodes.ControlSinkNode} can't have successors). Thus their insertion
-     * is postponed till the end of a round of
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction}.
-     * </p>
-     *
-     * @see State#impossiblePath()
-     * @see com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#finished()
-     */
-    public static class PostponedDeopt {
-
-        private final boolean goesBeforeFixed;
-        private final FixedWithNextNode fixed;
-        private final DeoptimizationReason deoptReason;
-
-        public PostponedDeopt(boolean goesBeforeFixed, FixedWithNextNode fixed, DeoptimizationReason deoptReason) {
-            this.goesBeforeFixed = goesBeforeFixed;
-            this.fixed = fixed;
-            this.deoptReason = deoptReason;
-        }
-
-        /*
-         * TODO Actually, we want to emit instructions to signal "should-not-reach-here". An
-         * imperfect substitute (as done here) is emitting FixedGuard(false).
-         * "should-not-reach-here" would be better for the runtime error it raises, thus pointing to
-         * a bug in FlowSensitiveReduction (the code was reachable, after all).
-         */
-        public void doRewrite(LogicNode falseConstant) {
-            metricUnconditionalDeoptInserted.increment();
-            StructuredGraph graph = fixed.graph();
-            // have to insert a FixedNode other than a ControlSinkNode
-            FixedGuardNode buckStopsHere = graph.add(new FixedGuardNode(falseConstant, deoptReason, DeoptimizationAction.None));
-            if (goesBeforeFixed) {
-                fixed.replaceAtPredecessor(buckStopsHere);
-            } else {
-                graph.addAfterFixed(fixed, buckStopsHere);
-            }
-        }
-
-    }
-
-    protected static class PostponedDeopts extends ArrayList<PostponedDeopt> {
-
-        private static final long serialVersionUID = 7188324432387121238L;
-
-        /**
-         * Enqueue adding a {@link com.oracle.graal.nodes.DeoptimizeNode} right before the fixed
-         * argument, will be done once we're done traversing the graph.
-         *
-         * @see #finished()
-         */
-        void addDeoptBefore(FixedWithNextNode fixed, DeoptimizationReason deoptReason) {
-            add(new PostponedDeopt(true, fixed, deoptReason));
-        }
-
-        /**
-         * Enqueue adding a {@link com.oracle.graal.nodes.DeoptimizeNode} right after the fixed
-         * argument, will be done once we're done traversing the graph.
-         *
-         * @see #finished()
-         */
-        void addDeoptAfter(FixedWithNextNode fixed, DeoptimizationReason deoptReason) {
-            add(new PostponedDeopt(false, fixed, deoptReason));
-        }
-
-    }
-
-    /**
-     * <p>
-     * One of the promises of
-     * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)}
-     * is that a "maximally reduced" node is returned. That is achieved in part by leveraging
-     * {@link Canonicalizable#canonical(com.oracle.graal.graph.spi.CanonicalizerTool)}. Doing so, in
-     * turn, requires this subclass of {@link com.oracle.graal.graph.spi.CanonicalizerTool}.
-     * </p>
-     */
-    public final class Tool implements CanonicalizerTool {
-
-        private final PhaseContext context;
-
-        public Tool(PhaseContext context) {
-            this.context = context;
-        }
-
-        @Override
-        public Assumptions assumptions() {
-            return context.getAssumptions();
-        }
-
-        @Override
-        public MetaAccessProvider getMetaAccess() {
-            return context.getMetaAccess();
-        }
-
-        @Override
-        public ConstantReflectionProvider getConstantReflection() {
-            return context.getConstantReflection();
-        }
-
-        @Override
-        public boolean canonicalizeReads() {
-            return false;
-        }
-    } // end of class FlowSensitiveReduction.Tool
-
-    protected final LogicConstantNode trueConstant;
-    protected final LogicConstantNode falseConstant;
-    protected final ConstantNode nullConstant;
-
-    protected final CanonicalizerTool tool;
-    protected final StructuredGraph graph;
-
-    protected EquationalReasoner reasoner;
-
-    protected final PostponedDeopts postponedDeopts = new PostponedDeopts();
-
-    protected BaseReduction(StartNode start, State initialState, PhaseContext context) {
-        super(start, initialState);
-        graph = start.graph();
-        trueConstant = LogicConstantNode.tautology(graph);
-        falseConstant = LogicConstantNode.contradiction(graph);
-        nullConstant = ConstantNode.defaultForKind(Kind.Object, graph); // ConstantNode.forObject(null,
-                                                                        // metaAccess, graph);
-        tool = new Tool(context);
-        reasoner = new EquationalReasoner(graph, tool, trueConstant, falseConstant, nullConstant);
-    }
-
-    /**
-     * <p>
-     * Test whether the output's stamp is an upcast of that of the input. For example, upon
-     * replacing a CheckCastNode in
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode, com.oracle.graal.nodes.ValueNode)}
-     * we don't want to be left with an upcast, as it loses precision.
-     * </p>
-     *
-     * <p>
-     * As usual with object stamps, they can be compared along different dimensions (alwaysNull,
-     * etc.) It's enough for one such dimension to show precision loss for the end result to be
-     * reported as such.
-     * </p>
-     *
-     */
-    public static boolean precisionLoss(ValueNode input, ValueNode output) {
-        ObjectStamp inputStamp = (ObjectStamp) input.stamp();
-        ObjectStamp outputStamp = (ObjectStamp) output.stamp();
-        if (FlowUtil.isMorePrecise(inputStamp.type(), outputStamp.type())) {
-            return true;
-        }
-        if (lessThan(outputStamp.alwaysNull(), inputStamp.alwaysNull())) {
-            return true;
-        }
-        if (lessThan(outputStamp.nonNull(), inputStamp.nonNull())) {
-            return true;
-        }
-        if (lessThan(outputStamp.isExactType(), inputStamp.isExactType())) {
-            return true;
-        }
-        return false;
-    }
-
-    private static boolean lessThan(boolean a, boolean b) {
-        return a == false && b == true;
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import com.oracle.graal.api.meta.ResolvedJavaType;
-import com.oracle.graal.nodes.LogicNode;
-import com.oracle.graal.nodes.ShortCircuitOrNode;
-import com.oracle.graal.nodes.ValueNode;
-import com.oracle.graal.nodes.calc.IsNullNode;
-import com.oracle.graal.nodes.java.InstanceOfNode;
-
-/**
- * @see #extract(com.oracle.graal.nodes.LogicNode)
- */
-class CastCheckExtractor {
-
-    public final ResolvedJavaType type;
-    public final ValueNode subject;
-
-    CastCheckExtractor(ResolvedJavaType type, ValueNode subject) {
-        this.type = type;
-        this.subject = subject;
-    }
-
-    private static CastCheckExtractor extractCastCheckInfo(LogicNode x, LogicNode y) {
-        if (x instanceof IsNullNode) {
-            IsNullNode isNull = (IsNullNode) x;
-            ValueNode subject = isNull.getValue();
-            if (isInstanceOfCheckOn(y, subject)) {
-                InstanceOfNode iOf = (InstanceOfNode) y;
-                return new CastCheckExtractor(iOf.type(), subject);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * This method detects whether the argument realizes the CheckCast pattern. If so, distills and
-     * returns the essentials of such check, otherwise returns null.
-     */
-    static CastCheckExtractor extract(LogicNode cond) {
-        if (!(cond instanceof ShortCircuitOrNode)) {
-            return null;
-        }
-        ShortCircuitOrNode orNode = (ShortCircuitOrNode) cond;
-        if (orNode.isXNegated() || orNode.isYNegated()) {
-            return null;
-        }
-        CastCheckExtractor result = extractCastCheckInfo(orNode.getX(), orNode.getY());
-        if (result != null) {
-            return result;
-        }
-        result = extractCastCheckInfo(orNode.getY(), orNode.getX());
-        return result;
-    }
-
-    /**
-     * Porcelain method.
-     */
-    static boolean isInstanceOfCheckOn(LogicNode cond, ValueNode subject) {
-        if (!(cond instanceof InstanceOfNode)) {
-            return false;
-        }
-        InstanceOfNode io = (InstanceOfNode) cond;
-        return io.getValue() == subject;
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,364 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, 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.cfs;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.IsNullNode;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.compiler.common.type.ObjectStamp;
-import com.oracle.graal.compiler.common.type.StampFactory;
-import com.oracle.graal.nodes.type.StampTool;
-import com.oracle.graal.phases.tiers.PhaseContext;
-
-import static com.oracle.graal.api.meta.DeoptimizationAction.InvalidateReprofile;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
-import static com.oracle.graal.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY;
-
-/**
- * <p>
- * This class implements control-flow sensitive reductions for
- * {@link com.oracle.graal.nodes.java.CheckCastNode}.
- * </p>
- *
- * <p>
- * The laundry-list of all flow-sensitive reductions is summarized in
- * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction}
- * </p>
- *
- * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
- */
-public abstract class CheckCastReduction extends GuardingPiReduction {
-
-    public CheckCastReduction(StartNode start, State initialState, PhaseContext context) {
-        super(start, initialState, context);
-    }
-
-    /**
-     * <p>
-     * Upon visiting a {@link com.oracle.graal.nodes.java.CheckCastNode}, based on flow-sensitive
-     * conditions, we need to determine whether:
-     * <ul>
-     * <li>it is redundant (in which case it should be simplified), or</li>
-     * <li>flow-sensitive information can be gained from it. "Gain information from it" requires
-     * lowering the {@link com.oracle.graal.nodes.java.CheckCastNode} such that a
-     * {@link com.oracle.graal.nodes.extended.GuardingNode GuardingNode} becomes available.</li>
-     * </ul>
-     * </p>
-     *
-     * <p>
-     * This method realizes the above by testing first for situations that require less work:
-     * <ol>
-     * <li>the stamp of the subject deems the check-cast redundant or unsatisfiable (ie,
-     * always-succeeds or always-fails). A previous round of canonicalization takes care of this
-     * situation, however it can also arise due to consecutive runs of
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} without intervening
-     * {@link com.oracle.graal.phases.common.CanonicalizerPhase canonicalization}.</li>
-     * <li>
-     * flow-sensitive information reveals the subject to be null, trivially fulfilling the
-     * check-cast.</li>
-     * <li>
-     * flow-sensitive information reveals the subject to be narrower than it stamp says. If the
-     * narrower ("downcasted") value fulfills the check-cast, the check-cast is removed.</li>
-     * <li>
-     * otherwise the check-cast provides additional flow-sensitive information. For that, a
-     * {@link com.oracle.graal.nodes.FixedGuardNode} is needed, as described in
-     * {@link #lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode, com.oracle.graal.nodes.ValueNode)}
-     * . Please notice this lowering is currently performed unconditionally: it might occur no
-     * flow-sensitive reduction is enabled down the road.</li>
-     * </ol>
-     * </p>
-     *
-     * <p>
-     * Precondition: the inputs (ie, object) hasn't been deverbosified yet.
-     * </p>
-     */
-    protected final void visitCheckCastNode(CheckCastNode checkCast) {
-
-        /*
-         * checkCast.object() hasn't been deverbosified yet.
-         */
-
-        if (!FlowUtil.hasLegalObjectStamp(checkCast)) {
-            // This situation is exercised by test Class_cast01
-            return;
-        }
-
-        final ValueNode subject = checkCast.object();
-        final ResolvedJavaType toType = checkCast.type();
-        ObjectStamp subjectStamp = (ObjectStamp) subject.stamp();
-        ResolvedJavaType subjectType = subjectStamp.type();
-
-        // --------- checkCast deemed redundant by subject-stamp alone ---------
-        // --------- in particular due to stamp informing always null ----------
-        boolean isRedundantPerStamp = StampTool.isPointerAlwaysNull(subject) || (subjectType != null && toType.isAssignableFrom(subjectType));
-        if (isRedundantPerStamp) {
-            metricCheckCastRemoved.increment();
-            checkCast.replaceAtUsages(subject);
-            graph.removeFixed(checkCast);
-            return;
-        }
-
-        assert !StampTool.isPointerAlwaysNull(subject) : "Null as per stamp subjects should have been handled above";
-
-        // --------- checkCast deemed unsatisfiable by subject-stamp alone ---------
-        if (state.knownNotToPassCheckCast(subject, toType)) {
-            postponedDeopts.addDeoptBefore(checkCast, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException);
-            state.impossiblePath();
-            // let FixedGuardNode(false).simplify() prune the dead-code control-path
-            return;
-        }
-
-        /*
-         * Remark: subject may be TypeProxyNode, GuardedValueNode, ProxyNode, GuardingPiNode, among
-         * others.
-         */
-
-        PiNode untrivialNull = reasoner.nonTrivialNull(subject);
-        if (untrivialNull != null) {
-            metricCheckCastRemoved.increment();
-            checkCast.replaceAtUsages(untrivialNull);
-            graph.removeFixed(checkCast);
-            return;
-        }
-
-        Witness w = state.typeInfo(subject);
-
-        if (w == null) {
-            /*
-             * If there's no witness, attempting `downcast(subject)` is futile.
-             */
-            visitCheckCastNodeLackingWitness(checkCast);
-            return;
-        }
-
-        visitCheckCastNodeWithWitness(checkCast);
-
-    }
-
-    /**
-     * Given that no witness is available for the {@link com.oracle.graal.nodes.java.CheckCastNode}
-     * 's subject there's no point in downcasting such subject, ie no
-     * {@link com.oracle.graal.nodes.PiNode} can be fabricated for the subject.
-     *
-     * @see #lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode,
-     *      com.oracle.graal.nodes.ValueNode)
-     *
-     */
-    private void visitCheckCastNodeLackingWitness(CheckCastNode checkCast) {
-        final ValueNode subject = checkCast.object();
-        final ResolvedJavaType toType = checkCast.type();
-        if (toType.isInterface()) {
-            return;
-        }
-        assert reasoner.downcast(subject) == subject;
-        lowerCheckCastAnchorFriendlyWay(checkCast, subject);
-    }
-
-    /**
-     * Porcelain method.
-     *
-     * <p>
-     * Rather than tracking the CheckCastNode via {@link com.oracle.graal.phases.common.cfs.State
-     * State} (doing so would add a special case because a
-     * {@link com.oracle.graal.nodes.java.CheckCastNode} isn't a
-     * {@link com.oracle.graal.nodes.extended.GuardingNode guarding node}) this method creates an
-     * anchor by lowering the CheckCastNode into a FixedGuardNode. Not the same as the
-     * {@link com.oracle.graal.nodes.java.CheckCastNode#lower(com.oracle.graal.nodes.spi.LoweringTool)
-     * lowering of a CheckCastNode} which results in a {@link com.oracle.graal.nodes.GuardingPiNode}
-     * (which is not a {@link com.oracle.graal.nodes.extended.GuardingNode guarding node}).
-     * </p>
-     *
-     * <p>
-     * With that, state tracking can proceed as usual.
-     * </p>
-     *
-     * <p>
-     * TODO This lowering is currently performed unconditionally: it might occur no flow-sensitive
-     * reduction is enabled down the road
-     * </p>
-     *
-     * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
-     *
-     */
-    public void lowerCheckCastAnchorFriendlyWay(CheckCastNode checkCast, ValueNode subject) {
-        ValueNode originalCheckCastObject = checkCast.object();
-
-        ObjectStamp subjectStamp = (ObjectStamp) subject.stamp();
-        final ResolvedJavaType toType = checkCast.type();
-        ObjectStamp resultStamp = (ObjectStamp) StampFactory.declaredTrusted(toType);
-        JavaTypeProfile profile = checkCast.profile();
-
-        assert FlowUtil.isLegalObjectStamp(subjectStamp);
-        assert subjectStamp.type() == null || !toType.isAssignableFrom(subjectStamp.type()) : "No need to lower in an anchor-friendly way in the first place";
-
-        /*
-         * Depending on what is known about the subject:
-         * 
-         * (a) definitely-non-null
-         * 
-         * (b) null-not-seen-in-profiling
-         * 
-         * (c) runtime-null-check-needed
-         * 
-         * the condition (of the cast-guard to be emitted) and the stamp (of the PiNode to be
-         * emitted) are going to be different. Each of the three branches below deals with one of
-         * the cases above.
-         */
-        LogicNode condition;
-        if (subjectStamp.nonNull()) {
-            /*
-             * (1 of 3) definitely-non-null
-             */
-            // addWithoutUnique for the same reason as in CheckCastNode.lower()
-            condition = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile));
-            reasoner.added.add(condition);
-            resultStamp = FlowUtil.asNonNullStamp(resultStamp);
-            // TODO fix in CheckCastNode.lower()
-        } else {
-            if (profile != null && profile.getNullSeen() == ProfilingInfo.TriState.FALSE) {
-                /*
-                 * (2 of 3) null-not-seen-in-profiling
-                 */
-                IsNullNode isNN = graph.unique(new IsNullNode(subject));
-                reasoner.added.add(isNN);
-                FixedGuardNode nullCheck = graph.add(new FixedGuardNode(isNN, UnreachedCode, InvalidateReprofile, true));
-                graph.addBeforeFixed(checkCast, nullCheck);
-                // not calling wrapInPiNode() because we don't want to rememberSubstitution()
-                PiNode nonNullGuarded = graph.unique(new PiNode(subject, FlowUtil.asNonNullStamp(subjectStamp), nullCheck));
-                reasoner.added.add(nonNullGuarded);
-                // addWithoutUnique for the same reason as in CheckCastNode.lower()
-                condition = graph.addWithoutUnique(new InstanceOfNode(toType, nonNullGuarded, profile));
-                reasoner.added.add(condition);
-                resultStamp = FlowUtil.asNonNullStamp(resultStamp);
-            } else {
-                /*
-                 * (3 of 3) runtime-null-check-needed
-                 */
-                // addWithoutUnique for the same reason as in CheckCastNode.lower()
-                InstanceOfNode typeTest = graph.addWithoutUnique(new InstanceOfNode(toType, subject, profile));
-                reasoner.added.add(typeTest);
-                LogicNode nullTest = graph.unique(new IsNullNode(subject));
-                reasoner.added.add(nullTest);
-                // TODO (ds) replace with probability of null-seen when available
-                final double shortCircuitProbability = NOT_FREQUENT_PROBABILITY;
-                condition = LogicNode.or(nullTest, typeTest, shortCircuitProbability);
-                reasoner.added.add(condition);
-            }
-        }
-
-        /*
-         * Add a cast-guard (checking only what needs to be checked) and a PiNode (to be used in
-         * place of the CheckCastNode).
-         */
-        FixedGuardNode castGuard = graph.add(new FixedGuardNode(condition, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException, InvalidateReprofile));
-        graph.addBeforeFixed(checkCast, castGuard);
-
-        assert FlowUtil.isLegalObjectStamp(resultStamp);
-        Witness w = state.typeInfo(subject);
-        assert !isTypeOfWitnessBetter(w, resultStamp);
-
-        if (!FlowUtil.lacksUsages(checkCast)) {
-            // not calling wrapInPiNode() because we don't want to rememberSubstitution()
-            PiNode checkedObject = graph.unique(new PiNode(subject, resultStamp, castGuard));
-            reasoner.added.add(checkedObject);
-            assert !precisionLoss(originalCheckCastObject, checkedObject);
-            assert !precisionLoss(subject, checkedObject);
-            checkCast.replaceAtUsages(checkedObject);
-        }
-
-        graph.removeFixed(checkCast);
-
-        if (resultStamp.nonNull()) {
-            state.trackIO(subject, toType, castGuard);
-        } else {
-            state.trackCC(subject, toType, castGuard);
-        }
-    }
-
-    /**
-     * Porcelain method.
-     */
-    public static boolean isTypeOfWitnessBetter(Witness w, ObjectStamp stamp) {
-        if (w == null) {
-            return false;
-        }
-        return FlowUtil.isMorePrecise(w.type(), stamp.type());
-    }
-
-    /**
-     *
-     * Please note in this method "subject" refers to the downcasted input to the checkCast.
-     *
-     * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
-     */
-    private void visitCheckCastNodeWithWitness(CheckCastNode checkCast) {
-
-        final ResolvedJavaType toType = checkCast.type();
-
-        ValueNode subject;
-        if (checkCast.object() instanceof CheckCastNode) {
-            subject = reasoner.downcast(checkCast);
-            if (subject == checkCast) {
-                subject = reasoner.downcast(checkCast.object());
-            }
-        } else {
-            subject = reasoner.downcast(checkCast.object());
-        }
-
-        ObjectStamp subjectStamp = (ObjectStamp) subject.stamp();
-        ResolvedJavaType subjectType = subjectStamp.type();
-
-        /*
-         * At this point, two sources of (partial) information: the witness and the stamp of
-         * subject. The latter might be more precise than the witness (eg, subject might be
-         * GuardedValueNode)
-         */
-
-        // --------- checkCast made redundant by downcasting its input ---------
-        if (subjectType != null && toType.isAssignableFrom(subjectType)) {
-            checkCast.replaceAtUsages(subject);
-            graph.removeFixed(checkCast);
-            return;
-        }
-
-        /*
-         * At this point, `downcast()` might or might not have delivered a more precise value. If
-         * more precise, it wasn't precise enough to conform to `toType`. Even so, for the
-         * `toType.isInterface()` case (dealt with below) we'll replace the checkCast's input with
-         * that value (its class-stamp being more precise than the original).
-         */
-
-        if (toType.isInterface()) {
-            boolean wasDowncasted = (subject != checkCast.object());
-            if (wasDowncasted) {
-                FlowUtil.replaceInPlace(checkCast, checkCast.object(), subject);
-            }
-            return;
-        }
-
-        lowerCheckCastAnchorFriendlyWay(checkCast, subject);
-
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,960 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, 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.cfs;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-
-/**
- * <p>
- * This class implements a simple partial evaluator that recursively reduces a given
- * {@link com.oracle.graal.nodes.calc.FloatingNode} into a simpler one based on the current state.
- * Such evaluator comes handy when visiting a {@link com.oracle.graal.nodes.FixedNode} N, just
- * before updating the state for N. At the pre-state, an {@link EquationalReasoner} can be used to
- * reduce N's inputs (actually only those inputs of Value and Condition
- * {@link com.oracle.graal.nodeinfo.InputType InputType}). For an explanation of where it's
- * warranted to replace "old input" with "reduced input", see the inline comments in method
- * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node n) deverbosify(Node n)}
- * </p>
- *
- * <p>
- * The name {@link EquationalReasoner EquationalReasoner} was chosen because it conveys what it
- * does.
- * </p>
- */
-public final class EquationalReasoner {
-
-    private static final DebugMetric metricInstanceOfRemoved = Debug.metric("FSR-InstanceOfRemoved");
-    private static final DebugMetric metricNullCheckRemoved = Debug.metric("FSR-NullCheckRemoved");
-    private static final DebugMetric metricObjectEqualsRemoved = Debug.metric("FSR-ObjectEqualsRemoved");
-    private static final DebugMetric metricEquationalReasoning = Debug.metric("FSR-EquationalReasoning");
-    private static final DebugMetric metricDowncasting = Debug.metric("FSR-Downcasting");
-    private static final DebugMetric metricNullInserted = Debug.metric("FSR-NullInserted");
-
-    private final StructuredGraph graph;
-    private final CanonicalizerTool tool;
-    private final LogicConstantNode trueConstant;
-    private final LogicConstantNode falseConstant;
-    private final ConstantNode nullConstant;
-
-    private State state;
-    private NodeBitMap visited;
-
-    /**
-     * The reduction of a {@link com.oracle.graal.nodes.calc.FloatingNode} performed by
-     * {@link EquationalReasoner EquationalReasoner} may result in a FloatingNode being added to the
-     * graph. Those nodes aren't tracked in the {@link EquationalReasoner#visited visited}
-     * {@link com.oracle.graal.graph.NodeBitMap NodeBitMap} but in this set instead (those nodes are
-     * added after the {@link com.oracle.graal.graph.NodeBitMap} was obtained).
-     */
-    final Set<ValueNode> added = Node.newSet();
-
-    /**
-     * The reduction of a FloatingNode performed by {@link EquationalReasoner EquationalReasoner}
-     * may result in a FloatingNode being added to the graph. Those nodes are tracked in this map,
-     * to avoid recomputing them.
-     *
-     * The substitutions tracked in this field become invalid as described in
-     * {@link #updateState(com.oracle.graal.phases.common.cfs.State) updateState(State)}
-     */
-    private final Map<ValueNode, ValueNode> substs = Node.newIdentityMap();
-
-    public EquationalReasoner(StructuredGraph graph, CanonicalizerTool tool, LogicConstantNode trueConstant, LogicConstantNode falseConstant, ConstantNode nullConstant) {
-        this.graph = graph;
-        this.tool = tool;
-        this.trueConstant = trueConstant;
-        this.falseConstant = falseConstant;
-        this.nullConstant = nullConstant;
-    }
-
-    /**
-     * {@link #added} grows during a run of
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase
-     * FlowSensitiveReductionPhase}, and doesn't survive across runs.
-     */
-    public void forceState(State s) {
-        state = s;
-        assert state.repOK();
-        substs.clear();
-        added.clear();
-        visited = null;
-        versionNrAsofLastForce = s.versionNr;
-    }
-
-    /**
-     * <p>
-     * Gaining more precise type information about an SSA value doesn't "invalidate" as such any of
-     * the substitutions tracked in {@link EquationalReasoner#substs substs}, at least not in the
-     * sense of making the value tracked by one such entry "wrong". However, clearing the
-     * {@link EquationalReasoner#substs substs} is still justified because next time they are
-     * computed, the newly computed reduction could (in principle) be more effective (due to the
-     * more precise type information).
-     * </p>
-     *
-     * <p>
-     * Between clearings of cached substitutions, it is expected they get applied a number of times
-     * to justify the bookkeeping cost.
-     * </p>
-     *
-     */
-    public void updateState(State s) {
-        assert s != null;
-        if (state == null || state != s || state.versionNr != versionNrAsofLastForce) {
-            forceState(s);
-        }
-    }
-
-    private int versionNrAsofLastForce = 0;
-
-    /**
-     * Reduce the argument based on the state at the program point where the argument is consumed.
-     * For most FixedNodes, that's how their inputs can be reduced. Two exceptions:
-     * <ul>
-     * <li>
-     * the condition of a {@link com.oracle.graal.nodes.GuardingPiNode}, see
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}
-     * </li>
-     * <li>
-     * the condition of a {@link com.oracle.graal.nodes.FixedGuardNode}, see
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode)}
-     * </li>
-     *
-     * </ul>
-     *
-     *
-     * <p>
-     * Part of the reduction work is delegated to baseCase-style reducers, whose contract explicitly
-     * requires them not to deverbosify the argument's inputs --- the decision is made based on the
-     * argument only (thus "base case"). Returning the unmodified argument is how a baseCase-style
-     * tells this method to fall to the default case (for a floating node only: walk into the
-     * argument's inputs, canonicalize followed by
-     * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)
-     * rememberSubstitution()} if any input changed).
-     * </p>
-     *
-     * <p>
-     * This method must behave as a function (idempotent query method), ie refrain from mutating the
-     * state other than updating caches:
-     * <ul>
-     * <li>{@link EquationalReasoner#added EquationalReasoner#added},</li>
-     * <li>{@link EquationalReasoner#visited EquationalReasoner#visited} and</li>
-     * <li>the cache updated via
-     * {@link EquationalReasoner#rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)
-     * EquationalReasoner#rememberSubstitution(ValueNode, FloatingNode)}.</li>
-     * </ul>
-     * </p>
-     *
-     * <p>
-     * In turn, baseCase-style reducers are even more constrained: besides behaving as functions,
-     * their contract prevents them from updating any caches (basically because they already grab
-     * the answer from caches, if the answer isn't there they should just return their unmodified
-     * argument).
-     * </p>
-     *
-     * <p>
-     * This method returns:
-     * <ul>
-     * <li>
-     * the original argument, in case no reduction possible.</li>
-     * <li>
-     * a {@link com.oracle.graal.nodes.ValueNode ValueNode} different from the argument, in case the
-     * conditions for a reduction were met. The node being returned might be already in the graph.
-     * In any case it's canonicalized already, the caller need not perform that again.</li>
-     * <li>
-     * the unmodified argument, in case no reduction was made. Otherwise, a maximally reduced
-     * {@link com.oracle.graal.nodes.ValueNode}.</li>
-     * </ul>
-     * </p>
-     *
-     * @see com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode)
-     *
-     * @see com.oracle.graal.phases.common.cfs.BaseReduction.Tool
-     *
-     */
-    public Node deverbosify(final Node n) {
-
-        // --------------------------------------------------------------------
-        // cases that don't initiate any call-chain that may enter this method
-        // --------------------------------------------------------------------
-
-        if (n == null) {
-            return null;
-        }
-        assert !(n instanceof GuardNode) : "This phase not intended to run during MidTier";
-        if (!(n instanceof ValueNode)) {
-            return n;
-        }
-        ValueNode v = (ValueNode) n;
-        if (v.stamp() instanceof IllegalStamp) {
-            return v;
-        }
-        if (FlowUtil.isLiteralNode(v)) {
-            return v;
-        }
-        ValueNode result = substs.get(v);
-        if (result != null) {
-            // picked cached substitution
-            return result;
-        }
-        if (FlowUtil.hasLegalObjectStamp(v) && state.isNull(v)) {
-            // it's ok to return nullConstant in deverbosify unlike in downcast
-            metricNullInserted.increment();
-            return nullConstant;
-        }
-        if (v instanceof ValueProxy) {
-            return v;
-        }
-        if (!(n instanceof FloatingNode)) {
-            return n;
-        }
-        if ((visited != null && visited.contains(n)) || added.contains(v)) {
-            return v;
-        }
-
-        // --------------------------------------------------------------------
-        // stack overflow prevention via added, visited
-        // --------------------------------------------------------------------
-
-        if (visited == null) {
-            visited = graph.createNodeBitMap();
-        }
-        visited.mark(n);
-
-        /*
-         * Past this point, if we ever want `n` to be deverbosified, it must be looked-up by one of
-         * the cases above. One sure way to achieve that is with `rememberSubstitution(old, new)`
-         */
-
-        /*
-         * `deverbosifyFloatingNode()` will drill down over floating inputs, when that not possible
-         * anymore it resorts to calling `downcast()`. Thus it's ok to take the
-         * `deverbosifyFloatingNode()` route first, as no downcasting opportunity will be missed.
-         */
-        return deverbosifyFloatingNode((FloatingNode) n);
-    }
-
-    /**
-     * This method:
-     *
-     * <ul>
-     * <li>
-     * Recurses only over floating inputs to attempt reductions, leave anything else as is.</li>
-     * <li>
-     * Performs copy-on-write aka lazy-DAG-copying as described in source comments, in-line.</li>
-     * <li>
-     * Usage: must be called only from {@link #deverbosify(com.oracle.graal.graph.Node)
-     * deverbosify(Node)}.</li>
-     * </ul>
-     */
-    public Node deverbosifyFloatingNode(final FloatingNode n) {
-
-        assert n != null : "Should have been caught in deverbosify()";
-        assert !(n instanceof ValueProxy) : "Should have been caught in deverbosify()";
-        assert !FlowUtil.isLiteralNode(n) : "Should have been caught in deverbosify()";
-
-        if (n instanceof PhiNode) {
-            /*
-             * Each input to a PhiNode should be deverbosified with the state applicable to the path
-             * providing such input, as done in visitAbstractEndNode()
-             */
-            return n;
-        }
-
-        final FloatingNode f = baseCaseFloating(n);
-        if (f != n) {
-            return f;
-        }
-
-        FloatingNode changed = null;
-        for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(f)) {
-            /*
-             * Although deverbosify() is invoked below, it's only for floating inputs. That way, the
-             * state can't be used to make invalid conclusions.
-             */
-            Node j = (i instanceof FloatingNode) ? deverbosify(i) : i;
-            if (i != j) {
-                assert j != f;
-                if (changed == null) {
-                    changed = (FloatingNode) f.copyWithInputs();
-                    added.add(changed);
-                    // copyWithInputs() implies graph.unique(changed)
-                    assert changed.isAlive();
-                    assert FlowUtil.lacksUsages(changed);
-                }
-                /*
-                 * Note: we don't trade i for j at each usage of i (doing so would change meaning)
-                 * but only at those usages consumed by `changed`. In turn, `changed` won't replace
-                 * `n` at arbitrary usages, but only where such substitution is valid as per the
-                 * state holding there. In practice, this means the buck stops at the "root"
-                 * FixedNode on whose inputs deverbosify() is invoked for the first time, via
-                 * deverbosifyInputsInPlace().
-                 */
-                FlowUtil.replaceInPlace(changed, i, j);
-            }
-        }
-        if (changed == null) {
-            assert visited.contains(f) || added.contains(f);
-            return f;
-        }
-        FlowUtil.inferStampAndCheck(changed);
-        added.add(changed);
-
-        if (changed instanceof Canonicalizable) {
-            ValueNode canon = (ValueNode) ((Canonicalizable) changed).canonical(tool);
-            if (canon != null && !canon.isAlive()) {
-                assert !canon.isDeleted();
-                canon = graph.addOrUniqueWithInputs(canon);
-            }
-            // might be already in `added`, no problem adding it again.
-            added.add(canon);
-            rememberSubstitution(f, canon);
-            return canon;
-        } else {
-            return changed;
-        }
-    }
-
-    /**
-     * In case of doubt (on whether a reduction actually triggered) it's always ok to invoke "
-     * <code>rememberSubstitution(f, downcast(f))</code>": this method records a map entry only if
-     * pre-image and image differ.
-     *
-     * @return the image of the substitution (ie, the second argument) unmodified.
-     */
-    private <M extends ValueNode> M rememberSubstitution(ValueNode from, M to) {
-        assert from != null && to != null;
-        if (from == to) {
-            return to;
-        }
-        // we don't track literals because they map to themselves
-        if (FlowUtil.isLiteralNode(from)) {
-            assert from == to;
-            return to;
-        }
-        /*
-         * It's ok for different keys (which were not unique in the graph after all) to map to the
-         * same value. However any given key can't map to different values.
-         */
-        ValueNode image = substs.get(from);
-        if (image != null) {
-            assert image == to;
-            return to;
-        }
-        substs.put(from, to);
-        return to;
-    }
-
-    /**
-     * The contract for this baseCase-style method is covered in
-     * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)
-     * EquationalReasoner#deverbosify()}.
-     *
-     * @return a {@link com.oracle.graal.nodes.calc.FloatingNode} different from the argument, in
-     *         case a reduction was made. The node being returned might be already in the graph. In
-     *         any case it's canonicalized already, the caller need not perform that again. In case
-     *         no reduction was made, this method returns the unmodified argument.
-     */
-    private FloatingNode baseCaseFloating(final FloatingNode f) {
-        if (f instanceof LogicNode) {
-            FloatingNode result = baseCaseLogicNode((LogicNode) f);
-            return rememberSubstitution(f, result);
-        }
-        return f;
-    }
-
-    /**
-     * <p>
-     * Reduce the argument based on the state at the program point for it (ie, based on
-     * "valid facts" only, without relying on any floating-guard-assumption).
-     * </p>
-     *
-     * <p>
-     * The inputs of the argument aren't traversed into, for that
-     * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)
-     * EquationalReasoner#deverbosify()} should be used instead.
-     * </p>
-     * <p>
-     * This method must behave as a function (idempotent query method): it should refrain from
-     * changing the state, as well as from updating caches (other than DebugMetric-s).
-     * </p>
-     *
-     * @return a {@link com.oracle.graal.nodes.LogicNode} different from the argument, in case a
-     *         reduction was made. The node being returned might be already in the graph. In any
-     *         case it's canonicalized already, the caller need not perform that again. In case no
-     *         reduction was made, this method returns the unmodified argument.
-     *
-     */
-    public FloatingNode baseCaseLogicNode(LogicNode condition) {
-        assert condition != null;
-        if (condition instanceof LogicConstantNode) {
-            return condition;
-        } else if (state.trueFacts.containsKey(condition)) {
-            metricEquationalReasoning.increment();
-            return trueConstant;
-        } else if (state.falseFacts.containsKey(condition)) {
-            metricEquationalReasoning.increment();
-            return falseConstant;
-        } else {
-            if (condition instanceof InstanceOfNode) {
-                return baseCaseInstanceOfNode((InstanceOfNode) condition);
-            } else if (condition instanceof IsNullNode) {
-                return baseCaseIsNullNode((IsNullNode) condition);
-            } else if (condition instanceof ObjectEqualsNode) {
-                return baseCaseObjectEqualsNode((ObjectEqualsNode) condition);
-            } else if (condition instanceof ShortCircuitOrNode) {
-                return baseCaseShortCircuitOrNode((ShortCircuitOrNode) condition);
-            }
-        }
-        return condition;
-    }
-
-    /**
-     * Actually the same result delivered by this method could be obtained by just letting
-     * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)
-     * EquationalReasoner#deverbosify()} handle the argument in the default case for floating nodes
-     * (ie, deverbosify inputs followed by canonicalize). However it's done here for metrics
-     * purposes.
-     *
-     * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made;
-     *         otherwise the unmodified argument.
-     *
-     */
-    private LogicNode baseCaseInstanceOfNode(InstanceOfNode instanceOf) {
-        ValueNode scrutinee = GraphUtil.unproxify(instanceOf.getValue());
-        if (!FlowUtil.hasLegalObjectStamp(scrutinee)) {
-            return instanceOf;
-        }
-        if (state.isNull(scrutinee)) {
-            metricInstanceOfRemoved.increment();
-            return falseConstant;
-        } else if (state.knownNotToPassInstanceOf(scrutinee, instanceOf.type())) {
-            // scrutinee turns out to be null -> falseConstant right answer
-            // scrutinee not null, but known-not-to-conform -> falseConstant
-            metricInstanceOfRemoved.increment();
-            return falseConstant;
-        } else if (state.isNonNull(scrutinee) && state.knownToConform(scrutinee, instanceOf.type())) {
-            metricInstanceOfRemoved.increment();
-            return trueConstant;
-        }
-        return instanceOf;
-    }
-
-    /**
-     * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was
-     *         performed; otherwise the unmodified argument.
-     *
-     */
-    private FloatingNode baseCaseIsNullNode(IsNullNode isNu) {
-        ValueNode object = isNu.getValue();
-        if (!FlowUtil.hasLegalObjectStamp(object)) {
-            return isNu;
-        }
-        if (state.isNull(object)) {
-            metricNullCheckRemoved.increment();
-            return trueConstant;
-        } else if (state.isNonNull(object)) {
-            metricNullCheckRemoved.increment();
-            return falseConstant;
-        }
-        return isNu;
-    }
-
-    /**
-     * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made;
-     *         otherwise the unmodified argument.
-     */
-    private LogicNode baseCaseObjectEqualsNode(ObjectEqualsNode equals) {
-        if (!FlowUtil.hasLegalObjectStamp(equals.getX()) || !FlowUtil.hasLegalObjectStamp(equals.getY())) {
-            return equals;
-        }
-        ValueNode x = GraphUtil.unproxify(equals.getX());
-        ValueNode y = GraphUtil.unproxify(equals.getY());
-        if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) {
-            metricObjectEqualsRemoved.increment();
-            return falseConstant;
-        } else if (state.isNull(x) && state.isNull(y)) {
-            metricObjectEqualsRemoved.increment();
-            return trueConstant;
-        }
-        return equals;
-    }
-
-    /**
-     * The following is tried:
-     *
-     * <ol>
-     * <li>
-     * A {@link com.oracle.graal.phases.common.cfs.Witness} that is at check-cast level level
-     * doesn't entail {@link com.oracle.graal.nodes.calc.IsNullNode} (on its own) nor
-     * {@link com.oracle.graal.nodes.java.InstanceOfNode} (also on its own) but of course it entails
-     * <code>(IsNull || IsInstanceOf)</code>. Good thing
-     * {@link com.oracle.graal.phases.common.cfs.CastCheckExtractor} detects that very pattern.</li>
-     * <li>
-     * Otherwise return the unmodified argument (later on,
-     * {@link #deverbosifyFloatingNode(com.oracle.graal.nodes.calc.FloatingNode)} will attempt to
-     * simplify the {@link com.oracle.graal.nodes.ShortCircuitOrNode}).</li>
-     * </ol>
-     *
-     * @return a {@link com.oracle.graal.nodes.LogicConstantNode}, in case a reduction was made;
-     *         otherwise the unmodified argument.
-     */
-    private LogicNode baseCaseShortCircuitOrNode(ShortCircuitOrNode orNode) {
-        CastCheckExtractor cast = CastCheckExtractor.extract(orNode);
-        if (cast != null) {
-            if (state.knownToConform(cast.subject, cast.type)) {
-                return trueConstant;
-            } else if (state.knownNotToPassCheckCast(cast.subject, cast.type)) {
-                return falseConstant;
-            }
-            return orNode;
-        }
-        return orNode;
-    }
-
-    /**
-     * It's always ok to use "<code>downcast(object)</code>" instead of " <code>object</code>"
-     * because this method re-wraps the argument in a {@link com.oracle.graal.nodes.PiNode} only if
-     * the new stamp is strictly more refined than the original.
-     *
-     * <p>
-     * This method does not
-     * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)}
-     * .
-     * </p>
-     *
-     * @return One of:
-     *         <ul>
-     *         <li>a {@link com.oracle.graal.nodes.PiNode} with more precise stamp than the input if
-     *         the state warrants such downcasting</li>
-     *         <li>a {@link com.oracle.graal.nodes.java.CheckCastNode CheckCastNode} for the same
-     *         scrutinee in question</li>
-     *         <li>the unmodified argument otherwise.</li>
-     *         </ul>
-     */
-    ValueNode downcast(final ValueNode object) {
-
-        // -------------------------------------------------
-        // actions based only on the stamp of the input node
-        // -------------------------------------------------
-
-        if (!FlowUtil.hasLegalObjectStamp(object)) {
-            return object;
-        }
-        if (FlowUtil.isLiteralNode(object)) {
-            return object;
-        }
-        if (StampTool.isPointerAlwaysNull(object.stamp())) {
-            return object;
-        }
-
-        // ------------------------------------------
-        // actions based on the stamp and the witness
-        // ------------------------------------------
-
-        ValueNode scrutinee = GraphUtil.unproxify(object);
-
-        PiNode untrivialNull = nonTrivialNull(scrutinee);
-        if (untrivialNull != null) {
-            metricNullInserted.increment();
-            return untrivialNull;
-        }
-
-        Witness w = state.typeInfo(scrutinee);
-        if (w == null) {
-            // no additional hints being tracked for the scrutinee
-            return object;
-        }
-
-        assert !w.clueless();
-
-        ObjectStamp inputStamp = (ObjectStamp) object.stamp();
-        ObjectStamp witnessStamp = w.asStamp();
-        if (inputStamp.equals(witnessStamp) || !FlowUtil.isMorePrecise(witnessStamp, inputStamp)) {
-            // the witness offers no additional precision over current one
-            fixupTypeProfileStamp(object);
-            return object;
-        }
-
-        assert !FlowUtil.isMorePrecise(inputStamp.type(), w.type());
-
-        ValueNode result;
-        if (object instanceof ValueProxy) {
-            result = downcastValueProxy((ValueProxy) object, w);
-        } else {
-            result = downcastedUtil(object, w);
-        }
-
-        assert !BaseReduction.precisionLoss(object, result);
-
-        return result;
-    }
-
-    /**
-     * TODO TypeProfileProxyNode.inferStamp doesn't infer non-null from non-null payload
-     *
-     * <p>
-     * And there's a bunch of asserts in
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} that assert no
-     * type-precision gets lost. Thus the need to fix-up on our own, as done here.
-     * </p>
-     */
-    private static void fixupTypeProfileStamp(ValueNode object) {
-        if (!(object instanceof TypeProfileProxyNode)) {
-            return;
-        }
-        TypeProfileProxyNode profile = (TypeProfileProxyNode) object;
-        ObjectStamp outgoinStamp = (ObjectStamp) profile.stamp();
-        ObjectStamp payloadStamp = (ObjectStamp) profile.getValue().stamp();
-        if (payloadStamp.nonNull() && !outgoinStamp.nonNull()) {
-            profile.setStamp(FlowUtil.asNonNullStamp(outgoinStamp));
-        }
-    }
-
-    /**
-     * <p>
-     * Porcelain method.
-     * </p>
-     *
-     * <p>
-     * Utility to create, add to the graph,
-     * {@link EquationalReasoner#rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)}
-     * , and return a {@link com.oracle.graal.nodes.PiNode} that narrows into the given stamp,
-     * anchoring the payload.
-     * </p>
-     *
-     * <p>
-     * The resulting node might not have been in the graph already.
-     * </p>
-     */
-    private PiNode wrapInPiNode(ValueNode payload, GuardingNode anchor, ObjectStamp newStamp, boolean remember) {
-        try (Debug.Scope s = Debug.scope("Downcast", payload)) {
-            assert payload != anchor : payload.graph().toString();
-            metricDowncasting.increment();
-            PiNode result = graph.unique(new PiNode(payload, newStamp, anchor.asNode()));
-            // we've possibly got a new node in the graph --- bookkeeping is in order.
-            added.add(result);
-            if (remember) {
-                rememberSubstitution(payload, result);
-            }
-            Debug.log("Downcasting from %s to %s", payload, result);
-            return result;
-        } catch (Throwable e) {
-            throw Debug.handle(e);
-        }
-    }
-
-    /**
-     *
-     * This method returns:
-     * <ul>
-     * <li><b>null</b>, if the argument is known null due to its stamp. Otherwise,</li>
-     * <li><b>a PiNode</b> wrapping the null constant and an anchor offering evidence as to why the
-     * argument is known null, if such anchor is available. Otherwise,</li>
-     * <li><b>null</b></li>
-     * </ul>
-     * <p>
-     * This method does not
-     * {@link #rememberSubstitution(com.oracle.graal.nodes.ValueNode, com.oracle.graal.nodes.ValueNode)}
-     * .
-     * </p>
-     */
-    public PiNode nonTrivialNull(ValueNode object) {
-        assert FlowUtil.hasLegalObjectStamp(object);
-        GuardingNode anchor = state.nonTrivialNullAnchor(object);
-        if (anchor == null) {
-            return null;
-        }
-        if (object instanceof GuardedNode && StampTool.isPointerAlwaysNull(object.stamp())) {
-            return (PiNode) object;
-        }
-        // notice nullConstant is wrapped, not object
-        PiNode result = wrapInPiNode(nullConstant, anchor, (ObjectStamp) StampFactory.alwaysNull(), false);
-        return result;
-    }
-
-    // @formatter:off
-    /**
-     * <p>ValueProxys can be classified along two dimensions,
-     * in addition to the fixed-floating dichotomy.</p>
-     *
-     * <p>
-     *     First, we might be interested in separating those ValueProxys
-     *     that are entitled to change (usually narrow) their stamp from those that aren't.
-     *     In the first category are:
-     *       PiNode, PiArrayNode, GuardingPiNode,
-     *       CheckCastNode, UnsafeCastNode, and
-     *       GuardedValueNode.
-     * </p>
-     *
-     * <p>
-     *     A note on stamp-narrowing ValueProxys:
-     *     our state abstraction tracks only the type refinements induced by CheckCastNode and GuardingPiNode
-     *     (which are fixed nodes, unlike the other stamp-narrowing ValueProxys;
-     *     the reason being that the state abstraction can be updated only at fixed nodes).
-     *     As a result, the witness for a (PiNode, PiArrayNode, UnsafeCastNode, or GuardedValueNode)
-     *     may be less precise than the proxy's stamp. We don't want to lose such precision,
-     *     thus <code>downcast(proxy) == proxy</code> in such cases.
-     * </p>
-     *
-     * <p>
-     *     The second classification focuses on
-     *     the additional information that travels with the proxy
-     *     (in addition to its "payload", ie getOriginalValue(), and any narrowing-stamp).
-     *     Such additional information boils down to:
-     *
-     *   (a) type profile (TypeProfileProxyNode)
-     *   (b) type profile (CheckCastNode)
-     *   (c) anchor (GuardedValueNode)
-     *   (d) anchor (PiNode)
-     *   (e) anchor and array length (PiArrayNode)
-     *   (f) optional anchor (UnsafeCastNode)
-     *   (g) deopt-condition (GuardingPiNode)
-     *   (h) LocationIdentity (MemoryProxyNOde)
-     *   (i) control-flow dependency (FixedValueAnchorNode)
-     *   (j) proxyPoint (ProxyNode -- think loops)
-     *</p>
-     */
-    // @formatter:on
-    private ValueNode downcastValueProxy(ValueProxy proxy, Witness w) {
-        assert FlowUtil.hasLegalObjectStamp((ValueNode) proxy);
-        assert FlowUtil.hasLegalObjectStamp((proxy).getOriginalNode());
-        assert GraphUtil.unproxify((ValueNode) proxy) == GraphUtil.unproxify(proxy.getOriginalNode());
-
-        assert GraphUtil.unproxify((ValueNode) proxy) == GraphUtil.unproxify((proxy).getOriginalNode());
-
-        if (proxy instanceof PiNode) {
-            return downcastPiNodeOrPiArrayNode((PiNode) proxy, w);
-        } else if (proxy instanceof GuardingPiNode) {
-            return downcastGuardingPiNode((GuardingPiNode) proxy, w);
-        } else if (proxy instanceof TypeProfileProxyNode) {
-            return downcastTypeProfileProxyNode((TypeProfileProxyNode) proxy);
-        } else if (proxy instanceof CheckCastNode) {
-            return downcastCheckCastNode((CheckCastNode) proxy, w);
-        } else if (proxy instanceof ProxyNode || proxy instanceof GuardedValueNode) {
-            // TODO scaladacapo return downcastedUtil((ValueNode) proxy, w);
-            return (ValueNode) proxy;
-        }
-
-        assert false : "TODO case not yet handled";
-
-        // TODO complete the missing implementation for the cases not yet handled
-
-        return ((ValueNode) proxy);
-    }
-
-    /**
-     * <p>
-     * Why would we want to downcast a GuardingPiNode? Is it even possible? Like, for example, a
-     * GuardingPiNode originating in the lowering of a CheckCastNode (carried out by
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
-     * visitCheckCastNode()}).
-     * </p>
-     *
-     * <p>
-     * It's both possible and desirable. Example: <code>
-     *         Number n = (Number) o;
-     *         if (n instanceof Integer) {
-     *            return n.intValue();
-     *         }
-     *     </code>
-     *
-     * The receiver of intValue() is a usage of a previous checkCast, for which the current witness
-     * provides a more refined type (and an anchor). In this case, the advantage of downcasting a
-     * GuardingPiNode is clear: devirtualizing the `intValue()` callsite.
-     * </p>
-     *
-     * @see #downcastValueProxy
-     */
-    public ValueNode downcastGuardingPiNode(GuardingPiNode envelope, Witness w) {
-        assert envelope != w.guard().asNode() : "The stamp of " + envelope + " would lead to downcasting with that very same GuardingPiNode as guard.";
-        return downcastedUtil(envelope, w);
-    }
-
-    /**
-     * <p>
-     * This method accepts both {@link com.oracle.graal.nodes.PiNode} and
-     * {@link com.oracle.graal.nodes.PiArrayNode} argument.
-     * </p>
-     *
-     * <p>
-     * In case a witness reveals a strictly more precise type than the
-     * {@link com.oracle.graal.nodes.PiNode}'s stamp, this method wraps the argument in a new
-     * {@link com.oracle.graal.nodes.PiNode} with updated stamp, and returns it.
-     * </p>
-     *
-     * <p>
-     * A {@link com.oracle.graal.nodes.PiArrayNode} argument ends up wrapped in a
-     * {@link com.oracle.graal.nodes.PiNode}. Thus, the
-     * {@link com.oracle.graal.nodes.PiArrayNode#length} information doesn't get lost.
-     * </p>
-     *
-     * <p>
-     * Note: {@link com.oracle.graal.nodes.PiNode}'s semantics allow un-packing its payload as soon
-     * as it type conforms to that of the {@link com.oracle.graal.nodes.PiNode} (that's what
-     * {@link com.oracle.graal.nodes.PiNode#canonical(com.oracle.graal.graph.spi.CanonicalizerTool)
-     * PiNode.canonical()} does). Not clear the benefits of duplicating that logic here.
-     * </p>
-     *
-     * @see #downcastValueProxy
-     */
-    private ValueNode downcastPiNodeOrPiArrayNode(PiNode envelope, Witness w) {
-        return downcastedUtil(envelope, w);
-    }
-
-    /**
-     * <p>
-     * In a case the payload of the {@link com.oracle.graal.nodes.TypeProfileProxyNode} can be
-     * downcasted, this method returns a copy-on-write version with the downcasted payload.
-     * </p>
-     *
-     * <p>
-     * Otherwise returns the unmodified argument.
-     * </p>
-     *
-     * @see #downcastValueProxy
-     */
-    private ValueNode downcastTypeProfileProxyNode(TypeProfileProxyNode envelope) {
-        ValueNode payload = envelope.getOriginalNode();
-        ValueNode d = downcast(payload);
-        if (payload != d) {
-            TypeProfileProxyNode changed = (TypeProfileProxyNode) envelope.copyWithInputs();
-            added.add(changed);
-            // copyWithInputs() implies graph.unique(changed)
-            FlowUtil.replaceInPlace(changed, payload, d);
-            FlowUtil.inferStampAndCheck(changed);
-            fixupTypeProfileStamp(changed);
-            /*
-             * It's not prudent to (1) obtain the canonical() of the (changed) TypeProfileProxyNode
-             * to (2) replace its usages; because we're potentially walking a DAG (after all,
-             * TypeProfileProxyNode is a floating-node). Those steps, which admittedly are needed,
-             * are better performed upon replacing in-place the inputs of a FixedNode, or during
-             * Canonicalize.
-             */
-            return changed;
-        }
-        fixupTypeProfileStamp(envelope);
-        return envelope;
-    }
-
-    /**
-     * <p>
-     * Re-wrap the checkCast in a type-refining {@link com.oracle.graal.nodes.PiNode PiNode} only if
-     * the downcasted scrutinee does not conform to the checkCast's target-type.
-     * </p>
-     */
-    private ValueNode downcastCheckCastNode(CheckCastNode checkCast, Witness w) {
-
-        final ResolvedJavaType toType = checkCast.type();
-
-        if (checkCast.object() instanceof CheckCastNode) {
-            ValueNode innerMost = checkCast;
-            while (innerMost instanceof CheckCastNode) {
-                innerMost = ((CheckCastNode) innerMost).object();
-            }
-            ValueNode deepest = downcast(innerMost);
-            ResolvedJavaType deepestType = ((ObjectStamp) deepest.stamp()).type();
-            if ((deepestType != null && deepestType.equals(toType)) || FlowUtil.isMorePrecise(deepestType, toType)) {
-                assert !w.knowsBetterThan(deepest);
-                return deepest;
-            }
-        }
-
-        ValueNode subject = downcast(checkCast.object());
-        ObjectStamp subjectStamp = (ObjectStamp) subject.stamp();
-        ResolvedJavaType subjectType = subjectStamp.type();
-
-        if (subjectType != null && toType.isAssignableFrom(subjectType)) {
-            assert !w.knowsBetterThan(subject);
-            return subject;
-        }
-
-        return downcastedUtil(checkCast, w);
-    }
-
-    /**
-     * <p>
-     * Porcelain method.
-     * </p>
-     *
-     * <p>
-     * This method wraps the argument in a new {@link com.oracle.graal.nodes.PiNode PiNode} (created
-     * to hold an updated stamp) provided the argument's stamp can be strictly refined, and returns
-     * it.
-     * </p>
-     */
-    private ValueNode downcastedUtil(ValueNode subject, Witness w) {
-
-        ObjectStamp originalStamp = (ObjectStamp) subject.stamp();
-        ObjectStamp outgoingStamp = originalStamp;
-
-        if (w.isNonNull() && !outgoingStamp.nonNull()) {
-            outgoingStamp = FlowUtil.asNonNullStamp(outgoingStamp);
-        }
-        if (FlowUtil.isMorePrecise(w.type(), outgoingStamp.type())) {
-            outgoingStamp = FlowUtil.asRefinedStamp(outgoingStamp, w.type());
-        }
-
-        if (outgoingStamp != originalStamp) {
-            assert FlowUtil.isMorePrecise(outgoingStamp, originalStamp);
-
-            boolean isWitnessGuardAnAliasForScrutinee = false;
-            if (w.guard() instanceof GuardingPiNode || w.guard() instanceof PiNode) {
-                /*
-                 * The guard offered by the witness canonicalizes into its subject (a possibly
-                 * type-refined scrutinee) provided its subject conforms as per stamp.
-                 */
-                if (w.guard().asNode().stamp().equals(outgoingStamp)) {
-                    isWitnessGuardAnAliasForScrutinee = true;
-                }
-            }
-
-            ValueNode result;
-            if (isWitnessGuardAnAliasForScrutinee) {
-                result = w.guard().asNode();
-                assert !w.knowsBetterThan(result);
-                return result; // TODO this works. explain why.
-            } else {
-                result = wrapInPiNode(subject, w.guard(), outgoingStamp, true);
-                assert !w.knowsBetterThan(result);
-                return result;
-            }
-
-        } else {
-            assert !w.knowsBetterThan(subject);
-            return subject;
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Evidence.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import com.oracle.graal.nodes.extended.GuardingNode;
-
-public class Evidence {
-
-    public final GuardingNode success;
-    public final boolean failure;
-
-    public Evidence(GuardingNode success, boolean failure) {
-        this.success = success;
-        this.failure = failure;
-        assert repOK();
-    }
-
-    public Evidence(GuardingNode success) {
-        this(success, false);
-    }
-
-    private Evidence(boolean failure) {
-        this(null, failure);
-    }
-
-    public boolean isPositive() {
-        return success != null;
-    }
-
-    public boolean isNegative() {
-        return failure;
-    }
-
-    private boolean repOK() {
-        // either success or failure, ie boolean-XOR
-        return (success != null) != failure;
-    }
-
-    public static Evidence COUNTEREXAMPLE = new Evidence(true);
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.GuardingNode;
-import com.oracle.graal.phases.tiers.PhaseContext;
-
-/**
- * <p>
- * This class implements control-flow sensitive reductions for
- * {@link com.oracle.graal.nodes.FixedGuardNode}.
- * </p>
- * 
- * <p>
- * The laundry-list of all flow-sensitive reductions is summarized in
- * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction}
- * </p>
- * 
- * @see #visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode)
- */
-public abstract class FixedGuardReduction extends CheckCastReduction {
-
-    public FixedGuardReduction(StartNode start, State initialState, PhaseContext context) {
-        super(start, initialState, context);
-    }
-
-    /**
-     * <p>
-     * Upon visiting a {@link com.oracle.graal.nodes.FixedGuardNode}, based on flow-sensitive
-     * conditions, we need to determine whether:
-     * <ul>
-     * <li>it is redundant (in which case it should be simplified), or</li>
-     * <li>flow-sensitive information can be gained from it.</li>
-     * </ul>
-     * </p>
-     * 
-     * <p>
-     * This method realizes the above by inspecting the
-     * {@link com.oracle.graal.nodes.FixedGuardNode}'s condition:
-     * <ol>
-     * <li>a constant condition signals the node won't be reduced here</li>
-     * <li>the outcome of the condition can be predicted:</li>
-     * <ul>
-     * <li>
-     * "always succeeds", after finding an equivalent (or stronger)
-     * {@link com.oracle.graal.nodes.extended.GuardingNode} in scope. The
-     * {@link com.oracle.graal.nodes.FixedGuardNode} is removed after replacing its usages with the
-     * existing guarding node</li>
-     * <li>
-     * "always fails", which warrants making that explicit by making the condition constant, see
-     * {@link #markFixedGuardNodeAlwaysFails(com.oracle.graal.nodes.FixedGuardNode)}</li>
-     * </ul>
-     * <li>otherwise the condition is tracked flow-sensitively</li>
-     * </ol>
-     * </p>
-     * 
-     * <p>
-     * Precondition: the condition hasn't been deverbosified yet.
-     * </p>
-     */
-    protected final void visitFixedGuardNode(FixedGuardNode f) {
-
-        /*
-         * A FixedGuardNode with LogicConstantNode condition is left untouched.
-         * `FixedGuardNode.simplify()` will eventually remove the FixedGuardNode (in case it
-         * "always succeeds") or kill code ("always fails").
-         */
-
-        if (f.condition() instanceof LogicConstantNode) {
-            if (FlowUtil.alwaysFails(f.isNegated(), f.condition())) {
-                state.impossiblePath();
-                // let FixedGuardNode(false).simplify() prune the dead-code control-path
-                return;
-            }
-            assert FlowUtil.alwaysSucceeds(f.isNegated(), f.condition());
-            return;
-        }
-
-        final boolean isTrue = !f.isNegated();
-        final Evidence evidence = state.outcome(isTrue, f.condition());
-
-        // can't produce evidence, must be information gain
-        if (evidence == null) {
-            state.addFact(isTrue, f.condition(), f);
-            return;
-        }
-
-        if (evidence.isPositive()) {
-            /*
-             * A FixedGuardNode can only be removed provided a replacement anchor is found (so
-             * called "evidence"), ie an anchor that amounts to the same combination of (negated,
-             * condition) as for the FixedGuardNode at hand. Just deverbosifying the condition in
-             * place isn't semantics-preserving.
-             * 
-             * Eliminate the current FixedGuardNode by using another GuardingNode already in scope,
-             * a GuardingNode that guards a condition that is at least as strong as that of the
-             * FixedGuardNode.
-             */
-            removeFixedGuardNode(f, evidence.success);
-            return;
-        }
-
-        assert evidence.isNegative();
-        markFixedGuardNodeAlwaysFails(f);
-
-    }
-
-    /**
-     * Porcelain method.
-     */
-    private void markFixedGuardNodeAlwaysFails(FixedGuardNode f) {
-        metricFixedGuardNodeRemoved.increment();
-        state.impossiblePath();
-        f.setCondition(f.isNegated() ? trueConstant : falseConstant);
-        // `f.condition()` if unused will be removed in finished()
-    }
-
-    /**
-     * Porcelain method.
-     * 
-     * <p>
-     * The `replacement` guard must be such that it implies the `old` guard. Moreover, rhe
-     * `replacement` guard must be in scope.
-     * </p>
-     */
-    private void removeFixedGuardNode(FixedGuardNode old, GuardingNode replacement) {
-        assert replacement != null;
-        metricFixedGuardNodeRemoved.increment();
-        old.replaceAtUsages(replacement.asNode());
-        graph.removeFixed(old);
-        // `old.condition()` if unused will be removed in finished()
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,605 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import static com.oracle.graal.api.meta.DeoptimizationAction.*;
-import static com.oracle.graal.api.meta.DeoptimizationReason.*;
-import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.tiers.*;
-
-/**
- * <p>
- * In a nutshell, {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} makes a
- * single pass in dominator-based order over the graph:
- * <ol>
- * <li>collecting properties of interest at control-splits; as well as for check-casts,
- * guarding-pis, null-checks, and fixed-guards. Such flow-sensitive information is tracked via a
- * dedicated {@link com.oracle.graal.phases.common.cfs.State state instance} for each control-flow
- * path.</li>
- * <li>performing rewritings that are safe at specific program-points. This comprises:
- * <ul>
- * <li>simplification of side-effects free expressions, via
- * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)}
- * <ul>
- * <li>
- * at certain {@link com.oracle.graal.nodes.FixedNode}, see
- * {@link #deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode)}</li>
- * <li>
- * including for devirtualization, see
- * {@link #deverbosifyInputsCopyOnWrite(com.oracle.graal.nodes.java.MethodCallTargetNode)}</li>
- * </ul>
- * </li>
- * <li>simplification of control-flow:
- * <ul>
- * <li>
- * by simplifying the input-condition to an {@link com.oracle.graal.nodes.IfNode}</li>
- * <li>
- * by eliminating redundant check-casts, guarding-pis, null-checks, and fixed-guards; where
- * "redundancy" is determined using flow-sensitive information. In these cases, redundancy can be
- * due to:
- * <ul>
- * <li>an equivalent, existing, guarding node is already in scope (thus, use it as replacement and
- * remove the redundant one)</li>
- * <li>"always fails" (thus, replace the node in question with <code>FixedGuardNode(false)</code>)</li>
- * </ul>
- * </li>
- * </ul>
- * </li>
- * </ul>
- * </li>
- * </ol>
- * </p>
- *
- * <p>
- * Metrics for this phase are displayed starting with <code>FSR-</code>prefix, their counters are
- * hosted in {@link com.oracle.graal.phases.common.cfs.BaseReduction},
- * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner} and
- * {@link com.oracle.graal.phases.common.cfs.State}.
- * </p>
- *
- * @see com.oracle.graal.phases.common.cfs.CheckCastReduction
- * @see com.oracle.graal.phases.common.cfs.GuardingPiReduction
- * @see com.oracle.graal.phases.common.cfs.FixedGuardReduction
- *
- */
-public class FlowSensitiveReduction extends FixedGuardReduction {
-
-    public FlowSensitiveReduction(StartNode start, State initialState, PhaseContext context) {
-        super(start, initialState, context);
-    }
-
-    /**
-     * <p>
-     * This method performs two kinds of cleanup:
-     * <ol>
-     * <li>
-     * marking as unreachable certain code-paths, as described in
-     * {@link com.oracle.graal.phases.common.cfs.BaseReduction.PostponedDeopt}</li>
-     * <li>
-     * Removing nodes not in use that were added during this phase, as described next.</li>
-     * </ol>
-     * </p>
-     *
-     *
-     * <p>
-     * Methods like
-     * {@link com.oracle.graal.phases.common.cfs.FlowUtil#replaceInPlace(com.oracle.graal.graph.Node, com.oracle.graal.graph.Node, com.oracle.graal.graph.Node)}
-     * may result in old inputs becoming disconnected from the graph. It's not advisable to
-     * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} at
-     * that moment, because one of the inputs that might get killed is one of {@link #nullConstant},
-     * {@link #falseConstant}, or {@link #trueConstant}; which thus could get killed too early,
-     * before another invocation of
-     * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)}
-     * needs them. To recap,
-     * {@link com.oracle.graal.nodes.util.GraphUtil#tryKillUnused(com.oracle.graal.graph.Node)} also
-     * recursively visits the inputs of the its argument.
-     * </p>
-     *
-     * <p>
-     * This method goes over all of the nodes that deverbosification might have added, which are
-     * either:
-     * <ul>
-     * <li>
-     * {@link com.oracle.graal.nodes.calc.FloatingNode}, added by
-     * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosifyFloatingNode(com.oracle.graal.nodes.calc.FloatingNode)}
-     * ; or</li>
-     * <li>
-     * {@link com.oracle.graal.nodes.java.MethodCallTargetNode}, added by
-     * {@link #deverbosifyInputsCopyOnWrite(com.oracle.graal.nodes.java.MethodCallTargetNode)}</li>
-     * </ul>
-     *
-     * Checking if they aren't in use, proceeding to remove them in that case.
-     * </p>
-     *
-     */
-    @Override
-    public void finished() {
-        if (!postponedDeopts.isEmpty()) {
-            for (PostponedDeopt postponed : postponedDeopts) {
-                postponed.doRewrite(falseConstant);
-            }
-            new DeadCodeEliminationPhase(Optional).apply(graph);
-        }
-        for (MethodCallTargetNode mcn : graph.getNodes().filter(MethodCallTargetNode.class)) {
-            if (mcn.isAlive() && FlowUtil.lacksUsages(mcn)) {
-                mcn.safeDelete();
-            }
-        }
-        for (Node n : graph.getNodes().filter(FloatingNode.class)) {
-            GraphUtil.tryKillUnused(n);
-        }
-        assert !isAliveWithoutUsages(trueConstant);
-        assert !isAliveWithoutUsages(falseConstant);
-        assert !isAliveWithoutUsages(nullConstant);
-        super.finished();
-    }
-
-    private static boolean isAliveWithoutUsages(FloatingNode node) {
-        return node.isAlive() && FlowUtil.lacksUsages(node);
-    }
-
-    private void registerControlSplit(Node pred, BeginNode begin) {
-        assert pred != null && begin != null;
-        assert !state.isUnreachable;
-
-        if (begin instanceof LoopExitNode) {
-            state.clear();
-            /*
-             * TODO return or not? (by not returning we agree it's ok to update the state as below)
-             */
-        }
-
-        if (pred instanceof IfNode) {
-            registerIfNode((IfNode) pred, begin);
-        } else if (pred instanceof TypeSwitchNode) {
-            registerTypeSwitchNode((TypeSwitchNode) pred, begin);
-        }
-    }
-
-    private void registerIfNode(IfNode ifNode, BeginNode begin) {
-        final boolean isThenBranch = (begin == ifNode.trueSuccessor());
-
-        if (ifNode.condition() instanceof LogicConstantNode) {
-            final LogicConstantNode constCond = (LogicConstantNode) ifNode.condition();
-            if (isThenBranch != constCond.getValue()) {
-                state.impossiblePath();
-                // let IfNode(constant) prune the dead-code control-path
-            }
-        }
-
-        if (state.isUnreachable) {
-            if (!(ifNode.condition() instanceof LogicConstantNode)) {
-                // if condition constant, no need to add a Deopt node
-                postponedDeopts.addDeoptAfter(begin, UnreachedCode);
-            }
-        } else {
-            state.addFact(isThenBranch, ifNode.condition(), begin);
-        }
-    }
-
-    /**
-     * TODO When tracking integer-stamps, the state at each successor of a TypeSwitchNode should
-     * track an integer-stamp for the LoadHubNode (meet over the constants leading to that
-     * successor). However, are LoadHubNode-s shared frequently enough?
-     */
-    private void registerTypeSwitchNode(TypeSwitchNode typeSwitch, BeginNode begin) {
-        if (typeSwitch.value() instanceof LoadHubNode) {
-            LoadHubNode loadHub = (LoadHubNode) typeSwitch.value();
-            ResolvedJavaType type = null;
-            for (int i = 0; i < typeSwitch.keyCount(); i++) {
-                if (typeSwitch.keySuccessor(i) == begin) {
-                    if (type == null) {
-                        type = typeSwitch.typeAt(i);
-                    } else {
-                        type = FlowUtil.widen(type, typeSwitch.typeAt(i));
-                    }
-                }
-            }
-            if (type == null) {
-                // `begin` denotes the default case of the TypeSwitchNode
-                return;
-            }
-            // it's unwarranted to assume loadHub.object() to be non-null
-            state.trackCC(loadHub.getValue(), type, begin);
-        }
-    }
-
-    /**
-     *
-     * <p>
-     * Reduce input nodes based on the state at the program point for the argument (ie, based on
-     * "valid facts" only, without relying on any floating-guard-assumption).
-     * </p>
-     *
-     * <p>
-     * For each (direct or indirect) child, a copy-on-write version is made in case any of its
-     * children changed, with the copy accommodating the updated children. If the parent was shared,
-     * copy-on-write prevents the updates from becoming visible to anyone but the invoker of this
-     * method.
-     * </p>
-     *
-     * <p>
-     * <b> Please note the parent node is mutated upon any descendant changing. No copy-on-write is
-     * performed for the parent node itself. </b>
-     * </p>
-     *
-     * <p>
-     * In more detail, for each direct {@link com.oracle.graal.nodes.ValueNode} input of the node at
-     * hand,
-     *
-     * <ol>
-     * <li>
-     * Obtain a lazy-copied version (via spanning tree) of the DAG rooted at the input-usage in
-     * question. Lazy-copying is done by walking a spanning tree of the original DAG, stopping at
-     * non-FloatingNodes but transitively walking FloatingNodes and their inputs. Upon arriving at a
-     * (floating) node N, the state's facts are checked to determine whether a constant C can be
-     * used instead in the resulting lazy-copied DAG. A NodeBitMap is used to realize the spanning
-     * tree.</li>
-     *
-     * <li>
-     * Provided one or more N-to-C node replacements took place, the resulting lazy-copied DAG has a
-     * parent different from the original (ie different object identity) which indicates the
-     * (copied, updated) DAG should replace the original via replaceFirstInput(), and inferStamp()
-     * should be invoked to reflect the updated inputs.</li>
-     *
-     * </ol>
-     * </p>
-     *
-     * @return whether any reduction was performed on the inputs of the arguments.
-     */
-    public boolean deverbosifyInputsInPlace(ValueNode parent) {
-        boolean changed = false;
-        for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) {
-            assert !(i instanceof GuardNode) : "This phase not intended to run during MidTier";
-            ValueNode j = (ValueNode) reasoner.deverbosify(i);
-            if (i != j) {
-                changed = true;
-                FlowUtil.replaceInPlace(parent, i, j);
-            }
-        }
-        if (changed) {
-            FlowUtil.inferStampAndCheck(parent);
-        }
-        return changed;
-    }
-
-    /**
-     * Similar to {@link #deverbosifyInputsInPlace(com.oracle.graal.nodes.ValueNode)}, except that
-     * not the parent but a fresh clone is updated upon any of its children changing.
-     *
-     * @return the original parent if no updated took place, a copy-on-write version of it
-     *         otherwise.
-     *
-     */
-    private MethodCallTargetNode deverbosifyInputsCopyOnWrite(MethodCallTargetNode parent) {
-        final CallTargetNode.InvokeKind ik = parent.invokeKind();
-        boolean shouldDowncastReceiver = ik.isIndirect();
-        MethodCallTargetNode changed = null;
-        for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) {
-            ValueNode j = (ValueNode) reasoner.deverbosify(i);
-            if (shouldDowncastReceiver) {
-                shouldDowncastReceiver = false;
-                j = reasoner.downcast(j);
-            }
-            if (i != j) {
-                assert j != parent;
-                if (changed == null) {
-                    changed = (MethodCallTargetNode) parent.copyWithInputs();
-                    reasoner.added.add(changed);
-                    // copyWithInputs() implies graph.unique(changed)
-                    assert changed.isAlive();
-                    assert FlowUtil.lacksUsages(changed);
-                }
-                FlowUtil.replaceInPlace(changed, i, j);
-            }
-        }
-        if (changed == null) {
-            return parent;
-        }
-        FlowUtil.inferStampAndCheck(changed);
-        /*
-         * No need to rememberSubstitution() because not called from deverbosify(). In detail, it's
-         * only deverbosify() that skips visited nodes (thus we'd better have recorded any
-         * substitutions we want for them). Not this case.
-         */
-        return changed;
-    }
-
-    /**
-     * Precondition: This method assumes that either:
-     *
-     * <ul>
-     * <li>the state has already stabilized (ie no more pending iterations in the "iterative"
-     * dataflow algorithm); or</li>
-     * <li>any rewritings made based on the state in its current form are conservative enough to be
-     * safe.</li>
-     * </ul>
-     *
-     * <p>
-     * The overarching goal is to perform just enough rewriting to trigger other phases (
-     * {@link com.oracle.graal.graph.spi.SimplifierTool SimplifierTool},
-     * {@link com.oracle.graal.phases.common.DeadCodeEliminationPhase DeadCodeEliminationPhase},
-     * etc) to perform the bulk of rewriting, thus lowering the maintenance burden.
-     * </p>
-     *
-     */
-    @Override
-    protected void node(FixedNode node) {
-
-        assert node.isAlive();
-
-        /*-------------------------------------------------------------------------------------
-         * Step 1: Unreachable paths are still visited (PostOrderNodeIterator requires all ends
-         * of a merge to have been visited), but time is saved by neither updating the state nor
-         * rewriting anything while on an an unreachable path.
-         *-------------------------------------------------------------------------------------
-         */
-        if (state.isUnreachable) {
-            return;
-        }
-
-        /*-------------------------------------------------------------------------------------
-         * Step 2: For an AbstractBeginNode, determine whether this path is reachable, register
-         * any associated guards.
-         *-------------------------------------------------------------------------------------
-         */
-        if (node instanceof BeginNode) {
-            BeginNode begin = (BeginNode) node;
-            Node pred = node.predecessor();
-
-            if (pred != null) {
-                registerControlSplit(pred, begin);
-            }
-            return;
-        }
-
-        /*-------------------------------------------------------------------------------------
-         * Step 3: Check whether EquationalReasoner caches should be cleared upon state updates.
-         *-------------------------------------------------------------------------------------
-         */
-        reasoner.updateState(state);
-
-        /*-------------------------------------------------------------------------------------
-         * Step 4: Whatever special-case handling makes sense for the FixedNode at hand before
-         * its inputs are reduced.
-         *-------------------------------------------------------------------------------------
-         */
-
-        if (node instanceof AbstractEndNode) {
-            visitAbstractEndNode((AbstractEndNode) node);
-            return;
-        } else if (node instanceof Invoke) {
-            visitInvoke((Invoke) node);
-            return;
-        } else if (node instanceof CheckCastNode) {
-            // it's important not to call deverbosification for visitCheckCastNode()
-            visitCheckCastNode((CheckCastNode) node);
-            return;
-        } else if (node instanceof GuardingPiNode) {
-            visitGuardingPiNode((GuardingPiNode) node);
-            return;
-        } else if (node instanceof NullCheckNode) {
-            visitNullCheckNode((NullCheckNode) node);
-            return;
-        } else if (node instanceof FixedGuardNode) {
-            visitFixedGuardNode((FixedGuardNode) node);
-            return;
-        } else if (node instanceof ConditionAnchorNode) {
-            // ConditionAnchorNode shouldn't occur during HighTier
-            return;
-        }
-
-        /*-------------------------------------------------------------------------------------
-         * Step 5: After special-case handling, we do our best for those FixedNode-s
-         * where the effort to reduce their inputs might pay off.
-         *
-         * Why is this useful? For example, by the time the BeginNode for an If-branch
-         * is visited (in general a ControlSplitNode), the If-condition will have gone already
-         * through simplification (and thus potentially have been reduced to a
-         * LogicConstantNode).
-         *-------------------------------------------------------------------------------------
-         */
-        boolean paysOffToReduce = false;
-        if (node instanceof ControlSplitNode) {
-            // desire to simplify control flow
-            paysOffToReduce = true;
-        } else if (node instanceof ReturnNode) {
-            paysOffToReduce = true;
-        } else if (node instanceof AccessFieldNode || node instanceof AccessArrayNode) {
-            // desire to remove null-checks
-            paysOffToReduce = true;
-        }
-
-        // TODO comb remaining FixedWithNextNode subclasses, pick those with chances of paying-off
-
-        // TODO UnsafeLoadNode takes a condition
-
-        if (paysOffToReduce) {
-            deverbosifyInputsInPlace(node);
-        }
-
-        /*---------------------------------------------------------------------------------------
-         * Step 6: Any additional special-case handling, this time after having inputs reduced.
-         * For example, leverage anchors provided by the FixedNode, to add facts to the factbase.
-         *---------------------------------------------------------------------------------------
-         */
-
-        // TODO some nodes are GuardingNodes (eg, FixedAccessNode) we could use them to track state
-        // TODO other nodes are guarded (eg JavaReadNode), thus *their* guards could be replaced.
-
-    }
-
-    /**
-     * In case the scrutinee:
-     *
-     * <ul>
-     * <li>is known to be null, an unconditional deopt is added.</li>
-     * <li>is known to be non-null, the NullCheckNode is removed.</li>
-     * <li>otherwise, the NullCheckNode is lowered to a FixedGuardNode which then allows using it as
-     * anchor for state-tracking.</li>
-     * </ul>
-     *
-     * <p>
-     * Precondition: the input (ie, object) hasn't been deverbosified yet.
-     * </p>
-     */
-    private void visitNullCheckNode(NullCheckNode ncn) {
-        ValueNode object = ncn.getObject();
-        if (state.isNull(object)) {
-            postponedDeopts.addDeoptBefore(ncn, NullCheckException);
-            state.impossiblePath();
-            return;
-        }
-        if (state.isNonNull(object)) {
-            /*
-             * Redundant NullCheckNode. Unlike GuardingPiNode or FixedGuardNode, NullCheckNode-s
-             * aren't used as GuardingNode-s, thus in this case can be removed without further ado.
-             */
-            assert FlowUtil.lacksUsages(ncn);
-            graph.removeFixed(ncn);
-            return;
-        }
-        /*
-         * Lower the NullCheckNode to a FixedGuardNode which then allows using it as anchor for
-         * state-tracking. TODO the assumption here is that the code emitted for the resulting
-         * FixedGuardNode is as efficient as for NullCheckNode.
-         */
-        IsNullNode isNN = graph.unique(new IsNullNode(object));
-        reasoner.added.add(isNN);
-        FixedGuardNode nullCheck = graph.add(new FixedGuardNode(isNN, UnreachedCode, InvalidateReprofile, true));
-        graph.replaceFixedWithFixed(ncn, nullCheck);
-
-        state.trackNN(object, nullCheck);
-    }
-
-    /**
-     * The {@link com.oracle.graal.nodes.AbstractEndNode} at the end of the current code path
-     * contributes values to {@link com.oracle.graal.nodes.PhiNode}s. Now is a good time to
-     * {@link EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)
-     * EquationalReasoner#deverbosify} those values.
-     *
-     * <p>
-     * Precondition: inputs haven't been deverbosified yet.
-     * </p>
-     */
-    private void visitAbstractEndNode(AbstractEndNode endNode) {
-        MergeNode merge = endNode.merge();
-        for (PhiNode phi : merge.phis()) {
-            if (phi instanceof ValuePhiNode && phi.getKind() == Kind.Object) {
-                assert phi.verify();
-                int index = merge.phiPredecessorIndex(endNode);
-                ValueNode original = phi.valueAt(index);
-                ValueNode reduced = (ValueNode) reasoner.deverbosify(original);
-                if (reduced != original) {
-                    phi.setValueAt(index, reduced);
-                    // `original` if unused will be removed in finished()
-                }
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * For one or more `invoke` arguments, flow-sensitive information may suggest their narrowing or
-     * simplification. In those cases, a new
-     * {@link com.oracle.graal.nodes.java.MethodCallTargetNode MethodCallTargetNode} is prepared
-     * just for this callsite, consuming reduced arguments.
-     * </p>
-     *
-     * <p>
-     * Specializing the {@link com.oracle.graal.nodes.java.MethodCallTargetNode
-     * MethodCallTargetNode} as described above may enable two optimizations:
-     * <ul>
-     * <li>
-     * devirtualization of an {@link com.oracle.graal.nodes.CallTargetNode.InvokeKind#Interface} or
-     * {@link com.oracle.graal.nodes.CallTargetNode.InvokeKind#Virtual} callsite (devirtualization
-     * made possible after narrowing the type of the receiver)</li>
-     * <li>
-     * (future work) actual-argument-aware inlining, ie, to specialize callees on the types of
-     * arguments other than the receiver (examples: multi-methods, the inlining problem, lambdas as
-     * arguments).</li>
-     *
-     * </ul>
-     * </p>
-     *
-     * <p>
-     * Precondition: inputs haven't been deverbosified yet.
-     * </p>
-     */
-    private void visitInvoke(Invoke invoke) {
-        if (invoke.asNode().stamp() instanceof IllegalStamp) {
-            return; // just to be safe
-        }
-        boolean isMethodCallTarget = invoke.callTarget() instanceof MethodCallTargetNode;
-        if (!isMethodCallTarget) {
-            return;
-        }
-        FlowUtil.replaceInPlace(invoke.asNode(), invoke.callTarget(), deverbosifyInputsCopyOnWrite((MethodCallTargetNode) invoke.callTarget()));
-        MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
-        if (callTarget.invokeKind() != CallTargetNode.InvokeKind.Interface && callTarget.invokeKind() != CallTargetNode.InvokeKind.Virtual) {
-            return;
-        }
-        ValueNode receiver = callTarget.receiver();
-        if (receiver == null) {
-            return;
-        }
-        if (!FlowUtil.hasLegalObjectStamp(receiver)) {
-            return;
-        }
-        Witness w = state.typeInfo(receiver);
-        ResolvedJavaType type;
-        ResolvedJavaType stampType = StampTool.typeOrNull(receiver);
-        if (w == null || w.cluelessAboutType()) {
-            // can't improve on stamp but wil try to devirtualize anyway
-            type = stampType;
-        } else {
-            type = FlowUtil.tighten(w.type(), stampType);
-        }
-        if (type == null) {
-            return;
-        }
-        ResolvedJavaMethod method = type.resolveConcreteMethod(callTarget.targetMethod(), invoke.getContextType());
-        if (method == null) {
-            return;
-        }
-        if (method.canBeStaticallyBound() || Modifier.isFinal(type.getModifiers())) {
-            metricMethodResolved.increment();
-            callTarget.setInvokeKind(CallTargetNode.InvokeKind.Special);
-            callTarget.setTargetMethod(method);
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.tiers.PhaseContext;
-
-public class FlowSensitiveReductionPhase extends BasePhase<PhaseContext> {
-
-    private final MetaAccessProvider metaAccess;
-
-    public MetaAccessProvider getMetaAccess() {
-        return metaAccess;
-    }
-
-    public FlowSensitiveReductionPhase(MetaAccessProvider metaAccess) {
-        this.metaAccess = metaAccess;
-    }
-
-    @Override
-    protected final void run(StructuredGraph graph, PhaseContext context) {
-        try (Debug.Scope s = Debug.scope("FlowSensitiveReduction")) {
-            if (graph.isOSR()) {
-                Debug.log("Skipping OSR method %s", graph.method() == null ? "" : graph.method().format("%H.%n"));
-                return;
-            }
-            Debug.dump(graph, "FlowSensitiveReduction initial");
-            new FlowSensitiveReduction(graph.start(), new State(), context).apply();
-            Debug.dump(graph, "FlowSensitiveReduction done");
-        } catch (Throwable e) {
-            throw Debug.handle(e);
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,284 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-
-public final class FlowUtil {
-
-    private FlowUtil() {
-        // no instances of this class
-    }
-
-    public static boolean lacksUsages(Node n) {
-        return n.hasNoUsages();
-    }
-
-    public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) {
-        if (a == null || b == null) {
-            return null;
-        } else if (a.equals(b)) {
-            return a;
-        } else {
-            return a.findLeastCommonAncestor(b);
-        }
-    }
-
-    /**
-     * @return whether the first argument is strictly more precise than the second.
-     */
-    public static boolean isMorePrecise(ResolvedJavaType a, ResolvedJavaType b) {
-        if (a == null) {
-            return false;
-        }
-        if (b == null) {
-            return true;
-        }
-        assert !a.isPrimitive();
-        assert !b.isPrimitive();
-        if (a.equals(b)) {
-            return false;
-        }
-        if (b.isInterface()) {
-            return b.isAssignableFrom(a);
-        }
-        if (a.isInterface()) {
-            return b.isInterface() && b.isAssignableFrom(a);
-        }
-        return b.isAssignableFrom(a);
-    }
-
-    public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) {
-        if (a == null) {
-            assert b == null || !b.isPrimitive();
-            return b;
-        }
-        if (b == null) {
-            assert !a.isPrimitive();
-            return a;
-        }
-        assert !a.isPrimitive();
-        assert !b.isPrimitive();
-        if (a.equals(b)) {
-            return a;
-        }
-        if (isMorePrecise(a, b)) {
-            return a;
-        } else if (isMorePrecise(b, a)) {
-            return b;
-        } else {
-            /*
-             * Not comparable, two cases:
-             * 
-             * Example 1: 'a' standing for j.l.Number and 'b' for j.l.String We return null for lack
-             * of a value representing NullType, the right answer. Same goes when both arguments are
-             * non-comparable interfaces.
-             * 
-             * Example 2: 'a' standing for sun/nio/ch/DirectBuffer (an interface) and b for
-             * java/nio/Buffer (an abstract class). The class always takes precedence.
-             */
-            if (a.isInterface()) {
-                return b.isInterface() ? null : b;
-            }
-            if (b.isInterface()) {
-                return a.isInterface() ? null : a;
-            }
-            return null; // a and b aren't comparable, can't tighten() them
-        }
-    }
-
-    /**
-     *
-     * There are "illegal" stamps that are not of type IllegalStamp.
-     *
-     * For example, there may be an IntegerStamp with upperBound < lowerBound that returns
-     * !isLegal() but we still know it's an integer and thus not of type IllegalStamp.
-     *
-     * An IllegalStamp should never happen. In contrast, !isLegal() values could happen due to dead
-     * code not yet removed, or upon some non-sideeffecting instructions floating out of a dead
-     * branch.
-     */
-    public static boolean isLegalObjectStamp(Stamp s) {
-        return isObjectStamp(s) && s.isLegal();
-    }
-
-    public static boolean hasLegalObjectStamp(ValueNode v) {
-        return isLegalObjectStamp(v.stamp());
-    }
-
-    public static boolean isObjectStamp(Stamp stamp) {
-        return stamp instanceof ObjectStamp;
-    }
-
-    public static void inferStampAndCheck(ValueNode n) {
-        n.inferStamp();
-        if (n.stamp() instanceof ObjectStamp) {
-            ObjectStamp objectStamp = (ObjectStamp) n.stamp();
-            assert !objectStamp.isExactType() || objectStamp.type() != null;
-        }
-    }
-
-    /**
-     * Compares the arguments along three dimensions (nullness, exactness, and type). For the first
-     * argument to be more precise than the second, it may not score lower in any dimension and must
-     * score higher in at least one dimension.
-     *
-     * When comparing types s and t, sameness counts as 0; while being more precise is awarded with
-     * a score of 1. In all other cases (non-comparable, or supertype) the score is -1.
-     *
-     * @return whether the first argument is strictly more precise than the second.
-     */
-    public static boolean isMorePrecise(ObjectStamp a, ObjectStamp b) {
-        int d0 = minus(a.alwaysNull(), b.alwaysNull());
-        if (d0 == -1) {
-            return false;
-        }
-        int d1 = minus(a.nonNull(), b.nonNull());
-        if (d1 == -1) {
-            return false;
-        }
-        int d2 = minus(a.isExactType(), b.isExactType());
-        if (d2 == -1) {
-            return false;
-        }
-        int d3;
-        ResolvedJavaType ta = a.type();
-        ResolvedJavaType tb = b.type();
-        if (ta == null) {
-            d3 = (tb == null) ? 0 : -1;
-        } else if (tb == null) {
-            d3 = 1;
-        } else if (isMorePrecise(ta, tb)) {
-            d3 = 1;
-        } else if (ta.equals(tb)) {
-            d3 = 0;
-        } else {
-            d3 = -1;
-        }
-        if (d3 == -1) {
-            return false;
-        }
-        int maxScore = Math.max(Math.max(d0, d1), Math.max(d2, d3));
-        return maxScore > 0;
-    }
-
-    private static int minus(boolean a, boolean b) {
-        int aa = a ? 1 : 0;
-        int bb = b ? 1 : 0;
-        return aa - bb;
-    }
-
-    public static LogicConstantNode asLogicConstantNode(LogicNode cond) {
-        return (cond instanceof LogicConstantNode) ? (LogicConstantNode) cond : null;
-    }
-
-    public static boolean isLiteralNode(ValueNode f) {
-        return f instanceof ConstantNode || f instanceof LogicConstantNode;
-    }
-
-    public static boolean isConstantTrue(LogicNode cond) {
-        LogicConstantNode c = asLogicConstantNode(cond);
-        return (c != null) && c.getValue();
-    }
-
-    public static boolean isConstantFalse(LogicNode cond) {
-        LogicConstantNode c = asLogicConstantNode(cond);
-        return (c != null) && !c.getValue();
-    }
-
-    public static boolean alwaysFails(boolean isNegated, LogicNode cond) {
-        LogicConstantNode c = asLogicConstantNode(cond);
-        return (c != null) && (c.getValue() == isNegated);
-    }
-
-    public static boolean alwaysSucceeds(boolean isNegated, LogicNode cond) {
-        LogicConstantNode c = asLogicConstantNode(cond);
-        return (c != null) && (c.getValue() != isNegated);
-    }
-
-    /**
-     * Returns (preserving order) the ValueNodes without duplicates found among the argument's
-     * direct inputs.
-     */
-    @SuppressWarnings("unchecked")
-    public static List<ValueNode> distinctValueAndConditionInputs(Node n) {
-        ArrayList<ValueNode> result = null;
-        NodePosIterator iter = n.inputs().iterator();
-        while (iter.hasNext()) {
-            Position pos = iter.nextPosition();
-            InputType inputType = pos.getInputType();
-            boolean isReducibleInput = (inputType == InputType.Value || inputType == InputType.Condition);
-            if (isReducibleInput) {
-                ValueNode i = (ValueNode) pos.get(n);
-                if (!isLiteralNode(i)) {
-                    if (result == null) {
-                        result = new ArrayList<>();
-                    }
-                    if (!result.contains(i)) {
-                        result.add(i);
-                    }
-                }
-            }
-        }
-        return result == null ? Collections.EMPTY_LIST : result;
-    }
-
-    public static ObjectStamp asNonNullStamp(ObjectStamp stamp) {
-        ObjectStamp result = (ObjectStamp) stamp.join(StampFactory.objectNonNull());
-        assert result.isLegal();
-        return result;
-    }
-
-    public static ObjectStamp asRefinedStamp(ObjectStamp stamp, ResolvedJavaType joinType) {
-        assert !joinType.isInterface();
-        ObjectStamp result = (ObjectStamp) stamp.join(StampFactory.declared(joinType));
-        assert result.isLegal();
-        return result;
-    }
-
-    /**
-     * Start situation: the parent node has <code>oldInput</code> among its (direct) inputs. After
-     * this method has run, all such occurrences have been replaced with <code>newInput</code>. In
-     * case that makes <code>oldInput</code> disconnected, it is removed from the graph.
-     */
-    public static void replaceInPlace(Node parent, Node oldInput, Node newInput) {
-        assert parent != null;
-        assert parent.inputs().contains(oldInput);
-        if (oldInput == newInput) {
-            return;
-        }
-        assert oldInput != null && newInput != null;
-        assert !isLiteralNode((ValueNode) oldInput);
-        do {
-            parent.replaceFirstInput(oldInput, newInput);
-        } while (parent.inputs().contains(oldInput));
-        // `oldInput` if unused wil be removed in finished()
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,384 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, 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.cfs;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.Debug;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.IsNullNode;
-import com.oracle.graal.nodes.extended.GuardingNode;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.compiler.common.type.ObjectStamp;
-import com.oracle.graal.nodes.type.StampTool;
-import com.oracle.graal.phases.tiers.PhaseContext;
-
-/**
- * <p>
- * This class implements control-flow sensitive reductions for
- * {@link com.oracle.graal.nodes.GuardingPiNode}.
- * </p>
- * 
- * <p>
- * The laundry-list of all flow-sensitive reductions is summarized in
- * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction}
- * </p>
- * 
- * @see #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)
- */
-public abstract class GuardingPiReduction extends BaseReduction {
-
-    public GuardingPiReduction(StartNode start, State initialState, PhaseContext context) {
-        super(start, initialState, context);
-    }
-
-    /**
-     * <p>
-     * By the time a {@link com.oracle.graal.nodes.GuardingPiNode GuardingPiNode} is visited, the
-     * available type refinements may allow reductions similar to those performed for
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction#visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode)
-     * CheckCastNode}.
-     * </p>
-     * 
-     * <ol>
-     * <li>
-     * If the condition needs no reduction (ie, it's already a
-     * {@link com.oracle.graal.nodes.LogicConstantNode LogicConstantNode}), this method basically
-     * gives up (thus letting other phases take care of it).</li>
-     * <li>
-     * Otherwise, an attempt is made to find a {@link com.oracle.graal.nodes.extended.GuardingNode}
-     * that implies the combination of (negated, condition) of the
-     * {@link com.oracle.graal.nodes.GuardingPiNode} being visited. Details in
-     * {@link #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}. If found, the node
-     * can be removed.</li>
-     * <li>
-     * Otherwise, the node is lowered to a {@link com.oracle.graal.nodes.FixedGuardNode} and its
-     * usages replaced with {@link com.oracle.graal.nodes.PiNode}. Details in
-     * {@link #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)}.</li>
-     * </ol>
-     * 
-     * <p>
-     * Precondition: the condition hasn't been deverbosified yet.
-     * </p>
-     * 
-     */
-    protected final void visitGuardingPiNode(GuardingPiNode envelope) {
-
-        if (!FlowUtil.hasLegalObjectStamp(envelope)) {
-            // this situation exercised by com.oracle.graal.jtt.optimize.NCE_FlowSensitive02
-            return;
-        }
-        if (!FlowUtil.hasLegalObjectStamp(envelope.object())) {
-            return;
-        }
-
-        /*
-         * (1 of 3) Cover the case of GuardingPiNode(LogicConstantNode, ...)
-         */
-
-        if (envelope.condition() instanceof LogicConstantNode) {
-            if (FlowUtil.alwaysFails(envelope.isNegated(), envelope.condition())) {
-                state.impossiblePath();
-                // let GuardingPiNode(false).canonical() prune the dead-code control-path
-                return;
-            }
-            // if not always-fails and condition-constant, then it always-succeeds!
-            assert FlowUtil.alwaysSucceeds(envelope.isNegated(), envelope.condition());
-            // let GuardingPiNode(true).canonical() replaceAtUsages
-            return;
-        }
-
-        /*
-         * The trick used in visitFixedGuardNode to look up an equivalent GuardingNode for the
-         * combination of (negated, condition) at hand doesn't work for GuardingPiNode, because the
-         * condition showing up here (a ShortCircuitOrNode that can be detected by
-         * CastCheckExtractor) doesn't appear as key in trueFacts, falseFacts. Good thing we have
-         * CastCheckExtractor!
-         */
-
-        /*
-         * (2 of 3) Cover the case of the condition known-to-be-false or known-to-be-true, but not
-         * LogicConstantNode.
-         * 
-         * If deverbosify(condition) == falseConstant, it would be safe to set:
-         * `envelope.setCondition(falseConstant)` (only the API won't allow).
-         * 
-         * On the other hand, it's totally unsafe to do something like that for trueConstant. What
-         * we can do about that case is the province of `tryRemoveGuardingPiNode(envelope)`
-         */
-
-        if (tryRemoveGuardingPiNode(envelope)) {
-            return;
-        }
-
-        /*
-         * Experience has shown that an attempt to eliminate the current GuardingPiNode by using a
-         * GuardingNode already in scope and with equivalent condition (grabbed from `trueFacts`
-         * resp. `falseFacts`) proves futile. Therefore we're not even attempting that here.
-         */
-
-        /*
-         * (3 of 3) Neither always-succeeds nor always-fails, ie we don't known. Converting to
-         * FixedGuardNode allows tracking the condition via a GuardingNode, thus potentially
-         * triggering simplifications down the road.
-         */
-        FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(envelope.condition(), envelope.getReason(), envelope.getAction(), envelope.isNegated()));
-        graph.addBeforeFixed(envelope, fixedGuard);
-
-        /*
-         * 
-         * TODO This lowering is currently performed unconditionally: it might occur no
-         * flow-sensitive reduction is enabled down the road
-         */
-
-        if (!FlowUtil.lacksUsages(envelope)) {
-            // not calling wrapInPiNode() because we don't want to rememberSubstitution()
-            PiNode replacement = graph.unique(new PiNode(envelope.object(), envelope.stamp(), fixedGuard));
-            reasoner.added.add(replacement);
-            // before removing the GuardingPiNode replace its usages
-            envelope.replaceAtUsages(replacement);
-        }
-
-        graph.removeFixed(envelope);
-
-        state.addFact(!fixedGuard.isNegated(), fixedGuard.condition(), fixedGuard);
-
-    }
-
-    /**
-     * <p>
-     * Based on flow-sensitive knowledge, two pre-requisites have to be fulfilled in order to remove
-     * a {@link com.oracle.graal.nodes.GuardingPiNode}:
-     * 
-     * <ul>
-     * <li>the condition must refer only to the payload of the
-     * {@link com.oracle.graal.nodes.GuardingPiNode}</li>
-     * <li>the condition must check properties about which the state tracks not only a true/false
-     * answer, but also an anchor witnessing that fact</li>
-     * <li>the condition may not check anything else beyond what's stated in the items above.</li>
-     * </ul>
-     * </p>
-     * 
-     * <p>
-     * Provided a condition as above can be reduced to a constant (and an anchor obtained in the
-     * process), this method replaces all usages of the
-     * {@link com.oracle.graal.nodes.GuardingPiNode} (necessarily of
-     * {@link com.oracle.graal.nodeinfo.InputType#Value}) with a
-     * {@link com.oracle.graal.nodes.PiNode} that wraps the payload and the anchor in question.
-     * </p>
-     * 
-     * <p>
-     * Precondition: the condition hasn't been deverbosified yet.
-     * </p>
-     * 
-     * @see #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)
-     * 
-     */
-    private boolean tryRemoveGuardingPiNode(GuardingPiNode envelope) {
-
-        LogicNode cond = envelope.condition();
-        ValueNode payload = envelope.object();
-
-        ObjectStamp outgoingStamp = (ObjectStamp) envelope.stamp();
-        ObjectStamp payloadStamp = (ObjectStamp) payload.stamp();
-
-        if (isNullCheckOn(cond, payload)) {
-            if (envelope.isNegated()) {
-                /*
-                 * GuardingPiNode succeeds if payload non-null
-                 */
-                if (!outgoingStamp.equals(FlowUtil.asNonNullStamp(payloadStamp))) {
-                    warnAboutOutOfTheBlueGuardingPiNode(envelope);
-                }
-                return tryRemoveGuardingPiNodeNonNullCond(envelope);
-            } else {
-                /*
-                 * GuardingPiNode succeeds if payload null
-                 */
-                ValueNode replacement = StampTool.isPointerAlwaysNull(payload) ? payload : reasoner.nonTrivialNull(payload);
-                if (replacement != null) {
-                    // replacement == null means !isKnownNull(payload)
-                    removeGuardingPiNode(envelope, replacement);
-                    return true;
-                }
-                return false;
-            }
-        } else if (CastCheckExtractor.isInstanceOfCheckOn(cond, payload)) {
-            if (envelope.isNegated()) {
-                return false;
-            }
-            /*
-             * GuardingPiNode succeeds if payload instanceof <something>
-             */
-            InstanceOfNode io = (InstanceOfNode) cond;
-            assert io.type() != null;
-            Witness w = state.typeInfo(payload);
-            if (w != null && w.isNonNull() && isEqualOrMorePrecise(w.type(), io.type())) {
-                ValueNode d = reasoner.downcast(payload);
-                removeGuardingPiNode(envelope, d);
-                return true;
-            }
-            return false;
-        } else if (cond instanceof ShortCircuitOrNode) {
-            if (envelope.isNegated()) {
-                return false;
-            }
-            CastCheckExtractor cce = CastCheckExtractor.extract(cond);
-            if (cce == null || cce.subject != payload) {
-                return false;
-            }
-            /*
-             * GuardingPiNode succeeds if payload check-casts toType
-             */
-            return tryRemoveGuardingPiNodeCheckCastCond(envelope, cce.type);
-        }
-
-        return false;
-    }
-
-    /**
-     * Porcelain method.
-     * 
-     * This method handles the case where the GuardingPiNode succeeds if payload known to be
-     * non-null.
-     * 
-     * @see #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)
-     */
-    private boolean tryRemoveGuardingPiNodeNonNullCond(GuardingPiNode envelope) {
-
-        ValueNode payload = envelope.object();
-
-        if (state.isNull(payload)) {
-            // the GuardingPiNode fails always
-            postponedDeopts.addDeoptBefore(envelope, envelope.getReason());
-            state.impossiblePath();
-            return true;
-        }
-
-        if (StampTool.isPointerNonNull(payload)) {
-            // payload needs no downcasting, it satisfies as-is the GuardingPiNode's condition.
-            if (precisionLoss(envelope, payload)) {
-                /*
-                 * TODO The GuardingPiNode has an outgoing stamp whose narrowing goes beyond what
-                 * the condition checks. That's suspicious.
-                 */
-                PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp()));
-                reasoner.added.add(replacement);
-                removeGuardingPiNode(envelope, replacement);
-                return true;
-            } else {
-                removeGuardingPiNode(envelope, payload);
-                return true;
-            }
-        }
-        // if a non-null witness available, the GuardingPiNode can be removed
-
-        Witness w = state.typeInfo(payload);
-        GuardingNode nonNullAnchor = (w != null && w.isNonNull()) ? w.guard() : null;
-        if (nonNullAnchor != null) {
-            PiNode replacement = graph.unique(new PiNode(payload, envelope.stamp(), nonNullAnchor.asNode()));
-            reasoner.added.add(replacement);
-            removeGuardingPiNode(envelope, replacement);
-            return true;
-        }
-
-        /*
-         * TODO What about, nodes that always denote non-null values? (Even though their stamp
-         * forgot to make that clear) Candidates: ObjectGetClassNode, Parameter(0) on instance
-         */
-
-        return false;
-    }
-
-    /**
-     * Porcelain method.
-     * 
-     * This method handles the case where the GuardingPiNode succeeds if payload null or its actual
-     * type equal or subtype of `toType`
-     * 
-     * @see #tryRemoveGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)
-     * 
-     */
-    private boolean tryRemoveGuardingPiNodeCheckCastCond(GuardingPiNode envelope, ResolvedJavaType toType) {
-        assert toType != null;
-        ValueNode payload = envelope.object();
-
-        ObjectStamp outgoingStamp = (ObjectStamp) envelope.stamp();
-        ObjectStamp payloadStamp = (ObjectStamp) payload.stamp();
-
-        if (!outgoingStamp.equals(FlowUtil.asRefinedStamp(payloadStamp, toType))) {
-            warnAboutOutOfTheBlueGuardingPiNode(envelope);
-        }
-
-        ValueNode d = reasoner.downcast(payload);
-        if (d == null) {
-            return false;
-        }
-
-        if (StampTool.isPointerAlwaysNull(d)) {
-            removeGuardingPiNode(envelope, d);
-            return true;
-        }
-        ObjectStamp dStamp = (ObjectStamp) d.stamp();
-        if (isEqualOrMorePrecise(dStamp.type(), toType)) {
-            removeGuardingPiNode(envelope, d);
-            return true;
-        }
-        return false;
-    }
-
-    /*
-     * TODO There should be an assert in GuardingPiNode to detect that as soon as it happens
-     * (constructor, setStamp).
-     */
-    private static void warnAboutOutOfTheBlueGuardingPiNode(GuardingPiNode envelope) {
-        Debug.log(String.format("GuardingPiNode has an outgoing stamp whose narrowing goes beyond what its condition checks: %s", envelope));
-    }
-
-    private static boolean isNullCheckOn(LogicNode cond, ValueNode subject) {
-        if (!(cond instanceof IsNullNode)) {
-            return false;
-        }
-        IsNullNode isNull = (IsNullNode) cond;
-        return isNull.getValue() == subject;
-    }
-
-    /**
-     * Porcelain method.
-     */
-    private void removeGuardingPiNode(GuardingPiNode envelope, ValueNode replacement) {
-        assert !precisionLoss(envelope, replacement);
-        metricGuardingPiNodeRemoved.increment();
-        envelope.replaceAtUsages(replacement);
-        assert FlowUtil.lacksUsages(envelope);
-        graph.removeFixed(envelope);
-    }
-
-    public static boolean isEqualOrMorePrecise(ResolvedJavaType a, ResolvedJavaType b) {
-        return a.equals(b) || FlowUtil.isMorePrecise(a, b);
-    }
-
-    public static boolean isEqualOrMorePrecise(ObjectStamp a, ObjectStamp b) {
-        return a.equals(b) || FlowUtil.isMorePrecise(a, b);
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Histogram.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import java.util.Map;
-import java.util.TreeMap;
-
-public class Histogram extends TreeMap<Integer, Integer> {
-
-    private static final long serialVersionUID = 7188324319057387738L;
-
-    private final String prefix;
-
-    public Histogram(String prefix) {
-        this.prefix = prefix;
-    }
-
-    public void tick(int bucket) {
-        Integer entry = get(bucket);
-        put(bucket, entry == null ? 1 : entry + 1);
-    }
-
-    public void print() {
-
-        // printing takes time, allow concurrent updates during printing
-        Histogram histogram = clone();
-
-        float casesTotal = 0;
-        for (int i : histogram.values()) {
-            casesTotal += i;
-        }
-        for (Map.Entry<Integer, Integer> entry : histogram.entrySet()) {
-            int numCases = entry.getValue();
-            int percentOut = (int) (numCases / casesTotal * 100);
-            String msg = prefix + String.format("%d iters in %4d cases (%2d %%)", entry.getKey(), numCases, percentOut);
-            if (entry.getKey() > 3) {
-                highlightInRed(msg);
-            } else {
-                System.out.println(msg);
-            }
-        }
-        System.out.println(prefix + "--------------------------");
-    }
-
-    @Override
-    public Histogram clone() {
-        return (Histogram) super.clone();
-    }
-
-    public static final String ANSI_RESET = "\u001B[0m";
-    public static final String ANSI_RED = "\u001B[31m";
-
-    public static void highlightInRed(String msg) {
-        System.out.println(ANSI_RED + msg + ANSI_RESET);
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/IterativeFlowSensitiveReductionPhase.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import static com.oracle.graal.graph.Graph.NodeEvent.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.Graph.NodeEventScope;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.util.*;
-import com.oracle.graal.phases.tiers.*;
-
-public class IterativeFlowSensitiveReductionPhase extends BasePhase<PhaseContext> {
-
-    private static final int MAX_ITERATIONS = 256;
-
-    private final CanonicalizerPhase canonicalizer;
-
-    public IterativeFlowSensitiveReductionPhase(CanonicalizerPhase canonicalizer) {
-        this.canonicalizer = canonicalizer;
-    }
-
-    // private Histogram histogram = new Histogram("FSR-");
-
-    @Override
-    protected void run(StructuredGraph graph, PhaseContext context) {
-        FlowSensitiveReductionPhase eliminate = new FlowSensitiveReductionPhase(context.getMetaAccess());
-        HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NODE_ADDED);
-        int count = 1;
-        while (true) {
-            try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
-                eliminate.apply(graph, context);
-            }
-            if (listener.getNodes().isEmpty()) {
-                // histogram.tick(count);
-                break;
-            }
-            for (Node node : graph.getNodes()) {
-                if (node instanceof Simplifiable) {
-                    listener.getNodes().add(node);
-                }
-            }
-            canonicalizer.applyIncremental(graph, context, listener.getNodes());
-            listener.getNodes().clear();
-            if (++count > MAX_ITERATIONS) {
-                // System.out.println("Bailing out IterativeFlowSensitiveReductionPhase for graph: "
-                // + graph);
-                // FlowUtil.visualize(graph, "Bailout");
-                throw new BailoutException("Number of iterations in FlowSensitiveReductionPhase exceeds %d", MAX_ITERATIONS);
-            }
-        }
-        // histogram.print();
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1017 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, 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.cfs;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.graph.*;
-
-/**
- * A State instance is mutated in place as each FixedNode is visited in a basic block of
- * instructions. Basic block: starts with a {@link com.oracle.graal.nodes.BeginNode BeginNode}, ends
- * at an {@link com.oracle.graal.nodes.EndNode EndNode} or
- * {@link com.oracle.graal.nodes.ControlSinkNode ControlSinkNode} and lacks intervening control
- * splits or merges.
- */
-public final class State extends MergeableState<State> implements Cloneable {
-
-    private static final DebugMetric metricTypeRegistered = Debug.metric("FSR-TypeRegistered");
-    private static final DebugMetric metricNullnessRegistered = Debug.metric("FSR-NullnessRegistered");
-    private static final DebugMetric metricObjectEqualsRegistered = Debug.metric("FSR-ObjectEqualsRegistered");
-    private static final DebugMetric metricImpossiblePathDetected = Debug.metric("FSR-ImpossiblePathDetected");
-
-    /**
-     * <p>
-     * Each state update results in a higher {@link State#versionNr versionNr}. The
-     * {@link State#versionNr versionNr} of different State instances can't be meaningfully compared
-     * (ie, same {@link State#versionNr versionNr} just indicates they've gone through the same
-     * number of updates). In particular, the {@link State#versionNr versionNr} of a merged state
-     * doesn't guarantee any more than being different from those of the states being merged.
-     * </p>
-     *
-     * <p>
-     * Still, {@link State#versionNr versionNr} proves useful in two cases:
-     *
-     * <ul>
-     * <li>recording the {@link State#versionNr versionNr} right after {@link State State} cloning,
-     * allows finding out afterwards whether (a) both states have diverged, (b) just one of them, or
-     * (c) none of them.</li>
-     * <li>a {@link State State} may become {@link State#isUnreachable isUnreachable}. In such case,
-     * it may make a difference whether any updates were performed on the state from the time it was
-     * cloned. Those updates indicate information not available in the state is was cloned from. For
-     * the purposes of {@link FlowSensitiveReduction FlowSensitiveReduction} an unreachable state
-     * need not be merged with any other (because control-flow won't reach the merge point over the
-     * path of the unreachable state).</li>
-     * </ul>
-     * </p>
-     *
-     */
-    int versionNr = 0;
-
-    boolean isUnreachable = false;
-
-    /**
-     * Getting here implies an opportunity was detected for dead-code-elimination. A counterpoint
-     * argument goes as follows: perhaps we don't get here that often, in which case the effort to
-     * detect an "impossible path" could be shaved off.
-     *
-     * @see com.oracle.graal.phases.common.cfs.BaseReduction.PostponedDeopt
-     */
-    void impossiblePath() {
-        isUnreachable = true;
-        metricImpossiblePathDetected.increment();
-    }
-
-    /**
-     * <p>
-     * This map tracks properties about reference-values, ie combinations of: definitely-null,
-     * known-to-be-non-null, seen-type.
-     * </p>
-     *
-     * <p>
-     * In contrast to {@link #trueFacts} and {@link #falseFacts}, this map can answer queries even
-     * though the exact {@link LogicNode} standing for such query hasn't been tracked. For example,
-     * queries about subtyping. Additionally, a {@link Witness} can combine separate pieces of
-     * information more flexibly, eg, two separate observations about non-null and check-cast are
-     * promoted to an instance-of witness.
-     * </p>
-     *
-     */
-    private Map<ValueNode, Witness> typeRefinements;
-
-    Map<LogicNode, GuardingNode> trueFacts;
-    Map<LogicNode, GuardingNode> falseFacts;
-
-    public State() {
-        this.typeRefinements = Node.newIdentityMap();
-        this.trueFacts = Node.newIdentityMap();
-        this.falseFacts = Node.newIdentityMap();
-    }
-
-    public State(State other) {
-        this.isUnreachable = other.isUnreachable;
-        this.versionNr = other.versionNr;
-        this.typeRefinements = Node.newIdentityMap();
-        for (Map.Entry<ValueNode, Witness> entry : other.typeRefinements.entrySet()) {
-            this.typeRefinements.put(entry.getKey(), new Witness(entry.getValue()));
-        }
-        this.trueFacts = Node.newIdentityMap(other.trueFacts);
-        this.falseFacts = Node.newIdentityMap(other.falseFacts);
-    }
-
-    public boolean repOK() {
-        // trueFacts and falseFacts disjoint
-        for (LogicNode trueFact : trueFacts.keySet()) {
-            assert !falseFacts.containsKey(trueFact) : trueFact + " tracked as both true and false fact.";
-        }
-        return true;
-    }
-
-    /**
-     * @return A new list containing only those states that are reachable.
-     */
-    private static ArrayList<State> reachableStates(List<State> states) {
-        ArrayList<State> result = new ArrayList<>(states);
-        Iterator<State> iter = result.iterator();
-        while (iter.hasNext()) {
-            if (iter.next().isUnreachable) {
-                iter.remove();
-            }
-        }
-        return result;
-    }
-
-    private Map<ValueNode, Witness> mergeKnownTypes(MergeNode merge, ArrayList<State> withReachableStates) {
-        Map<ValueNode, Witness> newKnownTypes = Node.newIdentityMap();
-
-        for (Map.Entry<ValueNode, Witness> entry : typeRefinements.entrySet()) {
-            ValueNode node = entry.getKey();
-            Witness type = new Witness(entry.getValue());
-
-            for (State other : withReachableStates) {
-                Witness otherType = other.typeInfo(node);
-                if (otherType == null) {
-                    type = null;
-                    break;
-                }
-                type.merge(otherType, merge);
-            }
-            if (type != null && type.knowsBetterThan(node)) {
-                assert node == GraphUtil.unproxify(node);
-                newKnownTypes.put(node, type);
-            }
-        }
-
-        return newKnownTypes;
-    }
-
-    /**
-     * <p>
-     * This method handles phis, by adding to the resulting state any information that can be gained
-     * (about type-refinement and nullness) based on the data available at each of the incoming
-     * branches.
-     * </p>
-     *
-     * <p>
-     * In more detail, <code>FlowSensitiveReduction#visitAbstractEndNode()</code> has already
-     * deverbosified the phi-values contributed by each reachable branch. The paths that
-     * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction} determined to be
-     * unreachable will be eliminated by canonicalization and dead code elimination. For now they
-     * still exist, thus polluting the result of
-     * {@link com.oracle.graal.nodes.ValuePhiNode#inferStamp()} but we are careful to skip them when
-     * merging type-witnesses and known-null maps.
-     * </p>
-     */
-    private void mergePhis(MergeNode merge, List<State> withStates, Map<ValueNode, Witness> newKnownPhiTypes) {
-
-        if (merge instanceof LoopBeginNode) {
-            return;
-        }
-
-        for (PhiNode phi : merge.phis()) {
-            assert phi == GraphUtil.unproxify(phi);
-            if (phi instanceof ValuePhiNode && phi.getKind() == Kind.Object) {
-                ArrayList<ValueNode> reachingValues = new ArrayList<>();
-                if (!isUnreachable) {
-                    reachingValues.add(phi.valueAt(0));
-                }
-                for (int i = 0; i < withStates.size(); i++) {
-                    State otherState = withStates.get(i);
-                    if (!otherState.isUnreachable) {
-                        reachingValues.add(phi.valueAt(i + 1));
-                    }
-                }
-                assert !reachingValues.isEmpty();
-                ObjectStamp phiStamp = (ObjectStamp) phi.stamp();
-                ObjectStamp nonPollutedStamp = (ObjectStamp) StampTool.meet(reachingValues);
-                Witness w = new Witness(nonPollutedStamp, merge);
-                if (w.isNull() && !phiStamp.alwaysNull()) {
-                    // precision gain: null
-                    newKnownPhiTypes.put(phi, w);
-                } else if (FlowUtil.isMorePrecise(w.type(), phiStamp.type())) {
-                    // precision gain regarding type
-                    newKnownPhiTypes.put(phi, w);
-                    // confirm no precision loss regarding nullness
-                    assert implies(phiStamp.nonNull(), w.isNonNull());
-                    assert implies(phiStamp.alwaysNull(), w.isNull());
-                } else if (w.isNonNull() && !phiStamp.nonNull()) {
-                    // precision gain: non-null
-                    newKnownPhiTypes.put(phi, w);
-                    // confirm no precision loss regarding type
-                    assert !FlowUtil.isMorePrecise(phiStamp.type(), w.type());
-                }
-            }
-        }
-
-    }
-
-    private static boolean implies(boolean a, boolean b) {
-        return !a || b;
-    }
-
-    @Override
-    public boolean merge(MergeNode merge, List<State> withStates) {
-
-        ArrayList<State> withReachableStates = reachableStates(withStates);
-        if (withReachableStates.isEmpty()) {
-            return true;
-        }
-
-        for (State other : withReachableStates) {
-            versionNr = Math.max(versionNr, other.versionNr) + 1;
-            if (!other.isUnreachable) {
-                isUnreachable = false;
-            }
-        }
-
-        if (isUnreachable) {
-            typeRefinements.clear();
-            trueFacts.clear();
-            falseFacts.clear();
-            return true;
-        }
-
-        // may also get updated in a moment, during processing of phi nodes.
-        Map<ValueNode, Witness> newKnownTypes = mergeKnownTypes(merge, withReachableStates);
-        // may also get updated in a moment, during processing of phi nodes.
-        mergePhis(merge, withStates, newKnownTypes);
-        this.typeRefinements = newKnownTypes;
-
-        this.trueFacts = mergeTrueFacts(withReachableStates, merge);
-        this.falseFacts = mergeFalseFacts(withReachableStates, merge);
-
-        assert repOK();
-
-        return true;
-    }
-
-    private Map<LogicNode, GuardingNode> mergeTrueFacts(ArrayList<State> withReachableStates, GuardingNode merge) {
-        Map<LogicNode, GuardingNode> newTrueConditions = Node.newIdentityMap();
-        for (Map.Entry<LogicNode, GuardingNode> entry : trueFacts.entrySet()) {
-            LogicNode check = entry.getKey();
-            GuardingNode guard = entry.getValue();
-
-            for (State other : withReachableStates) {
-                GuardingNode otherGuard = other.trueFacts.get(check);
-                if (otherGuard == null) {
-                    guard = null;
-                    break;
-                }
-                if (otherGuard != guard) {
-                    guard = merge;
-                }
-            }
-            if (guard != null) {
-                newTrueConditions.put(check, guard);
-            }
-        }
-        return newTrueConditions;
-    }
-
-    private Map<LogicNode, GuardingNode> mergeFalseFacts(ArrayList<State> withReachableStates, GuardingNode merge) {
-        Map<LogicNode, GuardingNode> newFalseConditions = Node.newIdentityMap();
-        for (Map.Entry<LogicNode, GuardingNode> entry : falseFacts.entrySet()) {
-            LogicNode check = entry.getKey();
-            GuardingNode guard = entry.getValue();
-
-            for (State other : withReachableStates) {
-                GuardingNode otherGuard = other.falseFacts.get(check);
-                if (otherGuard == null) {
-                    guard = null;
-                    break;
-                }
-                if (otherGuard != guard) {
-                    guard = merge;
-                }
-            }
-            if (guard != null) {
-                newFalseConditions.put(check, guard);
-            }
-        }
-        return newFalseConditions;
-    }
-
-    /**
-     * @return null if no type-witness available for the argument, the witness otherwise.
-     */
-    public Witness typeInfo(ValueNode object) {
-        assert FlowUtil.hasLegalObjectStamp(object);
-        return typeRefinements.get(GraphUtil.unproxify(object));
-    }
-
-    /**
-     * @return true iff the argument is known to stand for null.
-     */
-    public boolean isNull(ValueNode object) {
-        assert FlowUtil.hasLegalObjectStamp(object);
-        if (StampTool.isPointerAlwaysNull(object)) {
-            return true;
-        }
-        ValueNode scrutinee = GraphUtil.unproxify(object);
-        Witness w = typeRefinements.get(scrutinee);
-        return (w != null) && w.isNull();
-    }
-
-    /**
-     * <p>
-     * It makes a difference calling {@link Witness#isNonNull()} as opposed to
-     * {@link State#isNonNull(com.oracle.graal.nodes.ValueNode)}. The former guarantees the witness
-     * provides a guard certifying non-nullness. The latter just tells us there exists some guard
-     * that certifies the property we asked about.
-     * </p>
-     *
-     * <p>
-     * TODO improvement: isKnownNonNull could be made smarter by noticing some nodes always denote a
-     * non-null value (eg, ObjectGetClassNode). Similarly for isKnownNull. Code that looks at the
-     * stamp as well as code that looks for a non-null-witness would benefit from also checking such
-     * extended isKnownNonNull. Alternatively, the stamp of those nodes should always have
-     * is-non-null set.
-     * </p>
-     *
-     * @return true iff the argument is known to stand for non-null.
-     */
-    public boolean isNonNull(ValueNode object) {
-        assert FlowUtil.hasLegalObjectStamp(object);
-        if (StampTool.isPointerNonNull(object)) {
-            return true;
-        }
-        Witness w = typeInfo(object);
-        return w == null ? false : w.isNonNull();
-    }
-
-    /**
-     * @return true iff the argument definitely stands for an object-value that conforms to the
-     *         given type.
-     */
-    public boolean knownToConform(ValueNode object, ResolvedJavaType to) {
-        assert FlowUtil.hasLegalObjectStamp(object);
-        assert !to.isPrimitive();
-        ResolvedJavaType stampType = StampTool.typeOrNull(object);
-        if (stampType != null && to.isAssignableFrom(stampType)) {
-            return true;
-        }
-        final ValueNode scrutinee = GraphUtil.unproxify(object);
-        if (isNull(scrutinee)) {
-            return true;
-        }
-        Witness w = typeInfo(scrutinee);
-        boolean witnessAnswer = w != null && w.type() != null && to.isAssignableFrom(w.type());
-        if (witnessAnswer) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * @return true iff the argument is known to stand for an object that is definitely non-null and
-     *         moreover does not conform to the given type.
-     */
-    public boolean knownNotToPassCheckCast(ValueNode object, ResolvedJavaType to) {
-        assert FlowUtil.hasLegalObjectStamp(object);
-        assert !to.isPrimitive();
-        final ValueNode scrutinee = GraphUtil.unproxify(object);
-        if (isNull(scrutinee)) {
-            // known-null means it conforms to whatever `to`
-            // and thus passes the check-cast
-            return false;
-        }
-        if (!isNonNull(scrutinee)) {
-            // unless `null` can be ruled out, a positive answer isn't safe
-            return false;
-        }
-        ResolvedJavaType stampType = StampTool.typeOrNull(object);
-        if (stampType != null && knownNotToConform(stampType, to)) {
-            return true;
-        }
-        Witness w = typeInfo(scrutinee);
-        boolean witnessAnswer = w != null && !w.cluelessAboutType() && knownNotToConform(w.type(), to);
-        if (witnessAnswer) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * @return true iff the argument is known to stand for an object that definitely does not
-     *         conform to the given type (no matter whether the object turns out to be null or
-     *         non-null).
-     */
-    public boolean knownNotToPassInstanceOf(ValueNode object, ResolvedJavaType to) {
-        assert FlowUtil.hasLegalObjectStamp(object);
-        assert !to.isPrimitive();
-        final ValueNode scrutinee = GraphUtil.unproxify(object);
-        if (isNull(scrutinee)) {
-            return true;
-        }
-        ResolvedJavaType stampType = StampTool.typeOrNull(object);
-        if (stampType != null && knownNotToConform(stampType, to)) {
-            // object turns out to be null, positive answer is correct
-            // object turns out non-null, positive answer is also correct
-            return true;
-        }
-        Witness w = typeInfo(scrutinee);
-        boolean witnessAnswer = w != null && !w.cluelessAboutType() && knownNotToConform(w.type(), to);
-        if (witnessAnswer) {
-            // object turns out to be null, positive answer is correct
-            // object turns out non-null, positive answer is also correct
-            return true;
-        }
-        return false;
-    }
-
-    // @formatter:off
-    /**
-     * Determines if the first argument is known not to conform to the second argument.
-     *
-     * <pre>
-     *   \   |     |     |     |
-     *    \ b|     |     |     |
-     *   a \ |     |     |     |
-     *      \|iface|final|non-f|
-     *  -----+-----------------|
-     *  iface|  F  |  F  |  F  |
-     *  -----+-----------------|
-     *  final|  C  |  C  |  C  |
-     *  -----+-----------------|
-     *  non-f|  F  |  C  |  C  |
-     *  -----------------------+
-     *
-     *  where:
-     *    F:     false
-     *    C:     check
-     *    iface: interface
-     *    final: exact non-interface reference-type
-     *    non-f: non-exact non-interface reference-type
-     * </pre>
-     * @return true iff the first argument is known not to conform to the second argument.
-     */
-    // @formatter:on
-    public static boolean knownNotToConform(ResolvedJavaType a, ResolvedJavaType b) {
-        assert !a.isPrimitive();
-        assert !b.isPrimitive();
-        if (b.isAssignableFrom(a)) {
-            return false;
-        }
-        if (a.isInterface()) {
-            return false;
-        }
-        boolean aFinal = Modifier.isFinal(a.getModifiers());
-        if (b.isInterface() && !aFinal) {
-            return false;
-        }
-        if (a.isAssignableFrom(b)) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    @Override
-    public State clone() {
-        return new State(this);
-    }
-
-    /**
-     * Porcelain method.
-     */
-    private Witness getOrElseAddTypeInfo(ValueNode object) {
-        ValueNode scrutinee = GraphUtil.unproxify(object);
-        Witness w = typeRefinements.get(scrutinee);
-        if (w == null) {
-            w = new Witness();
-            typeRefinements.put(scrutinee, w);
-        }
-        return w;
-    }
-
-    /**
-     * <p>
-     * Updates this {@link State State} to account for an observation about the scrutinee being
-     * non-null. In case instanceof was observed,
-     * {@link #trackIO(com.oracle.graal.nodes.ValueNode, com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode)
-     * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead.
-     * </p>
-     *
-     * <p>
-     * No check is made on whether a contradiction would be introduced into the factbase (in which
-     * case the state should be marked unreachable), the caller takes care of that.
-     * </p>
-     *
-     * @return whether state was updated (iff the observation added any new information)
-     */
-    public boolean trackNN(ValueNode object, GuardingNode anchor) {
-        if (isDependencyTainted(object, anchor)) {
-            return false;
-        }
-        assert anchor instanceof FixedNode;
-        ResolvedJavaType stampType = StampTool.typeOrNull(object);
-        if (stampType != null && !stampType.isInterface()) {
-            return trackIO(object, stampType, anchor);
-        }
-        Witness w = getOrElseAddTypeInfo(object);
-        if (w.trackNN(anchor)) {
-            versionNr++;
-            assert repOK();
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Updates this {@link State State} to account for an observation about the scrutinee conforming
-     * to a type. In case instanceof was observed,
-     * {@link #trackIO(com.oracle.graal.nodes.ValueNode, com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode)
-     * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead.
-     *
-     * <p>
-     * No check is made on whether a contradiction would be introduced into the factbase (in which
-     * case the state should be marked unreachable), the caller must take care of that.
-     * </p>
-     *
-     * @return false iff the observed type is an interface, or doesn't provide any new information
-     *         not already known. Ie, this method returns true iff the observation resulted in
-     *         information gain.
-     */
-    public boolean trackCC(ValueNode object, ResolvedJavaType observed, GuardingNode anchor) {
-        if (observed.isInterface()) {
-            return false;
-        }
-        if (isDependencyTainted(object, anchor)) {
-            return false;
-        }
-        assert anchor instanceof FixedNode;
-        Witness w = getOrElseAddTypeInfo(object);
-        if (w.trackCC(observed, anchor)) {
-            versionNr++;
-            metricTypeRegistered.increment();
-            assert repOK();
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Updates this {@link State State} to account for an observation about the non-null scrutinee
-     * conforming to a type.
-     *
-     * <p>
-     * No check is made on whether a contradiction would be introduced into the factbase (in which
-     * case the state should be marked unreachable), the caller must take care of that.
-     * </p>
-     *
-     * @return whether state was updated (iff the observation added any new information)
-     */
-    public boolean trackIO(ValueNode object, ResolvedJavaType observed, GuardingNode anchor) {
-        assert !observed.isInterface() : "no infrastructure yet in State.Witness to support interfaces in general";
-        if (isDependencyTainted(object, anchor)) {
-            return false;
-        }
-        assert anchor instanceof FixedNode;
-        Witness w = getOrElseAddTypeInfo(object);
-        if (w.trackIO(observed, anchor)) {
-            versionNr++;
-            metricTypeRegistered.increment();
-            assert repOK();
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * This method increases {@link #versionNr} (thus potentially invalidating
-     * {@link EquationalReasoner EquationalReasoner}'s caches) only if the fact wasn't known
-     * already.
-     *
-     * <p>
-     * No check is made on whether a contradiction would be introduced into the factbase (in which
-     * case the state should be marked unreachable), the caller must take care of that.
-     * </p>
-     *
-     */
-    private void addFactPrimordial(LogicNode condition, Map<LogicNode, GuardingNode> to, GuardingNode anchor) {
-        assert condition != null;
-        if (!to.containsKey(condition)) {
-            versionNr++;
-            to.put(condition, anchor);
-        }
-    }
-
-    /**
-     * Ideas for the future.
-     * <ul>
-     * <li>track inferred less-than edges from (accumulated) CompareNode-s</li>
-     * <li>track set-representative for equality classes determined by (chained) IntegerTestNode</li>
-     * </ul>
-     *
-     */
-    public void addFact(boolean isTrue, LogicNode condition, GuardingNode anchor) {
-        assert anchor != null;
-        assert anchor instanceof FixedNode;
-        assert !isUnreachable;
-
-        if (condition instanceof LogicConstantNode) {
-            if (((LogicConstantNode) condition).getValue() != isTrue) {
-                impossiblePath();
-            }
-            return;
-        }
-
-        if (condition instanceof LogicNegationNode) {
-            addFact(!isTrue, ((LogicNegationNode) condition).getValue(), anchor);
-        } else if (condition instanceof ShortCircuitOrNode) {
-            /*
-             * We can register the conditions being or-ed as long as the anchor is a fixed node,
-             * because floating guards will be registered at a BeginNode but might be "valid" only
-             * later due to data flow dependencies. Therefore, registering both conditions of a
-             * ShortCircuitOrNode for a floating guard could lead to cycles in data flow, because
-             * the guard will be used as anchor for both conditions, and one condition could be
-             * depending on the other.
-             */
-            if (isTrue) {
-                CastCheckExtractor cce = CastCheckExtractor.extract(condition);
-                if (cce == null || isDependencyTainted(cce.subject, anchor)) {
-                    addFactPrimordial(condition, isTrue ? trueFacts : falseFacts, anchor);
-                } else {
-                    trackCC(cce.subject, cce.type, anchor);
-                }
-            } else {
-                ShortCircuitOrNode disjunction = (ShortCircuitOrNode) condition;
-                addFact(disjunction.isXNegated(), disjunction.getX(), anchor);
-                // previous addFact might have resulted in impossiblePath()
-                if (isUnreachable) {
-                    return;
-                }
-                addFact(disjunction.isYNegated(), disjunction.getY(), anchor);
-            }
-        } else if (condition instanceof InstanceOfNode) {
-            addFactInstanceOf(isTrue, (InstanceOfNode) condition, anchor);
-        } else if (condition instanceof IsNullNode) {
-            IsNullNode nullCheck = (IsNullNode) condition;
-            addNullness(isTrue, nullCheck.getValue(), anchor);
-        } else if (condition instanceof ObjectEqualsNode) {
-            addFactObjectEqualsNode(isTrue, (ObjectEqualsNode) condition, anchor);
-        } else {
-            addFactPrimordial(condition, isTrue ? trueFacts : falseFacts, anchor);
-        }
-        assert repOK();
-    }
-
-    /**
-     * An instanceof hint is tracked differently depending on whether it's an interface-test or not
-     * (because type-refinements currently lacks the ability to track interface types).
-     *
-     */
-    private void addFactInstanceOf(boolean isTrue, InstanceOfNode instanceOf, GuardingNode anchor) {
-        ValueNode object = instanceOf.getValue();
-        if (isTrue) {
-            if (knownNotToPassInstanceOf(object, instanceOf.type())) {
-                impossiblePath();
-                return;
-            }
-            addNullness(false, object, anchor);
-            if (instanceOf.type().isInterface()) {
-                if (!knownToConform(object, instanceOf.type())) {
-                    addFactPrimordial(instanceOf, trueFacts, anchor);
-                }
-            } else {
-                trackIO(object, instanceOf.type(), anchor);
-            }
-        }
-    }
-
-    private void addFactObjectEqualsNode(boolean isTrue, ObjectEqualsNode equals, GuardingNode anchor) {
-        if (isDependencyTainted(equals.getX(), anchor)) {
-            return;
-        }
-        if (isDependencyTainted(equals.getY(), anchor)) {
-            return;
-        }
-        assert anchor instanceof FixedNode;
-        ValueNode x = GraphUtil.unproxify(equals.getX());
-        ValueNode y = GraphUtil.unproxify(equals.getY());
-        if (isTrue) {
-            if (isNull(x) && isNonNull(y)) {
-                impossiblePath();
-                return;
-            }
-            if (isNonNull(x) && isNull(y)) {
-                impossiblePath();
-                return;
-            }
-            if (isNull(x) || isNull(y)) {
-                metricObjectEqualsRegistered.increment();
-                addNullness(true, equals.getX(), anchor);
-                addNullness(true, equals.getY(), anchor);
-            } else if (isNonNull(x) || isNonNull(y)) {
-                metricObjectEqualsRegistered.increment();
-                addNullness(false, equals.getX(), anchor);
-                addNullness(false, equals.getY(), anchor);
-            }
-            Witness wx = typeInfo(x);
-            Witness wy = typeInfo(y);
-            if (wx == null && wy == null) {
-                return;
-            } else if (wx != null && wy != null) {
-                // tighten their type-hints, provided at least one available
-                // both witnesses may have seen == null, ie they may be NN witnesses
-                ResolvedJavaType best = FlowUtil.tighten(wx.type(), wy.type());
-                if (best != null) {
-                    assert !best.isInterface();
-                    // type tightening is enough, nullness already taken care of
-                    trackCC(equals.getX(), best, anchor);
-                    trackCC(equals.getY(), best, anchor);
-                }
-            } else if (wx == null) {
-                typeRefinements.put(x, new Witness(wy));
-            } else if (wy == null) {
-                typeRefinements.put(y, new Witness(wx));
-            }
-        } else {
-            if (isNull(x) && !isNonNull(y)) {
-                metricObjectEqualsRegistered.increment();
-                addNullness(false, equals.getY(), anchor);
-            } else if (!isNonNull(x) && isNull(y)) {
-                metricObjectEqualsRegistered.increment();
-                addNullness(false, equals.getX(), anchor);
-            }
-        }
-    }
-
-    /**
-     * Adds information about the nullness of a value. If isNull is true then the value is known to
-     * be null, otherwise the value is known to be non-null.
-     */
-    public void addNullness(boolean isNull, ValueNode value, GuardingNode anchor) {
-        if (isDependencyTainted(value, anchor)) {
-            return;
-        }
-        assert anchor instanceof FixedNode;
-        ValueNode scrutinee = GraphUtil.unproxify(value);
-        boolean wasNull = isNull(scrutinee);
-        boolean wasNonNull = isNonNull(scrutinee);
-        if (isNull) {
-            if (wasNonNull) {
-                impossiblePath();
-            } else {
-                metricNullnessRegistered.increment();
-                versionNr++;
-                Witness w = getOrElseAddTypeInfo(scrutinee);
-                w.trackDN(anchor);
-            }
-        } else {
-            if (wasNull) {
-                impossiblePath();
-            } else {
-                metricNullnessRegistered.increment();
-                trackNN(scrutinee, anchor);
-            }
-        }
-        assert repOK();
-    }
-
-    /**
-     *
-     * @return true iff `value` may lose dependency not covered by `anchor`.
-     */
-    public static boolean isDependencyTainted(ValueNode value, GuardingNode anchor) {
-        assert anchor instanceof FixedNode;
-        if (value instanceof ValueProxy) {
-            if (value instanceof GuardedNode) {
-                GuardedNode gn = (GuardedNode) value;
-                GuardingNode guardian = gn.getGuard();
-                if (guardian != null) {
-                    boolean isGuardedByFixed = guardian instanceof FixedNode;
-                    if (!isGuardedByFixed) {
-                        return true;
-                    }
-                }
-            }
-            // if (value instanceof GuardingNode) {
-            // return true;
-            // }
-            ValueProxy proxy = (ValueProxy) value;
-            return isDependencyTainted(proxy.getOriginalNode(), anchor);
-        }
-        return false;
-    }
-
-    public void clear() {
-        versionNr = 0;
-        isUnreachable = false;
-        typeRefinements.clear();
-        trueFacts.clear();
-        falseFacts.clear();
-    }
-
-    /**
-     * <p>
-     * If the argument is known null due to its stamp, there's no need to have an anchor for that
-     * fact and this method returns null.
-     * </p>
-     *
-     * <p>
-     * Otherwise, if an anchor is found it is returned, null otherwise.
-     * </p>
-     */
-    public GuardingNode nonTrivialNullAnchor(ValueNode object) {
-        assert FlowUtil.hasLegalObjectStamp(object);
-        if (StampTool.isPointerAlwaysNull(object)) {
-            return null;
-        }
-        ValueNode scrutinee = GraphUtil.unproxify(object);
-        Witness w = typeRefinements.get(scrutinee);
-        if (w != null && w.isNull()) {
-            return w.guard();
-        }
-        return null;
-    }
-
-    /**
-     * This method:
-     * <ul>
-     * <li>
-     * attempts to find an existing {@link com.oracle.graal.nodes.extended.GuardingNode} that
-     * implies the property stated by the arguments. If found, returns it as positive evidence.</li>
-     * <li>
-     * otherwise, if the property of interest is known not to hold, negative evidence is returned.</li>
-     * <li>
-     * otherwise, null is returned.</li>
-     * </ul>
-     */
-    public Evidence outcome(boolean isTrue, LogicNode cond) {
-
-        // attempt to find an anchor for the condition of interest, verbatim
-        if (isTrue) {
-            GuardingNode existingGuard = trueFacts.get(cond);
-            if (existingGuard != null) {
-                return new Evidence(existingGuard);
-            }
-            if (falseFacts.containsKey(cond)) {
-                return Evidence.COUNTEREXAMPLE;
-            }
-        } else {
-            GuardingNode existingGuard = falseFacts.get(cond);
-            if (existingGuard != null) {
-                return new Evidence(existingGuard);
-            }
-            if (trueFacts.containsKey(cond)) {
-                return Evidence.COUNTEREXAMPLE;
-            }
-        }
-
-        if (cond instanceof IsNullNode) {
-            return outcomeIsNullNode(isTrue, (IsNullNode) cond);
-        }
-
-        if (cond instanceof InstanceOfNode) {
-            return outcomeInstanceOfNode(isTrue, (InstanceOfNode) cond);
-        }
-
-        if (cond instanceof ShortCircuitOrNode) {
-            return outcomeShortCircuitOrNode(isTrue, (ShortCircuitOrNode) cond);
-        }
-
-        // can't produce evidence
-        return null;
-    }
-
-    /**
-     * Utility method for {@link #outcome(boolean, com.oracle.graal.nodes.LogicNode)}.
-     */
-    private Evidence outcomeIsNullNode(boolean isTrue, IsNullNode isNullNode) {
-        if (isTrue) {
-            // grab an anchor attesting nullness
-            final GuardingNode replacement = nonTrivialNullAnchor(isNullNode.getValue());
-            if (replacement != null) {
-                return new Evidence(replacement);
-            }
-            if (isNonNull(isNullNode.getValue())) {
-                return Evidence.COUNTEREXAMPLE;
-            }
-        } else {
-            // grab an anchor attesting non-nullness
-            final Witness w = typeInfo(isNullNode.getValue());
-            if (w != null && w.isNonNull()) {
-                return new Evidence(w.guard());
-            }
-            if (isNull(isNullNode.getValue())) {
-                return Evidence.COUNTEREXAMPLE;
-            }
-        }
-        // can't produce evidence
-        return null;
-    }
-
-    /**
-     * Utility method for {@link #outcome(boolean, com.oracle.graal.nodes.LogicNode)}.
-     */
-    private Evidence outcomeInstanceOfNode(boolean isTrue, InstanceOfNode iOf) {
-        final Witness w = typeInfo(iOf.getValue());
-        if (isTrue) {
-            if (isNull(iOf.getValue())) {
-                return Evidence.COUNTEREXAMPLE;
-            }
-            // grab an anchor attesting instanceof
-            if ((w != null) && (w.type() != null)) {
-                if (w.isNonNull()) {
-                    if (iOf.type().isAssignableFrom(w.type())) {
-                        return new Evidence(w.guard());
-                    }
-                }
-                if (State.knownNotToConform(w.type(), iOf.type())) {
-                    // null -> fails instanceof
-                    // non-null but non-conformant -> also fails instanceof
-                    return Evidence.COUNTEREXAMPLE;
-                }
-            }
-        } else {
-            // grab an anchor attesting not-instanceof
-            // (1 of 2) attempt determining nullness
-            final GuardingNode nullGuard = nonTrivialNullAnchor(iOf.getValue());
-            if (nullGuard != null) {
-                return new Evidence(nullGuard);
-            }
-            // (2 of 2) attempt determining known-not-to-conform
-            if (w != null && !w.cluelessAboutType()) {
-                if (State.knownNotToConform(w.type(), iOf.type())) {
-                    return new Evidence(w.guard());
-                }
-            }
-        }
-        // can't produce evidence
-        return null;
-    }
-
-    /**
-     * Utility method for {@link #outcome(boolean, com.oracle.graal.nodes.LogicNode)}.
-     */
-    private Evidence outcomeShortCircuitOrNode(boolean isTrue, ShortCircuitOrNode orNode) {
-        if (!isTrue) {
-            // too tricky to reason about
-            return null;
-        }
-        CastCheckExtractor cce = CastCheckExtractor.extract(orNode);
-        if (cce != null) {
-            // grab an anchor attesting check-cast
-            Witness w = typeInfo(cce.subject);
-            if (w != null && w.type() != null) {
-                if (cce.type.isAssignableFrom(w.type())) {
-                    return new Evidence(w.guard());
-                }
-                if (isNonNull(cce.subject) && State.knownNotToConform(w.type(), cce.type)) {
-                    return Evidence.COUNTEREXAMPLE;
-                }
-            }
-        }
-        // search for positive-evidence for the first or-input
-        Evidence evidenceX = outcome(!orNode.isXNegated(), orNode.getX());
-        if (evidenceX != null && evidenceX.isPositive()) {
-            return evidenceX;
-        }
-        // search for positive-evidence for the second or-input
-        Evidence evidenceY = outcome(!orNode.isYNegated(), orNode.getY());
-        if (evidenceY != null && evidenceY.isPositive()) {
-            return evidenceY;
-        }
-        // check for contradictions on both or-inputs
-        if (evidenceX != null && evidenceY != null) {
-            assert evidenceX.isNegative() && evidenceY.isNegative();
-            return Evidence.COUNTEREXAMPLE;
-        }
-        // can't produce evidence
-        return null;
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Witness.java	Fri Jan 23 22:00:55 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,526 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common.cfs;
-
-import com.oracle.graal.api.meta.ResolvedJavaType;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.GuardingNode;
-import com.oracle.graal.compiler.common.type.ObjectStamp;
-
-/**
- * <p>
- * A witness progressively tracks more detailed properties about an object value (the scrutinee);
- * the properties in question comprise whether the scrutinee has been observed:
- *
- * <ul>
- * <li>as non-null,</li>
- * <li>in a successful checkcast, or</li>
- * <li>in a successful instanceof.</li>
- * </ul>
- * </p>
- *
- * <p>
- * A witness is updated only when doing so increases the information content of the witness. For
- * example, upon visiting a {@link com.oracle.graal.nodes.java.CheckCastNode CheckCastNode} the
- * witness gets a chance to become updated.
- * </p>
- *
- * <p>
- * Therefore, at any given time, a witness represents the most detailed knowledge available so far
- * about the scrutinee, which is the knowledge most relevant for upcoming program-points.
- * </p>
- *
- * <p>
- * The availability of witnesses about both non-nullness and checkcast (for a given scrutinee)
- * promotes to an instanceof-style witness . The "levels" of knowledge a witness may exhibit are
- * captured by {@link com.oracle.graal.phases.common.cfs.Witness.LEVEL}. For conciseness, the
- * following query methods are available for a {@link com.oracle.graal.phases.common.cfs.Witness}:
- * <ul>
- * <li>{@link #atNonNull()}</li>
- * <li>{@link #atCheckCast()}</li>
- * <li>{@link #atInstanceOf()}</li>
- * </ul>
- * </p>
- *
- * <p>
- * Only non-interface object types (ie, class and array types) are tracked. Small extensions are
- * required to track interfaces, extensions that might be added after the current scheme proves
- * itself.
- * </p>
- *
- * <p>
- * Some useful facts about the Statechart implemented by {@link Witness Witness}:
- *
- * <ul>
- * <li>the start-state is "clueless"</li>
- * <li>
- * A self-transition via trackCC from whichever the current state is to itself, without information
- * gain, is always possible. Just give {@link Object java.lang.Object} as observed type.</li>
- * </ul>
- * </p>
- *
- */
-public class Witness implements Cloneable {
-
-    private static enum LEVEL {
-        CLUELESS,
-        NN,
-        CC,
-        IO,
-        DN
-    }
-
-    private boolean atNonNull() {
-        return level == LEVEL.NN;
-    }
-
-    private boolean atCheckCast() {
-        return level == LEVEL.CC;
-    }
-
-    private boolean atInstanceOf() {
-        return level == LEVEL.IO;
-    }
-
-    private boolean atDefinitelyNull() {
-        return level == LEVEL.DN;
-    }
-
-    private void transition(LEVEL to, GuardingNode newAnchor) {
-        this.level = to;
-        this.gn = newAnchor;
-        assert repOK();
-    }
-
-    public Witness() {
-    }
-
-    public Witness(Witness other) {
-        level = other.level;
-        seen = other.seen;
-        gn = other.gn;
-    }
-
-    /**
-     * Counterpart to {@link #asStamp()}.
-     */
-    public Witness(ObjectStamp stamp, GuardingNode anchor) {
-        assert stamp.isLegal();
-        assert anchor != null;
-        if (stamp.alwaysNull()) {
-            // seen left null
-            transition(LEVEL.DN, anchor);
-        } else {
-            boolean isNonIface = (stamp.type() != null && !stamp.type().isInterface());
-            if (stamp.nonNull()) {
-                if (isNonIface) {
-                    seen = stamp.type();
-                    transition(LEVEL.IO, anchor);
-                } else {
-                    seen = null;
-                    transition(LEVEL.NN, anchor);
-                }
-            } else {
-                if (isNonIface) {
-                    seen = stamp.type();
-                    transition(LEVEL.CC, anchor);
-                } else {
-                    seen = null;
-                    transition(LEVEL.CLUELESS, null);
-                    assert clueless();
-                }
-            }
-        }
-        assert repOK();
-    }
-
-    public boolean isNonNull() {
-        return atNonNull() || atInstanceOf();
-    }
-
-    public boolean isNull() {
-        return atDefinitelyNull();
-    }
-
-    /**
-     * The most precise type known so far about the scrutinee. (Please notice that nothing can be
-     * deduced about the non-nullness-status of the scrutinee from invoking this method alone).
-     */
-    public ResolvedJavaType type() {
-        return seen;
-    }
-
-    public ObjectStamp asStamp() {
-        boolean isKnownExact = (seen != null && seen.equals(seen.asExactType()));
-        return new ObjectStamp(seen, isKnownExact, isNonNull(), isNull());
-    }
-
-    private LEVEL level = LEVEL.CLUELESS;
-    private ResolvedJavaType seen = null;
-
-    /**
-     * Evidence (ie, a {@link com.oracle.graal.nodes.extended.GuardingNode}) attesting to the status
-     * reported by this witness.
-     *
-     * May be one of:
-     *
-     * <ul>
-     * <li>
-     * {@link com.oracle.graal.nodes.BeginNode BeginNode},</li>
-     * <li>
-     * {@link com.oracle.graal.nodes.LoopExitNode LoopExitNode},</li>
-     * <li>
-     * {@link com.oracle.graal.nodes.FixedGuardNode FixedGuardNode}</li>
-     * <li>{@link com.oracle.graal.nodes.MergeNode MergeNode}, resulting from merging two witnesses
-     * with different values for this anchor</li>
-     * </ul>
-     *
-     * <p>
-     * An {@link com.oracle.graal.nodes.calc.ObjectEqualsNode ObjectEqualsNode} test results in the
-     * more-clueless of both scrutinees having its witness upgraded to that of the other (both
-     * scrutinees share the same {@link Witness Witness} instance from then on). For this reason,
-     * this field may also hold the anchors associated to an
-     * {@link com.oracle.graal.nodes.calc.ObjectEqualsNode ObjectEqualsNode} occurrence, ie nodes
-     * that can serve as {@link com.oracle.graal.nodes.extended.GuardingNode GuardingNode} for the
-     * purposes of building a {@link com.oracle.graal.nodes.PiNode PiNode}.
-     * </p>
-     *
-     */
-    private GuardingNode gn = null;
-
-    /**
-     * Invariants of this class:
-     * <ul>
-     * <li>All fields holding null is ok, the hallmark of a {@link #clueless() clueless} witness.
-     * Another way for a witness to be clueless is by recording <code>java.lang.Object</code> as the
-     * seen type and nothing more.</li>
-     * <li>{@link #seen seen} may be null as long as the only hint being recorded is non-nullness</li>
-     * <li>A non-null value for {@link #seen seen} can't be tracked with NN, that combination
-     * amounts to IO and is tracked as such</li>
-     * <li>At most one of NN, CC, IO may be tracked at any given time</li>
-     * <li>A non-null CC or a non-null IO force {@link #seen seen} to be non-null</li>
-     * <li>{@link #seen seen} must be null or denote a non-interface reference type (ie, either a
-     * class-type or an array-type)</li>
-     * </ul>
-     */
-    private boolean repOK() {
-        if (clueless()) {
-            assert level == LEVEL.CLUELESS;
-            return true;
-        }
-        if (atNonNull() || atDefinitelyNull()) {
-            assert seen == null;
-        }
-        if (seen != null) {
-            assert !seen.isInterface();
-            assert !seen.isPrimitive();
-        }
-        assert gn instanceof BeginNode || gn instanceof LoopExitNode || gn instanceof MergeNode || gn instanceof FixedGuardNode;
-        return true;
-    }
-
-    /**
-     * Helper method for readability in complex conditions.
-     */
-    public boolean clueless() {
-        return cluelessAboutType() && cluelessAboutNullity();
-    }
-
-    /**
-     * Helper method for readability in complex conditions.
-     */
-    public boolean cluelessAboutType() {
-        // TODO also clueless when `seen` is `java.lang.Object`
-        return seen == null;
-    }
-
-    /**
-     * Helper method for readability in complex conditions.
-     */
-    public boolean cluelessAboutNullity() {
-        return !atNonNull() && !atInstanceOf() && !atDefinitelyNull();
-    }
-
-    /**
-     * Whether this {@link Witness Witness} tracks information strictly more precise than that in
-     * the given {@link com.oracle.graal.compiler.common.type.ObjectStamp}.
-     */
-    boolean knowsBetterThan(ObjectStamp other) {
-        return FlowUtil.isMorePrecise(asStamp(), other);
-    }
-
-    /**
-     * Whether this {@link Witness Witness} tracks information strictly more precise than that in
-     * the {@link com.oracle.graal.compiler.common.type.ObjectStamp} of the given argument.
-     */
-    boolean knowsBetterThan(ValueNode other) {
-        return knowsBetterThan((ObjectStamp) other.stamp());
-    }
-
-    /**
-     * Porcelain method for internal use only, invoked upon a Facade method being notified about
-     * checkcast or instanceof.
-     *
-     * @return whether the state was updated (iff the observation adds any new information)
-     */
-    private boolean refinesSeenType(ResolvedJavaType observed) {
-        if (isNull()) {
-            return false;
-        }
-        if (cluelessAboutType() || FlowUtil.isMorePrecise(observed, seen)) {
-            seen = observed;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Updates this {@link Witness Witness} to account for an observation about the scrutinee being
-     * non-null. In case instanceof was observed,
-     * {@link #trackIO(com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode)
-     * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead
-     *
-     * @return whether this {@link Witness Witness} was updated (iff the observation adds any new
-     *         information)
-     */
-    public boolean trackNN(GuardingNode anchor) {
-        assert repOK();
-        assert !isNull();
-        try {
-            if (atInstanceOf()) {
-                return false;
-            }
-            if (atCheckCast()) {
-                transition(LEVEL.IO, anchor);
-                return true;
-            }
-            if (!atNonNull()) {
-                transition(LEVEL.NN, anchor);
-                return true;
-            }
-            return false;
-        } finally {
-            assert repOK();
-        }
-    }
-
-    /**
-     * Updates this {@link Witness Witness} to account for an observation about the scrutinee being
-     * null.
-     *
-     * @return whether this {@link Witness Witness} was updated (iff the observation adds any new
-     *         information)
-     */
-    public boolean trackDN(GuardingNode anchor) {
-        assert repOK();
-        assert !isNonNull();
-        try {
-            if (atDefinitelyNull()) {
-                return false;
-            }
-            assert level == LEVEL.CLUELESS || atCheckCast();
-            seen = null;
-            transition(LEVEL.DN, anchor);
-            return true;
-        } finally {
-            assert repOK();
-        }
-    }
-
-    /**
-     * Updates this {@link Witness Witness} to account for an observation about the scrutinee
-     * conforming to the provided type. In case instanceof was observed,
-     * {@link #trackIO(com.oracle.graal.api.meta.ResolvedJavaType, com.oracle.graal.nodes.extended.GuardingNode)
-     * <code>trackIO(ResolvedJavaType, GuardingNode)</code>} should be invoked instead.
-     *
-     * @return true iff information was gained.
-     */
-    public boolean trackCC(ResolvedJavaType observed, GuardingNode anchor) {
-        assert !observed.isInterface();
-        assert anchor != null;
-        assert repOK();
-        try {
-            boolean anchorObsolete = refinesSeenType(observed);
-            if (atInstanceOf()) {
-                /*
-                 * Statechart: self-transition at IO, potential information gain.
-                 */
-                if (anchorObsolete) {
-                    transition(LEVEL.IO, anchor);
-                    return true;
-                }
-                return false;
-            }
-            if (anchorObsolete) {
-                if (!atNonNull()) {
-                    /* Statechart: transition from clueless to CC. */
-                    transition(LEVEL.CC, anchor);
-                    return true;
-                } else {
-                    /* Statechart: transition from NN to IO. */
-                    transition(LEVEL.IO, anchor);
-                    return true;
-                }
-            }
-            /*
-             * Statechart: self-transition from whichever the current state is to itself, without
-             * information gain.
-             */
-            return false;
-        } finally {
-            assert repOK();
-        }
-    }
-
-    /**
-     * Updates this {@link Witness Witness} to account for an observation about the non-null
-     * scrutinee conforming to a type.
-     *
-     * @return whether this {@link Witness Witness} was updated (iff the observation adds any new
-     *         information)
-     */
-    public boolean trackIO(ResolvedJavaType observed, GuardingNode anchor) {
-        assert repOK();
-        assert !isNull();
-        try {
-            boolean gotMorePreciseType = refinesSeenType(observed);
-            if (!atInstanceOf() || gotMorePreciseType) {
-                transition(LEVEL.IO, anchor);
-                return true;
-            }
-            return gotMorePreciseType;
-        } finally {
-            assert repOK();
-        }
-    }
-
-    /**
-     * Shallow cloning is enough because what's reachable from {@link Witness} is primitive or used
-     * read-only when merging states.
-     */
-    @Override
-    public Witness clone() {
-        return new Witness(this);
-    }
-
-    /**
-     * @return null for a clueless method, non-null otherwise.
-     */
-    GuardingNode guard() {
-        return gn;
-    }
-
-    /**
-     * Merges another state into this one, by mutating this object, the other is left as is.
-     */
-    public void merge(Witness that, MergeNode merge) {
-        assert this.repOK();
-        assert that.repOK();
-
-        if (clueless()) {
-            return;
-        }
-
-        // preserve guarding node only if matches other, otherwise settle on `merge`
-        final GuardingNode resultGuard = (guard() == that.guard()) ? guard() : merge;
-
-        if (isNull()) {
-            switch (that.level) {
-                case CLUELESS:
-                case NN:
-                    // lose is-null status, gain nothing
-                    level = LEVEL.CLUELESS;
-                    seen = null;
-                    break;
-                case CC:
-                case IO:
-                    // demote to check-cast
-                    level = LEVEL.CC;
-                    seen = that.seen;
-                    break;
-                case DN:
-                    // keep is-null status
-            }
-            gn = resultGuard;
-            return;
-        }
-
-        if (that.isNull()) {
-            /*
-             * Same decisions as above (based on this-being-null and that-level) are now made based
-             * on (that-being-null and this-level). Because merge is commutative.
-             */
-            switch (level) {
-                case CLUELESS:
-                case NN:
-                    // lose is-null status, gain nothing
-                    level = LEVEL.CLUELESS;
-                    seen = null;
-                    break;
-                case CC:
-                    break;
-                case IO:
-                    // demote to check-cast
-                    level = LEVEL.CC;
-                    // keep this.seen as-is
-                    break;
-                case DN:
-                    // keep is-null status
-            }
-            gn = resultGuard;
-            return;
-        }
-
-        // by now we know neither this nor that are known-to-be-null
-        assert !isNull() && !that.isNull();
-
-        // umbrella type over the observations from both witnesses
-        ResolvedJavaType newSeen = (seen == null || that.seen == null) ? null : FlowUtil.widen(seen, that.seen);
-
-        /*
-         * guarantee on (both conformance and non-nullness) required from each input in order for
-         * the result to be able to offer such guarantee
-         */
-        final boolean resultIO = atInstanceOf() && that.atInstanceOf();
-        /* failing that, attempt to rescue type-conformance */
-        final boolean resultCC = !resultIO && (!cluelessAboutType() && !that.cluelessAboutType());
-        /* if all else fails, attempt to rescue non-nullness */
-        final boolean resultNN = !resultIO && !resultCC && (isNonNull() && that.isNonNull());
-
-        seen = newSeen;
-        level = resultIO ? LEVEL.IO : resultCC ? LEVEL.CC : resultNN ? LEVEL.NN : LEVEL.CLUELESS;
-        gn = resultGuard;
-
-        assert repOK();
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append(cluelessAboutType() ? "seen=?" : "seen=" + seen);
-        sb.append(";");
-        sb.append("gn=" + gn);
-        return sb.toString();
-    }
-
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java	Fri Jan 23 22:00:55 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java	Fri Jan 23 22:13:55 2015 +0100
@@ -33,7 +33,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.common.inlining.*;
 import com.oracle.graal.phases.graph.*;
 import com.oracle.graal.phases.tiers.*;
@@ -90,7 +89,6 @@
         try (Debug.Scope s = Debug.scope("InlineGraph", graph)) {
 
             ArrayList<Node> parameterUsages = replaceParamsWithMoreInformativeArguments(invoke, context);
-            parameterUsages = rewireParamsForDuplicateArguments(invoke, parameterUsages);
             if (parameterUsages != null && OptCanonicalizer.getValue()) {
                 assert !parameterUsages.isEmpty() : "The caller didn't have more information about arguments after all";
                 canonicalizer.applyIncremental(graph, context, parameterUsages);
@@ -107,48 +105,6 @@
         }
     }
 
-    /**
-     * This method detects duplicate arguments (therefore corresponding to different
-     * {@link ParameterNode}s) and updates the graph to make all of their usages refer to the first
-     * one of them.
-     *
-     * @return a (possibly updated) list of nodes for incremental canonicalization.
-     */
-    private ArrayList<Node> rewireParamsForDuplicateArguments(Invoke invoke, ArrayList<Node> parameterUsages0) {
-        ArrayList<Node> parameterUsages = parameterUsages0;
-        ArrayList<ParameterNode> params = new ArrayList<>();
-        List<ValueNode> originalArgs = invoke.callTarget().arguments();
-        List<ValueNode> argsInEffect = new ArrayList<>();
-        // some param-nodes might have been deleted by replaceParamsWithMoreInformativeArguments()
-        // that's why we obtain an up-to-date list
-        for (ParameterNode p : graph.getNodes(ParameterNode.class)) {
-            if (!FlowUtil.lacksUsages(p)) {
-                params.add(p);
-                argsInEffect.add(originalArgs.get(p.index()));
-            }
-        }
-        // argsInEffect and params paired by position
-        assert params.size() == argsInEffect.size();
-        int argIdx = 0;
-        for (ValueNode arg : argsInEffect) {
-            int firstOccurrrence = argsInEffect.indexOf(arg);
-            assert firstOccurrrence >= 0;
-            if (firstOccurrrence < argIdx) {
-                ParameterNode survivingParam = params.get(firstOccurrrence);
-                assert survivingParam.isAlive();
-                ParameterNode duplicateParam = params.get(argIdx);
-                assert duplicateParam.isAlive();
-                assert survivingParam != duplicateParam;
-                assert !isArgMoreInformativeThanParam(arg, survivingParam);
-                parameterUsages = trackParameterUsages(duplicateParam, parameterUsages);
-                // replaceFloating() deletes the duplicate param, unlike replaceAtUsages()
-                graph.replaceFloating(duplicateParam, survivingParam);
-            }
-            argIdx++;
-        }
-        return parameterUsages;
-    }
-
     private static boolean isArgMoreInformativeThanParam(ValueNode arg, ParameterNode param) {
         return arg.isConstant() || canStampBeImproved(arg, param);
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Fri Jan 23 22:00:55 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/IterativeInliningPhase.java	Fri Jan 23 22:13:55 2015 +0100
@@ -32,7 +32,6 @@
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
-import com.oracle.graal.phases.common.cfs.*;
 import com.oracle.graal.phases.common.inlining.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -73,14 +72,9 @@
 
                 new DeadCodeEliminationPhase(Optional).apply(graph);
 
-                boolean reduceOrEliminate = FlowSensitiveReduction.getValue() || ConditionalElimination.getValue();
-                if (reduceOrEliminate && OptCanonicalizer.getValue()) {
+                if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
                     canonicalizer.apply(graph, context);
-                    if (FlowSensitiveReduction.getValue()) {
-                        new IterativeFlowSensitiveReductionPhase(canonicalizer).apply(graph, context);
-                    } else {
-                        new IterativeConditionalEliminationPhase(canonicalizer).apply(graph, context);
-                    }
+                    new IterativeConditionalEliminationPhase(canonicalizer).apply(graph, context);
                 }
                 if (!progress) {
                     break;