s.insertBefore(BooleanCmp.create(BOOLEAN_CMP, boundscheck,
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_INT, boundscheck,
  private static OPT_Instruction generateValueProducingTypeCheck(OPT_Instruction s,                                                                  OPT_IR ir,                                                                  OPT_Operand RHSobj,                                                                  VM_TypeReference LHStype,                                                                  OPT_RegisterOperand RHStib,                                                                  OPT_RegisterOperand result) {    // Is LHStype a class?    if (LHStype.isClassType()) {      VM_Class LHSclass = (VM_Class)LHStype.peekResolvedType();      if (LHSclass != null && LHSclass.isResolved()) {        // Cases 4, 5, and 6 of VM_DynamicTypeCheck: LHSclass is a         // resolved class or interface        if (LHSclass.isInterface()) {          // A resolved interface (case 4)          int interfaceIndex = LHSclass.getDoesImplementIndex();          int interfaceMask = LHSclass.getDoesImplementBitMask();          OPT_RegisterOperand doesImpl =             InsertUnary(s, ir,  GET_DOES_IMPLEMENT_FROM_TIB,                         VM_TypeReference.IntArray, RHStib);          OPT_RegisterOperand entry =             InsertLoadOffset(s, ir, INT_LOAD, VM_TypeReference.Int,                              doesImpl, interfaceIndex << 2,                              new OPT_LocationOperand(VM_TypeReference.Int),                              TG());          OPT_RegisterOperand bit = InsertBinary(s, ir, INT_AND, VM_TypeReference.Int,                                                 entry, IC(interfaceMask));          s.insertBefore(BooleanCmp.create(BOOLEAN_CMP, result,                                            bit,                                           IC(0),                                           OPT_ConditionOperand.NOT_EQUAL(),                                           new OPT_BranchProfileOperand()));          if (VM_DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {            OPT_RegisterOperand doesImplLength =               InsertGuardedUnary(s, ir, ARRAYLENGTH, VM_TypeReference.Int, doesImpl.copy(), TG());            OPT_RegisterOperand boundscheck = ir.regpool.makeTempInt();            s.insertBefore(BooleanCmp.create(BOOLEAN_CMP, boundscheck,                                              doesImplLength,                                             IC(interfaceIndex),                                             OPT_ConditionOperand.GREATER(),                                             new OPT_BranchProfileOperand()));            s.insertBefore(Binary.create(INT_AND, result.copyD2D(),                                          result.copyD2U(), boundscheck));          }          OPT_Instruction continueAt = s.prevInstructionInCodeOrder();          s.remove();          return continueAt;        } else {          // A resolved class (cases 5 and 6 in VM_DynamicTypeCheck)          if (LHSclass.isFinal()) {            // For a final class, we can do a PTR compare of             // rhsTIB and the TIB of the class            OPT_Operand classTIB = getTIB(s, ir, LHSclass);            BooleanCmp.mutate(s, BOOLEAN_CMP, result, RHStib, classTIB,                               OPT_ConditionOperand.EQUAL(),                              new OPT_BranchProfileOperand());            return s.prevInstructionInCodeOrder();          } else {            // Do the full blown case 5 or 6 typecheck.            int LHSDepth = LHSclass.getTypeDepth();            int LHSId = LHSclass.getId();            OPT_RegisterOperand superclassIds =               InsertUnary(s, ir, GET_SUPERCLASS_IDS_FROM_TIB,                           VM_TypeReference.ShortArray, RHStib);            OPT_RegisterOperand refCandidate =               InsertLoadOffset(s, ir, USHORT_LOAD, VM_TypeReference.Short,                                superclassIds, LHSDepth << 1,                                new OPT_LocationOperand(VM_TypeReference.Short),                                TG());            s.insertBefore(BooleanCmp.create(BOOLEAN_CMP, result,                                              refCandidate,                                              IC(LHSId),                                              OPT_ConditionOperand.EQUAL(),                                             new OPT_BranchProfileOperand()));            if (VM_DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {              OPT_RegisterOperand superclassIdsLength =                 InsertGuardedUnary(s, ir, ARRAYLENGTH, VM_TypeReference.Int,                                    superclassIds.copyD2U(), TG());              OPT_RegisterOperand boundscheck = ir.regpool.makeTempInt();              s.insertBefore(BooleanCmp.create(BOOLEAN_CMP, boundscheck,                                                superclassIdsLength,                                                IC(LHSDepth),                                                OPT_ConditionOperand.GREATER(),                                               new OPT_BranchProfileOperand()));              s.insertBefore(Binary.create(INT_AND, result.copyD2D(),                                            result.copyD2U(), boundscheck));            }            OPT_Instruction continueAt = s.prevInstructionInCodeOrder();            s.remove();            return continueAt;          }        }      } else {        // A non-resolved class or interface.         // We expect these to be extremely uncommon in opt code in AOS.        // Mutate s into a call to VM_Runtime.instanceOf        VM_Method target = VM_Entrypoints.instanceOfMethod;        Call.mutate2(s, CALL, result, IC(target.getOffset()),                      OPT_MethodOperand.STATIC(target),                     RHSobj, IC(LHStype.getId()));        return callHelper(s, ir);      }    }    if (LHStype.isArrayType()) {      // Case 2 of VM_DynamicTypeCheck: LHS is an array.      VM_Array LHSArray = (VM_Array)LHStype.peekResolvedType();      if (LHSArray != null) {        VM_Type innermostElementType = LHSArray.getInnermostElementType();        if (innermostElementType.isPrimitiveType() ||             (innermostElementType.asClass().isResolved() &&              innermostElementType.asClass().isFinal())) {          // [^k of primitive or [^k of final class. Just like final classes,           // a PTR compare of rhsTIB and the TIB of the class gives the answer.          OPT_Operand classTIB = getTIB(s, ir, LHSArray);          BooleanCmp.mutate(s, BOOLEAN_CMP, result, RHStib, classTIB,                             OPT_ConditionOperand.EQUAL(), new OPT_BranchProfileOperand());          return s;        }      }      // We're going to have to branch anyways, so reduce to a branching case       // and do the real work there.      return convertToBranchingTypeCheck(s, ir, RHSobj, LHStype, RHStib, result);    }    OPT_OptimizingCompilerException.UNREACHABLE();    return null;  }