changeset 3109:3664989976e2

Merge
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Fri, 01 Jul 2011 12:57:10 +0200
parents 44b3508a12c8 (diff) c8bfc73cb21c (current diff)
children 883c2f14e7d0 5cdaa94cd622
files
diffstat 10 files changed, 282 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Fri Jul 01 12:57:10 2011 +0200
@@ -130,9 +130,9 @@
         }
         List<Loop> loops = null;
         try {
-            LoopUtil.computeLoops(graph);
+            loops = LoopUtil.computeLoops(graph);
         } catch (Throwable t) {
-
+            t.printStackTrace();
         }
 
         stream.println("  <nodes>");
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinterObserver.java	Fri Jul 01 12:57:10 2011 +0200
@@ -140,13 +140,18 @@
 
     @Override
     public void compilationEvent(CompilationEvent event) {
+        boolean lazyStart = false;
         if (printer == null && event.isErrorEvent()) {
-            this.compilationStarted(event); // lazy start
+            this.compilationStarted(event);
+            lazyStart = true;
         }
         if (printer != null && event.getGraph() != null && event.isHIRValid()) {
             Graph graph = event.getGraph();
             printer.print(graph, event.getLabel(), true, event.getDebugObjects());
         }
+        if (lazyStart) {
+            this.compilationFinished(event);
+        }
     }
 
     @Override
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NewInstance.java	Fri Jul 01 12:57:10 2011 +0200
@@ -35,7 +35,7 @@
 /**
  * The {@code NewInstance} instruction represents the allocation of an instance class object.
  */
-public final class NewInstance extends FloatingNode {
+public final class NewInstance extends FixedNodeWithNext {
     private static final EscapeOp ESCAPE = new NewInstanceEscapeOp();
 
     private static final int INPUT_COUNT = 0;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java	Fri Jul 01 12:57:10 2011 +0200
@@ -325,12 +325,12 @@
                     Merge merge = new Merge(graph);
                     assert p.predecessors().size() == 1 : "predecessors size: " + p.predecessors().size();
                     FixedNode next = p.next();
-                    p.setNext(null);
                     EndNode end = new EndNode(graph);
-                    p.replaceAndDelete(end);
+                    p.setNext(end);
                     merge.setNext(next);
                     merge.addEnd(end);
                     merge.setStateAfter(existingState);
+                    p.setStateAfter(existingState.duplicate(bci));
                     if (!(next instanceof LoopEnd)) {
                         target.firstInstruction = merge;
                     }
@@ -1203,7 +1203,14 @@
             } else {
                 EndNode end = new EndNode(graph);
                 ((Merge) result).addEnd(end);
-                result = end;
+                Placeholder p = new Placeholder(graph);
+                int bci = block.startBci;
+                if (block instanceof ExceptionBlock) {
+                    bci = ((ExceptionBlock) block).deoptBci;
+                }
+                p.setStateAfter(stateAfter.duplicate(bci));
+                p.setNext(end);
+                result = p;
             }
         }
         assert !(result instanceof LoopBegin || result instanceof Merge);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java	Fri Jul 01 12:57:10 2011 +0200
@@ -39,6 +39,7 @@
         List<Loop> loops = LoopUtil.computeLoops(graph);
 
 //        for (Loop loop : loops) {
+//            System.out.println("Peel loop : " + loop.loopBegin());
 //            LoopUtil.peelLoop(loop);
 //        }
 //        loops = LoopUtil.computeLoops(graph); // TODO (gd) avoid recomputing loops
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java	Fri Jul 01 12:57:10 2011 +0200
@@ -24,7 +24,6 @@
 
 import java.util.*;
 
-import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java	Fri Jul 01 12:57:10 2011 +0200
@@ -30,18 +30,61 @@
 import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.value.*;
 import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.graph.NodeWorkList.*;
 
 public class GraphUtil {
 
     public static interface ColoringLambda<T> {
         T color(Iterable<T> incomming, Merge merge);
+        T danglingColor(Iterable<T> incomming, Merge merge);
     }
 
     /**
      * colors down, applying the lambda at merge points, starting at the pre-colored points.
      */
     public static <T> void colorCFGDown(NodeMap<T> colors, ColoringLambda<T> lambda) {
-        List<Node> startingPoints = new LinkedList<Node>();
+        Set<Merge> delayed = new HashSet<Merge>();
+        Set<Node> currentPoints = new HashSet<Node>();
+        Set<Node> otherPoints = new HashSet<Node>();
+        Set<Merge> otherMerges = new HashSet<Merge>();
+        for (Entry<Node, T> entry : colors.entries()) {
+            currentPoints.add(entry.getKey());
+        }
+        ArrayList<T> incomming = new ArrayList<T>(2);
+        while (!currentPoints.isEmpty()) {
+            for (Node node : currentPoints) {
+                otherMerges.addAll(colorCFGDownToMerge(node, colors.get(node), colors));
+            }
+            for (Merge merge : otherMerges) {
+                incomming.clear();
+                for (EndNode end : merge.cfgPredecessors()) {
+                    incomming.add(colors.get(end));
+                }
+                T color = lambda.color(incomming, merge);
+                if (color != null) {
+                    colors.set(merge, color);
+                    colors.set(merge.next(), color);
+                    otherPoints.add(merge.next());
+                    delayed.remove(merge);
+                } else {
+                    delayed.add(merge);
+                }
+            }
+            Set<Node> tmp = currentPoints;
+            currentPoints = otherPoints;
+            otherPoints = tmp;
+            otherPoints.clear();
+            otherMerges.clear();
+        }
+        for (Merge merge : delayed) {
+            T color = lambda.danglingColor(incomming, merge);
+            if (color != null) {
+                colors.set(merge, color);
+            }
+        }
+
+
+        /*List<Node> startingPoints = new LinkedList<Node>();
         for (Entry<Node, T> entry : colors.entries()) {
             startingPoints.add(entry.getKey());
         }
@@ -65,9 +108,10 @@
                 colors.set(merge, color);
                 work.addAll(colorCFGDownToMerge(merge.next(), color, colors));
             } else {
+                System.out.println("Can not color " + merge);
                 work.addAgain(merge);
             }
-        }
+        }*/
     }
 
     private static <T> Collection<Merge> colorCFGDownToMerge(Node from, T color, NodeMap<T> colors) {
@@ -131,9 +175,16 @@
                         Value v = phi.valueAt(i);
                         if (v != null) {
                             T color = internalColoring.get(merge.phiPredecessorAt(i));
-                            Value replace = lambda.fixPhiInput(v, color);
-                            if (replace != v) {
-                                phi.setValueAt(i, replace);
+                            if (color != null) {
+                                Value replace = lambda.fixPhiInput(v, color);
+                                if (replace != v) {
+                                    phi.setValueAt(i, replace);
+                                } else {
+                                    if (lambda.explore(v) && coloring.get(v) == null && !work.isNew(v)) {
+                                        //System.out.println("Split : Add input " + input + " to work from " + node);
+                                        work.add(v);
+                                    }
+                                }
                             }
                         }
                     }
@@ -155,12 +206,9 @@
                                     Value v = phi.valueAt(i);
                                     if (v == node) {
                                         T color = internalColoring.get(merge.phiPredecessorAt(i));
-                                        if (color == null) {
-                                            //System.out.println("Split : color from " + usage + " is null");
-                                            delay = true;
-                                            break;
+                                        if (color != null) {
+                                            colors.add(color);
                                         }
-                                        colors.add(color);
                                     }
                                 }
                             } else {
@@ -226,37 +274,39 @@
                             }
                         }
                     }
-                }
+                    if (node instanceof StateSplit) {
+                        FrameState stateAfter = ((StateSplit) node).stateAfter();
+                        if (stateAfter != null && lambda.explore(stateAfter) && !work.isNew(stateAfter)) {
+                            //System.out.println("Split : Add framestate to work");
+                            work.add(stateAfter);
+                        }
+                    }
 
-                if (node instanceof StateSplit) {
-                    FrameState stateAfter = ((StateSplit) node).stateAfter();
-                    if (stateAfter != null && lambda.explore(stateAfter) && !work.isNew(stateAfter)) {
-                        //System.out.println("Split : Add framestate to work");
-                        work.add(stateAfter);
+                    if (node instanceof Merge) {
+                        for (Node usage : node.usages()) {
+                            if (!work.isNew(usage)) {
+                                work.add(usage);
+                            }
+                        }
                     }
-                }
+
+                    if (node instanceof LoopEnd) {
+                        work.add(((LoopEnd) node).loopBegin());
+                    }
 
-                if (node instanceof Merge) {
-                    for (Node usage : node.usages()) {
-                        if (!work.isNew(usage)) {
-                            work.add(usage);
+                    for (Node input : node.dataInputs()) {
+                        if (lambda.explore(input) && coloring.get(input) == null && !work.isNew(input)) {
+                            //System.out.println("Split : Add input " + input + " to work from " + node);
+                            work.add(input);
                         }
                     }
                 }
-
-                if (node instanceof LoopEnd) {
-                    work.add(((LoopEnd) node).loopBegin());
-                }
-
-                for (Node input : node.dataInputs()) {
-                    if (lambda.explore(input) && coloring.get(input) == null && !work.isNew(input)) {
-                        //System.out.println("Split : Add input " + input + " to work from " + node);
-                        work.add(input);
-                    }
-                }
             }
-        } catch (RuntimeException re) {
-            re.printStackTrace();
+        } catch (InfiniteWorkException re) {
+            System.out.println("Infinite work, current queue :");
+            for (Node n : work) {
+                System.out.println(" - " + n);
+            }
             GraalCompilation compilation = GraalCompilation.compilation();
             if (compilation.compiler.isObserved()) {
                 NodeMap<T> debugColoring = coloring.graph().createNodeMap();
@@ -265,8 +315,19 @@
                 }
                 Map<String, Object> debug = new HashMap<String, Object>();
                 debug.put("split", debugColoring);
-                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in split", coloring.graph(), true, false, debug));
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "RuntimeException in split", coloring.graph(), true, false, true, debug));
             }
+            throw re;
+        }
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved()) {
+            NodeMap<T> debugColoring = coloring.graph().createNodeMap();
+            for (Entry<Node, T> entry : internalColoring.entrySet()) {
+                debugColoring.set(entry.getKey(), entry.getValue());
+            }
+            Map<String, Object> debug = new HashMap<String, Object>();
+            debug.put("split", debugColoring);
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Split end!!", coloring.graph(), true, false, debug));
         }
     }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java	Fri Jul 01 12:57:10 2011 +0200
@@ -39,9 +39,9 @@
 
     public static class Loop {
         private final LoopBegin loopBegin;
-        private final NodeBitMap nodes;
+        private NodeBitMap nodes;
         private Loop parent;
-        private final NodeBitMap exits;
+        private NodeBitMap exits;
         public Loop(LoopBegin loopBegin, NodeBitMap nodes, NodeBitMap exits) {
             this.loopBegin = loopBegin;
             this.nodes = nodes;
@@ -67,6 +67,10 @@
         public void setParent(Loop parent) {
             this.parent = parent;
         }
+
+        public boolean isChild(Loop loop) {
+            return loop.parent != null && (loop.parent == this || loop.parent.isChild(this));
+        }
     }
 
     private static class PeelingResult {
@@ -90,26 +94,8 @@
         List<Loop> loops = new LinkedList<LoopUtil.Loop>();
         for (LoopBegin loopBegin : graph.getNodes(LoopBegin.class)) {
             NodeBitMap nodes = computeLoopNodes(loopBegin);
-            NodeBitMap exits = graph.createNodeBitMap();
-            Loop loop = new Loop(loopBegin, nodes, exits);
-            NodeFlood workCFG = graph.createNodeFlood();
-            workCFG.add(loopBegin.loopEnd());
-            for (Node n : workCFG) {
-                if (n == loopBegin) {
-                    continue;
-                }
-                if (IdentifyBlocksPhase.trueSuccessorCount(n) > 1) {
-                    for (Node sux : n.cfgSuccessors()) {
-                        if (!nodes.isMarked(sux) && sux instanceof FixedNode) {
-                            exits.mark(sux);
-                        }
-                    }
-                }
-                for (Node pred : n.cfgPredecessors()) {
-                    workCFG.add(pred);
-                }
-            }
-            loops.add(loop);
+            NodeBitMap exits = computeLoopExits(loopBegin, nodes);
+            loops.add(new Loop(loopBegin, nodes, exits));
         }
         for (Loop loop : loops) {
             for (Loop other : loops) {
@@ -123,6 +109,29 @@
         return loops;
     }
 
+    public static NodeBitMap computeLoopExits(LoopBegin loopBegin, NodeBitMap nodes) {
+        Graph graph = loopBegin.graph();
+        NodeBitMap exits = graph.createNodeBitMap();
+        NodeFlood workCFG = graph.createNodeFlood();
+        workCFG.add(loopBegin.loopEnd());
+        for (Node n : workCFG) {
+            if (n == loopBegin) {
+                continue;
+            }
+            if (IdentifyBlocksPhase.trueSuccessorCount(n) > 1) {
+                for (Node sux : n.cfgSuccessors()) {
+                    if (!nodes.isMarked(sux) && sux instanceof FixedNode) {
+                        exits.mark(sux);
+                    }
+                }
+            }
+            for (Node pred : n.cfgPredecessors()) {
+                workCFG.add(pred);
+            }
+        }
+        return exits;
+    }
+
     public static NodeBitMap computeLoopNodes(LoopBegin loopBegin) {
         return computeLoopNodesFrom(loopBegin, loopBegin.loopEnd());
     }
@@ -138,7 +147,7 @@
         }
         NodeBitMap inOrAfter = loopBegin.graph().createNodeBitMap();
         for (Node n : workData1) {
-            inOrAfter.mark(n);
+            markWithState(n, inOrAfter);
             for (Node usage : n.dataUsages()) {
                 if (usage instanceof Phi) { // filter out data graph cycles
                     Phi phi = (Phi) usage;
@@ -147,9 +156,6 @@
                         if (merge instanceof LoopBegin) {
                             LoopBegin phiLoop = (LoopBegin) merge;
                             int backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd());
-                            if (backIndex >= phi.valueCount()) {
-                                System.out.println("Wierd phi : " + phi);
-                            }
                             if (phi.valueAt(backIndex) == n) {
                                 continue;
                             }
@@ -161,9 +167,26 @@
         }
         NodeBitMap inOrBefore = loopBegin.graph().createNodeBitMap();
         for (Node n : workData2) {
-            inOrBefore.mark(n);
-            for (Node input : n.dataInputs()) {
-                workData2.add(input);
+            markWithState(n, inOrBefore);
+            if (n instanceof Phi) { // filter out data graph cycles
+                Phi phi = (Phi) n;
+                if (!phi.isDead()) {
+                    int backIndex = -1;
+                    Merge merge = phi.merge();
+                    if (!loopNodes.isMarked(merge) && merge instanceof LoopBegin) {
+                        LoopBegin phiLoop = (LoopBegin) merge;
+                        backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd());
+                    }
+                    for (int i = 0; i < phi.valueCount(); i++) {
+                        if (i != backIndex) {
+                            workData2.add(phi.valueAt(i));
+                        }
+                    }
+                }
+            } else {
+                for (Node input : n.dataInputs()) {
+                    workData2.add(input);
+                }
             }
             if (n instanceof Merge) { //add phis & counters
                 for (Node usage : n.dataUsages()) {
@@ -171,7 +194,7 @@
                 }
             }
         }
-        /*if (!recurse) {
+        if (!recurse) {
             recurse = true;
             GraalCompilation compilation = GraalCompilation.compilation();
             if (compilation.compiler.isObserved()) {
@@ -179,10 +202,10 @@
                 debug.put("loopNodes", loopNodes);
                 debug.put("inOrAfter", inOrAfter);
                 debug.put("inOrBefore", inOrBefore);
-                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Compute loop nodes", loopBegin.graph(), true, false, debug));
+                compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Compute loop nodes loop#" + loopBegin.id(), loopBegin.graph(), true, false, debug));
             }
             recurse = false;
-        }*/
+        }
         inOrAfter.setIntersect(inOrBefore);
         loopNodes.setUnion(inOrAfter);
         return loopNodes;
@@ -254,19 +277,20 @@
         if (compilation.compiler.isObserved()) {
             compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After rewirePeeling", loopEnd.graph(), true, false));
         }
+        // update parents
+        Loop parent = loop.parent();
+        while (parent != null) {
+            parent.nodes = computeLoopNodes(loop.loopBegin);
+            parent.exits = computeLoopExits(parent.loopBegin, parent.nodes);
+            parent = parent.parent;
+        }
     }
 
     private static void rewirePeeling(PeelingResult peeling, Loop loop, FixedNode from) {
         LoopBegin loopBegin = loop.loopBegin();
         Graph graph = loopBegin.graph();
         Node loopPred = loopBegin.singlePredecessor();
-        if (loopPred instanceof FixedNodeWithNext) {
-            ((FixedNodeWithNext) loopPred).setNext(peeling.begin);
-        } else if (loopPred instanceof StartNode) {
-            ((StartNode) loopPred).setStart(peeling.begin);
-        } else {
-            Util.shouldNotReachHere();
-        }
+        loopPred.successors().replace(loopBegin.forwardEdge(), peeling.begin);
         NodeBitMap loopNodes = loop.nodes();
         Node originalLast = from;
         if (originalLast == loopBegin.loopEnd()) {
@@ -346,7 +370,7 @@
                         phiMap = graph.createNodeMap();
                         newExitValues.set(originalValue, phiMap);
                     }
-                    phiMap.set(oEnd, (Value) originalValue);
+                    phiMap.set(original, (Value) originalValue);
                     phiMap.set(nEnd, (Value) newValue);
 
                     phiMap = newExitValues.get(newValue);
@@ -354,7 +378,7 @@
                         phiMap = graph.createNodeMap();
                         newExitValues.set(newValue, phiMap);
                     }
-                    phiMap.set(oEnd, (Value) originalValue);
+                    phiMap.set(original, (Value) originalValue);
                     phiMap.set(nEnd, (Value) newValue);
                 }
             }
@@ -399,7 +423,7 @@
 
         // prepare inital colors
         for (Node exitPoint : exitPoints) {
-                colors.set(exitPoint, exitPoint);
+            colors.set(exitPoint, exitPoint);
         }
 
         /*System.out.println("newExitValues");
@@ -427,6 +451,19 @@
                 }
                 return color;
             }
+            @Override
+            public Node danglingColor(Iterable<Node> incomming, Merge merge) {
+                Node color = null;
+                for (Node c : incomming) {
+                    if (color == null) {
+                        color = c;
+                    } else if (color != c) {
+                        return merge;
+                    }
+                }
+                assert color != null;
+                return color;
+            }
         });
 
         final NodeBitMap inOrBefore = inOrBefore(loop);
@@ -447,6 +484,7 @@
             private Value getValueAt(Node point, NodeMap<Value> valueMap, CiKind kind) {
                 Value value = valueMap.get(point);
                 if (value != null) {
+                    //System.out.println("getValueAt(" + point + ", valueMap, kind) = " + value);
                     return value;
                 }
                 Merge merge = (Merge) point;
@@ -468,19 +506,22 @@
                     for (EndNode end : merge.cfgPredecessors()) {
                         phi.addInput(getValueAt(colors.get(end), valueMap, kind));
                     }
+                    //System.out.println("getValueAt(" + point + ", valueMap, kind) = " + phi);
                     return phi;
                 } else {
                     assert v != null;
                     valueMap.set(point, v);
+                    //System.out.println("getValueAt(" + point + ", valueMap, kind) = " + v);
                     return v;
                 }
             }
             @Override
             public boolean explore(Node n) {
-                return !inOrBefore.isNew(n) && !inOrBefore.isMarked(n) && !(n instanceof Local); //TODO (gd) hum
+                return !inOrBefore.isNew(n) && !inOrBefore.isMarked(n) && !(n instanceof Local) && !(n instanceof Constant); //TODO (gd) hum
             }
             @Override
             public void fixNode(Node node, Node color) {
+                //System.out.println("fixNode(" + node + ", " + color + ")");
                 for (int i = 0; i < node.inputs().size(); i++) {
                     Node input = node.inputs().get(i);
                     if (input == null || newExitValues.isNew(input)) {
@@ -489,9 +530,7 @@
                     NodeMap<Value> valueMap = newExitValues.get(input);
                     if (valueMap != null) {
                         Value replacement = getValueAt(color, valueMap, ((Value) input).kind);
-                        //if (!(replacement instanceof Phi && replacement == node)) { // handle the Phi that were created when merging loop exits
-                            node.inputs().set(i, replacement);
-                        //}
+                        node.inputs().set(i, replacement);
                     }
                 }
             }
@@ -516,17 +555,24 @@
         LoopBegin loopBegin = loop.loopBegin();
         Graph graph = loopBegin.graph();
         NodeBitMap marked = computeLoopNodesFrom(loopBegin, from);
+        GraalCompilation compilation = GraalCompilation.compilation();
+        if (compilation.compiler.isObserved()) {
+            Map<String, Object> debug = new HashMap<String, Object>();
+            debug.put("marked", marked);
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After computeLoopNodesFrom", loopBegin.graph(), true, false, debug));
+        }
         if (from == loopBegin.loopEnd()) {
-            marked.clear(from);
+            clearWithState(from, marked);
         }
-        marked.clear(loopBegin);
+        clearWithState(loopBegin, marked);
         Map<Node, Node> replacements = new HashMap<Node, Node>();
         NodeMap<Placeholder> phis = graph.createNodeMap();
         NodeMap<Placeholder> exits = graph.createNodeMap();
 
         for (Node exit : loop.exits()) {
             if (marked.isMarked(exit.singlePredecessor())) {
-                marked.mark(((Placeholder) exit).stateAfter());
+                Placeholder pExit = (Placeholder) exit;
+                marked.mark(pExit.stateAfter());
                 Placeholder p = new Placeholder(graph);
                 replacements.put(exit, p);
                 exits.set(exit, p);
@@ -534,12 +580,6 @@
         }
 
         for (Node n : marked) {
-            if (n instanceof StateSplit) {
-                FrameState stateAfter = ((StateSplit) n).stateAfter();
-                if (stateAfter != null) {
-                    marked.mark(stateAfter);
-                }
-            }
             if (n instanceof Phi && ((Phi) n).merge() == loopBegin) {
                 Placeholder p = new Placeholder(graph);
                 replacements.put(n, p);
@@ -553,11 +593,11 @@
             }
         }
 
-        GraalCompilation compilation = GraalCompilation.compilation();
+        //GraalCompilation compilation = GraalCompilation.compilation();
         if (compilation.compiler.isObserved()) {
             Map<String, Object> debug = new HashMap<String, Object>();
             debug.put("marked", marked);
-            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Before addDuplicate", loopBegin.graph(), true, false, debug));
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Before addDuplicate loop#" + loopBegin.id(), loopBegin.graph(), true, false, debug));
         }
 
         Map<Node, Node> duplicates = graph.addDuplicate(marked, replacements);
@@ -567,7 +607,7 @@
             for (Node usage : n.dataUsages()) {
                 if (!marked.isMarked(usage)
                                 && !loop.nodes().isNew(usage) && loop.nodes().isMarked(usage)
-                                && !((usage instanceof Phi) || ((Phi) usage).merge() != loopBegin)) {
+                                && !((usage instanceof Phi) && ((Phi) usage).merge() != loopBegin)) {
                     dataOut.set(n, duplicates.get(n));
                     break;
                 }
@@ -595,18 +635,70 @@
         Graph graph = loop.loopBegin().graph();
         NodeBitMap inOrBefore = graph.createNodeBitMap();
         NodeFlood work = graph.createNodeFlood();
-        work.addAll(loop.nodes());
+        NodeBitMap loopNodes = loop.nodes();
+        work.addAll(loopNodes);
         for (Node n : work) {
             inOrBefore.mark(n);
             for (Node pred : n.predecessors()) {
                 work.add(pred);
             }
-            for (Node in : n.inputs()) {
-                if (in != null) {
-                    work.add(in);
+            if (n instanceof Phi) { // filter out data graph cycles
+                Phi phi = (Phi) n;
+                if (!phi.isDead()) {
+                    int backIndex = -1;
+                    Merge merge = phi.merge();
+                    if (!loopNodes.isNew(merge) && !loopNodes.isMarked(merge) && merge instanceof LoopBegin) {
+                        LoopBegin phiLoop = (LoopBegin) merge;
+                        backIndex = phiLoop.phiPredecessorIndex(phiLoop.loopEnd());
+                    }
+                    for (int i = 0; i < phi.valueCount(); i++) {
+                        if (i != backIndex) {
+                            work.add(phi.valueAt(i));
+                        }
+                    }
+                }
+            } else {
+                for (Node in : n.inputs()) {
+                    if (in != null) {
+                        work.add(in);
+                    }
+                }
+                if (n instanceof LoopBegin) {
+                    Loop p = loop.parent;
+                    boolean isParent = false;
+                    while (p != null) {
+                        if (p.loopBegin() == n) {
+                            isParent = true;
+                            break;
+                        }
+                        p = p.parent;
+                    }
+                    if (!isParent) {
+                        work.add(((LoopBegin) n).loopEnd());
+                    }
                 }
             }
         }
         return inOrBefore;
     }
+
+    private static void markWithState(Node n, NodeBitMap map) {
+        map.mark(n);
+        if (n instanceof StateSplit) {
+            FrameState stateAfter = ((StateSplit) n).stateAfter();
+            if (stateAfter != null) {
+                map.mark(stateAfter);
+            }
+        }
+    }
+
+    private static void clearWithState(Node n, NodeBitMap map) {
+        map.clear(n);
+        if (n instanceof StateSplit) {
+            FrameState stateAfter = ((StateSplit) n).stateAfter();
+            if (stateAfter != null) {
+                map.clear(stateAfter);
+            }
+        }
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameState.java	Fri Jul 01 12:57:10 2011 +0200
@@ -480,9 +480,17 @@
 
     @Override
     public String toString() {
-        /*StringBuilder sb = new StringBuilder();
+        return super.toString();
+    }
+
+    public String toDetailedString() {
+        StringBuilder sb = new StringBuilder();
         String nl = String.format("%n");
-        sb.append("[bci: ").append(bci).append("]").append(nl);
+        sb.append("[bci: ").append(bci).append("]");
+        if (rethrowException()) {
+            sb.append(" rethrows Exception");
+        }
+        sb.append(nl);
         for (int i = 0; i < localsSize(); ++i) {
             Value value = localAt(i);
             sb.append(String.format("  local[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value));
@@ -495,8 +503,7 @@
             Value value = lockAt(i);
             sb.append(String.format("  lock[%d] = %-8s : %s%n", i, value == null ? "bogus" : value.kind.javaName, value));
         }
-        return sb.toString();*/
-        return super.toString();
+        return sb.toString();
     }
 
     @Override
--- a/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java	Thu Jun 30 17:02:04 2011 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Coordinator/src/com/sun/hotspot/igv/coordinator/StandardGroupOrganizer.java	Fri Jul 01 12:57:10 2011 +0200
@@ -51,7 +51,7 @@
                 List<Group> children = new ArrayList<Group>();
                 children.add(g);
                 if(g.getGraphs().size() == 1) {
-                    //g.getGraphs().get(0).setName(g.getName() + " / " + g.getGraphs().get(0).getName());
+                    g.getGraphs().get(0).setName(g.getName() + " / " + g.getGraphs().get(0).getName());
                     result.add(new Pair<String, List<Group>>("", children));
                 } else {
                     Pair<String, List<Group>> p = new Pair<String, List<Group>>();