changeset 18995:a2cb19764970

Rename MergeNode to AbstractMergeNode.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 28 Jan 2015 01:04:20 +0100
parents 8b4ef818169c
children 46c2e70d54ad
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ValueAnchorCleanupPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/SinglePassNodeIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java
diffstat 59 files changed, 405 insertions(+), 405 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SimpleCFGTest.java	Wed Jan 28 01:04:20 2015 +0100
@@ -53,7 +53,7 @@
         IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5));
         graph.start().setNext(ifNode);
 
-        MergeNode merge = graph.add(new MergeNode());
+        AbstractMergeNode merge = graph.add(new AbstractMergeNode());
         merge.addForwardEnd(trueEnd);
         merge.addForwardEnd(falseEnd);
         ReturnNode returnNode = graph.add(new ReturnNode(null));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Wed Jan 28 01:04:20 2015 +0100
@@ -222,8 +222,8 @@
             TTY.print(" " + input.toString(Verbosity.Id));
         }
         TTY.println(")");
-        if (node instanceof MergeNode) {
-            for (PhiNode phi : ((MergeNode) node).phis()) {
+        if (node instanceof AbstractMergeNode) {
+            for (PhiNode phi : ((AbstractMergeNode) node).phis()) {
                 outputNode(phi);
             }
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Wed Jan 28 01:04:20 2015 +0100
@@ -177,7 +177,7 @@
     @SafeVarargs
     protected final void testPartialEscapeAnalysis(final String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) {
         prepareGraph(snippet, false);
-        for (MergeNode merge : graph.getNodes(MergeNode.class)) {
+        for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class)) {
             merge.setStateAfter(null);
         }
         new DeadCodeEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Jan 28 01:04:20 2015 +0100
@@ -331,7 +331,7 @@
     }
 
     @Override
-    public void visitMerge(MergeNode x) {
+    public void visitMerge(AbstractMergeNode x) {
     }
 
     @Override
@@ -346,7 +346,7 @@
     public void visitLoopEnd(LoopEndNode x) {
     }
 
-    private void moveToPhi(MergeNode merge, AbstractEndNode pred) {
+    private void moveToPhi(AbstractMergeNode merge, AbstractEndNode pred) {
         if (Options.TraceLIRGeneratorLevel.getValue() >= 1) {
             TTY.println("MOVE TO PHI from " + pred + " to " + merge);
         }
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java	Wed Jan 28 01:04:20 2015 +0100
@@ -693,7 +693,7 @@
                 }
 
                 @Override
-                protected Boolean merge(MergeNode merge, List<Boolean> states) {
+                protected Boolean merge(AbstractMergeNode merge, List<Boolean> states) {
                     return false;
                 }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/ComputeLoopFrequenciesClosure.java	Wed Jan 28 01:04:20 2015 +0100
@@ -45,7 +45,7 @@
     }
 
     @Override
-    protected Double merge(MergeNode merge, List<Double> states) {
+    protected Double merge(AbstractMergeNode merge, List<Double> states) {
         // a merge has the sum of all predecessor probabilities
         return states.stream().collect(Collectors.summingDouble(d -> d));
     }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -1077,7 +1077,7 @@
                 assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
                 assert block.firstInstruction.next() == null : "bytecodes already parsed for block";
 
-                if (block.firstInstruction instanceof AbstractBeginNode && !(block.firstInstruction instanceof MergeNode)) {
+                if (block.firstInstruction instanceof AbstractBeginNode && !(block.firstInstruction instanceof AbstractMergeNode)) {
                     /*
                      * This is the second time we see this block. Create the actual MergeNode and
                      * the End Node for the already existing edge. For simplicity, we leave the
@@ -1088,7 +1088,7 @@
                     // The EndNode for the already existing edge.
                     AbstractEndNode end = currentGraph.add(new EndNode());
                     // The MergeNode that replaces the placeholder.
-                    MergeNode mergeNode = currentGraph.add(new MergeNode());
+                    AbstractMergeNode mergeNode = currentGraph.add(new AbstractMergeNode());
                     FixedNode next = placeholder.next();
 
                     if (placeholder.predecessor() instanceof ControlSplitNode) {
@@ -1104,7 +1104,7 @@
                     block.firstInstruction = mergeNode;
                 }
 
-                MergeNode mergeNode = (MergeNode) block.firstInstruction;
+                AbstractMergeNode mergeNode = (AbstractMergeNode) block.firstInstruction;
 
                 // The EndNode for the newly merged edge.
                 AbstractEndNode newEnd = currentGraph.add(new EndNode());
@@ -1151,12 +1151,12 @@
                     parser.setCurrentFrameState(frameState);
                     currentBlock = block;
 
-                    if (lastInstr instanceof MergeNode) {
+                    if (lastInstr instanceof AbstractMergeNode) {
                         int bci = block.startBci;
                         if (block instanceof ExceptionDispatchBlock) {
                             bci = ((ExceptionDispatchBlock) block).deoptBci;
                         }
-                        ((MergeNode) lastInstr).setStateAfter(frameState.create(bci));
+                        ((AbstractMergeNode) lastInstr).setStateAfter(frameState.create(bci));
                     }
 
                     if (block == returnBlock) {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java	Wed Jan 28 01:04:20 2015 +0100
@@ -193,7 +193,7 @@
         return true;
     }
 
-    public void merge(MergeNode block, HIRFrameStateBuilder other) {
+    public void merge(AbstractMergeNode block, HIRFrameStateBuilder other) {
         assert isCompatibleWith(other);
 
         for (int i = 0; i < localsSize(); i++) {
@@ -208,7 +208,7 @@
         }
     }
 
-    private ValueNode merge(ValueNode currentValue, ValueNode otherValue, MergeNode block) {
+    private ValueNode merge(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) {
         if (currentValue == null || currentValue.isDeleted()) {
             return null;
 
@@ -318,7 +318,7 @@
         }
     }
 
-    private ValuePhiNode createLoopPhi(MergeNode block, ValueNode value) {
+    private ValuePhiNode createLoopPhi(AbstractMergeNode block, ValueNode value) {
         if (value == null) {
             return null;
         }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java	Wed Jan 28 01:04:20 2015 +0100
@@ -312,7 +312,7 @@
             if (newEarlyExit == null) {
                 continue;
             }
-            MergeNode merge = graph.add(new MergeNode());
+            AbstractMergeNode merge = graph.add(new AbstractMergeNode());
             AbstractEndNode originalEnd = graph.add(new EndNode());
             AbstractEndNode newEnd = graph.add(new EndNode());
             merge.addForwardEnd(originalEnd);
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java	Wed Jan 28 01:04:20 2015 +0100
@@ -184,7 +184,7 @@
         // TODO (gd) ?
     }
 
-    private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, MergeNode merge) {
+    private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, AbstractMergeNode merge) {
         PhiNode ret;
         if (phi instanceof ValuePhiNode) {
             ret = new ValuePhiNode(phi.stamp(), merge);
@@ -315,7 +315,7 @@
             end.safeDelete();
         } else {
             assert endsToMerge.size() > 1;
-            MergeNode newExitMerge = graph.add(new MergeNode());
+            AbstractMergeNode newExitMerge = graph.add(new AbstractMergeNode());
             newExit = newExitMerge;
             FrameState state = loopBegin.stateAfter();
             FrameState duplicateState = null;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -97,7 +97,7 @@
 
     @Override
     public boolean verify() {
-        assertTrue(predecessor() != null || this == graph().start() || this instanceof MergeNode, "begin nodes must be connected");
+        assertTrue(predecessor() != null || this == graph().start() || this instanceof AbstractMergeNode, "begin nodes must be connected");
         return super.verify();
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractEndNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -41,8 +41,8 @@
         gen.visitEndNode(this);
     }
 
-    public MergeNode merge() {
-        return (MergeNode) usages().first();
+    public AbstractMergeNode merge() {
+        return (AbstractMergeNode) usages().first();
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMergeNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes;
+
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
+
+/**
+ * Denotes the merging of multiple control-flow paths.
+ */
+@NodeInfo(allowedUsageTypes = {InputType.Association})
+public class AbstractMergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable {
+    public AbstractMergeNode() {
+    }
+
+    @Input(InputType.Association) protected NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        gen.visitMerge(this);
+    }
+
+    public int forwardEndIndex(AbstractEndNode end) {
+        return ends.indexOf(end);
+    }
+
+    public void addForwardEnd(AbstractEndNode end) {
+        ends.add(end);
+    }
+
+    public int forwardEndCount() {
+        return ends.size();
+    }
+
+    public AbstractEndNode forwardEndAt(int index) {
+        return ends.get(index);
+    }
+
+    @Override
+    public NodeIterable<AbstractEndNode> cfgPredecessors() {
+        return ends;
+    }
+
+    /**
+     * Determines if a given node is a phi whose {@linkplain PhiNode#merge() merge} is this node.
+     *
+     * @param value the instruction to test
+     * @return {@code true} if {@code value} is a phi and its merge is {@code this}
+     */
+    public boolean isPhiAtMerge(Node value) {
+        return value instanceof PhiNode && ((PhiNode) value).merge() == this;
+    }
+
+    /**
+     * Removes the given end from the merge, along with the entries corresponding to this end in the
+     * phis connected to the merge.
+     *
+     * @param pred the end to remove
+     */
+    public void removeEnd(AbstractEndNode pred) {
+        int predIndex = phiPredecessorIndex(pred);
+        assert predIndex != -1;
+        deleteEnd(pred);
+        for (PhiNode phi : phis().snapshot()) {
+            if (phi.isDeleted()) {
+                continue;
+            }
+            ValueNode removedValue = phi.valueAt(predIndex);
+            phi.removeInput(predIndex);
+            if (removedValue != null && removedValue.isAlive() && removedValue.hasNoUsages() && GraphUtil.isFloatingNode().apply(removedValue)) {
+                GraphUtil.killWithUnusedFloatingInputs(removedValue);
+            }
+        }
+    }
+
+    protected void deleteEnd(AbstractEndNode end) {
+        ends.remove(end);
+    }
+
+    public void clearEnds() {
+        ends.clear();
+    }
+
+    public NodeInputList<AbstractEndNode> forwardEnds() {
+        return ends;
+    }
+
+    public int phiPredecessorCount() {
+        return forwardEndCount();
+    }
+
+    public int phiPredecessorIndex(AbstractEndNode pred) {
+        return forwardEndIndex(pred);
+    }
+
+    public AbstractEndNode phiPredecessorAt(int index) {
+        return forwardEndAt(index);
+    }
+
+    public NodeIterable<PhiNode> phis() {
+        return this.usages().filter(PhiNode.class).filter(this::isPhiAtMerge);
+    }
+
+    @Override
+    public NodeIterable<Node> anchored() {
+        return super.anchored().filter(n -> !isPhiAtMerge(n));
+    }
+
+    /**
+     * This simplify method can deal with a null value for tool, so that it can be used outside of
+     * canonicalization.
+     */
+    @Override
+    public void simplify(SimplifierTool tool) {
+        FixedNode currentNext = next();
+        if (currentNext instanceof AbstractEndNode) {
+            AbstractEndNode origLoopEnd = (AbstractEndNode) currentNext;
+            AbstractMergeNode merge = origLoopEnd.merge();
+            if (merge instanceof LoopBeginNode && !(origLoopEnd instanceof LoopEndNode)) {
+                return;
+            }
+            // in order to move anchored values to the other merge we would need to check if the
+            // anchors are used by phis of the other merge
+            if (this.anchored().isNotEmpty()) {
+                return;
+            }
+            if (merge.stateAfter() == null && this.stateAfter() != null) {
+                // We hold a state, but the succeeding merge does not => do not combine.
+                return;
+            }
+            for (PhiNode phi : phis()) {
+                if (phi.usages().filter(isNotA(VirtualState.class)).and(node -> !merge.isPhiAtMerge(node)).isNotEmpty()) {
+                    return;
+                }
+            }
+            Debug.log("Split %s into ends for %s.", this, merge);
+            int numEnds = this.forwardEndCount();
+            for (int i = 0; i < numEnds - 1; i++) {
+                AbstractEndNode end = forwardEndAt(numEnds - 1 - i);
+                if (tool != null) {
+                    tool.addToWorkList(end);
+                }
+                AbstractEndNode newEnd;
+                if (merge instanceof LoopBeginNode) {
+                    newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge));
+                } else {
+                    newEnd = graph().add(new EndNode());
+                    merge.addForwardEnd(newEnd);
+                }
+                for (PhiNode phi : merge.phis()) {
+                    ValueNode v = phi.valueAt(origLoopEnd);
+                    ValueNode newInput;
+                    if (isPhiAtMerge(v)) {
+                        PhiNode endPhi = (PhiNode) v;
+                        newInput = endPhi.valueAt(end);
+                    } else {
+                        newInput = v;
+                    }
+                    phi.addInput(newInput);
+                }
+                this.removeEnd(end);
+                end.replaceAtPredecessor(newEnd);
+                end.safeDelete();
+                if (tool != null) {
+                    tool.addToWorkList(newEnd.predecessor());
+                }
+            }
+            graph().reduceTrivialMerge(this);
+        } else if (currentNext instanceof ReturnNode) {
+            ReturnNode returnNode = (ReturnNode) currentNext;
+            if (anchored().isNotEmpty() || returnNode.getMemoryMap() != null) {
+                return;
+            }
+            List<PhiNode> phis = phis().snapshot();
+            for (PhiNode phi : phis) {
+                for (Node usage : phi.usages().filter(isNotA(FrameState.class))) {
+                    if (usage != returnNode) {
+                        return;
+                    }
+                }
+            }
+
+            ValuePhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (ValuePhiNode) returnNode.result();
+            List<AbstractEndNode> endNodes = forwardEnds().snapshot();
+            for (AbstractEndNode end : endNodes) {
+                ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end)));
+                if (tool != null) {
+                    tool.addToWorkList(end.predecessor());
+                }
+                end.replaceAtPredecessor(newReturn);
+            }
+            GraphUtil.killCFG(this);
+            for (AbstractEndNode end : endNodes) {
+                end.safeDelete();
+            }
+            for (PhiNode phi : phis) {
+                if (phi.isAlive() && phi.hasNoUsages()) {
+                    GraphUtil.killWithUnusedFloatingInputs(phi);
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -35,12 +35,12 @@
 
     @OptionalInput(InputType.Guard) NodeInputList<ValueNode> values;
 
-    public GuardPhiNode(MergeNode merge) {
+    public GuardPhiNode(AbstractMergeNode merge) {
         super(StampFactory.forVoid(), merge);
         this.values = new NodeInputList<>(this);
     }
 
-    public GuardPhiNode(MergeNode merge, ValueNode[] values) {
+    public GuardPhiNode(AbstractMergeNode merge, ValueNode[] values) {
         super(StampFactory.forVoid(), merge);
         this.values = new NodeInputList<>(this, values);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -496,7 +496,7 @@
         if (trueSuccessor().next() instanceof AbstractEndNode && falseSuccessor().next() instanceof AbstractEndNode) {
             AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next();
             AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next();
-            MergeNode merge = trueEnd.merge();
+            AbstractMergeNode merge = trueEnd.merge();
             if (merge == falseEnd.merge() && trueSuccessor().anchored().isEmpty() && falseSuccessor().anchored().isEmpty()) {
                 PhiNode singlePhi = null;
                 int distinct = 0;
@@ -648,10 +648,10 @@
      * @return true if a transformation was made, false otherwise
      */
     private boolean removeIntermediateMaterialization(SimplifierTool tool) {
-        if (!(predecessor() instanceof MergeNode) || predecessor() instanceof LoopBeginNode) {
+        if (!(predecessor() instanceof AbstractMergeNode) || predecessor() instanceof LoopBeginNode) {
             return false;
         }
-        MergeNode merge = (MergeNode) predecessor();
+        AbstractMergeNode merge = (AbstractMergeNode) predecessor();
 
         if (!(condition() instanceof CompareNode)) {
             return false;
@@ -784,8 +784,8 @@
                 } else {
                     throw new GraalInternalError("Illegal state");
                 }
-            } else if (node instanceof MergeNode && !(node instanceof LoopBeginNode)) {
-                for (AbstractEndNode endNode : ((MergeNode) node).cfgPredecessors()) {
+            } else if (node instanceof AbstractMergeNode && !(node instanceof LoopBeginNode)) {
+                for (AbstractEndNode endNode : ((AbstractMergeNode) node).cfgPredecessors()) {
                     propagateZeroProbability(endNode);
                 }
                 return;
@@ -797,8 +797,8 @@
     private static boolean checkFrameState(FixedNode start) {
         FixedNode node = start;
         while (true) {
-            if (node instanceof MergeNode) {
-                MergeNode mergeNode = (MergeNode) node;
+            if (node instanceof AbstractMergeNode) {
+                AbstractMergeNode mergeNode = (AbstractMergeNode) node;
                 if (mergeNode.stateAfter() == null) {
                     return false;
                 } else {
@@ -841,7 +841,7 @@
      * @param oldMerge the merge being removed
      * @param phiValues the values of the phi at the merge, keyed by the merge ends
      */
-    private void connectEnds(List<AbstractEndNode> ends, Map<AbstractEndNode, ValueNode> phiValues, AbstractBeginNode successor, MergeNode oldMerge, SimplifierTool tool) {
+    private void connectEnds(List<AbstractEndNode> ends, Map<AbstractEndNode, ValueNode> phiValues, AbstractBeginNode successor, AbstractMergeNode oldMerge, SimplifierTool tool) {
         if (!ends.isEmpty()) {
             if (ends.size() == 1) {
                 AbstractEndNode end = ends.get(0);
@@ -851,7 +851,7 @@
             } else {
                 // Need a new phi in case the frame state is used by more than the merge being
                 // removed
-                MergeNode newMerge = graph().add(new MergeNode());
+                AbstractMergeNode newMerge = graph().add(new AbstractMergeNode());
                 PhiNode oldPhi = (PhiNode) oldMerge.usages().first();
                 PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(oldPhi.stamp(), newMerge));
 
@@ -881,7 +881,7 @@
      * @return null if {@code node} is neither a {@link ConstantNode} nor a {@link PhiNode} whose
      *         input values are all constants
      */
-    public static Constant[] constantValues(ValueNode node, MergeNode merge, boolean allowNull) {
+    public static Constant[] constantValues(ValueNode node, AbstractMergeNode merge, boolean allowNull) {
         if (node.isConstant()) {
             JavaConstant[] result = new JavaConstant[merge.forwardEndCount()];
             Arrays.fill(result, node.asConstant());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -37,7 +37,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo
-public class LoopBeginNode extends MergeNode implements IterableNodeType, LIRLowerable {
+public class LoopBeginNode extends AbstractMergeNode implements IterableNodeType, LIRLowerable {
 
     protected double loopFrequency;
     protected int nextEndIndex;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -44,7 +44,7 @@
     }
 
     @Override
-    public MergeNode merge() {
+    public AbstractMergeNode merge() {
         return loopBegin();
     }
 
@@ -80,7 +80,7 @@
 
     /**
      * Returns the 0-based index of this loop end. This is <b>not</b> the index into {@link PhiNode}
-     * values at the loop begin. Use {@link MergeNode#phiPredecessorIndex(AbstractEndNode)} for this
+     * values at the loop begin. Use {@link AbstractMergeNode#phiPredecessorIndex(AbstractEndNode)} for this
      * purpose.
      *
      * @return The 0-based index of this loop end.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -37,13 +37,13 @@
     @Input(InputType.Memory) NodeInputList<ValueNode> values;
     protected final LocationIdentity locationIdentity;
 
-    public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity) {
+    public MemoryPhiNode(AbstractMergeNode merge, LocationIdentity locationIdentity) {
         super(StampFactory.forVoid(), merge);
         this.locationIdentity = locationIdentity;
         this.values = new NodeInputList<>(this);
     }
 
-    public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) {
+    public MemoryPhiNode(AbstractMergeNode merge, LocationIdentity locationIdentity, ValueNode[] values) {
         super(StampFactory.forVoid(), merge);
         this.locationIdentity = locationIdentity;
         this.values = new NodeInputList<>(this, values);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes;
-
-import static com.oracle.graal.graph.iterators.NodePredicates.*;
-
-import java.util.*;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.util.*;
-
-/**
- * Denotes the merging of multiple control-flow paths.
- */
-@NodeInfo(allowedUsageTypes = {InputType.Association})
-public class MergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable {
-    public MergeNode() {
-    }
-
-    @Input(InputType.Association) protected NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
-
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        gen.visitMerge(this);
-    }
-
-    public int forwardEndIndex(AbstractEndNode end) {
-        return ends.indexOf(end);
-    }
-
-    public void addForwardEnd(AbstractEndNode end) {
-        ends.add(end);
-    }
-
-    public int forwardEndCount() {
-        return ends.size();
-    }
-
-    public AbstractEndNode forwardEndAt(int index) {
-        return ends.get(index);
-    }
-
-    @Override
-    public NodeIterable<AbstractEndNode> cfgPredecessors() {
-        return ends;
-    }
-
-    /**
-     * Determines if a given node is a phi whose {@linkplain PhiNode#merge() merge} is this node.
-     *
-     * @param value the instruction to test
-     * @return {@code true} if {@code value} is a phi and its merge is {@code this}
-     */
-    public boolean isPhiAtMerge(Node value) {
-        return value instanceof PhiNode && ((PhiNode) value).merge() == this;
-    }
-
-    /**
-     * Removes the given end from the merge, along with the entries corresponding to this end in the
-     * phis connected to the merge.
-     *
-     * @param pred the end to remove
-     */
-    public void removeEnd(AbstractEndNode pred) {
-        int predIndex = phiPredecessorIndex(pred);
-        assert predIndex != -1;
-        deleteEnd(pred);
-        for (PhiNode phi : phis().snapshot()) {
-            if (phi.isDeleted()) {
-                continue;
-            }
-            ValueNode removedValue = phi.valueAt(predIndex);
-            phi.removeInput(predIndex);
-            if (removedValue != null && removedValue.isAlive() && removedValue.hasNoUsages() && GraphUtil.isFloatingNode().apply(removedValue)) {
-                GraphUtil.killWithUnusedFloatingInputs(removedValue);
-            }
-        }
-    }
-
-    protected void deleteEnd(AbstractEndNode end) {
-        ends.remove(end);
-    }
-
-    public void clearEnds() {
-        ends.clear();
-    }
-
-    public NodeInputList<AbstractEndNode> forwardEnds() {
-        return ends;
-    }
-
-    public int phiPredecessorCount() {
-        return forwardEndCount();
-    }
-
-    public int phiPredecessorIndex(AbstractEndNode pred) {
-        return forwardEndIndex(pred);
-    }
-
-    public AbstractEndNode phiPredecessorAt(int index) {
-        return forwardEndAt(index);
-    }
-
-    public NodeIterable<PhiNode> phis() {
-        return this.usages().filter(PhiNode.class).filter(this::isPhiAtMerge);
-    }
-
-    @Override
-    public NodeIterable<Node> anchored() {
-        return super.anchored().filter(n -> !isPhiAtMerge(n));
-    }
-
-    /**
-     * This simplify method can deal with a null value for tool, so that it can be used outside of
-     * canonicalization.
-     */
-    @Override
-    public void simplify(SimplifierTool tool) {
-        FixedNode currentNext = next();
-        if (currentNext instanceof AbstractEndNode) {
-            AbstractEndNode origLoopEnd = (AbstractEndNode) currentNext;
-            MergeNode merge = origLoopEnd.merge();
-            if (merge instanceof LoopBeginNode && !(origLoopEnd instanceof LoopEndNode)) {
-                return;
-            }
-            // in order to move anchored values to the other merge we would need to check if the
-            // anchors are used by phis of the other merge
-            if (this.anchored().isNotEmpty()) {
-                return;
-            }
-            if (merge.stateAfter() == null && this.stateAfter() != null) {
-                // We hold a state, but the succeeding merge does not => do not combine.
-                return;
-            }
-            for (PhiNode phi : phis()) {
-                if (phi.usages().filter(isNotA(VirtualState.class)).and(node -> !merge.isPhiAtMerge(node)).isNotEmpty()) {
-                    return;
-                }
-            }
-            Debug.log("Split %s into ends for %s.", this, merge);
-            int numEnds = this.forwardEndCount();
-            for (int i = 0; i < numEnds - 1; i++) {
-                AbstractEndNode end = forwardEndAt(numEnds - 1 - i);
-                if (tool != null) {
-                    tool.addToWorkList(end);
-                }
-                AbstractEndNode newEnd;
-                if (merge instanceof LoopBeginNode) {
-                    newEnd = graph().add(new LoopEndNode((LoopBeginNode) merge));
-                } else {
-                    newEnd = graph().add(new EndNode());
-                    merge.addForwardEnd(newEnd);
-                }
-                for (PhiNode phi : merge.phis()) {
-                    ValueNode v = phi.valueAt(origLoopEnd);
-                    ValueNode newInput;
-                    if (isPhiAtMerge(v)) {
-                        PhiNode endPhi = (PhiNode) v;
-                        newInput = endPhi.valueAt(end);
-                    } else {
-                        newInput = v;
-                    }
-                    phi.addInput(newInput);
-                }
-                this.removeEnd(end);
-                end.replaceAtPredecessor(newEnd);
-                end.safeDelete();
-                if (tool != null) {
-                    tool.addToWorkList(newEnd.predecessor());
-                }
-            }
-            graph().reduceTrivialMerge(this);
-        } else if (currentNext instanceof ReturnNode) {
-            ReturnNode returnNode = (ReturnNode) currentNext;
-            if (anchored().isNotEmpty() || returnNode.getMemoryMap() != null) {
-                return;
-            }
-            List<PhiNode> phis = phis().snapshot();
-            for (PhiNode phi : phis) {
-                for (Node usage : phi.usages().filter(isNotA(FrameState.class))) {
-                    if (usage != returnNode) {
-                        return;
-                    }
-                }
-            }
-
-            ValuePhiNode returnValuePhi = returnNode.result() == null || !isPhiAtMerge(returnNode.result()) ? null : (ValuePhiNode) returnNode.result();
-            List<AbstractEndNode> endNodes = forwardEnds().snapshot();
-            for (AbstractEndNode end : endNodes) {
-                ReturnNode newReturn = graph().add(new ReturnNode(returnValuePhi == null ? returnNode.result() : returnValuePhi.valueAt(end)));
-                if (tool != null) {
-                    tool.addToWorkList(end.predecessor());
-                }
-                end.replaceAtPredecessor(newReturn);
-            }
-            GraphUtil.killCFG(this);
-            for (AbstractEndNode end : endNodes) {
-                end.safeDelete();
-            }
-            for (PhiNode phi : phis) {
-                if (phi.isAlive() && phi.hasNoUsages()) {
-                    GraphUtil.killWithUnusedFloatingInputs(phi);
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -32,28 +32,28 @@
 import com.oracle.graal.nodes.calc.*;
 
 /**
- * {@code PhiNode}s represent the merging of edges at a control flow merges ({@link MergeNode} or
- * {@link LoopBeginNode}). For a {@link MergeNode}, the order of the values corresponds to the order
+ * {@code PhiNode}s represent the merging of edges at a control flow merges ({@link AbstractMergeNode} or
+ * {@link LoopBeginNode}). For a {@link AbstractMergeNode}, the order of the values corresponds to the order
  * of the ends. For {@link LoopBeginNode}s, the first value corresponds to the loop's predecessor,
  * while the rest of the values correspond to the {@link LoopEndNode}s.
  */
 @NodeInfo
 public abstract class PhiNode extends FloatingNode implements Simplifiable {
 
-    @Input(InputType.Association) protected MergeNode merge;
+    @Input(InputType.Association) protected AbstractMergeNode merge;
 
-    protected PhiNode(Stamp stamp, MergeNode merge) {
+    protected PhiNode(Stamp stamp, AbstractMergeNode merge) {
         super(stamp);
         this.merge = merge;
     }
 
     public abstract NodeInputList<ValueNode> values();
 
-    public MergeNode merge() {
+    public AbstractMergeNode merge() {
         return merge;
     }
 
-    public void setMerge(MergeNode x) {
+    public void setMerge(AbstractMergeNode x) {
         updateUsages(merge, x);
         merge = x;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Jan 28 01:04:20 2015 +0100
@@ -404,12 +404,12 @@
         if (begin.forwardEndCount() == 1) { // bypass merge and remove
             reduceTrivialMerge(begin);
         } else { // convert to merge
-            MergeNode merge = this.add(new MergeNode());
+            AbstractMergeNode merge = this.add(new AbstractMergeNode());
             this.replaceFixedWithFixed(begin, merge);
         }
     }
 
-    public void reduceTrivialMerge(MergeNode merge) {
+    public void reduceTrivialMerge(AbstractMergeNode merge) {
         assert merge.forwardEndCount() == 1;
         assert !(merge instanceof LoopBeginNode) || ((LoopBeginNode) merge).loopEnds().isEmpty();
         for (PhiNode phi : merge.phis().snapshot()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Wed Jan 28 01:04:20 2015 +0100
@@ -35,13 +35,13 @@
 
     @Input protected NodeInputList<ValueNode> values;
 
-    public ValuePhiNode(Stamp stamp, MergeNode merge) {
+    public ValuePhiNode(Stamp stamp, AbstractMergeNode merge) {
         super(stamp, merge);
         assert stamp != StampFactory.forVoid();
         values = new NodeInputList<>(this);
     }
 
-    public ValuePhiNode(Stamp stamp, MergeNode merge, ValueNode[] values) {
+    public ValuePhiNode(Stamp stamp, AbstractMergeNode merge, ValueNode[] values) {
         super(stamp, merge);
         assert stamp != StampFactory.forVoid();
         this.values = new NodeInputList<>(this, values);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java	Wed Jan 28 01:04:20 2015 +0100
@@ -143,8 +143,8 @@
 
             assert nodeToBlock.get(cur) == null;
             nodeToBlock.set(cur, block);
-            if (cur instanceof MergeNode) {
-                for (PhiNode phi : ((MergeNode) cur).phis()) {
+            if (cur instanceof AbstractMergeNode) {
+                for (PhiNode phi : ((AbstractMergeNode) cur).phis()) {
                     nodeToBlock.set(phi, block);
                 }
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Wed Jan 28 01:04:20 2015 +0100
@@ -49,7 +49,7 @@
     void emitInvoke(Invoke i);
 
     // Handling of block-end nodes still needs to be unified in the LIRGenerator.
-    void visitMerge(MergeNode i);
+    void visitMerge(AbstractMergeNode i);
 
     void visitEndNode(AbstractEndNode i);
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java	Wed Jan 28 01:04:20 2015 +0100
@@ -71,7 +71,7 @@
     }
 
     private static void killEnd(AbstractEndNode end, SimplifierTool tool) {
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         if (merge != null) {
             merge.removeEnd(end);
             StructuredGraph graph = end.graph();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -321,7 +321,7 @@
                         graph.removeFloating((FloatingNode) node);
                     } else {
                         // case 2
-                        assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof MergeNode) : node + " -> " + canonical +
+                        assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode || canonical instanceof AbstractMergeNode) : node + " -> " + canonical +
                                         " : replacement should be floating or fixed and connected";
                         graph.replaceFloating((FloatingNode) node, canonical);
                     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -124,7 +124,7 @@
         }
 
         @Override
-        public boolean merge(MergeNode merge, List<State> withStates) {
+        public boolean merge(AbstractMergeNode merge, List<State> withStates) {
             Map<ValueNode, ResolvedJavaType> newKnownTypes = Node.newIdentityMap();
             Map<LogicNode, GuardingNode> newTrueConditions = Node.newIdentityMap();
             Map<LogicNode, GuardingNode> newFalseConditions = Node.newIdentityMap();
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -69,8 +69,8 @@
         for (FixedGuardNode fixedGuard : graph.getNodes(FixedGuardNode.class)) {
 
             AbstractBeginNode pred = AbstractBeginNode.prevBegin(fixedGuard);
-            if (pred instanceof MergeNode) {
-                MergeNode merge = (MergeNode) pred;
+            if (pred instanceof AbstractMergeNode) {
+                AbstractMergeNode merge = (AbstractMergeNode) pred;
                 if (fixedGuard.condition() instanceof CompareNode) {
                     CompareNode compare = (CompareNode) fixedGuard.condition();
                     List<AbstractEndNode> mergePredecessors = merge.cfgPredecessors().snapshot();
@@ -107,8 +107,8 @@
     }
 
     private void visitDeoptBegin(AbstractBeginNode deoptBegin, DeoptimizationAction deoptAction, DeoptimizationReason deoptReason, StructuredGraph graph) {
-        if (deoptBegin instanceof MergeNode) {
-            MergeNode mergeNode = (MergeNode) deoptBegin;
+        if (deoptBegin instanceof AbstractMergeNode) {
+            AbstractMergeNode mergeNode = (AbstractMergeNode) deoptBegin;
             Debug.log("Visiting %s", mergeNode);
             FixedNode next = mergeNode.next();
             while (mergeNode.isAlive()) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeadCodeEliminationPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -79,7 +79,7 @@
         deleteNodes(flood, graph);
 
         // remove chained Merges
-        for (MergeNode merge : graph.getNodes(MergeNode.class)) {
+        for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class)) {
             if (merge.forwardEndCount() == 1 && !(merge instanceof LoopBeginNode)) {
                 graph.reduceTrivialMerge(merge);
             }
@@ -102,7 +102,7 @@
     private static void disconnectCFGNodes(NodeFlood flood, StructuredGraph graph) {
         for (AbstractEndNode node : graph.getNodes(AbstractEndNode.class)) {
             if (!flood.isMarked(node)) {
-                MergeNode merge = node.merge();
+                AbstractMergeNode merge = node.merge();
                 if (merge != null && flood.isMarked(merge)) {
                     // We are a dead end node leading to a live merge.
                     merge.removeEnd(node);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DeoptimizationGroupingPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -52,9 +52,9 @@
                     if (cfg == null) {
                         cfg = ControlFlowGraph.compute(graph, true, true, false, false);
                     }
-                    MergeNode merge;
+                    AbstractMergeNode merge;
                     if (target instanceof AbstractDeoptimizeNode) {
-                        merge = graph.add(new MergeNode());
+                        merge = graph.add(new AbstractMergeNode());
                         EndNode firstEnd = graph.add(new EndNode());
                         ValueNode actionAndReason = ((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess());
                         ValueNode speculation = ((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess());
@@ -72,7 +72,7 @@
                         obsoletes.add((AbstractDeoptimizeNode) target);
                         target = merge;
                     } else {
-                        merge = (MergeNode) target;
+                        merge = (AbstractMergeNode) target;
                     }
                     EndNode newEnd = graph.add(new EndNode());
                     merge.addForwardEnd(newEnd);
@@ -84,7 +84,7 @@
                 }
             }
             if (obsoletes != null) {
-                ((DynamicDeoptimizeNode) ((MergeNode) target).next()).setStateBefore(fs);
+                ((DynamicDeoptimizeNode) ((AbstractMergeNode) target).next()).setStateBefore(fs);
                 for (AbstractDeoptimizeNode obsolete : obsoletes) {
                     obsolete.safeDelete();
                 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ExpandLogicPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -72,7 +72,7 @@
         }
         ifNode.clearSuccessors();
         Graph graph = ifNode.graph();
-        MergeNode trueTargetMerge = graph.add(new MergeNode());
+        AbstractMergeNode trueTargetMerge = graph.add(new AbstractMergeNode());
         trueTargetMerge.setNext(trueTarget);
         EndNode firstTrueEnd = graph.add(new EndNode());
         EndNode secondTrueEnd = graph.add(new EndNode());
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -150,7 +150,7 @@
         }
     }
 
-    public static MemoryMapImpl mergeMemoryMaps(MergeNode merge, List<? extends MemoryMap> states, boolean updateExistingPhis) {
+    public static MemoryMapImpl mergeMemoryMaps(AbstractMergeNode merge, List<? extends MemoryMap> states, boolean updateExistingPhis) {
         MemoryMapImpl newState = new MemoryMapImpl();
 
         Set<LocationIdentity> keys = CollectionsFactory.newSet();
@@ -237,7 +237,7 @@
         }
 
         @Override
-        protected Set<LocationIdentity> merge(MergeNode merge, List<Set<LocationIdentity>> states) {
+        protected Set<LocationIdentity> merge(AbstractMergeNode merge, List<Set<LocationIdentity>> states) {
             Set<LocationIdentity> result = CollectionsFactory.newSet();
             for (Set<LocationIdentity> other : states) {
                 result.addAll(other);
@@ -346,7 +346,7 @@
         }
 
         @Override
-        protected MemoryMapImpl merge(MergeNode merge, List<MemoryMapImpl> states) {
+        protected MemoryMapImpl merge(AbstractMergeNode merge, List<MemoryMapImpl> states) {
             return mergeMemoryMaps(merge, states, updateExistingPhis);
         }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FrameStateAssignmentPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -88,7 +88,7 @@
         }
 
         @Override
-        protected FrameState merge(MergeNode merge, List<FrameState> states) {
+        protected FrameState merge(AbstractMergeNode merge, List<FrameState> states) {
             FrameState singleFrameState = singleFrameState(states);
             return singleFrameState == null ? merge.stateAfter() : singleFrameState;
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -125,8 +125,8 @@
     }
 
     private static double getNodeWeight(ValueNode node) {
-        if (node instanceof MergeNode) {
-            return ((MergeNode) node).phiPredecessorCount();
+        if (node instanceof AbstractMergeNode) {
+            return ((AbstractMergeNode) node).phiPredecessorCount();
         } else if (node instanceof AbstractBeginNode || node instanceof AbstractEndNode || node instanceof MonitorIdNode || node instanceof ConstantNode || node instanceof ParameterNode ||
                         node instanceof CallTargetNode || node instanceof ValueProxy || node instanceof VirtualObjectNode || node instanceof ReinterpretNode) {
             return 0;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -47,7 +47,7 @@
 
 /**
  * This class is a phase that looks for opportunities for tail duplication. The static method
- * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List, PhaseContext, CanonicalizerPhase)}
+ * {@link #tailDuplicate(AbstractMergeNode, TailDuplicationDecision, List, PhaseContext, CanonicalizerPhase)}
  * can also be used to drive tail duplication from other places, e.g., inlining.
  */
 public class TailDuplicationPhase extends BasePhase<PhaseContext> {
@@ -84,7 +84,7 @@
          *            duplicated set of nodes.
          * @return true if the tail duplication should be performed, false otherwise.
          */
-        boolean doTransform(MergeNode merge, int fixedNodeCount);
+        boolean doTransform(AbstractMergeNode merge, int fixedNodeCount);
     }
 
     /**
@@ -94,7 +94,7 @@
      */
     public static final TailDuplicationDecision DEFAULT_DECISION = new TailDuplicationDecision() {
 
-        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
+        public boolean doTransform(AbstractMergeNode merge, int fixedNodeCount) {
             if (fixedNodeCount < TailDuplicationTrivialSize.getValue()) {
                 return true;
             }
@@ -144,7 +144,7 @@
     public static final TailDuplicationDecision TRUE_DECISION = new TailDuplicationDecision() {
 
         @Override
-        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
+        public boolean doTransform(AbstractMergeNode merge, int fixedNodeCount) {
             return true;
         }
     };
@@ -155,12 +155,12 @@
 
     @Override
     protected void run(StructuredGraph graph, PhaseContext phaseContext) {
-        if (graph.hasNode(MergeNode.class)) {
+        if (graph.hasNode(AbstractMergeNode.class)) {
             ToDoubleFunction<FixedNode> nodeProbabilities = new FixedNodeProbabilityCache();
 
             // A snapshot is taken here, so that new MergeNode instances aren't considered for tail
             // duplication.
-            for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
+            for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.class).snapshot()) {
                 if (!(merge instanceof LoopBeginNode) && nodeProbabilities.applyAsDouble(merge) >= TailDuplicationProbability.getValue()) {
                     tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext, canonicalizer);
                 }
@@ -172,7 +172,7 @@
      * This method attempts to duplicate the tail of the given merge. The merge must not be a
      * {@link LoopBeginNode}. If the merge is eligible for duplication (at least one fixed node in
      * its tail, no {@link MonitorEnterNode}/ {@link MonitorExitNode}, non-null
-     * {@link MergeNode#stateAfter()}) then the decision callback is used to determine whether the
+     * {@link AbstractMergeNode#stateAfter()}) then the decision callback is used to determine whether the
      * tail duplication should actually be performed. If replacements is non-null, then this list of
      * {@link PiNode}s is used to replace one value per merge end.
      *
@@ -185,7 +185,7 @@
      *            {@link PiNode} in the duplicated branch that corresponds to the entry.
      * @param phaseContext
      */
-    public static boolean tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<GuardedValueNode> replacements, PhaseContext phaseContext, CanonicalizerPhase canonicalizer) {
+    public static boolean tailDuplicate(AbstractMergeNode merge, TailDuplicationDecision decision, List<GuardedValueNode> replacements, PhaseContext phaseContext, CanonicalizerPhase canonicalizer) {
         assert !(merge instanceof LoopBeginNode);
         assert replacements == null || replacements.size() == merge.forwardEndCount();
         FixedNode fixed = merge;
@@ -209,11 +209,11 @@
     }
 
     /**
-     * This class encapsulates one tail duplication operation on a specific {@link MergeNode}.
+     * This class encapsulates one tail duplication operation on a specific {@link AbstractMergeNode}.
      */
     private static class DuplicationOperation {
 
-        private final MergeNode merge;
+        private final AbstractMergeNode merge;
         private final StructuredGraph graph;
 
         private final Map<ValueNode, PhiNode> bottomPhis = Node.newMap();
@@ -228,7 +228,7 @@
          * @param replacements A list of replacement {@link PiNode}s, or null. If this is non-null,
          *            then the size of the list needs to match the number of end nodes at the merge.
          */
-        public DuplicationOperation(MergeNode merge, List<GuardedValueNode> replacements, CanonicalizerPhase canonicalizer) {
+        public DuplicationOperation(AbstractMergeNode merge, List<GuardedValueNode> replacements, CanonicalizerPhase canonicalizer) {
             this.merge = merge;
             this.replacements = replacements;
             this.graph = merge.graph();
@@ -270,7 +270,7 @@
             }
 
             AbstractEndNode endAfter = createNewMerge(fixed, stateAfter);
-            MergeNode mergeAfter = endAfter.merge();
+            AbstractMergeNode mergeAfter = endAfter.merge();
             fixedNodes.add(endAfter);
             final Set<Node> duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter);
             mergeAfter.clearEnds();
@@ -448,7 +448,7 @@
          * @return The newly created end node.
          */
         private AbstractEndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) {
-            MergeNode newBottomMerge = graph.add(new MergeNode());
+            AbstractMergeNode newBottomMerge = graph.add(new AbstractMergeNode());
             AbstractEndNode newBottomEnd = graph.add(new EndNode());
             newBottomMerge.addForwardEnd(newBottomEnd);
             newBottomMerge.setStateAfter(stateAfterMerge);
@@ -477,7 +477,7 @@
          *            for newly created phis and to as a target for dependencies that pointed into
          *            the duplicated set of nodes.
          */
-        private void expandDuplicated(Set<Node> duplicatedNodes, MergeNode newBottomMerge) {
+        private void expandDuplicated(Set<Node> duplicatedNodes, AbstractMergeNode newBottomMerge) {
             Deque<Node> worklist = new ArrayDeque<>(duplicatedNodes);
 
             while (!worklist.isEmpty()) {
@@ -487,7 +487,7 @@
             }
         }
 
-        private void processUsages(Node duplicated, Set<Node> duplicatedNodes, MergeNode newBottomMerge, Deque<Node> worklist) {
+        private void processUsages(Node duplicated, Set<Node> duplicatedNodes, AbstractMergeNode newBottomMerge, Deque<Node> worklist) {
             Set<Node> unique = Node.newSet();
             duplicated.usages().snapshotTo(unique);
             Node newOutsideClone = null;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -58,8 +58,8 @@
 
     private static void tryUseTrappingNullCheck(MetaAccessProvider metaAccessProvider, DynamicDeoptimizeNode deopt) {
         Node predecessor = deopt.predecessor();
-        if (predecessor instanceof MergeNode) {
-            MergeNode merge = (MergeNode) predecessor;
+        if (predecessor instanceof AbstractMergeNode) {
+            AbstractMergeNode merge = (AbstractMergeNode) predecessor;
 
             // Process each predecessor at the merge, unpacking the reasons and speculations as
             // needed.
@@ -115,8 +115,8 @@
         if (speculation != null && !speculation.equals(JavaConstant.NULL_POINTER)) {
             return;
         }
-        if (predecessor instanceof MergeNode) {
-            MergeNode merge = (MergeNode) predecessor;
+        if (predecessor instanceof AbstractMergeNode) {
+            AbstractMergeNode merge = (AbstractMergeNode) predecessor;
             if (merge.phis().isEmpty()) {
                 for (AbstractEndNode end : merge.cfgPredecessors().snapshot()) {
                     checkPredecessor(deopt, end.predecessor(), deoptimizationReason);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ValueAnchorCleanupPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ValueAnchorCleanupPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -50,7 +50,7 @@
         }
 
         @Override
-        public boolean merge(MergeNode merge, List<State> withStates) {
+        public boolean merge(AbstractMergeNode merge, List<State> withStates) {
             for (State other : withStates) {
                 anchoredValues.retainAll(other.anchoredValues);
             }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java	Wed Jan 28 01:04:20 2015 +0100
@@ -344,7 +344,7 @@
                 for (ReturnNode returnNode : returnNodes) {
                     returnDuplicates.add((ReturnNode) duplicates.get(returnNode));
                 }
-                MergeNode merge = graph.add(new MergeNode());
+                AbstractMergeNode merge = graph.add(new AbstractMergeNode());
                 merge.setStateAfter(stateAfter);
                 ValueNode returnValue = mergeReturns(merge, returnDuplicates, canonicalizedNodes);
                 invokeNode.replaceAtUsages(returnValue);
@@ -448,8 +448,8 @@
                 } else {
                     StateSplit stateSplit = (StateSplit) usage;
                     FixedNode fixedStateSplit = stateSplit.asNode();
-                    if (fixedStateSplit instanceof MergeNode) {
-                        MergeNode merge = (MergeNode) fixedStateSplit;
+                    if (fixedStateSplit instanceof AbstractMergeNode) {
+                        AbstractMergeNode merge = (AbstractMergeNode) fixedStateSplit;
                         while (merge.isAlive()) {
                             AbstractEndNode end = merge.forwardEnds().first();
                             DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
@@ -469,7 +469,7 @@
         }
     }
 
-    public static ValueNode mergeReturns(MergeNode merge, List<? extends ReturnNode> returnNodes, List<Node> canonicalizedNodes) {
+    public static ValueNode mergeReturns(AbstractMergeNode merge, List<? extends ReturnNode> returnNodes, List<Node> canonicalizedNodes) {
         PhiNode returnValuePhi = null;
 
         for (ReturnNode returnNode : returnNodes) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Wed Jan 28 01:04:20 2015 +0100
@@ -173,7 +173,7 @@
 
         ValueNode originalReceiver = ((MethodCallTargetNode) invoke.callTarget()).receiver();
         // setup merge and phi nodes for results and exceptions
-        MergeNode returnMerge = graph.add(new MergeNode());
+        AbstractMergeNode returnMerge = graph.add(new AbstractMergeNode());
         returnMerge.setStateAfter(invoke.stateAfter());
 
         PhiNode returnValuePhi = null;
@@ -181,13 +181,13 @@
             returnValuePhi = graph.addWithoutUnique(new ValuePhiNode(invoke.asNode().stamp().unrestricted(), returnMerge));
         }
 
-        MergeNode exceptionMerge = null;
+        AbstractMergeNode exceptionMerge = null;
         PhiNode exceptionObjectPhi = null;
         if (invoke instanceof InvokeWithExceptionNode) {
             InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
             ExceptionObjectNode exceptionEdge = (ExceptionObjectNode) invokeWithException.exceptionEdge();
 
-            exceptionMerge = graph.add(new MergeNode());
+            exceptionMerge = graph.add(new AbstractMergeNode());
 
             FixedNode exceptionSux = exceptionEdge.next();
             graph.addBeforeFixed(exceptionSux, exceptionMerge);
@@ -459,7 +459,7 @@
         return costEstimateMethodDispatch < costEstimateTypeDispatch;
     }
 
-    private static AbstractBeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi,
+    private static AbstractBeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, AbstractMergeNode returnMerge, PhiNode returnValuePhi, AbstractMergeNode exceptionMerge, PhiNode exceptionObjectPhi,
                     boolean useForInlining) {
         Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining);
         AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
@@ -475,7 +475,7 @@
         return calleeEntryNode;
     }
 
-    private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining) {
+    private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, AbstractMergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining) {
         Invoke result = (Invoke) invoke.asNode().copyWithInputs();
         Node callTarget = result.callTarget().copyWithInputs();
         result.asNode().replaceFirstInput(result.callTarget(), callTarget);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java	Wed Jan 28 01:04:20 2015 +0100
@@ -114,9 +114,9 @@
                         parent = loops.get(null);
                         break;
                     } else {
-                        assert current.getClass() == MergeNode.class : current;
+                        assert current.getClass() == AbstractMergeNode.class : current;
                         // follow any path upwards - it doesn't matter which one
-                        current = ((MergeNode) current).forwardEndAt(0);
+                        current = ((AbstractMergeNode) current).forwardEndAt(0);
                     }
                 } else if (current instanceof LoopExitNode) {
                     // if we reach a loop exit then we follow this loop and have the same parent
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningIterator.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/InliningIterator.java	Wed Jan 28 01:04:20 2015 +0100
@@ -67,7 +67,7 @@
                 queueSuccessors(current);
             } else if (current instanceof LoopEndNode) {
                 // nothing to do
-            } else if (current instanceof MergeNode) {
+            } else if (current instanceof AbstractMergeNode) {
                 queueSuccessors(current);
             } else if (current instanceof FixedWithNextNode) {
                 queueSuccessors(current);
@@ -114,14 +114,14 @@
     }
 
     private void queueMerge(AbstractEndNode end) {
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) {
             queuedNodes.mark(merge);
             nodeQueue.add(merge);
         }
     }
 
-    private boolean visitedAllEnds(MergeNode merge) {
+    private boolean visitedAllEnds(AbstractMergeNode merge) {
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!queuedNodes.isMarked(merge.forwardEndAt(i))) {
                 return false;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/FixedNodeProbabilityCache.java	Wed Jan 28 01:04:20 2015 +0100
@@ -99,8 +99,8 @@
 
         double probability = 0.0;
         if (current.predecessor() == null) {
-            if (current instanceof MergeNode) {
-                MergeNode currentMerge = (MergeNode) current;
+            if (current instanceof AbstractMergeNode) {
+                AbstractMergeNode currentMerge = (AbstractMergeNode) current;
                 NodeInputList<AbstractEndNode> currentForwardEnds = currentMerge.forwardEnds();
                 /*
                  * Use simple iteration instead of streams, since the stream infrastructure adds
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Wed Jan 28 01:04:20 2015 +0100
@@ -38,7 +38,7 @@
      * @param merge the merge node
      * @param withStates the state at the the merge's end node except the first one.
      */
-    public abstract boolean merge(MergeNode merge, List<T> withStates);
+    public abstract boolean merge(AbstractMergeNode merge, List<T> withStates);
 
     /**
      * This method is called before a loop is entered (before the {@link LoopBeginNode} is visited).
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Wed Jan 28 01:04:20 2015 +0100
@@ -32,7 +32,7 @@
  * specified fixed node.
  * <p>
  * For this iterator the CFG is defined by the classical CFG nodes ({@link ControlSplitNode},
- * {@link MergeNode}...) and the {@link FixedWithNextNode#next() next} pointers of
+ * {@link AbstractMergeNode}...) and the {@link FixedWithNextNode#next() next} pointers of
  * {@link FixedWithNextNode}.
  * <p>
  * While iterating it maintains a user-defined state by calling the methods available in
@@ -77,9 +77,9 @@
                 loopEnd((LoopEndNode) current);
                 finishLoopEnds((LoopEndNode) current);
                 current = nextQueuedNode();
-            } else if (current instanceof MergeNode) {
-                merge((MergeNode) current);
-                current = ((MergeNode) current).next();
+            } else if (current instanceof AbstractMergeNode) {
+                merge((AbstractMergeNode) current);
+                current = ((AbstractMergeNode) current).next();
                 assert current != null;
             } else if (current instanceof FixedWithNextNode) {
                 FixedNode next = ((FixedWithNextNode) current).next();
@@ -126,8 +126,8 @@
         int maxIterations = nodeQueue.size();
         while (maxIterations-- > 0) {
             AbstractBeginNode node = nodeQueue.removeFirst();
-            if (node instanceof MergeNode) {
-                MergeNode merge = (MergeNode) node;
+            if (node instanceof AbstractMergeNode) {
+                AbstractMergeNode merge = (AbstractMergeNode) node;
                 state = nodeStates.get(merge.forwardEndAt(0)).clone();
                 ArrayList<T> states = new ArrayList<>(merge.forwardEndCount() - 1);
                 for (int i = 1; i < merge.forwardEndCount(); i++) {
@@ -181,7 +181,7 @@
         assert !nodeStates.containsKey(end);
         nodeStates.put(end, state);
         visitedEnds.mark(end);
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         boolean endsVisited = true;
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!visitedEnds.isMarked(merge.forwardEndAt(i))) {
@@ -200,7 +200,7 @@
         node(endNode);
     }
 
-    protected void merge(MergeNode merge) {
+    protected void merge(AbstractMergeNode merge) {
         node(merge);
     }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantBlockIterator.java	Wed Jan 28 01:04:20 2015 +0100
@@ -118,7 +118,7 @@
                         AbstractEndNode end = (AbstractEndNode) current.getEndNode();
 
                         // add the end node and see if the merge is ready for processing
-                        MergeNode merge = end.merge();
+                        AbstractMergeNode merge = end.merge();
                         if (allEndsVisited(states, current, merge)) {
                             ArrayList<StateT> mergedStates = mergeStates(states, state, current, successor, merge);
                             state = closure.merge(successor, mergedStates);
@@ -149,7 +149,7 @@
         }
     }
 
-    private static <StateT> boolean allEndsVisited(Map<FixedNode, StateT> states, Block current, MergeNode merge) {
+    private static <StateT> boolean allEndsVisited(Map<FixedNode, StateT> states, Block current, AbstractMergeNode merge) {
         for (AbstractEndNode forwardEnd : merge.forwardEnds()) {
             if (forwardEnd != current.getEndNode() && !states.containsKey(forwardEnd)) {
                 return false;
@@ -168,7 +168,7 @@
         return successors.get(0);
     }
 
-    private static <StateT> ArrayList<StateT> mergeStates(Map<FixedNode, StateT> states, StateT state, Block current, Block successor, MergeNode merge) {
+    private static <StateT> ArrayList<StateT> mergeStates(Map<FixedNode, StateT> states, StateT state, Block current, Block successor, AbstractMergeNode merge) {
         ArrayList<StateT> mergedStates = new ArrayList<>(merge.forwardEndCount());
         for (Block predecessor : successor.getPredecessors()) {
             assert predecessor == current || states.containsKey(predecessor.getEndNode());
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ReentrantNodeIterator.java	Wed Jan 28 01:04:20 2015 +0100
@@ -44,7 +44,7 @@
 
         protected abstract StateT processNode(FixedNode node, StateT currentState);
 
-        protected abstract StateT merge(MergeNode merge, List<StateT> states);
+        protected abstract StateT merge(AbstractMergeNode merge, List<StateT> states);
 
         protected abstract StateT afterSplit(AbstractBeginNode node, StateT oldState);
 
@@ -114,7 +114,7 @@
                             blockEndStates.put(current, state);
                         } else if (current instanceof EndNode) {
                             // add the end node and see if the merge is ready for processing
-                            MergeNode merge = ((EndNode) current).merge();
+                            AbstractMergeNode merge = ((EndNode) current).merge();
                             if (merge instanceof LoopBeginNode) {
                                 Map<LoopExitNode, StateT> loopExitState = closure.processLoop((LoopBeginNode) merge, state);
                                 for (Map.Entry<LoopExitNode, StateT> entry : loopExitState.entrySet()) {
@@ -176,7 +176,7 @@
                 current = nodeQueue.removeFirst();
                 assert blockEndStates.containsKey(current);
                 state = blockEndStates.remove(current);
-                assert !(current instanceof MergeNode) && current instanceof AbstractBeginNode;
+                assert !(current instanceof AbstractMergeNode) && current instanceof AbstractBeginNode;
             }
         } while (true);
     }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java	Wed Jan 28 01:04:20 2015 +0100
@@ -67,7 +67,7 @@
                 queueLoopExitSuccessors((LoopExitNode) current);
             } else if (current instanceof LoopEndNode) {
                 // nothing todo
-            } else if (current instanceof MergeNode) {
+            } else if (current instanceof AbstractMergeNode) {
                 queueSuccessors(current);
             } else if (current instanceof FixedWithNextNode) {
                 queueSuccessors(current);
@@ -142,13 +142,13 @@
     }
 
     private void queueMerge(AbstractEndNode end) {
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) {
             queue(merge);
         }
     }
 
-    private boolean visitedAllEnds(MergeNode merge) {
+    private boolean visitedAllEnds(AbstractMergeNode merge) {
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!queuedNodes.isMarked(merge.forwardEndAt(i))) {
                 return false;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/SinglePassNodeIterator.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/SinglePassNodeIterator.java	Wed Jan 28 01:04:20 2015 +0100
@@ -32,16 +32,16 @@
  * start node. Unlike in iterative dataflow analysis, a single pass is performed, which allows
  * keeping a smaller working set of pending {@link MergeableState}. This iteration scheme requires:
  * <ul>
- * <li>{@link MergeableState#merge(MergeNode, List)} to always return <code>true</code> (an
+ * <li>{@link MergeableState#merge(AbstractMergeNode, List)} to always return <code>true</code> (an
  * assertion checks this)</li>
  * <li>{@link #controlSplit(ControlSplitNode)} to always return all successors (otherwise, not all
  * associated {@link EndNode} will be visited. In turn, visiting all the end nodes for a given
- * {@link MergeNode} is a precondition before that merge node can be visited)</li>
+ * {@link AbstractMergeNode} is a precondition before that merge node can be visited)</li>
  * </ul>
  *
  * <p>
  * For this iterator the CFG is defined by the classical CFG nodes (
- * {@link com.oracle.graal.nodes.ControlSplitNode}, {@link com.oracle.graal.nodes.MergeNode}...) and
+ * {@link com.oracle.graal.nodes.ControlSplitNode}, {@link com.oracle.graal.nodes.AbstractMergeNode}...) and
  * the {@link com.oracle.graal.nodes.FixedWithNextNode#next() next} pointers of
  * {@link com.oracle.graal.nodes.FixedWithNextNode}.
  * </p>
@@ -101,7 +101,7 @@
      * <p>
      * Correspondingly each item may stand for:
      * <ul>
-     * <li>a {@link MergeNode} whose pre-state results from merging those of its forward-ends, see
+     * <li>a {@link AbstractMergeNode} whose pre-state results from merging those of its forward-ends, see
      * {@link #nextQueuedNode()}</li>
      * <li>a successor of a control-split node, in which case the state on entry to it (the
      * successor) is also stored in the item, see {@link #nextQueuedNode()}</li>
@@ -125,7 +125,7 @@
             if (node == null) {
                 return false;
             }
-            if (node instanceof MergeNode) {
+            if (node instanceof AbstractMergeNode) {
                 return stateOnEntry == null;
             }
             return (stateOnEntry != null);
@@ -169,9 +169,9 @@
                 loopEnd((LoopEndNode) current);
                 finishLoopEnds((LoopEndNode) current);
                 current = nextQueuedNode();
-            } else if (current instanceof MergeNode) {
-                merge((MergeNode) current);
-                current = ((MergeNode) current).next();
+            } else if (current instanceof AbstractMergeNode) {
+                merge((AbstractMergeNode) current);
+                current = ((AbstractMergeNode) current).next();
                 assert current != null;
             } else if (current instanceof FixedWithNextNode) {
                 FixedNode next = ((FixedWithNextNode) current).next();
@@ -228,7 +228,7 @@
      * the pre-state for that node.
      *
      * <p>
-     * Upon reaching a {@link MergeNode}, some entries are pruned from {@link #nodeStates} (ie, the
+     * Upon reaching a {@link AbstractMergeNode}, some entries are pruned from {@link #nodeStates} (ie, the
      * entries associated to forward-ends for that merge-node).
      * </p>
      */
@@ -237,8 +237,8 @@
             return null;
         }
         PathStart<T> elem = nodeQueue.removeFirst();
-        if (elem.node instanceof MergeNode) {
-            MergeNode merge = (MergeNode) elem.node;
+        if (elem.node instanceof AbstractMergeNode) {
+            AbstractMergeNode merge = (AbstractMergeNode) elem.node;
             state = pruneEntry(merge.forwardEndAt(0));
             ArrayList<T> states = new ArrayList<>(merge.forwardEndCount() - 1);
             for (int i = 1; i < merge.forwardEndCount(); i++) {
@@ -309,7 +309,7 @@
         assert !visitedEnds.isMarked(end);
         visitedEnds.mark(end);
         keepForLater(end, state);
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         boolean endsVisited = true;
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!visitedEnds.isMarked(merge.forwardEndAt(i))) {
@@ -328,7 +328,7 @@
         node(endNode);
     }
 
-    protected void merge(MergeNode merge) {
+    protected void merge(AbstractMergeNode merge) {
         node(merge);
     }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/StatelessPostOrderNodeIterator.java	Wed Jan 28 01:04:20 2015 +0100
@@ -58,9 +58,9 @@
                 assert !visitedEnds.isMarked(current);
                 visitedEnds.mark(current);
                 current = nodeQueue.pollFirst();
-            } else if (current instanceof MergeNode) {
-                merge((MergeNode) current);
-                current = ((MergeNode) current).next();
+            } else if (current instanceof AbstractMergeNode) {
+                merge((AbstractMergeNode) current);
+                current = ((AbstractMergeNode) current).next();
                 assert current != null;
             } else if (current instanceof FixedWithNextNode) {
                 node(current);
@@ -90,7 +90,7 @@
     private void queueMerge(EndNode end) {
         assert !visitedEnds.isMarked(end);
         visitedEnds.mark(end);
-        MergeNode merge = end.merge();
+        AbstractMergeNode merge = end.merge();
         boolean endsVisited = true;
         for (int i = 0; i < merge.forwardEndCount(); i++) {
             if (!visitedEnds.isMarked(merge.forwardEndAt(i))) {
@@ -111,7 +111,7 @@
         node(endNode);
     }
 
-    protected void merge(MergeNode merge) {
+    protected void merge(AbstractMergeNode merge) {
         node(merge);
     }
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -186,7 +186,7 @@
 
         @Override
         protected LocationSet merge(Block merge, List<LocationSet> states) {
-            assert merge.getBeginNode() instanceof MergeNode;
+            assert merge.getBeginNode() instanceof AbstractMergeNode;
 
             LocationSet initKillSet = new LocationSet();
             for (LocationSet state : states) {
@@ -239,8 +239,8 @@
 
         LocationSet set = new LocationSet();
         LocationSet excludedLocations = new LocationSet();
-        if (block.getBeginNode() instanceof MergeNode) {
-            MergeNode mergeNode = (MergeNode) block.getBeginNode();
+        if (block.getBeginNode() instanceof AbstractMergeNode) {
+            AbstractMergeNode mergeNode = (AbstractMergeNode) block.getBeginNode();
             for (MemoryPhiNode phi : mergeNode.usages().filter(MemoryPhiNode.class)) {
                 if (foundExcludeNode) {
                     set.add(phi.getLocationIdentity());
@@ -548,7 +548,7 @@
             Block dominatedBlock = path.size() == 0 ? null : path.peek();
             if (dominatedBlock != null && !currentBlock.getSuccessors().contains(dominatedBlock)) {
                 // the dominated block is not a successor -> we have a split
-                assert dominatedBlock.getBeginNode() instanceof MergeNode;
+                assert dominatedBlock.getBeginNode() instanceof AbstractMergeNode;
 
                 NewMemoryScheduleClosure closure = null;
                 if (currentBlock == upperBoundBlock) {
@@ -745,7 +745,7 @@
             // One PhiNode can use an input multiple times, the closure will be called for each
             // usage.
             PhiNode phi = (PhiNode) usage;
-            MergeNode merge = phi.merge();
+            AbstractMergeNode merge = phi.merge();
             Block mergeBlock = cfg.getNodeToBlock().get(merge);
             if (mergeBlock == null) {
                 throw new SchedulingError("no block for merge %s", merge.toString(Verbosity.Id));
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java	Wed Jan 28 01:04:20 2015 +0100
@@ -31,7 +31,7 @@
  */
 public class BlockWorkList {
 
-    MergeNode[] workList;
+    AbstractMergeNode[] workList;
     int[] workListNumbers;
     int workListIndex;
 
@@ -40,7 +40,7 @@
      * 
      * @param block the block to add
      */
-    public void add(MergeNode block) {
+    public void add(AbstractMergeNode block) {
         if (workList == null) {
             // worklist not allocated yet
             allocate();
@@ -59,7 +59,7 @@
      * @param block the block to add
      * @param number the number used to sort the block
      */
-    public void addSorted(MergeNode block, int number) {
+    public void addSorted(AbstractMergeNode block, int number) {
         if (workList == null) {
             // worklist not allocated yet
             allocate();
@@ -92,7 +92,7 @@
      * 
      * @return the next block in the list
      */
-    public MergeNode removeFromWorkList() {
+    public AbstractMergeNode removeFromWorkList() {
         if (workListIndex != 0) {
             return workList[--workListIndex];
         }
@@ -109,13 +109,13 @@
     }
 
     private void allocate() {
-        workList = new MergeNode[5];
+        workList = new AbstractMergeNode[5];
         workListNumbers = new int[5];
     }
 
     private void grow() {
         int prevLength = workList.length;
-        MergeNode[] nworkList = new MergeNode[prevLength * 3];
+        AbstractMergeNode[] nworkList = new AbstractMergeNode[prevLength * 3];
         System.arraycopy(workList, 0, nworkList, 0, prevLength);
         workList = nworkList;
 
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Wed Jan 28 01:04:20 2015 +0100
@@ -110,8 +110,8 @@
                     }
                 }
                 nodes.add(node);
-                if (node instanceof MergeNode) {
-                    for (PhiNode phi : ((MergeNode) node).phis()) {
+                if (node instanceof AbstractMergeNode) {
+                    for (PhiNode phi : ((AbstractMergeNode) node).phis()) {
                         visited.mark(phi);
                         nodes.add(phi);
                     }
@@ -172,9 +172,9 @@
                             pendingStateAfter = null;
                         }
 
-                        if (node instanceof MergeNode) {
+                        if (node instanceof AbstractMergeNode) {
                             // phis aren't scheduled, so they need to be added explicitly
-                            currentState.markAll(((MergeNode) node).phis());
+                            currentState.markAll(((AbstractMergeNode) node).phis());
                             if (node instanceof LoopBeginNode) {
                                 // remember the state at the loop entry, it's restored at exits
                                 loopEntryStates.put((LoopBeginNode) node, currentState.copy());
@@ -210,7 +210,7 @@
                             }
                         }
                         if (node instanceof AbstractEndNode) {
-                            MergeNode merge = ((AbstractEndNode) node).merge();
+                            AbstractMergeNode merge = ((AbstractEndNode) node).merge();
                             for (PhiNode phi : merge.phis()) {
                                 ValueNode phiValue = phi.valueAt((AbstractEndNode) node);
                                 assert phiValue == null || currentState.isMarked(phiValue) : phiValue + " not available at phi " + phi + " / end " + node + " in block " + block;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Wed Jan 28 01:04:20 2015 +0100
@@ -265,9 +265,9 @@
         out.println("HIR");
         out.disableIndentation();
 
-        if (block.getBeginNode() instanceof MergeNode) {
+        if (block.getBeginNode() instanceof AbstractMergeNode) {
             // Currently phi functions are not in the schedule, so print them separately here.
-            for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) {
+            for (ValueNode phi : ((AbstractMergeNode) block.getBeginNode()).phis()) {
                 printNode(phi, false);
             }
         }
@@ -585,9 +585,9 @@
         out.println("HIR");
         out.disableIndentation();
 
-        if (block.getBeginNode() instanceof MergeNode) {
+        if (block.getBeginNode() instanceof AbstractMergeNode) {
             // Currently phi functions are not in the schedule, so print them separately here.
-            for (ValueNode phi : ((MergeNode) block.getBeginNode()).phis()) {
+            for (ValueNode phi : ((AbstractMergeNode) block.getBeginNode()).phis()) {
                 printNode(phi, false);
             }
         }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Wed Jan 28 01:04:20 2015 +0100
@@ -276,8 +276,8 @@
                 if (node instanceof StateSplit && ((StateSplit) node).stateAfter() != null) {
                     nodes.add(((StateSplit) node).stateAfter());
                 }
-                if (node instanceof MergeNode) {
-                    for (PhiNode phi : ((MergeNode) node).phis()) {
+                if (node instanceof AbstractMergeNode) {
+                    for (PhiNode phi : ((AbstractMergeNode) node).phis()) {
                         nodes.add(phi);
                     }
                 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CollapseFrameForSingleSideEffectPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -72,7 +72,7 @@
             return new IterationState(this, begin, null, this.invalid);
         }
 
-        public static IterationState merge(MergeNode merge, Collection<IterationState> before, boolean invalid) {
+        public static IterationState merge(AbstractMergeNode merge, Collection<IterationState> before, boolean invalid) {
             return new IterationState(null, merge, before, invalid);
         }
 
@@ -152,7 +152,7 @@
         }
 
         @Override
-        protected IterationState merge(MergeNode merge, List<IterationState> states) {
+        protected IterationState merge(AbstractMergeNode merge, List<IterationState> states) {
             boolean invalid = false;
             for (IterationState state : states) {
                 if (state.invalid) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Wed Jan 28 01:04:20 2015 +0100
@@ -303,7 +303,7 @@
             EndNode elseEnd = graph.add(new EndNode());
             graph.addAfterFixed(elsePart, elseEnd);
 
-            MergeNode merge = graph.add(new MergeNode());
+            AbstractMergeNode merge = graph.add(new AbstractMergeNode());
             merge.addForwardEnd(thenEnd);
             merge.addForwardEnd(elseEnd);
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Wed Jan 28 01:04:20 2015 +0100
@@ -737,7 +737,7 @@
         } else if (returnNodes.size() == 1) {
             this.returnNode = returnNodes.get(0);
         } else {
-            MergeNode merge = snippet.add(new MergeNode());
+            AbstractMergeNode merge = snippet.add(new AbstractMergeNode());
             List<MemoryMapNode> memMaps = returnNodes.stream().map(n -> n.getMemoryMap()).collect(Collectors.toList());
             ValueNode returnValue = InliningUtil.mergeReturns(merge, returnNodes, null);
             this.returnNode = snippet.add(new ReturnNode(returnValue));
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Wed Jan 28 01:04:20 2015 +0100
@@ -204,7 +204,7 @@
     protected class MergeProcessor {
 
         protected final Block mergeBlock;
-        protected final MergeNode merge;
+        protected final AbstractMergeNode merge;
 
         protected final GraphEffectList mergeEffects;
         protected final GraphEffectList afterMergeEffects;
@@ -212,7 +212,7 @@
 
         public MergeProcessor(Block mergeBlock) {
             this.mergeBlock = mergeBlock;
-            this.merge = (MergeNode) mergeBlock.getBeginNode();
+            this.merge = (AbstractMergeNode) mergeBlock.getBeginNode();
             this.mergeEffects = new GraphEffectList();
             this.afterMergeEffects = new GraphEffectList();
         }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Wed Jan 28 01:01:54 2015 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Wed Jan 28 01:04:20 2015 +0100
@@ -86,7 +86,7 @@
                 } else if (usage instanceof ArrayLengthNode) {
                     verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value");
                 } else if (usage instanceof ValuePhiNode) {
-                    if (!(node instanceof MergeNode)) {
+                    if (!(node instanceof AbstractMergeNode)) {
                         ValuePhiNode phi = (ValuePhiNode) usage;
                         for (ValueNode input : phi.values()) {
                             verify(isWord(node) == isWord(input), node, input, "cannot merge word and non-word values");