injectMove(block, temp, rsop);
injectMove(block, temp, rsop.copyRO());
    void rectifyStacks(OPT_BasicBlock block, OperandStack stack,                        BasicBlockLE p) {      if (stack == null || stack.isEmpty()) {        if (VM.VerifyAssertions) VM._assert(p.stackState == null);        if (!p.isStackKnown())          p.setStackKnown();        if (DBG_STACK || DBG_SELECTED)          db("Rectified empty expression stack into "+p+"("+p.block+")");        return;      }      boolean generated = p.isGenerated();      // (1) Rectify the stacks.      if (!p.isStackKnown()) {        // First time we reached p. Thus, its expression stack         // is implicitly top and the meet degenerates to a copy operation         // with possibly some register renaming.        // (We need to ensure that non-local registers appear at         // most once on each expression stack).        if (DBG_STACK || DBG_SELECTED) {          db("First stack rectifiction for " + p + "(" +              p.block + ") simply saving");        }        if (VM.VerifyAssertions) VM._assert(p.stackState == null);        p.stackState = new OperandStack(stack.getCapacity());        for (int i = stack.getSize() - 1; i >= 0; i--) {          OPT_Operand op = stack.getFromTop(i);          if (op == DUMMY) {            p.stackState.push(DUMMY);          } else if (op instanceof OPT_RegisterOperand) {            OPT_RegisterOperand rop = op.asRegister();            if (rop.register.isLocal()) {              OPT_RegisterOperand temp = gc.temps.makeTemp(rop);              temp.setInheritableFlags(rop);              setGuard(temp, getGuard(rop));              OPT_Instruction move =                 Move.create(OPT_IRTools.getMoveOp(rop.type), temp, rop);              move.bcIndex = RECTIFY_BCI;              move.position = gc.inlineSequence;              block.appendInstructionRespectingTerminalBranch(move);              p.stackState.push(temp.copy());              if (DBG_STACK || DBG_SELECTED)                db("Inserted " + move + " into " + block + " to rename local");            } else {              p.stackState.push(rop.copy());            }          } else {            p.stackState.push(op.copy());          }        }        p.setStackKnown();        return;      } else {        // A real rectification.        // We need to update mergedStack such that         // mergedStack[i] = meet(mergedStack[i], stack[i]).        if (DBG_STACK || DBG_SELECTED) db("rectifying stacks");        try {            if (VM.VerifyAssertions)                VM._assert(stack.getSize() == p.stackState.getSize());        } catch (NullPointerException e) {            System.err.println("stack size " + stack.getSize());            System.err.println(stack);            System.err.println(p.stackState);            System.err.println(gc.method.toString());            block.printExtended();            p.block.printExtended();            throw e;        }        for (int i = 0; i < stack.getSize(); ++i) {          OPT_Operand sop = stack.getFromTop(i);          OPT_Operand mop = p.stackState.getFromTop(i);          if ((sop == DUMMY) || (sop instanceof ReturnAddressOperand)) {            if (VM.VerifyAssertions) VM._assert(mop.similar(sop));            continue;          } else if (sop.isConstant() || mop.isConstant()) {            if (mop.similar(sop)) {              continue; // constants are similar; so we don't have to do anything.            }             // sigh. Non-similar constants.             if (mop.isConstant()) {              // Insert move instructions in all predecessor               // blocks except 'block' to move mop into a register.              OPT_RegisterOperand mopTmp = gc.temps.makeTemp(mop);              if (DBG_STACK || DBG_SELECTED) db("Merged stack has constant operand "+mop);              for (OPT_BasicBlockEnumeration preds = p.block.getIn(); preds.hasMoreElements();) {                OPT_BasicBlock pred = preds.next();                if (pred == block) continue;                injectMove(pred, mopTmp, mop);              }              p.stackState.replaceFromTop(i, mopTmp.copy());              if (generated) {                if (DBG_STACK || DBG_SELECTED)                  db("\t...forced to regenerate " + p + " (" + p.block + ") because of this");                markBlockForRegeneration(p);                generated = false;                p.block.deleteOut();                if (DBG_CFG || DBG_SELECTED) db("Deleted all out edges of " + p.block);              }              mop = mopTmp;            }            if (sop.isConstant()) {              // Insert move instruction into block.              OPT_RegisterOperand sopTmp = gc.temps.makeTemp(sop);              if (DBG_STACK || DBG_SELECTED) db("incoming stack has constant operand "+sop);              injectMove(block, sopTmp, sop);              sop = sopTmp;            }          }          // sop and mop are OPT_RegisterOperands (either originally or because          // we forced them to be above due to incompatible constants.          OPT_RegisterOperand rsop = sop.asRegister();          OPT_RegisterOperand rmop = mop.asRegister();          if (rmop.register != rsop.register) {            // must insert move at end of block to get register #s to match            OPT_RegisterOperand temp = rsop.copyRO();            temp.setRegister(rmop.register);            injectMove(block, temp, rsop);          }          OPT_Operand meet = OPT_Operand.meet(rmop, rsop, rmop.register);          if (DBG_STACK || DBG_SELECTED) db("Meet of "+rmop+" and "+rsop+" is "+ meet);          if (meet != rmop) {            if (generated) {              if (DBG_STACK || DBG_SELECTED)                db("\t...forced to regenerate " + p + " (" + p.block + ") because of this");              markBlockForRegeneration(p);              generated = false;              p.block.deleteOut();              if (DBG_CFG || DBG_SELECTED) db("Deleted all out edges of " + p.block);            }            p.stackState.replaceFromTop(i, meet);          }        }      }    }