changeset 4522:cf13124efdd9

Restructure phi functions in LIR; Re-enabled C1Visualizer output
author Christian Wimmer <Christian.Wimmer@Oracle.com>
date Wed, 08 Feb 2012 15:35:21 -0800
parents 333896b40999
children ade4281b79c3
files graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Block.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/ControlFlowGraph.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/lir/LIRInstruction.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java
diffstat 24 files changed, 384 insertions(+), 548 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/AbstractAssembler.java	Wed Feb 08 15:35:21 2012 -0800
@@ -48,6 +48,10 @@
         l.patchInstructions(this);
     }
 
+    public abstract void align(int modulus);
+
+    public abstract void jmp(Label l);
+
     protected abstract void patchJumpTarget(int branch, int jumpTarget);
 
     protected final void emitByte(int x) {
--- a/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64Assembler.java	Wed Feb 08 15:35:21 2012 -0800
@@ -759,6 +759,7 @@
         }
     }
 
+    @Override
     public final void jmp(Label l) {
         if (l.isBound()) {
             jmp(l.position(), false);
@@ -2876,6 +2877,7 @@
         testl(AMD64.rax, new CiAddress(Word, r.asValue(Word), 0));
     }
 
+    @Override
     public void align(int modulus) {
         if (codeBuffer.position() % modulus != 0) {
             nop(modulus - (codeBuffer.position() % modulus));
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/AssignRegisters.java	Wed Feb 08 15:35:21 2012 -0800
@@ -53,7 +53,6 @@
         for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) {
             Block block = lir.linearScanOrder().get(i);
             assert trace("start block %s", block);
-            assert block.phis == null : "Register assignment must run after phi functions have been replaced by moves";
 
             curRegisterRefMap = frameMap.initRegisterRefMap();
             curFrameRefMap = frameMap.initFrameRefMap();
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java	Wed Feb 08 15:35:21 2012 -0800
@@ -35,7 +35,6 @@
 import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
 
 public class DataFlowAnalysis {
     private final LIR lir;
@@ -130,10 +129,6 @@
 
         curOpId = 0;
         for (Block block : blocks()) {
-            if (block.phis != null) {
-                block.phis.forEachOutput(defProc);
-            }
-
             for (LIRInstruction op : block.lir) {
                 op.setId(curOpId);
                 setBlockOf(curOpId, block);
@@ -161,11 +156,10 @@
     private int curOpId;
 
     private void backwardDataFlow() {
-        ValueProcedure inputProc =       new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return use(value, curOpId); } };
-        ValueProcedure aliveProc =       new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return use(value, curOpId + 1); } };
-        PhiValueProcedure phiInputProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, -1); } };
-        ValueProcedure tempProc =        new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return def(value, true); } };
-        ValueProcedure outputProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return def(value, false); } };
+        ValueProcedure inputProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId); } };
+        ValueProcedure aliveProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId + 1); } };
+        ValueProcedure tempProc =     new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, true); } };
+        ValueProcedure outputProc =   new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, false); } };
 
         blockLiveIn = new BitSet[blocks().size()];
         registerLive = new BitSet();
@@ -182,12 +176,6 @@
                     assert trace("  sux %s  suxLive: %s", sux, suxLive);
                     variableLive.or(suxLive);
                 }
-
-                if (sux.phis != null) {
-                    curOpId = block.getLastLirInstructionId();
-                    assert trace("  phis %d  variableLive: %s", curOpId, variableLive);
-                    sux.phis.forEachInput(block, phiInputProc);
-                }
             }
 
             assert registerLive.isEmpty() : "no fixed register must be alive before processing a block";
@@ -204,12 +192,6 @@
                 op.forEachInput(inputProc);
             }
 
-            if (block.phis != null) {
-                curOpId = block.getFirstLirInstructionId();
-                assert trace("  phis %d  variableLive: %s  registerLive: %s", curOpId, variableLive, registerLive);
-                block.phis.forEachOutput(outputProc);
-            }
-
             assert registerLive.isEmpty() : "no fixed register must be alive after processing a block";
             assert liveIn(block) == null;
             setLiveIn(block, variableLive);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/LinearScanAllocator.java	Wed Feb 08 15:35:21 2012 -0800
@@ -37,7 +37,6 @@
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 
@@ -150,7 +149,7 @@
     private CiValue[] curOutRegisterState;
     private BitSet curLiveIn;
     private int curOpId;
-    private Block curPhiBlock;
+    private boolean curPhiDefs;
 
     private LocationMap canonicalSpillLocations;
 
@@ -179,13 +178,13 @@
     }
 
     private void allocate() {
-        ValueProcedure recordUseProc =    new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return recordUse(value, mode); } };
-        ValueProcedure killNonLiveProc =  new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return killNonLive(value); } };
-        ValueProcedure unblockProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return unblock(value); } };
-        ValueProcedure killProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return kill(value); } };
-        ValueProcedure blockProc =        new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return block(value); } };
-        PhiValueProcedure useProc =          new PhiValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
-        ValueProcedure defProc =          new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } };
+        ValueProcedure recordUseProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return recordUse(value); } };
+        ValueProcedure killNonLiveProc =  new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } };
+        ValueProcedure unblockProc =      new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return unblock(value); } };
+        ValueProcedure killProc =         new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value); } };
+        ValueProcedure blockProc =        new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } };
+        ValueProcedure useProc =          new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
+        ValueProcedure defProc =          new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } };
 
         assert trace("==== start linear scan allocation ====");
         canonicalSpillLocations = new LocationMap(lir.numVariables());
@@ -207,20 +206,11 @@
             }
             assert traceState();
 
-            if (block.phis != null) {
-                assert trace("  phis");
-                curPhiBlock = block;
-                curOpId = block.getFirstLirInstructionId();
-                block.phis.forEachOutput(defProc);
-                curOpId = -1;
-                curPhiBlock = null;
-            }
-
-            setBeginLocationsFor(block, new LocationMap(curLocations));
-
             for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) {
                 LIRInstruction op = block.lir.get(opIdx);
                 curOpId = op.id();
+                curPhiDefs = opIdx == 0;
+
                 assert trace("  op %d %s", op.id(), op);
 
                 System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length);
@@ -253,26 +243,18 @@
                 // State values are the least critical and can get the leftover registers (or stack slots if no more register available).
                 op.forEachState(useProc);
 
-
+                if (opIdx == 0) {
+                    assert !moveResolver.hasMappings() : "cannot insert spill moves before label";
+                    setBeginLocationsFor(block, new LocationMap(curLocations));
+                }
                 moveResolver.resolve();
 
                 dataFlow.forEachKilled(op, true, unblockProc);
                 dataFlow.forEachKilled(op, true, killProc);
 
-//                curInstruction = null;
                 curOpId = -1;
             }
 
-            for (Block sux : block.getSuccessors()) {
-                if (sux.phis != null) {
-                    assert trace("  phis of successor %s", sux);
-                    System.arraycopy(curOutRegisterState, 0, curInRegisterState, 0, curOutRegisterState.length);
-                    curOpId = block.getLastLirInstructionId() + 1;
-                    sux.phis.forEachInput(block, useProc);
-                    curOpId = -1;
-                }
-            }
-
             assert endLocationsFor(block) == null;
             setEndLocationsFor(block, curLocations);
 
@@ -343,11 +325,10 @@
         }
     }
 
-    private CiValue recordUse(CiValue value, OperandMode mode) {
+    private CiValue recordUse(CiValue value) {
         if (isVariable(value)) {
-            int id = mode == OperandMode.Input ? curOpId : curOpId + 1;
-            assert lastUseFor(asVariable(value)) <= id;
-            setLastUseFor(asVariable(value), id);
+            assert lastUseFor(asVariable(value)) <= curOpId;
+            setLastUseFor(asVariable(value), curOpId);
 
         }
         return value;
@@ -357,7 +338,7 @@
         assert mode == OperandMode.Input || mode == OperandMode.Alive;
         if (isVariable(value)) {
             // State values are not recorded beforehand because it does not matter if they are spilled. Still, it is necessary to record them as used now.
-            recordUse(value, mode);
+            recordUse(value);
 
             Location curLoc = curLocations.get(asVariable(value));
             if (isStackSlot(curLoc.location) && flags.contains(OperandFlag.Stack)) {
@@ -459,13 +440,14 @@
         }
 
         if (flags.contains(OperandFlag.Stack) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) {
-            return selectSpillSlot(variable, mode);
+            return selectSpillSlot(variable);
         }
 
         if (bestSpillCandidate == null) {
-            if (curPhiBlock != null) {
-                return selectSpillSlot(variable, mode);
+            if (curPhiDefs) {
+                return selectSpillSlot(variable);
             }
+
             // This should not happen as long as all LIR instructions have fulfillable register constraints. But be safe in product mode and bail out.
             assert false;
             throw new CiBailout("No register available");
@@ -479,7 +461,7 @@
     private void spill(Location value) {
         Location newLoc = spillLocation(value.variable);
         assert trace("      spill %s to %s", value, newLoc);
-        if (curPhiBlock == null) {
+        if (!curPhiDefs) {
             moveResolver.add(value, newLoc);
         }
         curLocations.put(newLoc);
@@ -542,16 +524,16 @@
         }
         curOutRegisterState[reg.number] = loc;
         curLocations.put(loc);
-        recordUse(variable, mode);
+        recordUse(variable);
 
         assert trace("      selected register %s", loc);
         return loc;
     }
 
-    private Location selectSpillSlot(Variable variable, OperandMode mode) {
+    private Location selectSpillSlot(Variable variable) {
         Location loc = spillLocation(variable);
         curLocations.put(loc);
-        recordUse(variable, mode);
+        recordUse(variable);
 
         assert trace("      selected spill slot %s", loc);
         return loc;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java	Wed Feb 08 15:35:21 2012 -0800
@@ -33,7 +33,8 @@
 import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
+import com.oracle.max.graal.compiler.lir.StandardOp.PhiJumpOp;
+import com.oracle.max.graal.compiler.lir.StandardOp.PhiLabelOp;
 import com.oracle.max.graal.compiler.util.*;
 
 public abstract class ResolveDataFlow {
@@ -47,16 +48,17 @@
         this.dataFlow = dataFlow;
     }
 
-    private Block curToBlock;
     private LocationMap curFromLocations;
 
     public void execute() {
-        ValueProcedure locMappingProc =    new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return locMapping(value); } };
-        PhiValueProcedure phiMappingProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue input, CiValue output) { return phiMapping(input, output); } };
+        ValueProcedure locMappingProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return locMapping(value); } };
 
         assert trace("==== start resolve data flow ====");
         for (Block toBlock : lir.linearScanOrder()) {
-            curToBlock = toBlock;
+            PhiLabelOp phiDefs = null;
+            if (toBlock.lir.get(0) instanceof PhiLabelOp) {
+                phiDefs = (PhiLabelOp) toBlock.lir.get(0);
+            }
 
             for (Block fromBlock : toBlock.getPredecessors()) {
                 assert trace("start edge %s -> %s", fromBlock, toBlock);
@@ -68,16 +70,20 @@
                     toLocations.forEachLocation(locMappingProc);
                 }
 
-                if (toBlock.phis != null) {
-                    toBlock.phis.forEachInput(fromBlock, phiMappingProc);
+                if (phiDefs != null) {
+                    PhiJumpOp phiInputs = (PhiJumpOp) fromBlock.lir.get(fromBlock.lir.size() - 1);
+                    phiMapping(phiInputs.getPhiInputs(), phiDefs.getPhiDefinitions());
+                    phiInputs.markResolved();
                 }
 
                 moveResolver.resolve();
                 assert trace("end edge %s -> %s", fromBlock, toBlock);
             }
 
-            // Phi functions are resolved with moves now, so delete them.
-            toBlock.phis = null;
+            if (phiDefs != null) {
+                // Phi functions are resolved with moves now, so delete them.
+                phiDefs.markResolved();
+            }
         }
         moveResolver.finish();
         assert trace("==== end resolve data flow ====");
@@ -86,17 +92,19 @@
     private CiValue locMapping(CiValue value) {
         Location to = asLocation(value);
         Location from = curFromLocations.get(to.variable);
-        if (value != from && dataFlow.liveIn(curToBlock).get(to.variable.index)) {
+        if (value != from && from != null) {
             moveResolver.add(from, to);
         }
         return value;
     }
 
-    private CiValue phiMapping(CiValue input, CiValue output) {
-        if (input != output) {
-            moveResolver.add(input, asLocation(output));
+    private void phiMapping(CiValue[] inputs, CiValue[] outputs) {
+        assert inputs.length != outputs.length;
+        for (int i = 0; i < inputs.length; i++) {
+            if (inputs[i] != outputs[i]) {
+                moveResolver.add(inputs[i], asLocation(outputs[i]));
+            }
         }
-        return input;
     }
 
     private void findInsertPos(Block fromBlock, Block toBlock) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Wed Feb 08 15:35:21 2012 -0800
@@ -37,7 +37,6 @@
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 
@@ -154,15 +153,14 @@
     }
 
     private void allocate() {
-        ValueProcedure killNonLiveProc =  new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return killNonLive(value); } };
-        ValueProcedure killBeginProc =    new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return kill(value, false); } };
-        ValueProcedure killEndProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return kill(value, true); } };
-        ValueProcedure killLocationProc = new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return killLocation(value); } };
-        ValueProcedure blockProc =        new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return block(value); } };
-        ValueProcedure loadProc =         new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return load(value, mode, flags); } };
-        ValueProcedure spillProc =        new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return spill(value, mode, flags); } };
-        PhiValueProcedure useSlotProc =   new PhiValueProcedure() { @Override public CiValue doValue(CiValue value) { return useSlot(value); } };
-        ValueProcedure defSlotProc =      new ValueProcedure() {    @Override public CiValue doValue(CiValue value) { return defSlot(value); } };
+        ValueProcedure killNonLiveProc =  new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } };
+        ValueProcedure killBeginProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, false); } };
+        ValueProcedure killEndProc =      new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, true); } };
+        ValueProcedure killLocationProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killLocation(value); } };
+        ValueProcedure blockProc =        new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } };
+        ValueProcedure loadProc =         new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return load(value, mode, flags); } };
+        ValueProcedure spillProc =        new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return spill(value, mode, flags); } };
+        ValueProcedure useSlotProc =      new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return useSlot(value); } };
 
         assert trace("==== start spill all allocation ====");
         curInRegisterState = new Object[maxRegisterNum()];
@@ -184,11 +182,6 @@
             }
             assert traceState();
 
-            if (block.phis != null) {
-                assert trace("  phis");
-                block.phis.forEachOutput(defSlotProc);
-            }
-
             for (int opIdx = 0; opIdx < block.lir.size(); opIdx++) {
                 LIRInstruction op = block.lir.get(opIdx);
                 curInstruction = op;
@@ -224,15 +217,6 @@
                 curInstruction = null;
             }
             assert checkEmpty(curOutRegisterState);
-
-            for (Block sux : block.getSuccessors()) {
-                if (sux.phis != null) {
-                    assert trace("  phis of successor %s", sux);
-                    sux.phis.forEachInput(block, useSlotProc);
-                }
-            }
-
-            assert checkEmpty(curOutRegisterState);
             assert locationsFor(block) == null;
             setLocationsFor(block, curStackLocations);
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/IntervalPrinter.java	Wed Feb 08 15:35:21 2012 -0800
@@ -35,26 +35,24 @@
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
+import com.oracle.max.graal.debug.*;
 
 public final class IntervalPrinter {
 
-    @SuppressWarnings("unused")
     public static void printBeforeAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow) {
-        // TODO(tw): Fix printing.
-//        if (context.isObserved()) {
-//            IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, null);
-//            context.observable.fireCompilationEvent(label, lir, printer.execute());
-//        }
+        if (Debug.isDumpEnabled()) {
+            IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, null);
+            Debug.dump(lir, label);
+            Debug.dump(printer.execute(), label);
+        }
     }
 
-    @SuppressWarnings("unused")
     public static void printAfterAllocation(String label, LIR lir, RiRegisterConfig registerConfig, DataFlowAnalysis dataFlow, LocationMap[] blockEndLocations) {
-        // TODO(tw): Fix printing.
-//        if (context.isObserved()) {
-//            IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, blockEndLocations);
-//            context.observable.fireCompilationEvent(label, lir, printer.execute());
-//        }
+        if (Debug.isDumpEnabled()) {
+            IntervalPrinter printer = new IntervalPrinter(lir, registerConfig, dataFlow, blockEndLocations);
+            Debug.dump(lir, label);
+            Debug.dump(printer.execute(), label);
+        }
     }
 
 
@@ -128,16 +126,13 @@
         ValueProcedure varProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return var(value); } };
 
         for (Block block : lir.linearScanOrder()) {
-            if (block.phis != null) {
-                block.phis.forEachOutput(varProc);
-            }
             for (LIRInstruction op : block.lir) {
                 op.forEachOutput(varProc);
             }
         }
 
-        PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
-        ValueProcedure    defProc = new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, flags); } };
+        ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
+        ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, flags); } };
 
         intervals.put("call", new Interval(-2, "call", "", "call", "hasCall"));
         intervals.put("st", new Interval(-1, "st", "", "st", "hasState"));
@@ -157,13 +152,6 @@
                 }
             }
 
-            curOpId = block.getLastLirInstructionId() + 1;
-            for (Block sux : block.getSuccessors()) {
-                if (sux.phis != null) {
-                    sux.phis.forEachInput(block, useProc);
-                }
-            }
-
             for (int j = block.lir.size() - 1; j >= 0; j--) {
                 LIRInstruction op = block.lir.get(j);
                 if (op.id() >= 0) {
@@ -188,11 +176,6 @@
                 }
             }
 
-            if (block.phis != null) {
-                curOpId = block.getFirstLirInstructionId() + 1;
-                block.phis.forEachOutput(defProc);
-            }
-
             for (Interval interval : intervals.values()) {
                 if (interval.lastTo != 0) {
                     interval.ranges.add(new Range(block.getFirstLirInstructionId(), interval.lastTo));
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java	Wed Feb 08 15:35:21 2012 -0800
@@ -83,6 +83,10 @@
         assert checkValid();
     }
 
+    public boolean hasMappings() {
+        return mappingFrom.size() > 0;
+    }
+
     public void resolve() {
         assert checkValid();
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java	Wed Feb 08 15:35:21 2012 -0800
@@ -97,7 +97,6 @@
         assert trace("==== start verify register allocation ====");
         do {
             Block block = workList.remove(0);
-            assert block.phis == null : "phi functions must have been resolved with moves";
 
             // Must copy state because it is modified.
             curInputState = copy(stateFor(block));
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompiler.java	Wed Feb 08 15:35:21 2012 -0800
@@ -81,6 +81,9 @@
         if (osrBCI != -1) {
             throw new CiBailout("No OSR supported");
         }
+        Debug.dump(this, "compiler");
+        Debug.dump(method, "method");
+
         return Debug.scope(createScopeName(method), new Callable<CiTargetMethod>() {
             public CiTargetMethod call() {
                 final CiAssumptions assumptions = GraalOptions.OptAssumptions ? new CiAssumptions() : null;
@@ -189,6 +192,7 @@
 
         final SchedulePhase schedule = new SchedulePhase();
         schedule.apply(graph);
+        Debug.dump(schedule, "final schedule");
 
         final Block[] blocks = schedule.getCFG().getBlocks();
         final Block startBlock = schedule.getCFG().getStartBlock();
@@ -219,6 +223,7 @@
     public FrameMap emitLIR(final LIR lir, StructuredGraph graph, final RiResolvedMethod method) {
         final FrameMap frameMap = backend.newFrameMap(runtime.getRegisterConfig(method));
         final LIRGenerator lirGenerator = backend.newLIRGenerator(graph, frameMap, method, lir, xir);
+        Debug.dump(lirGenerator, "LIRGenerator");
 
         Debug.scope("LIRGen", new Runnable() {
             public void run() {
@@ -226,13 +231,7 @@
                     lirGenerator.doBlock(b);
                 }
 
-                for (Block b : lir.linearScanOrder()) {
-                    if (b.phis != null) {
-                        b.phis.fillInputs(lirGenerator);
-                    }
-                }
-
-                Debug.dump(lirGenerator, "After LIR generation");
+                Debug.dump(lir, "After LIR generation");
                 if (GraalOptions.PrintLIR && !TTY.isSuppressed()) {
                     LIR.printLIR(lir.linearScanOrder());
                 }
@@ -269,6 +268,7 @@
             targetMethod.setAssumptions(assumptions);
         }
 
+        Debug.dump(lir, "After code generation");
         Debug.dump(targetMethod, "After code generation");
         return targetMethod;
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Block.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/Block.java	Wed Feb 08 15:35:21 2012 -0800
@@ -45,14 +45,12 @@
     protected Block postdominator;
 
     // Fields that still need to be worked on, try to remove them later.
-    public FrameState lastState;
     public List<LIRInstruction> lir;
     public boolean align;
     public int linearScanNumber;
-    public LIRPhiMapping phis;
 
     public Block() {
-        id = -1;
+        id = ControlFlowGraph.BLOCK_ID_INITIAL;
     }
 
     public int getId() {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/ControlFlowGraph.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/cfg/ControlFlowGraph.java	Wed Feb 08 15:35:21 2012 -0800
@@ -24,6 +24,7 @@
 
 import java.util.*;
 
+import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.graph.*;
 import com.oracle.max.graal.nodes.*;
 
@@ -79,6 +80,9 @@
         return loops;
     }
 
+    protected static final int BLOCK_ID_INITIAL = -1;
+    protected static final int BLOCK_ID_VISITED = -2;
+
     private void identifyBlocks() {
         // Find all block headers
         int numBlocks = 0;
@@ -129,22 +133,24 @@
 
         do {
             Block block = stack.get(stack.size() - 1);
-            if (block.id == -1) {
+            if (block.id == BLOCK_ID_INITIAL) {
                 // First time we see this block: push all successors.
                 for (Node suxNode : block.getEndNode().cfgSuccessors()) {
                     Block suxBlock = blockFor(suxNode);
-                    if (suxBlock.id < 0) {
+                    assert suxBlock.id != BLOCK_ID_VISITED;
+                    if (suxBlock.id == BLOCK_ID_INITIAL) {
                         stack.add(suxBlock);
                     }
                 }
-                block.id = -2;
-            } else {
+                block.id = BLOCK_ID_VISITED;
+            } else if (block.id == BLOCK_ID_VISITED) {
                 // Second time we see this block: All successors haved been processed, so insert block into reverse postorder list.
-                assert block.id == -2;
                 stack.remove(stack.size() - 1);
+                reversePostOrder[reversePostOrderId] = block;
                 block.id = reversePostOrderId;
-                reversePostOrder[reversePostOrderId] = block;
                 reversePostOrderId--;
+            } else {
+                throw Util.shouldNotReachHere();
             }
         } while (!stack.isEmpty());
         assert reversePostOrderId == -1;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Feb 08 15:35:21 2012 -0800
@@ -48,7 +48,7 @@
 import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.cfg.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.lir.StandardOp.ParametersOp;
+import com.oracle.max.graal.compiler.lir.StandardOp.*;
 import com.oracle.max.graal.compiler.util.*;
 import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.graph.*;
@@ -130,7 +130,9 @@
     /**
      * Mapping from blocks to the lock state at the end of the block, indexed by the id number of the block.
      */
-    private LockScope[] blockLocks;
+    private BlockMap<LockScope> blockLocks;
+
+    private BlockMap<FrameState> blockLastState;
 
     /**
      * The list of currently locked monitors.
@@ -149,7 +151,8 @@
         this.xir = xir;
         this.xirSupport = new XirSupport();
         this.debugInfoBuilder = new DebugInfoBuilder(nodeOperands);
-        this.blockLocks = new LockScope[lir.linearScanOrder().size()];
+        this.blockLocks = new BlockMap<>(lir.cfg);
+        this.blockLastState = new BlockMap<>(lir.cfg);
     }
 
     @Override
@@ -157,14 +160,6 @@
         return target;
     }
 
-    private LockScope locksFor(Block block) {
-        return blockLocks[block.getId()];
-    }
-
-    private void setLocksFor(Block block, LockScope locks) {
-        blockLocks[block.getId()] = locks;
-    }
-
     /**
      * Returns the operand that has been previously initialized by {@link #setResult()}
      * with the result of an instruction.
@@ -300,7 +295,21 @@
         assert block.lir == null : "LIR list already computed for this block";
         block.lir = new ArrayList<>();
 
-        emitLabel(new Label(), block.align);
+        if (GraalOptions.AllocSSA && block.getBeginNode() instanceof MergeNode) {
+            assert phiValues.isEmpty();
+            MergeNode merge = (MergeNode) block.getBeginNode();
+            for (PhiNode phi : merge.phis()) {
+                if (phi.type() == PhiType.Value) {
+                    CiValue phiValue = newVariable(phi.kind());
+                    setResult(phi, phiValue);
+                    phiValues.add(phiValue);
+                }
+            }
+            append(new PhiLabelOp(new Label(), block.align, phiValues.toArray(new CiValue[phiValues.size()])));
+            phiValues.clear();
+        } else {
+            append(new LabelOp(new Label(), block.align));
+        }
 
         if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
             TTY.println("BEGIN Generating LIR for block B" + block.getId());
@@ -308,7 +317,7 @@
 
         curLocks = null;
         for (Block pred : block.getPredecessors()) {
-            LockScope predLocks = locksFor(pred);
+            LockScope predLocks = blockLocks.get(pred);
             if (curLocks == null) {
                 curLocks = predLocks;
             } else if (curLocks != predLocks && (!pred.isLoopEnd() || predLocks != null)) {
@@ -326,8 +335,8 @@
 
             for (Block pred : block.getPredecessors()) {
                 if (fs == null) {
-                    fs = pred.lastState;
-                } else if (fs != pred.lastState) {
+                    fs = blockLastState.get(pred);
+                } else if (fs != blockLastState.get(pred)) {
                     fs = null;
                     break;
                 }
@@ -345,10 +354,6 @@
             lastState = fs;
         }
 
-        if (GraalOptions.AllocSSA && block.getBeginNode() instanceof MergeNode) {
-            block.phis = new LIRPhiMapping(block, this);
-        }
-
         List<Node> nodes = lir.nodesFor(block);
         for (int i = 0; i < nodes.size(); i++) {
             Node instr = nodes.get(i);
@@ -406,8 +411,8 @@
             TTY.println("END Generating LIR for block B" + block.getId());
         }
 
-        setLocksFor(currentBlock, curLocks);
-        block.lastState = lastState;
+        blockLocks.put(currentBlock, curLocks);
+        blockLastState.put(block, lastState);
         currentBlock = null;
 
         if (GraalOptions.PrintIRWithLIR) {
@@ -665,27 +670,65 @@
 
     @Override
     public void visitMerge(MergeNode x) {
-        if (x.next() instanceof LoopBeginNode) {
-            moveToPhi((LoopBeginNode) x.next(), x);
-        }
     }
 
     @Override
     public void visitEndNode(EndNode end) {
-        assert end.merge() != null;
         moveToPhi(end.merge(), end);
-        emitJump(getLIRBlock(end.merge()), null);
     }
 
     @Override
     public void visitLoopEnd(LoopEndNode x) {
-        moveToPhi(x.loopBegin(), x);
         if (GraalOptions.GenLoopSafepoints && x.hasSafepointPolling()) {
             emitSafepointPoll(x);
         }
-        emitJump(getLIRBlock(x.loopBegin()), null);
+        moveToPhi(x.loopBegin(), x);
     }
 
+    private ArrayList<CiValue> phiValues = new ArrayList<>();
+
+    private void moveToPhi(MergeNode merge, FixedNode pred) {
+        if (GraalOptions.AllocSSA) {
+            assert phiValues.isEmpty();
+            for (PhiNode phi : merge.phis()) {
+                if (phi.type() == PhiType.Value) {
+                    phiValues.add(operand(phi.valueAt(pred)));
+                }
+            }
+            append(new PhiJumpOp(getLIRBlock(merge), phiValues.toArray(new CiValue[phiValues.size()])));
+            phiValues.clear();
+            return;
+        }
+
+        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
+            TTY.println("MOVE TO PHI from " + pred + " to " + merge);
+        }
+        PhiResolver resolver = new PhiResolver(this);
+        for (PhiNode phi : merge.phis()) {
+            if (phi.type() == PhiType.Value) {
+                ValueNode curVal = phi.valueAt(pred);
+                resolver.move(operand(curVal), operandForPhi(phi));
+            }
+        }
+        resolver.dispose();
+
+        append(new JumpOp(getLIRBlock(merge), null));
+    }
+
+    private CiValue operandForPhi(PhiNode phi) {
+        assert phi.type() == PhiType.Value : "wrong phi type: " + phi;
+        CiValue result = operand(phi);
+        if (result == null) {
+            // allocate a variable for this phi
+            Variable newOperand = newVariable(phi.kind());
+            setResult(phi, newOperand);
+            return newOperand;
+        } else {
+            return result;
+        }
+    }
+
+
     public void emitSafepointPoll(FixedNode x) {
         if (!lastState.method().noSafepointPolls()) {
             XirSnippet snippet = xir.genSafepointPoll(site(x));
@@ -1127,40 +1170,6 @@
     }
 
 
-
-    private void moveToPhi(MergeNode merge, FixedNode pred) {
-        if (GraalOptions.AllocSSA) {
-            return;
-        }
-
-        if (GraalOptions.TraceLIRGeneratorLevel >= 1) {
-            TTY.println("MOVE TO PHI from " + pred + " to " + merge);
-        }
-        PhiResolver resolver = new PhiResolver(this);
-        for (PhiNode phi : merge.phis()) {
-            if (phi.type() == PhiType.Value) {
-                ValueNode curVal = phi.valueAt(pred);
-                resolver.move(operand(curVal), operandForPhi(phi));
-            }
-        }
-        resolver.dispose();
-    }
-
-    private CiValue operandForPhi(PhiNode phi) {
-        assert phi.type() == PhiType.Value : "wrong phi type: " + phi;
-        CiValue result = operand(phi);
-        if (result == null) {
-            // allocate a variable for this phi
-            Variable newOperand = newVariable(phi.kind());
-            setResult(phi, newOperand);
-            return newOperand;
-        } else {
-            return result;
-        }
-    }
-
-
-
     protected XirArgument toXirArgument(CiValue v) {
         if (v == null) {
             return null;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java	Wed Feb 08 15:35:21 2012 -0800
@@ -162,22 +162,22 @@
     /**
      * The output operands for this instruction (modified by the register allocator).
      */
-    protected final CiValue[] outputs;
+    protected CiValue[] outputs;
 
     /**
      * The input operands for this instruction (modified by the register allocator).
      */
-    protected final CiValue[] inputs;
+    protected CiValue[] inputs;
 
     /**
      * The alive operands for this instruction (modified by the register allocator).
      */
-    protected final CiValue[] alives;
+    protected CiValue[] alives;
 
     /**
      * The temp operands for this instruction (modified by the register allocator).
      */
-    protected final CiValue[] temps;
+    protected CiValue[] temps;
 
     /**
      * Used to emit debug information.
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java	Wed Feb 08 17:40:55 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.max.graal.compiler.lir;
-
-import java.util.*;
-
-import com.oracle.max.cri.ci.*;
-import com.oracle.max.graal.compiler.cfg.*;
-import com.oracle.max.graal.compiler.gen.*;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
-import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.nodes.*;
-import com.oracle.max.graal.nodes.PhiNode.*;
-
-public class LIRPhiMapping {
-    private final Block block;
-
-    private CiValue[][] inputs;
-    private CiValue[] results;
-
-    public LIRPhiMapping(Block block, LIRGenerator gen) {
-        this.block = block;
-
-        assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges";
-        MergeNode mergeNode = (MergeNode) block.getBeginNode();
-        List<PhiNode> phis = mergeNode.phis().snapshot();
-
-        for (int i = 0; i < phis.size(); i++) {
-            PhiNode phi = phis.get(i);
-            if (phi.type() == PhiType.Value) {
-                gen.setResult(phi, gen.newVariable(phi.kind()));
-            }
-        }
-    }
-
-    public void fillInputs(LIRGenerator gen) {
-        assert block.getBeginNode() instanceof MergeNode : "phi functions are only present at control flow merges";
-        MergeNode mergeNode = (MergeNode) block.getBeginNode();
-        List<PhiNode> phis = mergeNode.phis().snapshot();
-
-        int numPhis = 0;
-        for (int i = 0; i < phis.size(); i++) {
-            if (phis.get(i).type() == PhiType.Value) {
-                numPhis++;
-            }
-        }
-        int numPreds = block.numberOfPreds();
-
-        results = new CiValue[numPhis];
-        inputs = new CiValue[numPreds][numPhis];
-
-        int phiIdx = 0;
-        for (int i = 0; i < phis.size(); i++) {
-            PhiNode phi = phis.get(i);
-            if (phi.type() == PhiType.Value) {
-                results[phiIdx] = gen.operand(phi);
-                for (int j = 0; j < numPreds; j++) {
-                    assert j == mergeNode.phiPredecessorIndex((FixedNode) block.predAt(j).getEndNode()) : "block predecessors and node predecessors must have same order";
-                    inputs[j][phiIdx] = gen.operand(phi.valueAt(j));
-                }
-                phiIdx++;
-            }
-        }
-        assert phiIdx == numPhis;
-    }
-
-    public CiValue[] results() {
-        return results;
-    }
-
-    public CiValue[] inputs(Block pred) {
-        assert pred.numberOfSux() == 1 && pred.suxAt(0) == block;
-        return inputs[block.getPredecessors().indexOf(pred)];
-    }
-
-    private static final EnumSet<OperandFlag> INPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-    private static final EnumSet<OperandFlag> OUTPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-
-    public void forEachInput(Block pred, PhiValueProcedure proc) {
-        CiValue[] predInputs = inputs(pred);
-        for (int i = 0; i < predInputs.length; i++) {
-            predInputs[i] = proc.doValue(predInputs[i], results[i]);
-        }
-    }
-
-    public void forEachOutput(ValueProcedure proc) {
-        for (int i = 0; i < results.length; i++) {
-            results[i] = proc.doValue(results[i], OperandMode.Output, OUTPUT_FLAGS);
-        }
-    }
-
-    public abstract static class PhiValueProcedure extends ValueProcedure {
-        /**
-         * Iterator method to be overwritten. This version of the iterator has both the input and output of the phi function as parameters.
-         * to keep the signature short.
-         *
-         * @param input The input value that is iterated.
-         * @param output The output value that is iterated.
-         * @return The new value to replace the input value that was passed in.
-         */
-        protected CiValue doValue(CiValue input, CiValue output) {
-            return doValue(input, OperandMode.Input, INPUT_FLAGS);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "PhiMapping for " + block + ": " + Arrays.toString(results);
-    }
-}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRVerifier.java	Wed Feb 08 15:35:21 2012 -0800
@@ -33,7 +33,6 @@
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode;
 import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure;
-import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure;
 import com.oracle.max.graal.compiler.util.*;
 
 public final class LIRVerifier {
@@ -96,8 +95,8 @@
     private BitSet curRegistersDefined;
 
     private void verify() {
-        PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
-        ValueProcedure defProc =    new ValueProcedure() {    @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } };
+        ValueProcedure useProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return use(value, mode, flags); } };
+        ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { return def(value, mode, flags); } };
 
         curRegistersDefined = new BitSet();
         for (Block block : lir.linearScanOrder()) {
@@ -109,13 +108,24 @@
                 curVariablesLive.or(liveOutFor(block.getDominator()));
             }
 
-            if (block.phis != null) {
-                assert beforeRegisterAllocation;
-                curInstruction = block.phis;
-                block.phis.forEachOutput(defProc);
+            assert block.lir.get(0) instanceof StandardOp.LabelOp : "block must start with label";
+            if (block.numberOfPreds() > 1) {
+                assert block.lir.get(0) instanceof StandardOp.PhiLabelOp : "phi mapping required for multiple predecessors";
+                CiValue[] phiDefinitions = ((StandardOp.PhiLabelOp) block.lir.get(0)).getPhiDefinitions();
+                if (!beforeRegisterAllocation) {
+                    assert phiDefinitions.length == 0;
+                }
+                for (Block pred : block.getPredecessors()) {
+                    assert pred.numberOfSux() == 1;
+                    LIRInstruction last = pred.lir.get(pred.lir.size() - 1);
+                    assert last instanceof StandardOp.PhiJumpOp : "phi mapping required for multiple successors";
+                    CiValue[] phiUses = ((StandardOp.PhiJumpOp) last).getPhiInputs();
+                    if (!beforeRegisterAllocation) {
+                        assert phiUses.length == 0;
+                    }
+                }
             }
 
-            assert block.lir.get(0) instanceof StandardOp.LabelOp : "block must start with label";
             if (block.numberOfSux() > 0) {
                 LIRInstruction last = block.lir.get(block.lir.size() - 1);
                 assert last instanceof StandardOp.JumpOp || last instanceof LIRXirInstruction : "block with successor must end with unconditional jump";
@@ -139,14 +149,6 @@
                 curInstruction = null;
             }
 
-            for (Block sux : block.getSuccessors()) {
-                if (sux.phis != null) {
-                    assert beforeRegisterAllocation;
-                    curInstruction = sux.phis;
-                    sux.phis.forEachInput(block, useProc);
-                }
-            }
-
             setLiveOutFor(block, curVariablesLive);
         }
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOp.java	Wed Feb 08 15:35:21 2012 -0800
@@ -35,23 +35,130 @@
  */
 public class StandardOp {
 
+    private static CiValue[] EMPTY = new CiValue[0];
+
     /**
-     * Marker interface for a LIR operation that defines the position of a label.
+     * LIR operation that defines the position of a label.
      * The first operation of every block must implement this interface.
      */
-    public interface LabelOp {
-        Label getLabel();
+    public static class LabelOp extends LIRInstruction {
+        private final Label label;
+        private final boolean align;
+
+        protected LabelOp(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps, Label label, boolean align) {
+            super(opcode, outputs, info, inputs, alives, temps);
+            this.label = label;
+            this.align = align;
+        }
+
+        public LabelOp(Label label, boolean align) {
+            this("LABEL", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm) {
+            if (align) {
+                tasm.asm.align(tasm.target.wordSize);
+            }
+            tasm.asm.bind(label);
+        }
+
+        @Override
+        public String operationString() {
+            return label.toString() + " " + super.operationString();
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            throw Util.shouldNotReachHere();
+        }
+
+        public Label getLabel() {
+            return label;
+        }
+    }
+
+    public static class PhiLabelOp extends LabelOp {
+        public PhiLabelOp(Label label, boolean align, CiValue[] phiDefinitions) {
+            super("PHI_LABEL", phiDefinitions, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Output) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+            }
+            throw Util.shouldNotReachHere();
+        }
+
+        public void markResolved() {
+            outputs = EMPTY;
+        }
+
+        public CiValue[] getPhiDefinitions() {
+            return outputs;
+        }
     }
 
     /**
-     * Marker interface for a LIR operation that is an unconditional jump to {@link #destination()}.
+     * LIR operation that is an unconditional jump to {@link #destination()}.
      * When the LIR is constructed, the last operation of every block must implement this interface. After
      * register allocation, unnecessary jumps can be deleted.
      *
      * TODO Currently, a block can also end with an XIR operation.
      */
-    public interface JumpOp {
-        LabelRef destination();
+    public static class JumpOp extends LIRInstruction {
+        private final LabelRef destination;
+
+        protected JumpOp(Object opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps, LabelRef destination) {
+            super(opcode, outputs, info, inputs, alives, temps);
+            this.destination = destination;
+        }
+
+        public JumpOp(LabelRef destination, LIRDebugInfo info) {
+            this("JUMP", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, destination);
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm) {
+            tasm.asm.jmp(destination.label());
+        }
+
+        @Override
+        public String operationString() {
+            return  destination + " " + super.operationString();
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            throw Util.shouldNotReachHere();
+        }
+
+        public LabelRef destination() {
+            return destination;
+        }
+    }
+
+    public static class PhiJumpOp extends JumpOp {
+        public PhiJumpOp(LabelRef destination, CiValue[] phiInputs) {
+            super("PHI_JUMP", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, phiInputs, LIRInstruction.NO_OPERANDS, destination);
+        }
+
+        @Override
+        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
+            if (mode == OperandMode.Alive) {
+                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
+            }
+            throw Util.shouldNotReachHere();
+        }
+
+        public void markResolved() {
+            alives = EMPTY;
+        }
+
+        public CiValue[] getPhiInputs() {
+            return alives;
+        }
     }
 
     /**
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlow.java	Wed Feb 08 15:35:21 2012 -0800
@@ -39,41 +39,6 @@
 
 public class AMD64ControlFlow {
 
-    public static class LabelOp extends AMD64LIRInstruction implements StandardOp.LabelOp {
-        private final Label label;
-        private final boolean align;
-
-        public LabelOp(Label label, boolean align) {
-            super("LABEL", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-            this.label = label;
-            this.align = align;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            if (align) {
-                masm.align(tasm.target.wordSize);
-            }
-            masm.bind(label);
-        }
-
-        @Override
-        public String operationString() {
-            return label.toString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw Util.shouldNotReachHere();
-        }
-
-        @Override
-        public Label getLabel() {
-            return label;
-        }
-    }
-
-
     public static class ReturnOp extends AMD64LIRInstruction {
         public ReturnOp(CiValue input) {
             super("RETURN", LIRInstruction.NO_OPERANDS, null, new CiValue[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
@@ -94,36 +59,6 @@
     }
 
 
-    public static class JumpOp extends AMD64LIRInstruction implements StandardOp.JumpOp {
-        private final LabelRef destination;
-
-        public JumpOp(LabelRef destination, LIRDebugInfo info) {
-            super("JUMP", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-            this.destination = destination;
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.jmp(destination.label());
-        }
-
-        @Override
-        public LabelRef destination() {
-            return destination;
-        }
-
-        @Override
-        public String operationString() {
-            return  "[" + destination + "]";
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw Util.shouldNotReachHere();
-        }
-    }
-
-
     public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp {
         protected Condition condition;
         protected LabelRef destination;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Feb 08 15:35:21 2012 -0800
@@ -39,6 +39,8 @@
 import com.oracle.max.cri.xir.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.lir.*;
+import com.oracle.max.graal.compiler.lir.StandardOp.JumpOp;
+import com.oracle.max.graal.compiler.lir.StandardOp.LabelOp;
 import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.DivOp;
 import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op1Reg;
 import com.oracle.max.graal.compiler.target.amd64.AMD64Arithmetic.Op1Stack;
@@ -52,8 +54,6 @@
 import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.CondMoveOp;
 import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.FloatBranchOp;
 import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.FloatCondMoveOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.JumpOp;
-import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.LabelOp;
 import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.ReturnOp;
 import com.oracle.max.graal.compiler.target.amd64.AMD64ControlFlow.TableSwitchOp;
 import com.oracle.max.graal.compiler.target.amd64.AMD64Move.CompareAndSwapOp;
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotDebugConfig.java	Wed Feb 08 15:35:21 2012 -0800
@@ -49,6 +49,7 @@
         this.dumpFilter = dumpFilter;
         this.methodFilter = methodFilter;
         dumpHandlers.add(new IdealGraphPrinterDumpHandler(GraalOptions.PrintIdealGraphAddress, GraalOptions.PrintIdealGraphPort));
+        dumpHandlers.add(new CFGPrinterObserver());
     }
 
     public boolean isLogEnabled() {
--- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java	Wed Feb 08 15:35:21 2012 -0800
@@ -1173,7 +1173,7 @@
     private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) {
        @Override
        protected XirTemplate create(CiXirAssembler asm, long flags) {
-           asm.restart();
+           asm.restart(CiKind.Void);
            XirParameter objHub = asm.createInputParameter("objectHub", CiKind.Object);
            XirOperand hub = asm.createConstantInputParameter("hub", CiKind.Object);
            XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor);
@@ -1188,7 +1188,7 @@
            // if we get an exact match: continue
            asm.jneq(falseSucc, objHub, checkHub);
 
-           return asm.finishTemplate(objHub, "typeCheck");
+           return asm.finishTemplate("typeCheck");
        }
     };
 
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinter.java	Wed Feb 08 15:35:21 2012 -0800
@@ -50,7 +50,6 @@
  */
 class CFGPrinter extends CompilationPrinter {
 
-    public final ByteArrayOutputStream buffer;
     public final CiTarget target;
     public final RiRuntime runtime;
     public LIR lir;
@@ -61,9 +60,8 @@
      *
      * @param buffer where the output generated via this printer shown be written
      */
-    public CFGPrinter(ByteArrayOutputStream buffer, CiTarget target, RiRuntime runtime) {
-        super(buffer);
-        this.buffer = buffer;
+    public CFGPrinter(OutputStream out, CiTarget target, RiRuntime runtime) {
+        super(out);
         this.target = target;
         this.runtime = runtime;
     }
@@ -347,22 +345,6 @@
         begin("IR");
         out.println("LIR");
 
-        if (block.phis != null) {
-            CiValue[] results = block.phis.results();
-            for (int i = 0; i < results.length; i++) {
-                if (i == 0) {
-                    out.printf("nr %4d ", block.getFirstLirInstructionId()).print(COLUMN_END);
-                }
-                out.print("instruction PHI ").print(results[i].toString()).print(" = (");
-                String sep = "";
-                for (Block pred : block.getPredecessors()) {
-                    out.print(sep).print(block.phis.inputs(pred)[i].toString());
-                    sep = ", ";
-                }
-                out.print(")").print(COLUMN_END).println(COLUMN_END);
-            }
-        }
-
         for (int i = 0; i < lirInstructions.size(); i++) {
             LIRInstruction inst = lirInstructions.get(i);
             out.printf("nr %4d ", inst.id()).print(COLUMN_END);
--- a/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Wed Feb 08 17:40:55 2012 +0100
+++ b/graal/com.oracle.max.graal.printer/src/com/oracle/max/graal/printer/CFGPrinterObserver.java	Wed Feb 08 15:35:21 2012 -0800
@@ -27,14 +27,13 @@
 
 import com.oracle.max.cri.ci.*;
 import com.oracle.max.cri.ri.*;
-import com.oracle.max.criutils.*;
 import com.oracle.max.graal.alloc.util.*;
+import com.oracle.max.graal.compiler.*;
 import com.oracle.max.graal.compiler.alloc.*;
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.compiler.lir.*;
-import com.oracle.max.graal.compiler.observer.*;
 import com.oracle.max.graal.compiler.schedule.*;
-import com.oracle.max.graal.graph.*;
+import com.oracle.max.graal.debug.*;
 import com.oracle.max.graal.java.*;
 import com.oracle.max.graal.nodes.*;
 
@@ -42,103 +41,84 @@
  * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the <a
  * href="http://java.net/projects/c1visualizer/">C1 Visualizer</a>.
  */
-public class CFGPrinterObserver implements CompilationObserver {
+public class CFGPrinterObserver implements DebugDumpHandler {
+
+    private CFGPrinter cfgPrinter;
 
-    /**
-     * A thread local stack of {@link CFGPrinter}s to support thread-safety and re-entrant compilation.
-     */
-    private ThreadLocal<LinkedList<CFGPrinter>> observations = new ThreadLocal<LinkedList<CFGPrinter>>() {
-        @Override
-        protected java.util.LinkedList<CFGPrinter> initialValue() {
-            return new LinkedList<>();
-        }
-    };
+    private GraalCompiler compiler;
+    private RiResolvedMethod method;
+    private SchedulePhase schedule;
 
     @Override
-    public void compilationStarted(CompilationEvent event) {
-        if (TTY.isSuppressed()) {
+    public void dump(final Object object, final String message) {
+        Debug.sandbox("CFGPrinter", new Runnable() {
+            @Override
+            public void run() {
+                dumpSandboxed(object, message);
+            }
+        });
+    }
+
+    private void dumpSandboxed(final Object object, final String message) {
+        if (object instanceof GraalCompiler) {
+            compiler = (GraalCompiler) object;
+            return;
+        } else if (object instanceof SchedulePhase) {
+            schedule = (SchedulePhase) object;
+            return;
+        } else if (object instanceof LIRGenerator) {
+            cfgPrinter.lirGenerator = (LIRGenerator) object;
             return;
         }
-        RiRuntime runtime = event.debugObject(RiRuntime.class);
-        CiTarget target = event.debugObject(CiTarget.class);
 
-        CFGPrinter cfgPrinter = new CFGPrinter(new ByteArrayOutputStream(), target, runtime);
-        cfgPrinter.printCompilation(event.debugObject(RiResolvedMethod.class));
-        observations.get().push(cfgPrinter);
-    }
-
-    @Override
-    public void compilationEvent(CompilationEvent event) {
-        if (TTY.isSuppressed()) {
-            return;
-        }
-        CFGPrinter cfgPrinter = observations.get().peek();
         if (cfgPrinter == null) {
-            return;
+            File file = new File("compilations-" + System.currentTimeMillis() + ".cfg");
+            try {
+                OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
+                cfgPrinter = new CFGPrinter(out, compiler.target, compiler.runtime);
+            } catch (FileNotFoundException e) {
+                throw new InternalError("Could not open " + file.getAbsolutePath());
+            }
         }
 
         RiRuntime runtime = cfgPrinter.runtime;
-        if (event.debugObject(LIR.class) != null) {
-            cfgPrinter.lir = event.debugObject(LIR.class);
-        }
-        if (event.debugObject(LIRGenerator.class) != null) {
-            cfgPrinter.lirGenerator = event.debugObject(LIRGenerator.class);
+        if (object instanceof RiResolvedMethod) {
+            method = (RiResolvedMethod) object;
+            cfgPrinter.printCompilation(method);
+
+            cfgPrinter.lir = null;
+            cfgPrinter.lirGenerator = null;
+            schedule = null;
+
+        } else if (object instanceof BciBlockMapping) {
+            BciBlockMapping blockMap = (BciBlockMapping) object;
+            cfgPrinter.printCFG(message, blockMap);
+            cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method));
+
+        } else if (object instanceof LIR) {
+            cfgPrinter.lir = (LIR) object;
+            cfgPrinter.printCFG(message, ((LIR) object).codeEmittingOrder(), schedule);
+
+        } else if (object instanceof StructuredGraph) {
+            SchedulePhase curSchedule = schedule;
+            if (curSchedule == null) {
+                try {
+                    curSchedule = new SchedulePhase();
+                    curSchedule.apply((StructuredGraph) object);
+                } catch (Throwable ex) {
+                    // ignore
+                }
+            }
+            cfgPrinter.printCFG(message, Arrays.asList(curSchedule.getCFG().getBlocks()), curSchedule);
+
+        } else if (object instanceof CiTargetMethod) {
+            cfgPrinter.printMachineCode(runtime.disassemble((CiTargetMethod) object), null);
+        } else if (object instanceof Interval[]) {
+            cfgPrinter.printIntervals(message, (Interval[]) object);
+        } else if (object instanceof IntervalPrinter.Interval[]) {
+            cfgPrinter.printIntervals(message, (IntervalPrinter.Interval[]) object);
         }
 
-        BciBlockMapping blockMap = event.debugObject(BciBlockMapping.class);
-        Graph graph = event.debugObject(Graph.class);
-        SchedulePhase schedule = event.debugObject(SchedulePhase.class);
-        LinearScan allocator = event.debugObject(LinearScan.class);
-        Interval[] intervals = event.debugObject(Interval[].class);
-        IntervalPrinter.Interval[] printIntervals = event.debugObject(IntervalPrinter.Interval[].class);
-        CiTargetMethod targetMethod = event.debugObject(CiTargetMethod.class);
-
-        if (blockMap != null) {
-            cfgPrinter.printCFG(event.label, blockMap);
-            cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method));
-        }
-        if (cfgPrinter.lir != null) {
-            cfgPrinter.printCFG(event.label, cfgPrinter.lir.codeEmittingOrder(), schedule);
-            if (targetMethod != null) {
-                cfgPrinter.printMachineCode(runtime.disassemble(targetMethod), null);
-            }
-        } else if (graph != null) {
-            if (schedule == null) {
-                try {
-                    schedule = new SchedulePhase();
-                    schedule.apply((StructuredGraph) graph);
-                } catch (Throwable t) {
-                    // nothing to do here...
-                }
-            }
-            cfgPrinter.printCFG(event.label, Arrays.asList(schedule.getCFG().getBlocks()), schedule);
-        }
-        if (allocator != null && intervals != null) {
-            cfgPrinter.printIntervals(event.label, intervals);
-        }
-        if (printIntervals != null) {
-            cfgPrinter.printIntervals(event.label, printIntervals);
-        }
-    }
-
-    @Override
-    public void compilationFinished(CompilationEvent event) {
-        if (TTY.isSuppressed()) {
-            return;
-        }
-        CFGPrinter cfgPrinter = observations.get().pop();
         cfgPrinter.flush();
-
-        OutputStream stream = CompilationPrinter.globalOut();
-        if (stream != null) {
-            synchronized (stream) {
-                try {
-                    stream.write(cfgPrinter.buffer.toByteArray());
-                    stream.flush();
-                } catch (IOException e) {
-                    TTY.println("WARNING: Error writing CFGPrinter output: %s", e);
-                }
-            }
-        }
     }
 }