t.insertBefore(IfCmp.create(INT_IFCMP, null,
t.insertBefore(IfCmp.create(INT_IFCMP, oldGuard,
  private static OPT_Instruction generateBranchingTypeCheck(OPT_Instruction s, 							    OPT_IR ir, 							    OPT_RegisterOperand RHSobj,							    VM_Type LHStype, 							    OPT_RegisterOperand RHStib, 							    OPT_BasicBlock trueBlock, 							    OPT_BasicBlock falseBlock) {    OPT_Instruction continueAt = Goto.create(GOTO, trueBlock.makeJumpTarget());    continueAt.copyPosition(s);    s.insertBefore(continueAt);    s.remove();    if (VM.BuildForFastDynamicTypeCheck) {      if (LHStype.isClassType()) {	VM_Class LHSclass = LHStype.asClass();	if (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 LHSInterfaceId = LHSclass.getInterfaceId();	    OPT_BasicBlock myBlock = continueAt.getBasicBlock();	    OPT_BasicBlock maybeBlock = 	      myBlock.createSubBlock(continueAt.bcIndex, ir);	    myBlock.insertOut(maybeBlock);	    maybeBlock.insertOut(trueBlock);	    maybeBlock.insertOut(falseBlock);	    maybeBlock.setInfrequent(true);	    ir.cfg.addLastInCodeOrder(maybeBlock);	    OPT_RegisterOperand trits = 	      InsertUnary(continueAt, ir, GET_IMPLEMENTS_TRITS_FROM_TIB, 			  OPT_ClassLoaderProxy.ByteArrayType, RHStib);	    if (VM_DynamicTypeCheck.MIN_IMPLEMENTS_TRITS_SIZE <= LHSInterfaceId){	      OPT_RegisterOperand tritsLength = 		InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, VM_Type.IntType,				   trits, TG());	      OPT_Instruction lengthCheck = 		IfCmp.create(INT_IFCMP, null, tritsLength, I(LHSInterfaceId),			     OPT_ConditionOperand.LESS_EQUAL(), 			     maybeBlock.makeJumpTarget(),			     OPT_BranchProfileOperand.unlikely());	      continueAt.insertBefore(lengthCheck);	      OPT_BasicBlock oldBlock = myBlock;	      myBlock = myBlock.splitNodeWithLinksAt(lengthCheck, ir);	      oldBlock.insertOut(maybeBlock); // required due to splitNode!	    }	    // NOTE: Assuming that VM_DynamicTypeCheck.NO = 0, YES = 1, MAYBE = 2	    OPT_RegisterOperand trit = 	      InsertLoadOffset(continueAt, ir, UBYTE_LOAD, VM_Type.ByteType, 			       trits.copyU2U(), LHSInterfaceId, 			       new OPT_LocationOperand(VM_Type.ByteType), TG());	    continueAt.insertBefore(IfCmp2.create(INT_IFCMP2, null, trit, 						  I(VM_DynamicTypeCheck.YES),						  OPT_ConditionOperand.GREATER(),						  maybeBlock.makeJumpTarget(),						  new OPT_BranchProfileOperand(),						  OPT_ConditionOperand.LESS(), 						  falseBlock.makeJumpTarget(),						  new OPT_BranchProfileOperand()));	    OPT_RegisterOperand LHSRuntimeClass = 	      getVMType(maybeBlock.lastInstruction(), ir, LHSclass);	    OPT_Instruction maybeCall = 	      Call.create2(CALL, trit.copyD2D(), null, 			   OPT_MethodOperand.STATIC(initialInstanceOfInterfaceMethod), 			   LHSRuntimeClass, RHStib.copyD2U());	    maybeCall.copyPosition(s);	    maybeBlock.appendInstruction(maybeCall);	    maybeBlock.appendInstruction(IfCmp.create(INT_IFCMP, null, 						      trit.copyD2U(), I(0),						      OPT_ConditionOperand.EQUAL(), 						      falseBlock.makeJumpTarget(),						      new OPT_BranchProfileOperand()));	    maybeBlock.appendInstruction(Goto.create(GOTO, 						     trueBlock.makeJumpTarget()));	    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_RegisterOperand classTIB = getTIB(continueAt, ir, LHSclass);	      continueAt.insertBefore(IfCmp.create(INT_IFCMP, null, 						   RHStib, classTIB,						   OPT_ConditionOperand.NOT_EQUAL(), 						   falseBlock.makeJumpTarget(),						   new OPT_BranchProfileOperand()));	      return continueAt;	    } else {	      // Do the full blown case 5 or 6 typecheck.	      int LHSDepth = LHSclass.getTypeDepth();	      int LHSId = LHSclass.getDictionaryId();	      OPT_RegisterOperand superclassIds = 		InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, 			    OPT_ClassLoaderProxy.ShortArrayType, RHStib);	      if (VM_DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {		OPT_RegisterOperand superclassIdsLength = 		  InsertGuardedUnary(continueAt, 				     ir, ARRAYLENGTH, VM_Type.IntType, 				     superclassIds.copyD2U(), TG());		OPT_Instruction lengthCheck = 		  IfCmp.create(INT_IFCMP, null, superclassIdsLength, I(LHSDepth),			       OPT_ConditionOperand.LESS(), 			       falseBlock.makeJumpTarget(),			       new OPT_BranchProfileOperand());		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, SHORT_LOAD, VM_Type.ShortType,				 superclassIds, LHSDepth << 1, 				 new OPT_LocationOperand(VM_Type.ShortType), 				 TG());	      continueAt.insertBefore(IfCmp.create(INT_IFCMP, null, 						   refCandidate, I(LHSId),						   OPT_ConditionOperand.NOT_EQUAL(), 						   falseBlock.makeJumpTarget(),						   new OPT_BranchProfileOperand()));	      return continueAt;	    }	  }	} else {	  // A non-resolved class or interface. Case 3 of VM_DynamicTypeCheck	  // Branch on the result of a call to 	  // VM_DynamicTypeCheck.instanceOfUnresolved	  OPT_RegisterOperand LHSRuntimeClass = 	    getVMType(continueAt, ir, LHSclass);	  OPT_RegisterOperand result = ir.regpool.makeTempInt();	  OPT_Instruction call = Call.create2(CALL, result, null, 					      OPT_MethodOperand.STATIC(instanceOfUnresolvedMethod), 					      LHSRuntimeClass, RHStib);	  call.copyPosition(continueAt);	  continueAt.insertBefore(call);	  call = _callHelper(call, ir);	  continueAt.insertBefore(IfCmp.create(INT_IFCMP, null, 					       result.copyD2U(), I(0),					       OPT_ConditionOperand.EQUAL(), 					       falseBlock.makeJumpTarget(),					       new OPT_BranchProfileOperand()));	  return continueAt;	}      }      if (LHStype.isArrayType()) {	// Case 2 of VM_DynamicTypeCheck: LHS is an array.	VM_Array LHSArray = LHStype.asArray();	OPT_RegisterOperand 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(INT_IFCMP, null, 					       RHStib, classTIB,					       OPT_ConditionOperand.NOT_EQUAL(), 					       falseBlock.makeJumpTarget(),					       new OPT_BranchProfileOperand()));	  return continueAt;	}	OPT_Instruction shortcircuit = 	  IfCmp.create(INT_IFCMP, null, 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_Instruction call;	OPT_RegisterOperand rhsType = 	  InsertUnary(continueAt, ir, GET_TYPE_FROM_TIB, 		      OPT_ClassLoaderProxy.VM_Type_type, RHStib.copyD2U());	OPT_RegisterOperand callResult = ir.regpool.makeTempInt();	if (innermostElementType == VM_Type.JavaLangObjectType) {	  OPT_IntConstantOperand lhsDimension = I(LHSArray.getDimensionality());	  OPT_RegisterOperand rhsDimension = 	    getField(continueAt, ir, rhsType, dimensionField);	  OPT_Instruction dimTest = 	    IfCmp2.create(INT_IFCMP2, null, rhsDimension, lhsDimension,			  OPT_ConditionOperand.GREATER(), 			  trueBlock.makeJumpTarget(),			  new OPT_BranchProfileOperand(),			  OPT_ConditionOperand.LESS(), 			  falseBlock.makeJumpTarget(),			  new OPT_BranchProfileOperand());	  continueAt.insertBefore(dimTest);	  OPT_BasicBlock testBlock = 	    mainBlock.splitNodeWithLinksAt(dimTest, ir);	  mainBlock.insertOut(trueBlock);	  mainBlock.insertOut(falseBlock);	  OPT_RegisterOperand rhsInnermostElementType = 	    getField(continueAt,ir,rhsType.copyU2U(),innermostElementTypeField);	  OPT_RegisterOperand rhsInnermostElementTypeDimension = 	    getField(continueAt, ir, rhsInnermostElementType, dimensionField);	  continueAt.insertBefore(IfCmp.create(INT_IFCMP, null, 					       rhsInnermostElementTypeDimension,					       I(0),					       OPT_ConditionOperand.NOT_EQUAL(), 					       falseBlock.makeJumpTarget(),					       new OPT_BranchProfileOperand()));	  return continueAt;	} else {	  OPT_RegisterOperand lhsInnermostElementType = 	    getVMType(continueAt, ir, innermostElementType);	  VM_Method target = 	    innermostElementType.isResolved() ? instanceOfArray : 	    instanceOfUnresolvedArray;	  call = Call.create3(CALL, callResult, null, 			      OPT_MethodOperand.STATIC(target), 			      lhsInnermostElementType, 			      I(LHSArray.getDimensionality()), 			      rhsType);	  call.copyPosition(continueAt);	  continueAt.insertBefore(call);	  call = _callHelper(call, ir);	  continueAt.insertBefore(IfCmp.create(INT_IFCMP, null, 					       callResult.copyD2U(), I(0),					       OPT_ConditionOperand.EQUAL(), 					       falseBlock.makeJumpTarget(),					       new OPT_BranchProfileOperand()));	  return continueAt;	}      }    } else { // !VM.BuildForFastDynamicTypeCheck      OPT_BasicBlock myBlock = continueAt.getBasicBlock();      OPT_BasicBlock callBlock = myBlock.splitNodeAt(continueAt.prevInstructionInCodeOrder(), ir);      OPT_BasicBlock cacheBlock = myBlock.createSubBlock(continueAt.bcIndex, ir);      myBlock.insertOut(cacheBlock);      myBlock.insertOut(trueBlock);      cacheBlock.insertOut(trueBlock);      cacheBlock.insertOut(callBlock);      ir.cfg.linkInCodeOrder(myBlock, cacheBlock);      ir.cfg.linkInCodeOrder(cacheBlock, callBlock);      if (LHStype.isResolved()) { 	// type equality test	OPT_Instruction t = myBlock.lastInstruction();	OPT_RegisterOperand LHStib = getTIB(t, ir, LHStype);	t.insertBefore(IfCmp.create(INT_IFCMP, null, 				    RHStib, 				    LHStib.copyD2U(),				    OPT_ConditionOperand.EQUAL(),				    trueBlock.makeJumpTarget(),				    new OPT_BranchProfileOperand()));	// cache check	t = cacheBlock.lastInstruction();	OPT_RegisterOperand cacheEntry = 	  InsertLoadOffset(t, ir, INT_LOAD,			   OPT_ClassLoaderProxy.JavaLangObjectArrayType,			   RHStib.copyD2U(),			   TIB_TYPE_CACHE_TIB_INDEX << 2);	t.insertBefore(IfCmp.create(INT_IFCMP, null, 				    cacheEntry,				    LHStib.copyD2U(),				    OPT_ConditionOperand.EQUAL(),				    trueBlock.makeJumpTarget(),				    new OPT_BranchProfileOperand()));      }            // call general out-of-line type checking routine.      OPT_RegisterOperand result = ir.regpool.makeTempInt();      OPT_Instruction call = Call.create2(CALL, result, null, 					  OPT_MethodOperand.STATIC(VM_Entrypoints.instanceOfMethod), 					  RHSobj.copyU2U(), I(LHStype.getTibOffset()));      call.copyPosition(continueAt);      continueAt.insertBefore(call);      call = _callHelper(call, ir);      continueAt.insertBefore(IfCmp.create(INT_IFCMP, null, 					   result.copyD2U(), I(0),					   OPT_ConditionOperand.EQUAL(), 					   falseBlock.makeJumpTarget(),					   new OPT_BranchProfileOperand()));      return continueAt;    }    OPT_OptimizingCompilerException.UNREACHABLE();    return null;  }