changeset 3044:0c519981c6cf

LoopBegin is not a merge
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Thu, 16 Jun 2011 22:36:56 +0200
parents 47aef13c569c
children bde28dd4dec0
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.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/BlockMap.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.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/ir/Phi.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/schedule/IdentifyBlocksPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.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/Node.java
diffstat 11 files changed, 272 insertions(+), 123 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Thu Jun 16 22:36:56 2011 +0200
@@ -130,14 +130,14 @@
         }
         stream.println("  </edges>");
 
-        stream.println("  <controlFlow>");
         if (schedule != null) {
+            stream.println("  <controlFlow>");
             for (Block block : schedule.getBlocks()) {
                 printBlock(graph, block);
             }
+            printNoBlock();
+            stream.println("  </controlFlow>");
         }
-        printNoBlock();
-        stream.println("  </controlFlow>");
 
         stream.println(" </graph>");
         flush();
@@ -209,7 +209,7 @@
         stream.printf("   <block name='%d'>%n", block.blockID());
         stream.printf("    <successors>%n");
         for (Block sux : block.getSuccessors()) {
-            if (sux.firstNode() instanceof LoopBegin && block.lastNode() instanceof LoopEnd) {
+            if (sux.firstNode() instanceof LoopBegin && block.lastNode() instanceof LoopEnd) { //TODO gd
                 // Skip back edges.
             } else {
                 stream.printf("     <successor name='%d'/>%n", sux.blockID());
@@ -218,10 +218,10 @@
         stream.printf("    </successors>%n");
         stream.printf("    <nodes>%n");
 
-        ArrayList<Node> nodes = new ArrayList<Node>(block.getInstructions());
+        Set<Node> nodes = new HashSet<Node>(block.getInstructions());
         if (nodes.size() > 0) {
             // if this is the first block: add all locals to this block
-            if (nodes.get(0) == graph.start()) {
+            if (block.getInstructions() == graph.start()) {
                 for (Node node : graph.getNodes()) {
                     if (node instanceof Local) {
                         nodes.add(node);
@@ -239,7 +239,9 @@
                     if (merge.stateBefore() != null) {
                         nodes.add(merge.stateBefore());
                     }
-                    for (Node usage : merge.usages()) {
+                }
+                if (node instanceof PhiPoint) {
+                    for (Node usage : node.usages()) {
                         if (usage instanceof Phi || usage instanceof LoopCounter) {
                             nodes.add(usage);
                         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Jun 16 22:36:56 2011 +0200
@@ -33,7 +33,7 @@
 import com.oracle.max.asm.*;
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.alloc.*;
-import com.oracle.max.graal.compiler.alloc.OperandPool.*;
+import com.oracle.max.graal.compiler.alloc.OperandPool.VariableFlag;
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.globalstub.*;
 import com.oracle.max.graal.compiler.graph.*;
@@ -43,11 +43,17 @@
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.Bytecodes.MemoryBarriers;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
-import com.sun.cri.ri.RiType.*;
+import com.sun.cri.ri.RiType.Representation;
+import com.sun.cri.xir.CiXirAssembler.XirConstant;
+import com.sun.cri.xir.CiXirAssembler.XirInstruction;
+import com.sun.cri.xir.CiXirAssembler.XirOperand;
+import com.sun.cri.xir.CiXirAssembler.XirParameter;
+import com.sun.cri.xir.CiXirAssembler.XirRegister;
+import com.sun.cri.xir.CiXirAssembler.XirTemp;
 import com.sun.cri.xir.*;
-import com.sun.cri.xir.CiXirAssembler.*;
 
 /**
  * This class traverses the HIR instructions and generates LIR instructions from them.
@@ -267,6 +273,16 @@
                 }
             }
         }
+        if (block.blockSuccessors().size() == 1 && !(block.lastInstruction() instanceof LoopEnd)) {
+            Node firstInstruction = block.blockSuccessors().get(0).firstInstruction();
+            if (firstInstruction instanceof Placeholder) {
+                firstInstruction = ((Placeholder) firstInstruction).next();
+            }
+            //System.out.println("suxSz == 1, fst=" + firstInstruction);
+            if (firstInstruction instanceof LoopBegin) {
+                moveToPhi((LoopBegin) firstInstruction, block.lastInstruction());
+            }
+        }
         if (block.blockSuccessors().size() >= 1 && !jumpsToNextBlock(block.lastInstruction())) {
             block.lir().jump(getLIRBlock((FixedNode) block.lastInstruction().successors().get(0)));
         }
@@ -282,7 +298,9 @@
 
     @Override
     public void visitMerge(Merge x) {
-        // Nothing to do.
+        if (x.next() instanceof LoopBegin) {
+            moveToPhi((LoopBegin) x.next(), x);
+        }
     }
 
     private static boolean jumpsToNextBlock(Node node) {
@@ -1034,7 +1052,7 @@
             lastState = fs;
         } else if (block.blockPredecessors().size() == 1) {
             FrameState fs = block.blockPredecessors().get(0).lastState();
-            assert fs != null;
+            assert fs != null; //TODO gd maybe this assert should be removed
             if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
                 TTY.println("STATE CHANGE (singlePred)");
                 if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
@@ -1385,7 +1403,7 @@
         }
     }
 
-    void moveToPhi(PhiResolver resolver, Value curVal, Value suxVal, List<Phi> phis, int predIndex) {
+    /*void moveToPhi(PhiResolver resolver, Value curVal, Value suxVal, List<Phi> phis, int predIndex) {
         // move current value to referenced phi function
         if (suxVal instanceof Phi) {
             Phi phi = (Phi) suxVal;
@@ -1411,29 +1429,12 @@
                 resolver.move(operand, operandForPhi(phi));
             }
         }
-    }
-
-    private List<Phi> getPhis(LIRBlock block) {
-        if (block.getInstructions().size() > 0) {
-            Node i = block.firstInstruction();
-            if (i instanceof Merge) {
-                List<Phi> result = new ArrayList<Phi>();
-                for (Node n : i.usages()) {
-                    if (n instanceof Phi) {
-                        result.add((Phi) n);
-                    }
-                }
-                return result;
-            }
-        }
-        return null;
-    }
+    }*/
 
     @Override
     public void visitEndNode(EndNode end) {
         setNoResult(end);
-        Merge merge = end.merge();
-        moveToPhi(merge, merge.endIndex(end));
+        moveToPhi(end.merge(), end);
         lir.jump(getLIRBlock(end.merge()));
     }
 
@@ -1441,54 +1442,49 @@
     @Override
     public void visitLoopEnd(LoopEnd x) {
         setNoResult(x);
-        //moveToPhi(x.loopBegin(), x.loopBegin().endCount()); //TODO gd
+        moveToPhi(x.loopBegin(), x);
         lir.jump(getLIRBlock(x.loopBegin()));
     }
 
-    private void moveToPhi(Merge merge, int nextSuccIndex) {
+    private void moveToPhi(PhiPoint merge, Node pred) {
+        int nextSuccIndex = merge.phiPointPredecessorIndex(pred);
         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);
-                    if (curVal != null && curVal != phi) {
-                        if (curVal instanceof Phi) {
-                            operandForPhi((Phi) curVal);
-                        }
-                        CiValue operand = curVal.operand();
-                        if (operand.isIllegal()) {
-                            assert curVal instanceof Constant || curVal instanceof Local : "these can be produced lazily" + curVal + "/" + phi;
-                            operand = operandForInstruction(curVal);
-                        }
-                        resolver.move(operand, operandForPhi(phi));
+        for (Phi phi : merge.phis()) {
+            if (!phi.isDead()) {
+                Value curVal = phi.valueAt(nextSuccIndex);
+                if (curVal != null && curVal != phi) {
+                    if (curVal instanceof Phi) {
+                        operandForPhi((Phi) curVal);
+                    }
+                    CiValue operand = curVal.operand();
+                    if (operand.isIllegal()) {
+                        assert curVal instanceof Constant || curVal instanceof Local : "these can be produced lazily" + curVal + "/" + phi;
+                        operand = operandForInstruction(curVal);
+                    }
+                    resolver.move(operand, operandForPhi(phi));
+                }
+            }
+        }
+        resolver.dispose();
+        //TODO (gd) remove that later ?
+        if (merge instanceof LoopBegin) {
+            LoopBegin loopBegin = (LoopBegin) merge;
+            for (LoopCounter counter : loopBegin.counters()) {
+                if (counter.operand().isIllegal()) {
+                    createResultVariable(counter);
+                }
+                if (nextSuccIndex == 0) {
+                    lir.move(operandForInstruction(counter.init()), counter.operand());
+                } else {
+                    if (counter.kind == CiKind.Int) {
+                        this.arithmeticOpInt(IADD, counter.operand(), counter.operand(), operandForInstruction(counter.stride()), CiValue.IllegalValue);
+                    } else {
+                        assert counter.kind == CiKind.Long;
+                        this.arithmeticOpLong(LADD, counter.operand(), counter.operand(), operandForInstruction(counter.stride()));
                     }
                 }
             }
         }
-        resolver.dispose();
-        /*
-        //TODO (gd) remove that later
-        if (merge instanceof LoopBegin) {
-            for (Node usage : merge.usages()) {
-                if (usage instanceof LoopCounter) {
-                    LoopCounter counter = (LoopCounter) usage;
-                    if (counter.operand().isIllegal()) {
-                        createResultVariable(counter);
-                    }
-                    if (nextSuccIndex == 0) { // (gd) nasty
-                        lir.move(operandForInstruction(counter.init()), counter.operand());
-                    } else {
-                        if (counter.kind == CiKind.Int) {
-                            this.arithmeticOpInt(IADD, counter.operand(), counter.operand(), operandForInstruction(counter.stride()), CiValue.IllegalValue);
-                        } else {
-                            assert counter.kind == CiKind.Long;
-                            this.arithmeticOpLong(LADD, counter.operand(), counter.operand(), operandForInstruction(counter.stride()));
-                        }
-                    }
-                }
-            }
-        }*/
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/BlockMap.java	Thu Jun 16 22:36:56 2011 +0200
@@ -29,6 +29,7 @@
 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.value.*;
 import com.sun.cri.bytecode.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopBegin.java	Thu Jun 16 22:36:56 2011 +0200
@@ -22,11 +22,14 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
+import java.util.*;
+
 import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
 
-public class LoopBegin extends Instruction {
+public class LoopBegin extends StateSplit implements PhiPoint{
 
     private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
@@ -68,4 +71,39 @@
         LoopBegin x = new LoopBegin(into);
         return x;
     }
+
+    @Override
+    public int phiPointPredecessorCount() {
+        return 2;
+    }
+
+    @Override
+    public int phiPointPredecessorIndex(Node pred) {
+        Node singlePredecessor = this.singlePredecessor();
+        if (pred == singlePredecessor) {
+            return 0;
+        } else if (pred == this.loopEnd()) {
+            return 1;
+        } else if (singlePredecessor instanceof Placeholder) {
+            singlePredecessor = singlePredecessor.singlePredecessor();
+            if (pred == singlePredecessor) {
+                return 0;
+            }
+        }
+        throw Util.shouldNotReachHere("unknown pred : " + pred + "(sp=" + singlePredecessor + ", le=" + this.loopEnd() + ")");
+    }
+
+    @Override
+    public Node asNode() {
+        return this;
+    }
+
+    @Override
+    public Collection<Phi> phis() {
+        return Util.filter(this.usages(), Phi.class);
+    }
+
+    public Collection<LoopCounter> counters() {
+        return Util.filter(this.usages(), LoopCounter.class);
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Merge.java	Thu Jun 16 22:36:56 2011 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.max.graal.compiler.ir;
 
+import java.util.*;
+
 import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.compiler.value.*;
@@ -33,7 +35,7 @@
  * about the basic block, including the successor and
  * predecessor blocks, exception handlers, liveness information, etc.
  */
-public class Merge extends StateSplit {
+public class Merge extends StateSplit implements PhiPoint{
 
     private static final int INPUT_COUNT = 0;
 
@@ -294,4 +296,25 @@
             }
         }
     }
+
+    @Override
+    public int phiPointPredecessorCount() {
+        return endCount();
+    }
+
+    @Override
+    public int phiPointPredecessorIndex(Node pred) {
+        EndNode end = (EndNode) pred;
+        return endIndex(end);
+    }
+
+    @Override
+    public Node asNode() {
+        return this;
+    }
+
+    @Override
+    public Collection<Phi> phis() {
+        return Util.filter(this.usages(), Phi.class);
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Thu Jun 16 22:36:56 2011 +0200
@@ -54,17 +54,18 @@
     /**
      * The merge node for this phi.
      */
-    public Merge merge() {
-        return (Merge) inputs().get(super.inputCount() + INPUT_MERGE);
+    public PhiPoint merge() {
+        return (PhiPoint) inputs().get(super.inputCount() + INPUT_MERGE);
     }
 
-    public void setMerge(Value n) {
+    public void setMerge(Node n) {
+        assert n instanceof PhiPoint;
         inputs().set(super.inputCount() + INPUT_MERGE, n);
     }
 
-    public Phi(CiKind kind, Merge merge, Graph graph) {
+    public Phi(CiKind kind, PhiPoint merge, Graph graph) {
         super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        setMerge(merge);
+        setMerge(merge.asNode());
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Thu Jun 16 22:36:56 2011 +0200
@@ -264,28 +264,25 @@
     }
 
     public void mergeOrClone(Block target, FrameStateAccess newState) {
-        Instruction first = target.firstInstruction;
+        StateSplit first = (StateSplit) target.firstInstruction;
+
         if (target.isLoopHeader && isVisited(target)) {
-            first = ((LoopBegin) first).loopEnd();
+            first = ((LoopBegin) target.firstInstruction.next()).loopEnd();
         }
-        assert first instanceof StateSplit;
-
-        int bci = target.startBci;
-
-        FrameState existingState = ((StateSplit) first).stateBefore();
+        FrameState existingState = first.stateBefore();
 
         if (existingState == null) {
             // copy state because it is modified
-            FrameState duplicate = newState.duplicate(bci);
+            FrameState duplicate = newState.duplicate(target.startBci);
 
             // if the block is a loop header, insert all necessary phis
-            if (first instanceof LoopBegin && target.isLoopHeader) {
-                assert first instanceof Merge;
-                insertLoopPhis((Merge) first, duplicate);
-                ((Merge) first).setStateBefore(duplicate);
-            } else {
-                ((StateSplit) first).setStateBefore(duplicate);
+            if (target.isLoopHeader && !isVisited(target)) {
+                LoopBegin loopBegin = (LoopBegin) target.firstInstruction.next();
+                assert target.firstInstruction instanceof Placeholder && loopBegin != null;
+                //System.out.println("insertLoopPhis with " + target.loopHeaderState);
+                insertLoopPhis(loopBegin, loopBegin.stateBefore());
             }
+            first.setStateBefore(duplicate);
         } else {
             if (!GraalOptions.AssumeVerifiedBytecode && !existingState.isCompatibleWith(newState)) {
                 // stacks or locks do not match--bytecodes would not verify
@@ -300,8 +297,6 @@
                 assert !target.isLoopHeader;
                 Merge merge = new Merge(graph);
 
-
-
                 Placeholder p = (Placeholder) first;
                 assert p.predecessors().size() == 1;
                 assert p.next() == null;
@@ -325,20 +320,20 @@
         }
     }
 
-    private void insertLoopPhis(Merge merge, FrameState newState) {
+    private void insertLoopPhis(LoopBegin loopBegin, FrameState newState) {
         int stackSize = newState.stackSize();
         for (int i = 0; i < stackSize; i++) {
             // always insert phis for the stack
             Value x = newState.stackAt(i);
             if (x != null) {
-                newState.setupPhiForStack(merge, i).addInput(x);
+                newState.setupPhiForStack(loopBegin, i).addInput(x);
             }
         }
         int localsSize = newState.localsSize();
         for (int i = 0; i < localsSize; i++) {
             Value x = newState.localAt(i);
             if (x != null) {
-                newState.setupPhiForLocal(merge, i).addInput(x);
+                newState.setupPhiForLocal(loopBegin, i).addInput(x);
             }
         }
     }
@@ -1129,7 +1124,10 @@
                 LoopBegin loopBegin = new LoopBegin(graph);
                 LoopEnd loopEnd = new LoopEnd(graph);
                 loopEnd.setLoopBegin(loopBegin);
-                block.firstInstruction = loopBegin;
+                Placeholder p = new Placeholder(graph);
+                p.setNext(loopBegin);
+                loopBegin.setStateBefore(stateAfter.duplicate(block.startBci));
+                block.firstInstruction = p;
             } else {
                 block.firstInstruction = new Placeholder(graph);
             }
@@ -1138,8 +1136,8 @@
         addToWorkList(block);
 
         FixedNode result = null;
-        if (block.firstInstruction instanceof LoopBegin && isVisited(block)) {
-            result = ((LoopBegin) block.firstInstruction).loopEnd();
+        if (block.isLoopHeader && isVisited(block)) {
+            result = ((LoopBegin) block.firstInstruction.next()).loopEnd();
         } else {
             result = block.firstInstruction;
         }
@@ -1177,9 +1175,13 @@
             if (!isVisited(block)) {
                 markVisited(block);
                 // now parse the block
-                frameState.initializeFrom(((StateSplit) block.firstInstruction).stateBefore());
-                lastInstr = block.firstInstruction;
-                assert block.firstInstruction.next() == null : "instructions already appended at block " + block.blockID;
+                if (block.isLoopHeader) {
+                    lastInstr = (LoopBegin) block.firstInstruction.next();
+                } else {
+                    lastInstr = block.firstInstruction;
+                }
+                frameState.initializeFrom(((StateSplit) lastInstr).stateBefore());
+                assert lastInstr.next() == null : "instructions already appended at block " + block.blockID;
 
                 if (block == returnBlock) {
                     createReturnBlock(block);
@@ -1196,7 +1198,8 @@
         }
         for (Block b : blocksVisited) {
             if (b.isLoopHeader) {
-                LoopBegin begin = (LoopBegin) b.firstInstruction;
+                Instruction loopHeaderInstr = b.firstInstruction;
+                LoopBegin begin = (LoopBegin) loopHeaderInstr.next();
                 LoopEnd end = begin.loopEnd();
 
 //              This can happen with degenerated loops like this one:
@@ -1207,6 +1210,8 @@
 //                    }
 //                }
                 if (end.stateBefore() != null) {
+                    //loopHeaderMerge.stateBefore().merge(begin, end.stateBefore());
+                    //assert loopHeaderMerge.equals(end.stateBefore());
                     begin.stateBefore().merge(begin, end.stateBefore());
                 } else {
                     end.delete();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Thu Jun 16 22:36:56 2011 +0200
@@ -126,6 +126,20 @@
         return trueSuccessorCount(n) > 1 || n instanceof Anchor || n instanceof Return || n instanceof Unwind;
     }
 
+    private void print() {
+        System.out.println("nodeToBlock :");
+        System.out.println(nodeToBlock);
+        System.out.println("Blocks :");
+        for (Block b : blocks) {
+            System.out.println(b + " [S:" + b.getSuccessors() + ", P:" + b.getPredecessors() + ", D:" + b.getDominators());
+            System.out.println("  f " + b.firstNode());
+            for (Node n : b.getInstructions()) {
+                System.out.println("  - " + n);
+            }
+            System.out.println("  l " + b.lastNode());
+        }
+    }
+
     private void identifyBlocks() {
 
         // Identify blocks.
@@ -143,6 +157,9 @@
                             // Either dead code or at a merge node => stop iteration.
                             break;
                         }
+                        if (n instanceof LoopBegin) {
+                            block = null;
+                        }
                         assert n.predecessors().size() == 1 : "preds: " + n;
                         n = n.predecessors().get(0);
                     }
@@ -150,22 +167,31 @@
             }
         }
 
+//        System.out.println("identify blocks");
+//        print();
+
         // Connect blocks.
+        //TODO gd restructure this
         for (Block block : blocks) {
             Node n = block.firstNode();
-            if (n instanceof Merge) {
-                for (Node usage : n.usages()) {
-                    if (usage instanceof Phi || usage instanceof LoopCounter) {
-                        nodeToBlock.set(usage, block);
-                    }
+            LoopBegin loopBegin = null;
+            if (n instanceof Merge) {
+                Merge m = (Merge) n;
+                for (Phi phi : m.phis()) {
+                    nodeToBlock.set(phi, block);
                 }
-                Merge m = (Merge) n;
                 for (int i = 0; i < m.endCount(); ++i) {
                     EndNode end = m.endAt(i);
                     Block predBlock = nodeToBlock.get(end);
                     predBlock.addSuccessor(block);
                 }
+                if (m.next() instanceof LoopBegin) {
+                    loopBegin = (LoopBegin) m.next();
+                }
             } else {
+                if (n instanceof LoopBegin) {
+                    loopBegin = (LoopBegin) n;
+                }
                 for (Node pred : n.predecessors()) {
                     if (isFixed(pred)) {
                         Block predBlock = nodeToBlock.get(pred);
@@ -173,8 +199,19 @@
                     }
                 }
             }
+            if (loopBegin != null) {
+                for (Phi phi : loopBegin.phis()) {
+                    nodeToBlock.set(phi, block);
+                }
+                for (LoopCounter counter : loopBegin.counters()) {
+                    nodeToBlock.set(counter, block);
+                }
+            }
         }
 
+//        System.out.println("connect");
+//        print();
+
         for (Node n : graph.getNodes()) {
             if (n instanceof FrameState) {
                 FrameState f = (FrameState) n;
@@ -204,8 +241,15 @@
                 }
             }
 
+//            System.out.println("dom + cycles");
+//            print();
+
             assignLatestPossibleBlockToNodes();
+//            System.out.println("assign last");
+//            print();
             sortNodesWithinBlocks();
+//            System.out.println("sort");
+//            print();
         } else {
             computeJavaBlocks();
         }
@@ -289,9 +333,9 @@
         for (Node usage : n.usages()) {
             if (usage instanceof Phi) {
                 Phi phi = (Phi) usage;
-                Merge merge = phi.merge();
-                Block mergeBlock = nodeToBlock.get(merge);
-                assert mergeBlock != null : "no block for merge " + merge.id();
+                PhiPoint merge = phi.merge();
+                Block mergeBlock = nodeToBlock.get(merge.asNode());
+                assert mergeBlock != null : "no block for merge " + merge.asNode().id();
                 for (int i = 0; i < phi.valueCount(); ++i) {
                     if (phi.valueAt(i) == n) {
                         if (mergeBlock.getPredecessors().size() == 0) {
@@ -303,19 +347,19 @@
                         block = getCommonDominator(block, mergeBlock.getPredecessors().get(i));
                     }
                 }
-            } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) {
+            } else if (usage instanceof FrameState && ((FrameState) usage).block() != null && !(n instanceof Constant)) { //TODO gd humm..
                 Merge merge = ((FrameState) usage).block();
                 for (int i = 0; i < merge.endCount(); ++i) {
                     EndNode pred = merge.endAt(i);
                     block = getCommonDominator(block, nodeToBlock.get(pred));
                 }
-            /*} else if (usage instanceof LoopCounter) { //TODO gd
+            } else if (usage instanceof LoopCounter) { //TODO gd
                 LoopCounter counter = (LoopCounter) usage;
                 if (n == counter.init()) {
                     LoopBegin loopBegin = counter.loopBegin();
                     Block mergeBlock = nodeToBlock.get(loopBegin);
                     block = getCommonDominator(block, mergeBlock.dominator());
-                }*/
+                }
             } else {
                 block = getCommonDominator(block, assignLatestPossibleBlockToNode(usage));
             }
@@ -356,7 +400,7 @@
 
         if (b.firstNode() == b.lastNode()) {
             Node node = b.firstNode();
-            if (!(node instanceof Merge) || node instanceof LoopEnd) {
+            if (!(node instanceof Merge || node instanceof LoopBegin) || node instanceof LoopEnd) {
                 scheduleFirst = false;
             }
         }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/Util.java	Thu Jun 16 22:36:56 2011 +0200
@@ -27,6 +27,7 @@
 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.graph.*;
 import com.sun.cri.ci.*;
 import com.sun.cri.ri.*;
 
@@ -424,4 +425,15 @@
     public static String valueString(Value value) {
         return (value == null) ? "-" : ("" + value.kind.typeChar + value.id());
     }
+
+    @SuppressWarnings("unchecked")
+    public static <T extends Node> Collection<T> filter(Collection<Node> nodes, Class<T> clazz) {
+        ArrayList<T> phis = new ArrayList<T>();
+        for (Node node : nodes) {
+            if (clazz.isInstance(node)) {
+                phis.add((T) node);
+            }
+        }
+        return phis;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Thu Jun 16 22:36:56 2011 +0200
@@ -187,6 +187,28 @@
         return true;
     }
 
+    public boolean equals(FrameStateAccess other) {
+        if (stackSize() != other.stackSize() || localsSize() != other.localsSize() || locksSize() != other.locksSize()) {
+            return false;
+        }
+        for (int i = 0; i < stackSize(); i++) {
+            Value x = stackAt(i);
+            Value y = other.stackAt(i);
+            if (x != y) {
+                return false;
+            }
+        }
+        for (int i = 0; i < locksSize(); i++) {
+            if (lockAt(i) != other.lockAt(i)) {
+                return false;
+            }
+        }
+        if (other.outerFrameState() != outerFrameState()) {
+            return false;
+        }
+        return true;
+    }
+
     /**
      * Gets the size of the local variables.
      */
@@ -282,7 +304,7 @@
      * @param block the block begin for which we are creating the phi
      * @param i the index into the stack for which to create a phi
      */
-    public Phi setupPhiForStack(Merge block, int i) {
+    public Phi setupPhiForStack(PhiPoint block, int i) {
         Value p = stackAt(i);
         if (p != null) {
             if (p instanceof Phi) {
@@ -303,7 +325,7 @@
      * @param block the block begin for which we are creating the phi
      * @param i the index of the local variable for which to create the phi
      */
-    public Phi setupPhiForLocal(Merge block, int i) {
+    public Phi setupPhiForLocal(PhiPoint block, int i) {
         Value p = localAt(i);
         if (p instanceof Phi) {
             Phi phi = (Phi) p;
@@ -351,7 +373,7 @@
         }
     }
 
-    public void merge(Merge block, FrameStateAccess other) {
+    public void merge(PhiPoint block, FrameStateAccess other) {
         checkSize(other);
         for (int i = 0; i < valuesSize(); i++) {
             Value x = valueAt(i);
@@ -378,7 +400,7 @@
                     }
 
                     if (phi.valueCount() == 0) {
-                        int size = block.endCount();
+                        int size = block.phiPointPredecessorCount();
                         for (int j = 0; j < size; ++j) {
                             phi.addInput(x);
                         }
@@ -387,7 +409,7 @@
                         phi.addInput((x == y) ? phi : y);
                     }
 
-                    assert phi.valueCount() == block.endCount() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.endCount();
+                    assert phi.valueCount() == block.phiPointPredecessorCount() + (block instanceof LoopBegin ? 0 : 1) : "valueCount=" + phi.valueCount() + " predSize= " + block.phiPointPredecessorCount();
                }
             }
         }
--- a/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Thu Jun 16 13:09:18 2011 +0200
+++ b/graal/com.oracle.max.graal.graph/src/com/oracle/max/graal/graph/Node.java	Thu Jun 16 22:36:56 2011 +0200
@@ -53,6 +53,11 @@
     public List<Node> predecessors() {
         return Collections.unmodifiableList(predecessors);
     }
+    
+    public Node singlePredecessor(){
+        assert predecessors.size() == 1;
+        return predecessors.get(0);
+    }
 
     public List<Node> usages() {
         return Collections.unmodifiableList(usages);