changeset 2967:60a58915c94d

Removed next pointer from EndNode to Merge. New scheduler.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 15 Jun 2011 16:53:30 +0200
parents 0048537e3cd7
children 9133554259c5
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BlockEnd.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Instruction.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java
diffstat 16 files changed, 208 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java	Wed Jun 15 16:53:30 2011 +0200
@@ -25,8 +25,10 @@
 import java.util.*;
 
 import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.graph.*;
 
 /**
  * This class optimizes moves, particularly those that result from eliminating SSA form.
@@ -190,6 +192,12 @@
         List<LIRInstruction> instructions = block.lir().instructionsList();
 
         assert numSux == 2 : "method should not be called otherwise";
+
+        if ( instructions.get(instructions.size() - 1).code != LIROpcode.Branch) {
+            for (Node n : block.getInstructions()) {
+                TTY.println("instr: " + n);
+            }
+        }
         assert instructions.get(instructions.size() - 1).code == LIROpcode.Branch : "block with successor must end with branch block=B" + block.blockID();
         assert instructions.get(instructions.size() - 1) instanceof LIRBranch : "branch must be LIROpBranch";
         assert ((LIRBranch) instructions.get(instructions.size() - 1)).cond() == Condition.TRUE : "block must end with unconditional branch";
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Jun 15 16:53:30 2011 +0200
@@ -260,9 +260,19 @@
                 }
             }
         }
-        if (block.blockSuccessors().size() >= 1 && (block.getInstructions().size() == 0  || !jumpsToNextBlock(block.getInstructions().get(block.getInstructions().size() - 1)))) {
+        if (block.blockSuccessors().size() >= 1 && !jumpsToNextBlock(block.lastInstruction())) {
             moveToPhi();
-            block.lir().jump(block.blockSuccessors().get(0));
+            Node last = block.lastInstruction();
+            if (last instanceof EndNode) {
+                EndNode end = (EndNode) last;
+                block.lir().jump(getLIRBlock(end.merge()));
+            } else if (last instanceof LoopEnd) {
+                LoopEnd loopEnd = (LoopEnd) last;
+                block.lir().jump(getLIRBlock(loopEnd.loopBegin()));
+            } else {
+//                TTY.println("lastInstr: " + block.lastInstruction() + ", block=" + block.blockID());
+                block.lir().jump(getLIRBlock((FixedNode) block.lastInstruction().successors().get(0)));
+            }
         }
 
         if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
@@ -697,7 +707,7 @@
         }
     }
 
-    protected LIRBlock getLIRBlock(Instruction b) {
+    protected LIRBlock getLIRBlock(FixedNode b) {
         if (b == null) {
             return null;
         }
@@ -1409,25 +1419,33 @@
         if (bb.numberOfSux() == 1) {
 
             Node lastNode = bb.lastInstruction();
-            if (lastNode instanceof Instruction || lastNode == lastNode.graph().start()) {
-                Node nextInstr = lastNode.successors().get(Instruction.SUCCESSOR_NEXT);
-                int nextSuccIndex = lastNode.successorTags()[Instruction.SUCCESSOR_NEXT];
+            if (lastNode instanceof EndNode || lastNode instanceof LoopEnd || lastNode instanceof Anchor) {
+                Node nextInstr = null;
+                int nextSuccIndex;
 
                 if (lastNode instanceof LoopEnd) {
                     LoopEnd loopEnd = (LoopEnd) lastNode;
                     nextInstr = loopEnd.loopBegin();
-                    nextSuccIndex = loopEnd.loopBegin().predecessors().size() + 1;
+                    nextSuccIndex = loopEnd.loopBegin().endCount();
+                } else if (lastNode instanceof Anchor) {
+                    assert false;
+                    nextSuccIndex = -1;
+                } else {
+                    assert lastNode instanceof EndNode;
+                    nextInstr = ((EndNode) lastNode).merge();
+                    nextSuccIndex = nextInstr.inputs().variablePart().indexOf(lastNode);
                 }
+
                 if (nextInstr instanceof Merge) {
                     Merge merge = (Merge) nextInstr;
-                    assert nextSuccIndex > 0 : "nextSuccIndex=" + nextSuccIndex + ", lastNode=" + lastNode + ", nextInstr=" + nextInstr + "; preds=" + nextInstr.predecessors() + "; predIndex=" + nextInstr.predecessorsIndex();
+                    assert nextSuccIndex >= 0 : "nextSuccIndex=" + nextSuccIndex + ", lastNode=" + lastNode + ", nextInstr=" + nextInstr + "; preds=" + nextInstr.predecessors() + "; predIndex=" + nextInstr.predecessorsIndex();
 
                     PhiResolver resolver = new PhiResolver(this);
                     for (Node n : merge.usages()) {
                         if (n instanceof Phi) {
                             Phi phi = (Phi) n;
                             if (!phi.isDead()) {
-                                Value curVal = phi.valueAt(nextSuccIndex - 1);
+                                Value curVal = phi.valueAt(nextSuccIndex);
                                 if (curVal != null && curVal != phi) {
                                     if (curVal instanceof Phi) {
                                         operandForPhi((Phi) curVal);
@@ -1446,6 +1464,7 @@
                 }
                 return;
             }
+            /*
 
             assert false : "lastNode=" + lastNode + " instr=" + bb.getInstructions();
 
@@ -1489,7 +1508,7 @@
                     }
                     resolver.dispose();
                 }
-            }
+            }*/
         }
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Wed Jun 15 16:53:30 2011 +0200
@@ -141,7 +141,7 @@
                 valueToBlock.put(i, b);
             }
         }
-        startBlock = lirBlocks.get(0);
+        startBlock = valueToBlock.get(graph.start());
         assert startBlock != null;
         assert startBlock.blockPredecessors().size() == 0;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BlockEnd.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/BlockEnd.java	Wed Jun 15 16:53:30 2011 +0200
@@ -51,14 +51,14 @@
     /**
      * The list of instructions that produce input for this instruction.
      */
-    public Instruction blockSuccessor(int index) {
+    public FixedNode blockSuccessor(int index) {
         assert index >= 0 && index < blockSuccessorCount;
-        return (Instruction) successors().get(super.successorCount() + SUCCESSOR_COUNT + index);
+        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_COUNT + index);
     }
 
-    public Instruction setBlockSuccessor(int index, Instruction n) {
+    public FixedNode setBlockSuccessor(int index, FixedNode n) {
         assert index >= 0 && index < blockSuccessorCount;
-        return (Merge) successors().set(super.successorCount() + SUCCESSOR_COUNT + index, n);
+        return (FixedNode) successors().set(super.successorCount() + SUCCESSOR_COUNT + index, n);
     }
 
     public int blockSuccessorCount() {
@@ -87,19 +87,6 @@
     }
 
     /**
-     * Gets the block begin associated with this block end.
-     * @return the beginning of this basic block
-     */
-    public Merge begin() {
-        for (Node n : predecessors()) {
-            if (n instanceof Merge) {
-                return (Merge) n;
-            }
-        }
-        return null;
-    }
-
-    /**
      * Substitutes a successor block in this block end's successor list. Note that
      * this method updates all occurrences in the list.
      * @param oldSucc the old successor to replace
@@ -121,7 +108,7 @@
      * Gets the successor corresponding to the default (fall through) case.
      * @return the default successor
      */
-    public Instruction defaultSuccessor() {
+    public FixedNode defaultSuccessor() {
         return blockSuccessor(blockSuccessorCount - 1);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Wed Jun 15 16:53:30 2011 +0200
@@ -121,7 +121,7 @@
             case AT: return BE;
             case AE: return BT;
         }
-        throw new IllegalArgumentException();
+        throw new IllegalArgumentException(this.toString());
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/EndNode.java	Wed Jun 15 16:53:30 2011 +0200
@@ -27,7 +27,7 @@
 import com.sun.cri.ci.*;
 
 
-public final class EndNode extends Instruction {
+public final class EndNode extends FixedNode {
     public static final int SUCCESSOR_COUNT = 0;
     public static final int INPUT_COUNT = 0;
     public EndNode(Graph graph) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ExceptionDispatch.java	Wed Jun 15 16:53:30 2011 +0200
@@ -64,7 +64,7 @@
     /**
      * Constructs a new ExceptionDispatch instruction.
      */
-    public ExceptionDispatch(Value exception, Instruction catchSuccessor, Instruction otherSuccessor, RiType catchType, Graph graph) {
+    public ExceptionDispatch(Value exception, FixedNode catchSuccessor, FixedNode otherSuccessor, RiType catchType, Graph graph) {
         super(CiKind.Int, 2, INPUT_COUNT, SUCCESSOR_COUNT, graph);
         setException(exception);
         setBlockSuccessor(0, otherSuccessor);
@@ -80,7 +80,7 @@
      * Gets the block corresponding to the catch block.
      * @return the true successor
      */
-    public Instruction catchSuccessor() {
+    public FixedNode catchSuccessor() {
         return blockSuccessor(1);
     }
 
@@ -88,7 +88,7 @@
      * Gets the block corresponding to the rest of the dispatch chain.
      * @return the false successor
      */
-    public Instruction otherSuccessor() {
+    public FixedNode otherSuccessor() {
         return blockSuccessor(0);
     }
 
@@ -97,7 +97,7 @@
      * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
      * @return the corresponding successor
      */
-    public Instruction successor(boolean istrue) {
+    public FixedNode successor(boolean istrue) {
         return blockSuccessor(istrue ? 1 : 0);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Wed Jun 15 16:53:30 2011 +0200
@@ -67,7 +67,7 @@
      * Gets the block corresponding to the true successor.
      * @return the true successor
      */
-    public Instruction trueSuccessor() {
+    public FixedNode trueSuccessor() {
         return blockSuccessor(0);
     }
 
@@ -75,7 +75,7 @@
      * Gets the block corresponding to the false successor.
      * @return the false successor
      */
-    public Instruction falseSuccessor() {
+    public FixedNode falseSuccessor() {
         return blockSuccessor(1);
     }
 
@@ -84,7 +84,7 @@
      * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
      * @return the corresponding successor
      */
-    public Instruction successor(boolean istrue) {
+    public FixedNode successor(boolean istrue) {
         return blockSuccessor(istrue ? 0 : 1);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Instruction.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Instruction.java	Wed Jun 15 16:53:30 2011 +0200
@@ -60,11 +60,11 @@
      * Links to next instruction in a basic block, to {@code null} if this instruction is the end of a basic block or to
      * itself if not in a block.
      */
-    public Instruction next() {
-        return (Instruction) successors().get(super.successorCount() + SUCCESSOR_NEXT);
+    public FixedNode next() {
+        return (FixedNode) successors().get(super.successorCount() + SUCCESSOR_NEXT);
     }
 
-    public Node setNext(Instruction next) {
+    public Node setNext(FixedNode next) {
         return successors().set(super.successorCount() + SUCCESSOR_NEXT, next);
     }
 
@@ -87,18 +87,6 @@
     }
 
     /**
-     * Get the number of predecessors.
-     * @return the number of predecessors
-     */
-    public int numberOfPreds() {
-        return predecessors().size();
-    }
-
-    public Instruction predAt(int j) {
-        return (Instruction) predecessors().get(j);
-    }
-
-    /**
      * Gets the state after the instruction, if it is recorded.
      * @return the state after the instruction
      */
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Wed Jun 15 16:53:30 2011 +0200
@@ -108,7 +108,6 @@
             }
             hasSucc = true;
         }
-
         return builder.toString();
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Wed Jun 15 16:53:30 2011 +0200
@@ -83,8 +83,13 @@
 
     private void iterateSuccessors() {
         for (Node current : flood) {
-            for (Node successor : current.successors()) {
-                flood.add(successor);
+            if (current instanceof EndNode) {
+                EndNode end = (EndNode) current;
+                flood.add(end.merge());
+            } else {
+                for (Node successor : current.successors()) {
+                    flood.add(successor);
+                }
             }
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Wed Jun 15 16:53:30 2011 +0200
@@ -162,7 +162,7 @@
         // 1. create the start block
         Block startBlock = nextBlock(Instruction.SYNCHRONIZATION_ENTRY_BCI);
         markOnWorkList(startBlock);
-        lastInstr = createTarget(startBlock, frameState);
+        lastInstr = (Instruction) createTarget(startBlock, frameState);
         graph.start().setStart(lastInstr);
 
         if (isSynchronized(method.accessFlags())) {
@@ -264,8 +264,7 @@
 
     private void finishStartBlock(Block startBlock) {
         assert bci() == 0;
-        Instruction target = createTargetAt(0, frameState);
-        appendGoto(target);
+        appendGoto(createTargetAt(0, frameState));
     }
 
     public void mergeOrClone(Block target, FrameStateAccess newState) {
@@ -311,11 +310,10 @@
                 assert p.predecessors().size() == 1;
                 assert p.next() == null;
 
-                Node pred = p.predecessors().get(0);
                 EndNode end = new EndNode(graph);
                 p.replace(end);
                 merge.addEnd(end);
-                end.setNext(merge);
+                //end.setNext(merge);
                 target.firstInstruction = merge;
                 merge.setStateBefore(existingState);
                 first = merge;
@@ -431,8 +429,7 @@
             }
             FrameState stateWithException = entryState.duplicateModified(bci, CiKind.Void, currentExceptionObject);
 
-            Instruction successor = createTarget(dispatchBlock, stateWithException);
-            currentNext.setNext(successor);
+            currentNext.setNext(createTarget(dispatchBlock, stateWithException));
             return entry;
         }
         return null;
@@ -665,14 +662,14 @@
         If ifNode = new If(new Compare(x, cond, y, graph), graph);
         append(ifNode);
         BlockMap.BranchOverride override = branchOverride.get(bci());
-        Instruction tsucc;
+        FixedNode tsucc;
         if (override == null || override.taken == false) {
             tsucc = createTargetAt(stream().readBranchDest(), frameState);
         } else {
             tsucc = createTarget(override.block, frameState);
         }
         ifNode.setBlockSuccessor(0, tsucc);
-        Instruction fsucc;
+        FixedNode fsucc;
         if (override == null || override.taken == true) {
             fsucc = createTargetAt(stream().nextBCI(), frameState);
         } else {
@@ -1116,11 +1113,11 @@
         return x;
     }
 
-    private Instruction createTargetAt(int bci, FrameStateAccess stateAfter) {
+    private FixedNode createTargetAt(int bci, FrameStateAccess stateAfter) {
         return createTarget(blockFromBci[bci], stateAfter);
     }
 
-    private Instruction createTarget(Block block, FrameStateAccess stateAfter) {
+    private FixedNode createTarget(Block block, FrameStateAccess stateAfter) {
         assert block != null && stateAfter != null;
         assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null :
             "non-loop block must be iterated after all its predecessors. startBci=" + block.startBci + ", " + block.getClass().getSimpleName() + ", " + block.firstInstruction.next();
@@ -1142,7 +1139,7 @@
         mergeOrClone(block, stateAfter);
         addToWorkList(block);
 
-        Instruction result = null;
+        FixedNode result = null;
         if (block.firstInstruction instanceof LoopBegin && isVisited(block)) {
             result = ((LoopBegin) block.firstInstruction).loopEnd();
         } else {
@@ -1153,7 +1150,7 @@
 
         if (result instanceof Merge) {
             EndNode end = new EndNode(graph);
-            end.setNext(result);
+            //end.setNext(result);
             ((Merge) result).addEnd(end);
             result = end;
         }
@@ -1260,20 +1257,20 @@
 
             Block nextBlock = block.next == null ? unwindBlock() : block.next;
             if (block.handler.catchType().isResolved()) {
-                Instruction catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState);
-                Instruction nextDispatch = createTarget(nextBlock, frameState);
+                FixedNode catchSuccessor = createTarget(blockFromBci[block.handler.handlerBCI()], frameState);
+                FixedNode nextDispatch = createTarget(nextBlock, frameState);
                 append(new ExceptionDispatch(frameState.stackAt(0), catchSuccessor, nextDispatch, block.handler.catchType(), graph));
             } else {
                 Deoptimize deopt = new Deoptimize(DeoptAction.InvalidateRecompile, graph);
                 deopt.setMessage("unresolved " + block.handler.catchType().name());
                 append(deopt);
-                Instruction nextDispatch = createTarget(nextBlock, frameState);
+                FixedNode nextDispatch = createTarget(nextBlock, frameState);
                 appendGoto(nextDispatch);
             }
         }
     }
 
-    private void appendGoto(Instruction target) {
+    private void appendGoto(FixedNode target) {
         lastInstr.setNext(target);
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Wed Jun 15 16:53:30 2011 +0200
@@ -236,6 +236,7 @@
             System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
         }
 
+        assert invoke.successors().get(0) != null : invoke;
         assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
         Instruction pred;
         if (withReceiver) {
@@ -243,7 +244,7 @@
             clipNode.setNode(new IsNonNull(parameters[0], compilation.graph));
             pred = clipNode;
         } else {
-            pred = new Merge(compilation.graph);
+            pred = new Placeholder(compilation.graph);//(Instruction) invoke.predecessors().get(0);//new Merge(compilation.graph);
         }
         invoke.predecessors().get(0).successors().replace(invoke, pred);
         replacements.put(startNode, pred);
@@ -261,6 +262,10 @@
             }
         }
 
+        if (pred instanceof Placeholder) {
+            pred.replace(((Placeholder)pred).next());
+        }
+
         if (returnNode != null) {
             List<Node> usages = new ArrayList<Node>(invoke.usages());
             for (Node usage : usages) {
@@ -273,17 +278,18 @@
             Node returnDuplicate = duplicates.get(returnNode);
             returnDuplicate.inputs().clearAll();
 
-            Merge mergeAfter = new Merge(compilation.graph);
-
             assert returnDuplicate.predecessors().size() == 1;
             Node returnPred = returnDuplicate.predecessors().get(0);
-            int index = returnDuplicate.predecessorsIndex().get(0);
-            mergeAfter.successors().setAndClear(0, invoke, 0);
-            returnPred.successors().set(index, mergeAfter);
 
-            returnDuplicate.delete();
+//            Merge mergeAfter = new Merge(compilation.graph);
+//            mergeAfter.setStateBefore(stateAfter);
+//            int index = returnDuplicate.predecessorsIndex().get(0);
+//            mergeAfter.successors().setAndClear(0, invoke, 0);
+//            returnPred.successors().set(index, mergeAfter);
 
-            mergeAfter.setStateBefore(stateAfter);
+            int index = returnDuplicate.predecessorsIndex().get(0);
+            returnPred.successors().setAndClear(index, invoke, 0);
+            returnDuplicate.delete();
         }
 
         if (exceptionEdge != null) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Wed Jun 15 16:53:30 2011 +0200
@@ -78,6 +78,13 @@
     private Block assignBlock(Node n, Block b) {
         assert nodeToBlock.get(n) == null;
         nodeToBlock.set(n, b);
+        for (Node input : n.inputs()) {
+            if (input instanceof FrameState) {
+                assert nodeToBlock.get(n) == null;
+                nodeToBlock.set(n, b);
+            }
+        }
+
         if (b.firstNode() == null) {
             b.setFirstNode(n);
             b.setLastNode(n);
@@ -91,6 +98,26 @@
         return b;
     }
 
+    private Block assignBlockNew(Node n, Block b) {
+        if (b == null) {
+            b = createBlock();
+        }
+
+        assert nodeToBlock.get(n) == null;
+        nodeToBlock.set(n, b);
+        if (b.lastNode() == null) {
+            b.setFirstNode(n);
+            b.setLastNode(n);
+        } else {
+            if (b.firstNode() != b.lastNode()) {
+                b.getInstructions().add(0, b.firstNode());
+            }
+            b.setFirstNode(n);
+        }
+
+        return b;
+    }
+
     public static boolean isFixed(Node n) {
         return n != null && ((n instanceof FixedNode) || n == n.graph().start());
     }
@@ -101,7 +128,8 @@
 
     private void identifyBlocks() {
         // Identify blocks.
-        final ArrayList<Node> blockBeginNodes = new ArrayList<Node>();
+
+        /*final ArrayList<Node> blockBeginNodes = new ArrayList<Node>();
         NodeIterator.iterate(EdgeType.SUCCESSORS, graph.start(), null, new NodeVisitor() {
             @Override
             public boolean visit(Node n) {
@@ -145,27 +173,79 @@
                 }
                 return true;
             }}
-        );
+        );*/
+
+        for (Node n : graph.getNodes()) {
+            if (n != null) {
+                if (n instanceof EndNode || n instanceof Return || n instanceof Unwind || n instanceof LoopEnd) {
+                    Block block = null;
+                    while (nodeToBlock.get(n) == null) {
+                        if (block != null && IdentifyBlocksPhase.trueSuccessorCount(n) > 1) {
+
+
+                            // We are at a split => start a new block.
+                            block = null;
+                        }
+                        block = assignBlockNew(n, block);
+                        if (n.predecessors().size() == 0) {
+                            // Either dead code or at a merge => stop iteration.
+                            break;
+                        }
+                        if (n.predecessors().size() > 1) {
+                            TTY.println("n=" + n);
+                            for (Node p : n.predecessors()) {
+                                TTY.println("pred=" + p);
+                            }
+                            for (Node s : n.successors()) {
+                                TTY.println("succ=" + s);
+                            }
+                        }
+                        assert n.predecessors().size() == 1 : "preds: " + n;
+                        n = n.predecessors().get(0);
+                    }
+                }
+            }
+        }
 
         // Connect blocks.
-        for (Node n : blockBeginNodes) {
-            Block block = nodeToBlock.get(n);
-            for (Node pred : n.predecessors()) {
-                if (isFixed(pred)) {
-                    Block predBlock = nodeToBlock.get(pred);
-                    predBlock.addSuccessor(block);
-                }
-            }
-
+        for (Block block : blocks) {
+            Node n = block.firstNode();
             if (n instanceof Merge) {
+                //TTY.println("merge " + n + " is first of block " + block.blockID());
                 for (Node usage : n.usages()) {
                     if (usage instanceof Phi) {
                         nodeToBlock.set(usage, block);
                     }
                 }
+                Merge m = (Merge) n;
+//                TTY.println("merging " + m.endCount() + " ends");
+                for (int i=0; i<m.endCount(); ++i) {
+                    EndNode end = m.endAt(i);
+                    Block predBlock = nodeToBlock.get(end);
+                    predBlock.addSuccessor(block);
+                }
+            } else {
+//                TTY.println("node " + n + " is first of block " + block.blockID());
+                for (Node pred : n.predecessors()) {
+                    if (isFixed(pred)) {
+                        Block predBlock = nodeToBlock.get(pred);
+                        predBlock.addSuccessor(block);
+                    }
+                }
             }
+
+//            TTY.println("node " + block.lastNode() + " is last");
         }
 
+//        for (Block block : blocks) {
+//            TTY.print("Block B" + block.blockID() + ": ");
+//            TTY.print("preds=");
+//            for (Block p : block.getPredecessors()) {
+//                TTY.print("B" + p.blockID() + ";");
+//            }
+//            TTY.println();
+//        }
+
         for (Node n : graph.getNodes()) {
             if (n instanceof FrameState) {
                 FrameState f = (FrameState) n;
@@ -174,6 +254,11 @@
                     assert predBlock != null;
                     nodeToBlock.set(f, predBlock);
                     predBlock.getInstructions().add(f);
+                } else if (f.usages().size() == 1) {
+//                    Block predBlock = nodeToBlock.get(f.usages().get(0));
+//                    assert predBlock != null;
+//                    nodeToBlock.set(f, predBlock);
+//                    predBlock.getInstructions().add(f);
                 } else {
                     assert f.predecessors().size() == 0;
                 }
@@ -186,8 +271,8 @@
         if (scheduleAllNodes) {
 
             // Add successors of loop end nodes. Makes the graph cyclic.
-            for (Node n : blockBeginNodes) {
-                Block block = nodeToBlock.get(n);
+            for (Block block : blocks) {
+                Node n = block.firstNode();
                 if (n instanceof LoopBegin) {
                     LoopBegin loopBegin = (LoopBegin) n;
                     nodeToBlock.get(loopBegin.loopEnd()).addSuccessor(block);
@@ -295,10 +380,9 @@
                 }
             } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) {
                 Merge merge = ((FrameState) usage).block();
-                for (Node pred : merge.predecessors()) {
-                    if (isFixed(pred)) {
-                        block = getCommonDominator(block, nodeToBlock.get(pred));
-                    }
+                for (int i=0; i<merge.endCount(); ++i) {
+                    EndNode pred = merge.endAt(i);
+                    block = getCommonDominator(block, nodeToBlock.get(pred));
                 }
             } else {
                 block = getCommonDominator(block, assignLatestPossibleBlockToNode(usage));
@@ -335,6 +419,8 @@
         assert !map.isMarked(b.firstNode()) && nodeToBlock.get(b.firstNode()) == b;
 
         boolean scheduleFirst = true;
+        assert !instructions.contains(b.lastNode());
+        assert !instructions.contains(b.firstNode());
 
         if (b.firstNode() == b.lastNode()) {
             Node node = b.firstNode();
@@ -349,6 +435,7 @@
             addToSorting(b, i, sortedInstructions, map);
         }
         addToSorting(b, b.lastNode(), sortedInstructions, map);
+        assert sortedInstructions.get(sortedInstructions.size() - 1) == b.lastNode() : "lastNode=" + b.lastNode() + ", firstNode=" + b.firstNode();
         b.setInstructions(sortedInstructions);
     }
 
@@ -357,8 +444,13 @@
             return;
         }
 
+        FrameState state = null;
         for (Node input : i.inputs()) {
-            addToSorting(b, input, sortedInstructions, map);
+//            if (input instanceof FrameState) {
+//               state = (FrameState) input;
+//            } else {
+                addToSorting(b, input, sortedInstructions, map);
+//            }
         }
 
         for (Node pred : i.predecessors()) {
@@ -367,6 +459,10 @@
 
         map.mark(i);
 
+        if (state != null) {
+            addToSorting(b, state, sortedInstructions, map);
+        }
+
         for (Node succ : i.successors()) {
             if (succ instanceof FrameState) {
                 addToSorting(b, succ, sortedInstructions, map);
@@ -458,21 +554,4 @@
         }
         return i;
     }
-
-    public static int truePredecessorCount(Node n) {
-        if (n == null) {
-            return 0;
-        }
-        int i = 0;
-        for (Node s : n.predecessors()) {
-            if (isFixed(s)) {
-                i++;
-            }
-        }
-
-        if (n instanceof LoopBegin) {
-            i++;
-        }
-        return i;
-    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Wed Jun 15 16:53:30 2011 +0200
@@ -378,7 +378,7 @@
                     }
 
                     if (phi.valueCount() == 0) {
-                        int size = block.predecessors().size();
+                        int size = block.endCount();
                         for (int j = 0; j < size; ++j) {
                             phi.addInput(x);
                         }
@@ -390,7 +390,7 @@
                     if (block instanceof LoopBegin) {
 //                        assert phi.valueCount() == ((LoopBegin) block).loopEnd().predecessors().size() + 1 : "loop, valueCount=" + phi.valueCount() + " predSize= " + ((LoopBegin) block).loopEnd().predecessors().size();
                     } else {
-                        assert phi.valueCount() == block.predecessors().size() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.predecessors().size();
+                        assert phi.valueCount() == block.endCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.endCount();
                     }
                }
             }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java	Wed Jun 15 13:49:12 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/NodeArray.java	Wed Jun 15 16:53:30 2011 +0200
@@ -128,6 +128,7 @@
         assert !self().isDeleted() : "trying to set input/successor of deleted node: " + self().shortName();
         assert node == Node.Null || node.graph == self().graph : "node is from different graph: (this=" + self() + ") and (node=" + node + ")";
         assert node == Node.Null || node.id() != Node.DeletedID : "inserted node must not be deleted";
+        assert node != self() || node.getClass().toString().contains("Phi") : "No direct circles allowed in the graph! " + node;
         
         Node old = get(index);
         if (old != node) {
@@ -229,7 +230,7 @@
         assert self().successors == this;
         Node value = clearedNode.successors.get(clearedIndex);
         self().successorTags[index] = clearedNode.successorTags[clearedIndex];
-        assert value != Node.Null;
+        assert value != Node.Null : "cannot clear null value";
         clearedNode.successors.nodes[clearedIndex] = Node.Null;
         set(index, Node.Null);
         nodes[index] = value;