void remove_phi(Method m){
  Deque<Block> code=dfs(m.entry.to);
  SetMap<Block,Edge> pred=preds(code);
  Map<Integer,Integer> locals=new TreeMap<Integer,Integer>();
  Map<Block,Deque<Expr>> exprs=new TreeMap<Block,Deque<Expr>>();
  ConflictGraph conflicts=new ConflictGraph();
  printMethod(m,"BEFORE SCHED");
  addTraceAttr(m);
  restused:   if (m.needsArguments() || m.needsRest()) {
    int rest=m.getParams().length;
    for (    Expr e : m.entry.to)     if (e.op == OP_arg && e.imm[0] == rest)     break restused;
    m.flags&=~(METHOD_Arguments | METHOD_Needrest);
    m.flags|=METHOD_IgnoreRest;
    verboseStatus("IGNORE_REST for " + m.getName());
  }
  int max_local=m.getParams().length - 1;
  sched_greedy(m,code,locals,pred,exprs,conflicts);
  alloc_locals(code,locals,conflicts,m.fixedLocals);
  Set<Edge> splits=new TreeSet<Edge>();
  for (  Block b : code) {
    for (    Expr e : b) {
      if (e.op != OP_phi)       break;
      if (!locals.containsKey(e.id))       continue;
      addTraceAttr(e);
      int lhs=locals.get(e.id);
      for (int i=e.args.length - 1; i >= 0; i--) {
        traceEntry("PhiInput");
        addTraceAttr("i",i);
        addTraceAttr(e.args[i]);
        int rhs=locals.get(e.args[i].id);
        if (lhs != rhs) {
          Edge p=e.pred[i];
          if (!splits.contains(p)) {
            split(p,m,pred);
            splits.add(p=e.pred[i]);
          }
          traceEntry("copyPhiInput");
          addTraceAttr("lhs",lhs);
          addTraceAttr("rhs",rhs);
          Expr get=getlocal(m,rhs);
          prepend(p,get);
          append(p,setlocal(m,lhs,get));
        }
      }
    }
    b.exprs=exprs.get(b);
    for (    Expr e : b.exprs) {
      int loc=max_local;
      if (e.op == OP_getlocal || e.op == OP_setlocal) {
        loc=e.imm[0]=locals.get(e.imm[0]);
      }
 else       if (e.op == OP_hasnext2) {
        int loc0=locals.get(e.locals[0].id);
        int loc1=locals.get(e.locals[1].id);
        e.imm=new int[]{loc0,loc1};
        loc=loc0 > loc1 ? loc0 : loc1;
      }
      if (loc > max_local)       max_local=loc;
    }
  }
  m.local_count=max_local + 1;
  cfgopt(m);
  printMethod(m,"AFTER SCHED");
}

void remove_phi ( Method m ) { Deque < Block > code = dfs ( m . entry . to ) ; SetMap < Block , Edge > pred = preds ( code ) ; Map < Integer , Integer > locals = new TreeMap < Integer , Integer > ( ) ; Map < Block , Deque < Expr > > exprs = new TreeMap < Block , Deque < Expr > > ( ) ; ConflictGraph conflicts = new ConflictGraph ( ) ; printMethod ( m , "BEFORE SCHED" ) ; addTraceAttr ( m ) ; restused : if ( m . needsArguments ( ) || m . needsRest ( ) ) { int rest = m . getParams ( ) . length ; for ( Expr e : m . entry . to ) if ( e . op == OP_arg && e . imm [ 0 ] == rest ) break restused ; m . flags &= ~ ( METHOD_Arguments | METHOD_Needrest ) ; m . flags |= METHOD_IgnoreRest ; verboseStatus ( "IGNORE_REST for " + m . getName ( ) ) ; } int max_local = m . getParams ( ) . length - 1 ; sched_greedy ( m , code , locals , pred , exprs , conflicts ) ; alloc_locals ( code , locals , conflicts , m . fixedLocals ) ; Set < Edge > splits = new TreeSet < Edge > ( ) ; for ( Block b : code ) { for ( Expr e : b ) { if ( e . op != OP_phi ) break ; if ( ! locals . containsKey ( e . id ) ) continue ; addTraceAttr ( e ) ; int lhs = locals . get ( e . id ) ; for ( int i = e . args . length - 1 ; i >= 0 ; i -- ) { traceEntry ( "PhiInput" ) ; addTraceAttr ( "i" , i ) ; addTraceAttr ( e . args [ i ] ) ; int rhs = locals . get ( e . args [ i ] . id ) ; if ( lhs != rhs ) { Edge p = e . pred [ i ] ; if ( ! splits . contains ( p ) ) { split ( p , m , pred ) ; splits . add ( p = e . pred [ i ] ) ; } traceEntry ( "copyPhiInput" ) ; addTraceAttr ( "lhs" , lhs ) ; addTraceAttr ( "rhs" , rhs ) ; Expr get = getlocal ( m , rhs ) ; prepend ( p , get ) ; append ( p , setlocal ( m , lhs , get ) ) ; } } } b . exprs = exprs . get ( b ) ; for ( Expr e : b . exprs ) { int loc = max_local ; if ( e . op == OP_getlocal || e . op == OP_setlocal ) { loc = e . imm [ 0 ] = locals . get ( e . imm [ 0 ] ) ; } else if ( e . op == OP_hasnext2 ) { int loc0 = locals . get ( e . locals [ 0 ] . id ) ; int loc1 = locals . get ( e . locals [ 1 ] . id ) ; e . imm = new int [ ] { loc0 , loc1 } ; loc = loc0 > loc1 ? loc0 : loc1 ; } if ( loc > max_local ) max_local = loc ; } } m . local_count = max_local + 1 ; cfgopt ( m ) ; printMethod ( m , "AFTER SCHED" ) ; }
the last phase before emitting code . - stack scheduling - scope scheduling - assign local variables - replace phi ' s with copies if necessary - recompute frame size
