falseProb);
(OPT_BranchProfileOperand)falseProb.copy());
  private static OPT_Instruction generateBranchingTypeCheck(OPT_Instruction s,                                                             OPT_IR ir,                                                             OPT_Operand RHSobj,                                                            VM_TypeReference LHStype,                                                             OPT_RegisterOperand RHStib,                                                             OPT_BasicBlock trueBlock,                                                             OPT_BasicBlock falseBlock,                                                            OPT_RegisterOperand oldGuard,                                                            OPT_BranchProfileOperand falseProb) {    OPT_Instruction continueAt = Goto.create(GOTO, trueBlock.makeJumpTarget());    continueAt.copyPosition(s);    s.insertBefore(continueAt);    s.remove();    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(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB,                         VM_TypeReference.IntArray, RHStib);          if (VM_DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {            OPT_RegisterOperand doesImplLength =               InsertGuardedUnary(continueAt,                                  ir, ARRAYLENGTH, VM_TypeReference.Int,                                  doesImpl.copyD2U(), TG());            OPT_Instruction lengthCheck =               IfCmp.create(INT_IFCMP, oldGuard, doesImplLength, IC(interfaceIndex),                           OPT_ConditionOperand.LESS_EQUAL(),                            falseBlock.makeJumpTarget(),                           OPT_BranchProfileOperand.unlikely());            continueAt.insertBefore(lengthCheck);            OPT_BasicBlock oldBlock = continueAt.getBasicBlock();            oldBlock.splitNodeWithLinksAt(lengthCheck, ir);            oldBlock.insertOut(falseBlock); // required due to splitNode!          }          OPT_RegisterOperand entry =             InsertLoadOffset(continueAt, ir, INT_LOAD, VM_TypeReference.Int,                             doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2),                              new OPT_LocationOperand(VM_TypeReference.Int),                              TG());          OPT_RegisterOperand bit =             InsertBinary(continueAt, ir, INT_AND, VM_TypeReference.Int, entry, IC(interfaceMask));          continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard,                                                bit, IC(0),                                               OPT_ConditionOperand.EQUAL(),                                                falseBlock.makeJumpTarget(),                                               falseProb));          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(continueAt, ir, LHSclass);            continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard,                                                  RHStib, classTIB,                                                 OPT_ConditionOperand.NOT_EQUAL(),                                                  falseBlock.makeJumpTarget(),                                                 falseProb));            return continueAt;          } else {            // Do the full blown case 5 or 6 typecheck.            int LHSDepth = LHSclass.getTypeDepth();            int LHSId = LHSclass.getId();            OPT_RegisterOperand superclassIds =               InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB,                           VM_TypeReference.ShortArray, RHStib);            if (VM_DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {              OPT_RegisterOperand superclassIdsLength =                 InsertGuardedUnary(continueAt,                                    ir, ARRAYLENGTH, VM_TypeReference.Int,                                    superclassIds.copyD2U(), TG());              OPT_Instruction lengthCheck =                 IfCmp.create(INT_IFCMP, oldGuard, superclassIdsLength, IC(LHSDepth),                             OPT_ConditionOperand.LESS(),                              falseBlock.makeJumpTarget(),                             OPT_BranchProfileOperand.unlikely());              continueAt.insertBefore(lengthCheck);              OPT_BasicBlock oldBlock = continueAt.getBasicBlock();              oldBlock.splitNodeWithLinksAt(lengthCheck, ir);              oldBlock.insertOut(falseBlock); // required due to splitNode!            }            OPT_RegisterOperand refCandidate =               InsertLoadOffset(continueAt, ir, USHORT_LOAD, VM_TypeReference.Short,                               superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1),                                new OPT_LocationOperand(VM_TypeReference.Short),                                TG());            continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard,                                                  refCandidate, IC(LHSId),                                                 OPT_ConditionOperand.NOT_EQUAL(),                                                  falseBlock.makeJumpTarget(),                                                 falseProb));            return continueAt;          }        }      } else {        // A non-resolved class or interface. Case 3 of VM_DynamicTypeCheck        // Branch on the result of a call to         // VM_Runtime.instance        OPT_RegisterOperand result = ir.regpool.makeTempInt();        VM_Method target = VM_Entrypoints.instanceOfMethod;        OPT_Instruction call = Call.create2(CALL, result, AC(target.getOffset()),                                            OPT_MethodOperand.STATIC(target),                                            RHSobj, IC(LHStype.getId()));        call.copyPosition(continueAt);        continueAt.insertBefore(call);        call = callHelper(call, ir);        continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard,                                              result.copyD2U(), IC(0),                                             OPT_ConditionOperand.EQUAL(),                                              falseBlock.makeJumpTarget(),                                             falseProb));        return continueAt;      }    }    if (LHStype.isArrayType()) {      // Case 2 of VM_DynamicTypeCheck: LHS is an array.      VM_Array LHSArray = (VM_Array)LHStype.peekResolvedType();      if (LHSArray != null) {        OPT_Operand classTIB = getTIB(continueAt, ir, LHSArray);        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.          continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard,                                                RHStib, classTIB,                                               OPT_ConditionOperand.NOT_EQUAL(),                                                falseBlock.makeJumpTarget(),                                               falseProb));          return continueAt;        }        // TODO: branch probability calculation is somewhat bogus for this case.        OPT_Instruction shortcircuit =           IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB,                       OPT_ConditionOperand.EQUAL(),                        trueBlock.makeJumpTarget(),                       new OPT_BranchProfileOperand());        continueAt.insertBefore(shortcircuit);        OPT_BasicBlock myBlock = shortcircuit.getBasicBlock();        OPT_BasicBlock mainBlock =           myBlock.splitNodeWithLinksAt(shortcircuit, ir);        myBlock.insertOut(trueBlock);       // must come after the splitNodeAt        OPT_RegisterOperand rhsType =           InsertUnary(continueAt, ir, GET_TYPE_FROM_TIB,                       VM_TypeReference.VM_Type, RHStib.copyD2U());        if (innermostElementType.isJavaLangObjectType()) {          OPT_IntConstantOperand lhsDimension = IC(LHStype.getDimensionality());          OPT_RegisterOperand rhsDimension =             getField(continueAt, ir, rhsType, VM_Entrypoints.dimensionField);          OPT_Instruction dimTest =             IfCmp2.create(INT_IFCMP2, oldGuard, rhsDimension, lhsDimension,                          OPT_ConditionOperand.GREATER(),                           trueBlock.makeJumpTarget(),                          ((OPT_BranchProfileOperand)falseProb.copy()).flip(),                          OPT_ConditionOperand.LESS(),                           falseBlock.makeJumpTarget(),                          falseProb);          continueAt.insertBefore(dimTest);          OPT_BasicBlock testBlock =             mainBlock.splitNodeWithLinksAt(dimTest, ir);          mainBlock.insertOut(trueBlock);          mainBlock.insertOut(falseBlock);          OPT_RegisterOperand rhsInnermostElementType =             getField(continueAt,ir,rhsType.copyU2U(),VM_Entrypoints.innermostElementTypeField);          OPT_RegisterOperand rhsInnermostElementTypeDimension =             getField(continueAt, ir, rhsInnermostElementType, VM_Entrypoints.dimensionField);          continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard,                                                rhsInnermostElementTypeDimension,                                               IC(0),                                               OPT_ConditionOperand.NOT_EQUAL(),                                                falseBlock.makeJumpTarget(),                                               falseProb));          return continueAt;        }      }       // Not a case we want to handle inline      VM_Method target = VM_Entrypoints.instanceOfMethod;      OPT_RegisterOperand callResult = ir.regpool.makeTempInt();      OPT_Instruction call = Call.create2(CALL, callResult, AC(target.getOffset()), OPT_MethodOperand.STATIC(target),                                           RHSobj, IC(LHStype.getId()));      call.copyPosition(continueAt);      continueAt.insertBefore(call);      call = callHelper(call, ir);      continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard,                                            callResult.copyD2U(), IC(0),                                           OPT_ConditionOperand.EQUAL(),                                            falseBlock.makeJumpTarget(),                                           falseProb));      return continueAt;    }    OPT_OptimizingCompilerException.UNREACHABLE();    return null;  }