private void replaceUse(
      SsaInsn use, SsaInsn prev, ArrayList<RegisterSpec> newRegs, HashSet<SsaInsn> deletedInsns) {
    int index;
    int length = newRegs.size();
    SsaInsn next;
    RegisterSpecList sources;
    RegisterSpec source, result;
    CstLiteralBits indexReg;

    switch (use.getOpcode().getOpcode()) {
      case RegOps.AGET:
        // Replace array gets with moves
        next = getMoveForInsn(use);
        sources = use.getSources();
        indexReg = ((CstLiteralBits) sources.get(1).getTypeBearer());
        index = indexReg.getIntBits();
        if (index < length) {
          source = newRegs.get(index);
          result = source.withReg(next.getResult().getReg());
          insertPlainInsnBefore(next, RegisterSpecList.make(source), result, RegOps.MOVE, null);
        } else {
          // Throw an exception if the index is out of bounds
          insertExceptionThrow(next, sources.get(1), deletedInsns);
          deletedInsns.add(next.getBlock().getInsns().get(2));
        }
        deletedInsns.add(next);
        break;
      case RegOps.APUT:
        // Replace array puts with moves
        sources = use.getSources();
        indexReg = ((CstLiteralBits) sources.get(2).getTypeBearer());
        index = indexReg.getIntBits();
        if (index < length) {
          source = sources.get(0);
          result = source.withReg(newRegs.get(index).getReg());
          insertPlainInsnBefore(use, RegisterSpecList.make(source), result, RegOps.MOVE, null);
          // Update the newReg entry to mark value as unknown now
          newRegs.set(index, result.withSimpleType());
        } else {
          // Throw an exception if the index is out of bounds
          insertExceptionThrow(use, sources.get(2), deletedInsns);
        }
        break;
      case RegOps.ARRAY_LENGTH:
        // Replace array lengths with const instructions
        TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
        // CstInteger lengthReg = CstInteger.make(length);
        next = getMoveForInsn(use);
        insertPlainInsnBefore(
            next, RegisterSpecList.EMPTY, next.getResult(), RegOps.CONST, (Constant) lengthReg);
        deletedInsns.add(next);
        break;
      case RegOps.MARK_LOCAL:
        // Remove mark local instructions
        break;
      case RegOps.FILL_ARRAY_DATA:
        // Create const instructions for each fill value
        Insn ropUse = use.getOriginalRopInsn();
        FillArrayDataInsn fill = (FillArrayDataInsn) ropUse;
        ArrayList<Constant> constList = fill.getInitValues();
        for (int i = 0; i < length; i++) {
          RegisterSpec newFill =
              RegisterSpec.make(newRegs.get(i).getReg(), (TypeBearer) constList.get(i));
          insertPlainInsnBefore(
              use, RegisterSpecList.EMPTY, newFill, RegOps.CONST, constList.get(i));
          // Update the newRegs to hold the new const value
          newRegs.set(i, newFill);
        }
        break;
      default:
    }
  }
Replaces the use for a scalar replaceable array. Gets and puts become move instructions, and
array lengths and fills are handled. Can also identify ArrayIndexOutOfBounds exceptions and
throw them if detected.

@param use {@code non-null;} move result instruction for array
@param prev {@code non-null;} instruction for instantiating new array
@param newRegs {@code non-null;} mapping of array indices to new registers
@param deletedInsns {@code non-null;} set of instructions marked for deletion
android/android_framework/dex-maker/src/main/java/com/android/dx/ssa/EscapeAnalysis.java