/**
   * Replaces the last insn in this block. The provided insn must have some branchingness.
   *
   * @param insn {@code non-null;} rop-form insn to add, which must branch.
   */
  public void replaceLastInsn(Insn insn) {
    if (insn.getOpcode().getBranchingness() == Rop.BRANCH_NONE) {
      throw new IllegalArgumentException("last insn must branch");
    }

    SsaInsn oldInsn = insns.get(insns.size() - 1);
    SsaInsn newInsn = SsaInsn.makeFromRop(insn, this);

    insns.set(insns.size() - 1, newInsn);

    parent.onInsnRemoved(oldInsn);
    parent.onInsnAdded(newInsn);
  }
  /**
   * Replaces an SsaInsn containing a PlainInsn with a new PlainInsn. The new PlainInsn is
   * constructed with a new RegOp and new sources.
   *
   * <p>TODO move this somewhere else.
   *
   * @param insn {@code non-null;} an SsaInsn containing a PlainInsn
   * @param newSources {@code non-null;} new sources list for new insn
   * @param newOpcode A RegOp from {@link RegOps}
   * @param cst {@code null-ok;} constant for new instruction, if any
   */
  private void replacePlainInsn(
      NormalSsaInsn insn, RegisterSpecList newSources, int newOpcode, Constant cst) {

    Insn originalRopInsn = insn.getOriginalRopInsn();
    Rop newRop = Rops.ropFor(newOpcode, insn.getResult(), newSources, cst);
    Insn newRopInsn;
    if (cst == null) {
      newRopInsn =
          new PlainInsn(newRop, originalRopInsn.getPosition(), insn.getResult(), newSources);
    } else {
      newRopInsn =
          new PlainCstInsn(
              newRop, originalRopInsn.getPosition(), insn.getResult(), newSources, cst);
    }
    NormalSsaInsn newInsn = new NormalSsaInsn(newRopInsn, insn.getBlock());

    List<SsaInsn> insns = insn.getBlock().getInsns();

    ssaMeth.onInsnRemoved(insn);
    insns.set(insns.lastIndexOf(insn), newInsn);
    ssaMeth.onInsnAdded(newInsn);
  }