OPT_SSA.addAtEnd(ir, bb, ci, c.phi.getBasicBlock().isExceptionHandlerBasicBlock());
if (shouldSplitBlock) { OPT_BasicBlock criticalBlock = OPT_IRTools.makeBlockOnEdge(bb, c.phi.getBasicBlock(), ir);  criticalBlock.appendInstructionRespectingTerminalBranch(ci); } else OPT_SSA.addAtEnd(ir, bb, ci, c.phi.getBasicBlock().isExceptionHandlerBasicBlock());
  private java.util.Set scheduleCopies (OPT_BasicBlock bb, OPT_LiveAnalysis live,                                    VariableStacks s) {    // pushed records variables renamed in this block    java.util.Set pushed = new java.util.HashSet(4);    // compute out liveness from information in LiveAnalysis    OPT_LiveSet out = new OPT_LiveSet();    for (Enumeration outBlocks = bb.getOut(); outBlocks.hasMoreElements(); ) {      OPT_BasicBlock ob = (OPT_BasicBlock)outBlocks.nextElement();      OPT_LiveAnalysis.BBLiveElement le = live.getLiveInfo(ob);      out.add(le.in());    }    // initialization    java.util.HashMap map = new java.util.HashMap(4);    java.util.HashSet usedByAnother = new java.util.HashSet(4);    OPT_LinkedListObjectElement copySet = null;    OPT_LinkedListObjectElement workList = null;    // collect copies required in this block.  These copies move    // the appropriate rval into the lval of each phi node in    // control children of the current block.    Enumeration e = bb.getOut();    while (e.hasMoreElements()) {      OPT_BasicBlock bbs = (OPT_BasicBlock)e.nextElement();      if (bbs.isExit()) continue;      for (OPT_Instruction phi = bbs.firstInstruction();           phi != bbs.lastInstruction();           phi = phi.nextInstructionInCodeOrder()) {        if (phi.operator() != PHI) continue;        for (int index=0; index<Phi.getNumberOfPreds(phi); index++) {          if (Phi.getPred(phi,index).block != bb) continue;          OPT_Operand rval = Phi.getValue(phi, index);          if (rval.isRegister() && Phi.getResult(phi).asRegister().register              == rval.asRegister().register)             continue;          Copy c = new Copy(phi, index);          copySet = OPT_LinkedListObjectElement.cons(c, copySet);          if (c.source instanceof OPT_RegisterOperand) {            OPT_Register r = c.source.asRegister().register;            map.put(r, r);            usedByAnother.add(r);          }          if (c.destination instanceof OPT_RegisterOperand) {            OPT_Register r = c.destination.asRegister().register;            map.put(r, r);          }        }      }    }    //  the copies that need to be added to this block are processed    //  in a worklist that ensures that copies are inserted only    //  after the destination register has been read by any other copy    //  that needs it.    //    // initialize work list with all copies whose destination is not    // the source for any other copy, and delete such copies from    // the set of needed copies.    OPT_LinkedListObjectElement ptr = OPT_LinkedListObjectElement.cons(null,         copySet);    OPT_LinkedListObjectElement head = ptr;    while (ptr.getNext() != null) {      Copy c = (Copy)((OPT_LinkedListObjectElement)ptr.getNext()).getValue();      if (!usedByAnother.contains(c.destination.register)) {        workList = OPT_LinkedListObjectElement.cons(c, workList);        ptr.setNext(ptr.getNext().getNext());      }       else         ptr = (OPT_LinkedListObjectElement)ptr.getNext();    }    copySet = (OPT_LinkedListObjectElement)head.getNext();    // while there is any more work to do.    while (workList != null || copySet != null) {      // while there are copies that can be correctly inserted.      while (workList != null) {        Copy c = (Copy)workList.getValue();        workList = (OPT_LinkedListObjectElement)workList.getNext();        OPT_Register r = c.destination.register;        VM_Type tt = c.destination.type;        if (tt == null) {          tt = VM_Type.IntType;          VM.sysWrite("OPT_SSA, warning: null type in " + c.destination              + "\n");        }        // this check captures cases when the result of a phi        // in a control successor is live on exit of the current        // block.  this means it is incorrect to simply insert        // a copy of the destination in the current block.  so        // we rename the destination to a new temporary, and        // record the renaming so that dominator blocks get the        // new name.        if (out.contains(r)) {          OPT_Register t = ir.regpool.getReg(r);          OPT_Instruction save = OPT_SSA.makeMoveInstruction(ir, t, r,               tt);          c.phi.insertFront(save);          s.push(r, new OPT_RegisterOperand(t, tt));          pushed.add(r);        }        OPT_Instruction ci = null;        // insert copy operation required to remove phi        if (c.source instanceof OPT_NullConstantOperand) {          if (tt.isReferenceType())            ci = OPT_SSA.makeMoveInstruction(ir,                 r, (OPT_ConstantOperand)c.source);        }         else if (c.source instanceof OPT_ConstantOperand) {          ci = OPT_SSA.makeMoveInstruction(ir, r,               (OPT_ConstantOperand)c.source);        }         else if (c.source instanceof OPT_RegisterOperand) {          OPT_Register sr = c.source.asRegister().register;          ci = OPT_SSA.makeMoveInstruction(ir, r, (OPT_Register)map.get(sr),               tt);          map.put(sr, r);        }         else {          throw  new OPT_OptimizingCompilerException("Unexpected phi operand "              + c.source + " encountered during SSA teardown", true);        }        if (ci != null)          OPT_SSA.addAtEnd(ir, bb, ci,               c.phi.getBasicBlock().isExceptionHandlerBasicBlock());        // source has been copied and so can now be overwritten        // safely.  so now add any copies _to_ the source of the        // current copy to the work list.        if (c.source instanceof OPT_RegisterOperand) {          OPT_Register saved = c.source.asRegister().register;          OPT_LinkedListObjectElement ptr1 = OPT_LinkedListObjectElement.cons(              null, copySet);          OPT_LinkedListObjectElement head1 = ptr1;          while (ptr1.getNext() != null) {            Copy cc = (Copy)((OPT_LinkedListObjectElement)ptr1.getNext()).                getValue();            if (cc.destination.asRegister().register == saved) {              workList = OPT_LinkedListObjectElement.cons(cc, workList);              ptr1.setNext(ptr1.getNext().getNext());            }             else               ptr1 = (OPT_LinkedListObjectElement)ptr1.getNext();          }          copySet = (OPT_LinkedListObjectElement)head1.getNext();        }      }      // and empty work list with work remaining in the copy set      // implies a cycle in the dependencies amongst copies.  deal      // with this: break the cycle by copying the destination       // of an arbitrary member of the copy set into a temporary.      // this destination has thus been saved, and can now be      // safely overwritten.  so, add that copy to the work list.      if (copySet != null) {        Copy c = (Copy)copySet.getValue();        copySet = (OPT_LinkedListObjectElement)copySet.getNext();        OPT_Register tt = ir.regpool.getReg(c.destination.register);        OPT_SSA.addAtEnd(ir, bb, OPT_SSA.makeMoveInstruction(            ir, tt, c.destination.register,             c.destination.type),             c.phi.getBasicBlock().isExceptionHandlerBasicBlock());        map.put(c.destination.register, tt);        workList = OPT_LinkedListObjectElement.cons(c, workList);      }    }    return  pushed;  }