if (rhs.isRegister()) { OPT_Register rrhs = rhs.asRegister().register;    if (!rrhs.isSSA()) continue;     if (rrhs.isPhysical()) continue; }
  static void copyPropagation (OPT_IR ir) {    // Use register list to enumerate register objects     OPT_Register elemNext;    boolean reiterate = true;    while (reiterate) {         // /MT/ better think about proper ordering.      reiterate = false;      instructions: for (OPT_Register reg = ir.regpool.getFirstSymbolicRegister();           reg != null; reg = elemNext) {        elemNext = reg.getNext(); // we may remove reg, so get elemNext up front        if (reg.useList == null ||   // Copy propagation not possible if reg                                      // has no uses	    reg.defList == null ||   // Copy propagation not possible if reg                                      // has no defs	    !reg.isSSA())            // Flow-insensitive copy prop only possible                                      // for SSA registers.          continue;        // isSSA => reg has exactly one definition, reg.defList.        OPT_RegisterOperand lhs = reg.defList;        OPT_Instruction defInstr = lhs.instruction;        OPT_Operand rhs;        // Copy/constant propagation only possible when defInstr is a move        if (defInstr.isMove()) {          rhs = Move.getVal(defInstr);        } else if (defInstr.operator() == PHI) {	  OPT_Operand phiVal = equivalentValforPHI (defInstr);	  if (phiVal == null)  continue  instructions;          rhs = phiVal;        } else {          continue  instructions;	}        // If rhs is a non-SSA register, then we can't propagate it to         // uses of lhs.        if (rhs.isRegister() && !rhs.asRegister().register.isSSA())          continue;	reiterate = ir.options.getOptLevel() > 1;        // Now substitute rhs for all uses of lhs, updating the         // register list as we go.	if (rhs.isRegister()) {	  OPT_RegisterOperand nextUse;	  OPT_RegisterOperand rhsRegOp = rhs.asRegister();	  for (OPT_RegisterOperand use = reg.useList; use != null; use = nextUse) {	    nextUse = use.getNext(); // get early before reg's useList is updated. 	    if (VM.VerifyAssertions) VM._assert(rhsRegOp.register.getType() == use.register.getType());            OPT_DefUse.transferUse(use, rhsRegOp);	  }	} else if (rhs.isConstant()) {	  // NOTE: no need to incrementally update use's register list since we are going	  //       to blow it all away as soon as this loop is done.	  for (OPT_RegisterOperand use = reg.useList; use != null; use = use.getNext()) {            int index = use.getIndexInInstruction();            use.instruction.putOperand(index, rhs);          }	} else {	  throw new OPT_OptimizingCompilerException("OPT_Simple.copyPropagation: unexpected operand type");	}	// defInstr is now dead. Remove it.	defInstr.remove();	if (rhs.isRegister())	  OPT_DefUse.removeUse(rhs.asRegister());	ir.regpool.removeRegister(lhs.register);      }    }  }