changeset 2834:bfce42cd9c07

Graph duplication now passes all tests
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 31 May 2011 13:34:52 +0200
parents 27c00b180416
children c1c8a0291771
files graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java graal/GraalCompiler/src/com/sun/c1x/graph/IR.java graal/GraalCompiler/src/com/sun/c1x/ir/AccessField.java graal/GraalCompiler/src/com/sun/c1x/ir/If.java graal/GraalCompiler/src/com/sun/c1x/ir/IfOp.java graal/GraalCompiler/src/com/sun/c1x/ir/InstanceOf.java graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java graal/GraalCompiler/src/com/sun/c1x/ir/LoadIndexed.java graal/GraalCompiler/src/com/sun/c1x/ir/Local.java graal/GraalCompiler/src/com/sun/c1x/ir/LogicOp.java graal/GraalCompiler/src/com/sun/c1x/ir/MonitorEnter.java graal/GraalCompiler/src/com/sun/c1x/ir/MonitorExit.java graal/GraalCompiler/src/com/sun/c1x/ir/NegateOp.java graal/GraalCompiler/src/com/sun/c1x/ir/NewMultiArray.java graal/GraalCompiler/src/com/sun/c1x/ir/NewObjectArray.java graal/GraalCompiler/src/com/sun/c1x/ir/NullCheck.java graal/GraalCompiler/src/com/sun/c1x/ir/Return.java graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java graal/GraalCompiler/src/com/sun/c1x/ir/Value.java graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java graal/GraalGraph/src/com/oracle/graal/graph/Graph.java
diffstat 22 files changed, 104 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/gen/LIRGenerator.java	Tue May 31 13:34:52 2011 +0200
@@ -388,7 +388,7 @@
             dims[i] = toXirArgument(x.dimension(i));
         }
 
-        XirSnippet snippet = xir.genNewMultiArray(site(x), dims, x.elementKind);
+        XirSnippet snippet = xir.genNewMultiArray(site(x), dims, x.elementType);
         emitXir(snippet, x, stateFor(x), null, true);
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java	Tue May 31 13:34:52 2011 +0200
@@ -1079,7 +1079,7 @@
 
         // Exit the monitor and unwind the stack.
         genMonitorExit(lock);
-        append(new Unwind(frameState.apop(), graph));
+        append(new Unwind(frameState.apop(), graph.end(), graph));
 
         // The sync handler is always the last thing to add => we can clear the frameState.
         frameState = null;
@@ -1148,7 +1148,7 @@
                 append(new MonitorExit(rootMethodSynchronizedObject, lockAddress, lockNumber, graph));
                 frameState.unlock();
             }
-            append(new Unwind(frameState.apop(), graph));
+            append(new Unwind(frameState.apop(), graph.end(), graph));
         } else {
             assert frameState.stackSize() == 1;
 
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Tue May 31 13:34:52 2011 +0200
@@ -82,6 +82,14 @@
         }
 
         new PhiSimplifier(this);
+
+//        Graph newGraph = new Graph();
+//        HashMap<Node, Node> replacement = new HashMap<Node, Node>();
+//        replacement.put(compilation.graph.start(), newGraph.start());
+//        replacement.put(compilation.graph.end(), newGraph.end());
+//        newGraph.addDuplicate(compilation.graph.getNodes(), replacement);
+//        compilation.graph = newGraph;
+
         Schedule schedule = new Schedule(this.compilation.graph);
         List<Block> blocks = schedule.getBlocks();
         List<LIRBlock> lirBlocks = new ArrayList<LIRBlock>();
@@ -160,14 +168,6 @@
         // Graph builder must set the startBlock and the osrEntryBlock
         new GraphBuilder(compilation, this, compilation.graph).build();
 
-//        Graph newGraph = new Graph();
-//        HashMap<Node, Node> replacement = new HashMap<Node, Node>();
-//        replacement.put(compilation.graph.start(), newGraph.start());
-//        replacement.put(compilation.graph.end(), newGraph.end());
-//        newGraph.addDuplicate(compilation.graph.getNodes(), replacement);
-//
-//        compilation.graph = newGraph;
-
         verifyAndPrint("After graph building");
 
         if (C1XOptions.PrintCompilation) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/AccessField.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/AccessField.java	Tue May 31 13:34:52 2011 +0200
@@ -66,14 +66,12 @@
      * @param kind the result kind of the access
      * @param object the instruction producing the receiver object
      * @param field the compiler interface representation of the field
-     * @param stateBefore the state before the field access
      * @param inputCount
      * @param successorCount
      * @param graph
      */
     public AccessField(CiKind kind, Value object, RiField field, int inputCount, int successorCount, Graph graph) {
         super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
-//        assert object != null : "every field access must reference some object";
         this.field = field;
         setObject(object);
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/If.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/If.java	Tue May 31 13:34:52 2011 +0200
@@ -77,15 +77,14 @@
     /**
      * Constructs a new If instruction.
      * @param x the instruction producing the first input to the instruction
-     * @param cond the condition (comparison operation)
+     * @param condition the condition (comparison operation)
      * @param y the instruction that produces the second input to this instruction
-     * @param stateAfter the state before the branch but after the input values have been popped
      * @param graph
      */
-    public If(Value x, Condition cond, Value y, Graph graph) {
+    public If(Value x, Condition condition, Value y, Graph graph) {
         super(CiKind.Illegal, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         assert (x == null && y == null) || Util.archKindsEqual(x, y);
-        condition = cond;
+        this.condition = condition;
         setX(x);
         setY(y);
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/IfOp.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/IfOp.java	Tue May 31 13:34:52 2011 +0200
@@ -80,19 +80,20 @@
     /**
      * Constructs a new IfOp.
      * @param x the instruction producing the first value to be compared
-     * @param cond the condition of the comparison
+     * @param condition the condition of the comparison
      * @param y the instruction producing the second value to be compared
      * @param trueValue the value produced if the condition is true
      * @param falseValue the value produced if the condition is false
      */
-    public IfOp(Value x, Condition cond, Value y, Value trueValue, Value falseValue, Graph graph) {
+    public IfOp(Value x, Condition condition, Value y, Value trueValue, Value falseValue, Graph graph) {
         // TODO: return the appropriate bytecode IF_ICMPEQ, etc
         super(trueValue.kind.meet(falseValue.kind), Bytecodes.ILLEGAL, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        this.condition = cond;
+        this.condition = condition;
         setTrueValue(trueValue);
         setFalseValue(falseValue);
     }
 
+    // for copying
     private IfOp(CiKind kind, Condition cond, Graph graph) {
         super(kind, Bytecodes.ILLEGAL, null, null, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.condition = cond;
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/InstanceOf.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/InstanceOf.java	Tue May 31 13:34:52 2011 +0200
@@ -41,7 +41,6 @@
      * Constructs a new InstanceOf instruction.
      * @param targetClass the target class of the instanceof check
      * @param object the instruction producing the object input to this instruction
-     * @param stateBefore the state before this instruction
      * @param graph
      */
     public InstanceOf(RiType targetClass, Value targetClassInstruction, Value object, Graph graph) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Invoke.java	Tue May 31 13:34:52 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.sun.c1x.ir;
 
+import java.util.*;
+
 import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.c1x.util.*;
@@ -184,6 +186,15 @@
     }
 
     @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("opcode", Bytecodes.nameOf(opcode));
+        properties.put("target", CiUtil.format("%H.%n(%p):%r", target, false));
+        properties.put("bci", bci);
+        return properties;
+    }
+
+    @Override
     public Node copy(Graph into) {
         Invoke x = new Invoke(bci, opcode, kind, new Value[argumentCount], target, returnType, into);
         x.setNonNull(isNonNull());
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/LoadIndexed.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LoadIndexed.java	Tue May 31 13:34:52 2011 +0200
@@ -40,12 +40,11 @@
      * @param array the instruction producing the array
      * @param index the instruction producing the index
      * @param length the instruction producing the length
-     * @param elementType the element type
-     * @param stateAfter the after before executing this instruction
+     * @param elementKind the element type
      * @param graph
      */
-    public LoadIndexed(Value array, Value index, Value length, CiKind elementType, Graph graph) {
-        super(elementType.stackKind(), array, index, length, elementType, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    public LoadIndexed(Value array, Value index, Value length, CiKind elementKind, Graph graph) {
+        super(elementKind.stackKind(), array, index, length, elementKind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
     /**
@@ -88,7 +87,7 @@
 
     @Override
     public Node copy(Graph into) {
-        LoadIndexed x = new LoadIndexed(null, null, null, kind, into);
+        LoadIndexed x = new LoadIndexed(null, null, null, elementKind(), into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Local.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Local.java	Tue May 31 13:34:52 2011 +0200
@@ -43,7 +43,6 @@
     public Local(CiKind kind, int javaIndex, Graph graph) {
         super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         this.index = javaIndex;
-        this.inputs().set(0, graph.start());
     }
 
     /**
@@ -98,6 +97,4 @@
         x.setNonNull(isNonNull());
         return x;
     }
-
-
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/LogicOp.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LogicOp.java	Tue May 31 13:34:52 2011 +0200
@@ -45,7 +45,8 @@
         super(x.kind, opcode, x, y, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
-    public LogicOp(CiKind kind, int opcode, Graph graph) {
+    // for copying
+    private LogicOp(CiKind kind, int opcode, Graph graph) {
         super(kind, opcode, null, null, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
 
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorEnter.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorEnter.java	Tue May 31 13:34:52 2011 +0200
@@ -45,7 +45,6 @@
      * @param object the instruction producing the object
      * @param lockAddress the address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack
      * @param lockNumber the number of the lock
-     * @param stateAfter the state after
      * @param graph
      */
     public MonitorEnter(Value object, Value lockAddress, int lockNumber, Graph graph) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorExit.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/MonitorExit.java	Tue May 31 13:34:52 2011 +0200
@@ -39,7 +39,6 @@
      * @param object the instruction produces the object value
      * @param lockAddress the address of the on-stack lock object or {@code null} if the runtime does not place locks on the stack
      * @param lockNumber the number of the lock
-     * @param stateBefore the state after executing this instruction
      * @param graph
      */
     public MonitorExit(Value object, Value lockAddress, int lockNumber, Graph graph) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NegateOp.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NegateOp.java	Tue May 31 13:34:52 2011 +0200
@@ -69,6 +69,7 @@
         setX(x);
     }
 
+    // for copying
     private NegateOp(CiKind kind, Graph graph) {
         super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NewMultiArray.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NewMultiArray.java	Tue May 31 13:34:52 2011 +0200
@@ -67,23 +67,23 @@
         return dimensionCount;
     }
 
-    public final RiType elementKind;
+    public final RiType elementType;
     public final int cpi;
     public final RiConstantPool constantPool;
 
     /**
      * Constructs a new NewMultiArray instruction.
-     * @param elementKind the element type of the array
+     * @param elementType the element type of the array
      * @param dimensions the instructions which produce the dimensions for this array
      * @param stateBefore the state before this instruction
      * @param cpi the constant pool index for resolution
      * @param riConstantPool the constant pool for resolution
      * @param graph
      */
-    public NewMultiArray(RiType elementKind, Value[] dimensions, int cpi, RiConstantPool riConstantPool, Graph graph) {
+    public NewMultiArray(RiType elementType, Value[] dimensions, int cpi, RiConstantPool riConstantPool, Graph graph) {
         super(null, dimensions.length, SUCCESSOR_COUNT, graph);
         this.constantPool = riConstantPool;
-        this.elementKind = elementKind;
+        this.elementType = elementType;
         this.cpi = cpi;
 
         this.dimensionCount = dimensions.length;
@@ -102,7 +102,7 @@
      * @return the element type of the array
      */
     public RiType elementType() {
-        return elementKind;
+        return elementType;
     }
 
     @Override
@@ -114,12 +114,12 @@
           }
           out.print(dimension(i));
         }
-        out.print("] ").print(CiUtil.toJavaName(elementKind));
+        out.print("] ").print(CiUtil.toJavaName(elementType));
     }
 
     @Override
     public Node copy(Graph into) {
-        NewMultiArray x = new NewMultiArray(elementKind, new Value[dimensionCount], cpi, constantPool, into);
+        NewMultiArray x = new NewMultiArray(elementType, new Value[dimensionCount], cpi, constantPool, into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NewObjectArray.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NewObjectArray.java	Tue May 31 13:34:52 2011 +0200
@@ -41,7 +41,6 @@
      * Constructs a new NewObjectArray instruction.
      * @param elementClass the class of elements in this array
      * @param length the instruction producing the length of the array
-     * @param stateBefore the state before the allocation
      * @param graph
      */
     public NewObjectArray(RiType elementClass, Value length, Graph graph) {
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/NullCheck.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/NullCheck.java	Tue May 31 13:34:52 2011 +0200
@@ -26,6 +26,7 @@
 import com.sun.c1x.debug.*;
 import com.sun.c1x.util.*;
 import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
 /**
@@ -71,6 +72,12 @@
         setObject(object);
     }
 
+    // for copying
+    private NullCheck(CiKind kind, Graph graph) {
+        super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+        setNonNull(true);
+    }
+
     @Override
     public void accept(ValueVisitor v) {
         v.visitNullCheck(this);
@@ -109,7 +116,7 @@
 
     @Override
     public Node copy(Graph into) {
-        NullCheck x = new NullCheck(null, into);
+        NullCheck x = new NullCheck(kind, into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Return.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Return.java	Tue May 31 13:34:52 2011 +0200
@@ -75,6 +75,11 @@
         successors().set(SUCCESSOR_END, graph.end());
     }
 
+    // for copying
+    private Return(CiKind kind, Graph graph) {
+        super(kind, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
+    }
+
     @Override
     public void accept(ValueVisitor v) {
         v.visitReturn(this);
@@ -91,7 +96,7 @@
 
     @Override
     public Node copy(Graph into) {
-        Return x = new Return(null, into);
+        Return x = new Return(kind, into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Unwind.java	Tue May 31 13:34:52 2011 +0200
@@ -64,10 +64,10 @@
         return (Value) inputs().set(super.inputCount() + INPUT_EXCEPTION, n);
     }
 
-    public Unwind(Value exception, Graph graph) {
+    public Unwind(Value exception, Node successor, Graph graph) {
         super(CiKind.Object, 0, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setException(exception);
-        successors().set(SUCCESSOR_END, graph.end());
+        successors().set(SUCCESSOR_END, successor);
     }
 
     @Override
@@ -82,7 +82,7 @@
 
     @Override
     public Node copy(Graph into) {
-        Unwind x = new Unwind(null, into);
+        Unwind x = new Unwind(null, null, into);
         x.setNonNull(isNonNull());
         return x;
     }
--- a/graal/GraalCompiler/src/com/sun/c1x/ir/Value.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Value.java	Tue May 31 13:34:52 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.sun.c1x.ir;
 
+import java.util.*;
+
 import com.oracle.graal.graph.*;
 import com.sun.c1x.debug.*;
 import com.sun.cri.ci.*;
@@ -213,4 +215,14 @@
 
     public abstract void print(LogStream out);
 
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> properties = super.getDebugProperties();
+        properties.put("kind", kind.toString());
+        properties.put("nonNull", isNonNull);
+        properties.put("operand", operand == null ? "null" : operand.toString());
+        return properties;
+    }
+
+
 }
--- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameStateBuilder.java	Tue May 31 13:34:52 2011 +0200
@@ -54,6 +54,7 @@
         if (!isStatic(method.accessFlags())) {
             // add the receiver and assume it is non null
             Local local = new Local(method.holder().kind(), javaIndex, graph);
+            local.inputs().set(0, graph.start());
             local.setNonNull(true);
             local.setDeclaredType(method.holder());
             storeLocal(javaIndex, local);
@@ -67,6 +68,7 @@
             RiType type = sig.argumentTypeAt(i, accessingClass);
             CiKind kind = type.kind().stackKind();
             Local local = new Local(kind, index, graph);
+            local.inputs().set(0, graph.start());
             if (type.isResolved()) {
                 local.setDeclaredType(type);
             }
--- a/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java	Tue May 31 09:51:59 2011 +0200
+++ b/graal/GraalGraph/src/com/oracle/graal/graph/Graph.java	Tue May 31 13:34:52 2011 +0200
@@ -74,22 +74,18 @@
 
     public void addDuplicate(Collection<Node> nodes, Map<Node, Node> replacements) {
         Map<Node, Node> newNodes = new HashMap<Node, Node>();
+        // create node duplicates
         for (Node node : nodes) {
             if (node != null && !replacements.containsKey(node)) {
-                newNodes.put(node, node.copy(this));
+                Node newNode = node.copy(this);
+                assert newNode.getClass() == node.getClass();
+                newNodes.put(node, newNode);
             }
         }
+        // re-wire inputs
         for (Entry<Node, Node> entry : newNodes.entrySet()) {
             Node oldNode = entry.getKey();
             Node node = entry.getValue();
-            for (int i = 0; i < oldNode.successors().size(); i++) {
-                Node succ = oldNode.successors().get(i);
-                Node target = replacements.get(succ);
-                if (target == null) {
-                    target = newNodes.get(succ);
-                }
-                node.successors().set(i, target);
-            }
             for (int i = 0; i < oldNode.inputs().size(); i++) {
                 Node input = oldNode.inputs().get(i);
                 Node target = replacements.get(input);
@@ -102,12 +98,6 @@
         for (Entry<Node, Node> entry : replacements.entrySet()) {
             Node oldNode = entry.getKey();
             Node node = entry.getValue();
-            for (int i = 0; i < oldNode.successors().size(); i++) {
-                Node succ = oldNode.successors().get(i);
-                if (newNodes.containsKey(succ)) {
-                    node.successors().set(i, newNodes.get(succ));
-                }
-            }
             for (int i = 0; i < oldNode.inputs().size(); i++) {
                 Node input = oldNode.inputs().get(i);
                 if (newNodes.containsKey(input)) {
@@ -115,5 +105,30 @@
                 }
             }
         }
+        // re-wire successors
+        for (Entry<Node, Node> entry : newNodes.entrySet()) {
+            Node oldNode = entry.getKey();
+            Node node = entry.getValue();
+            for (int i = 0; i < oldNode.predecessors().size(); i++) {
+                Node pred = oldNode.predecessors().get(i);
+                int predIndex = oldNode.predecessorsIndex().get(i);
+                Node source = replacements.get(pred);
+                if (source == null) {
+                    source = newNodes.get(pred);
+                }
+                source.successors().set(predIndex,  node);
+            }
+        }
+        for (Entry<Node, Node> entry : replacements.entrySet()) {
+            Node oldNode = entry.getKey();
+            Node node = entry.getValue();
+            for (int i = 0; i < oldNode.predecessors().size(); i++) {
+                Node pred = oldNode.predecessors().get(i);
+                int predIndex = oldNode.predecessorsIndex().get(i);
+                if (newNodes.containsKey(pred)) {
+                    newNodes.get(pred).successors().set(predIndex, node);
+                }
+            }
+        }
     }
 }