diff options
Diffstat (limited to 'src/jit/valuenum.cpp')
-rw-r--r-- | src/jit/valuenum.cpp | 246 |
1 files changed, 146 insertions, 100 deletions
diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp index 5bc96ed4a9..f7cc0c9a23 100644 --- a/src/jit/valuenum.cpp +++ b/src/jit/valuenum.cpp @@ -76,7 +76,6 @@ ValueNumStore::ValueNumStore(Compiler* comp, IAllocator* alloc) , m_VNFunc2Map(nullptr) , m_VNFunc3Map(nullptr) , m_VNFunc4Map(nullptr) - , m_uPtrToLocNotAFieldCount(1) { // We have no current allocation chunks. for (unsigned i = 0; i < TYP_COUNT; i++) @@ -604,6 +603,7 @@ ValueNumStore::Chunk::Chunk( switch (attribs) { case CEA_None: + case CEA_NotAField: break; // Nothing to do. case CEA_Const: switch (typ) @@ -911,6 +911,7 @@ class Object* ValueNumStore::s_specialRefConsts[] = {nullptr, nullptr, nullptr}; ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func) { assert(VNFuncArity(func) == 0); + assert(func != VNF_NotAField); ValueNum res; @@ -1029,9 +1030,9 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V { if (typ != TYP_BYREF) // We don't want/need to optimize a zero byref { - genTreeOps oper = genTreeOps(func); - ValueNum ZeroVN, OneVN; // We may need to create one of these in the switch below. - switch (oper) + ValueNum resultVN = NoVN; + ValueNum ZeroVN, OneVN; // We may need to create one of these in the switch below. + switch (genTreeOps(func)) { case GT_ADD: // This identity does not apply for floating point (when x == -0.0) @@ -1041,11 +1042,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg0VN == ZeroVN) { - return arg1VN; + resultVN = arg1VN; } else if (arg1VN == ZeroVN) { - return arg0VN; + resultVN = arg0VN; } } break; @@ -1055,7 +1056,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg1VN == ZeroVN) { - return arg0VN; + resultVN = arg0VN; } break; @@ -1066,11 +1067,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V { if (arg0VN == OneVN) { - return arg1VN; + resultVN = arg1VN; } else if (arg1VN == OneVN) { - return arg0VN; + resultVN = arg0VN; } } @@ -1080,11 +1081,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg0VN == ZeroVN) { - return ZeroVN; + resultVN = ZeroVN; } else if (arg1VN == ZeroVN) { - return ZeroVN; + resultVN = ZeroVN; } } break; @@ -1097,7 +1098,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V { if (arg1VN == OneVN) { - return arg0VN; + resultVN = arg0VN; } } break; @@ -1109,11 +1110,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg0VN == ZeroVN) { - return arg1VN; + resultVN = arg1VN; } else if (arg1VN == ZeroVN) { - return arg0VN; + resultVN = arg0VN; } break; @@ -1122,11 +1123,11 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg0VN == ZeroVN) { - return ZeroVN; + resultVN = ZeroVN; } else if (arg1VN == ZeroVN) { - return ZeroVN; + resultVN = ZeroVN; } break; @@ -1142,7 +1143,7 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V ZeroVN = VNZeroForType(typ); if (arg1VN == ZeroVN) { - return arg0VN; + resultVN = arg0VN; } break; @@ -1150,30 +1151,35 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V // (x == x) => true (unless x is NaN) if (!varTypeIsFloating(TypeOfVN(arg0VN)) && (arg0VN != NoVN) && (arg0VN == arg1VN)) { - return VNOneForType(typ); + resultVN = VNOneForType(typ); } if ((arg0VN == VNForNull() && IsKnownNonNull(arg1VN)) || (arg1VN == VNForNull() && IsKnownNonNull(arg0VN))) { - return VNZeroForType(typ); + resultVN = VNZeroForType(typ); } break; case GT_NE: // (x != x) => false (unless x is NaN) if (!varTypeIsFloating(TypeOfVN(arg0VN)) && (arg0VN != NoVN) && (arg0VN == arg1VN)) { - return VNZeroForType(typ); + resultVN = VNZeroForType(typ); } if ((arg0VN == VNForNull() && IsKnownNonNull(arg1VN)) || (arg1VN == VNForNull() && IsKnownNonNull(arg0VN))) { - return VNOneForType(typ); + resultVN = VNOneForType(typ); } break; default: break; } + + if ((resultVN != NoVN) && (TypeOfVN(resultVN) == typ)) + { + return resultVN; + } } } else // must be a VNF_ function @@ -2072,10 +2078,11 @@ bool ValueNumStore::CanEvalForConstantArgs(VNFunc vnf) case GT_MKREFANY: // We can't evaluate these. case GT_RETFILT: case GT_LIST: + case GT_FIELD_LIST: case GT_ARR_LENGTH: return false; case GT_MULHI: - // should be rare, not worth the complexity and risk of getting it wrong + assert(false && "Unexpected GT_MULHI node encountered before lowering"); return false; default: return true; @@ -2545,6 +2552,11 @@ ValueNumPair ValueNumStore::VNPairApplySelectors(ValueNumPair map, FieldSeqNode* return ValueNumPair(liberalVN, conservVN); } +bool ValueNumStore::IsVNNotAField(ValueNum vn) +{ + return m_chunks.GetNoExpand(GetChunkNum(vn))->m_attribs == CEA_NotAField; +} + ValueNum ValueNumStore::VNForFieldSeq(FieldSeqNode* fieldSeq) { if (fieldSeq == nullptr) @@ -2553,7 +2565,11 @@ ValueNum ValueNumStore::VNForFieldSeq(FieldSeqNode* fieldSeq) } else if (fieldSeq == FieldSeqStore::NotAField()) { - return VNForNotAField(); + // We always allocate a new, unique VN in this call. + Chunk* c = GetAllocChunk(TYP_REF, CEA_NotAField); + unsigned offsetWithinChunk = c->AllocVN(); + ValueNum result = c->m_baseVN + offsetWithinChunk; + return result; } else { @@ -2585,22 +2601,22 @@ FieldSeqNode* ValueNumStore::FieldSeqVNToFieldSeq(ValueNum vn) { return nullptr; } - else if (vn == VNForNotAField()) + + assert(IsVNFunc(vn)); + + VNFuncApp funcApp; + GetVNFunc(vn, &funcApp); + if (funcApp.m_func == VNF_NotAField) { return FieldSeqStore::NotAField(); } - else - { - assert(IsVNFunc(vn)); - VNFuncApp funcApp; - GetVNFunc(vn, &funcApp); - assert(funcApp.m_func == VNF_FieldSeq); - ssize_t fieldHndVal = ConstantValue<ssize_t>(funcApp.m_args[0]); - FieldSeqNode* head = - m_pComp->GetFieldSeqStore()->CreateSingleton(reinterpret_cast<CORINFO_FIELD_HANDLE>(fieldHndVal)); - FieldSeqNode* tail = FieldSeqVNToFieldSeq(funcApp.m_args[1]); - return m_pComp->GetFieldSeqStore()->Append(head, tail); - } + + assert(funcApp.m_func == VNF_FieldSeq); + const ssize_t fieldHndVal = ConstantValue<ssize_t>(funcApp.m_args[0]); + FieldSeqNode* head = + m_pComp->GetFieldSeqStore()->CreateSingleton(reinterpret_cast<CORINFO_FIELD_HANDLE>(fieldHndVal)); + FieldSeqNode* tail = FieldSeqVNToFieldSeq(funcApp.m_args[1]); + return m_pComp->GetFieldSeqStore()->Append(head, tail); } ValueNum ValueNumStore::FieldSeqVNAppend(ValueNum fsVN1, ValueNum fsVN2) @@ -2609,40 +2625,31 @@ ValueNum ValueNumStore::FieldSeqVNAppend(ValueNum fsVN1, ValueNum fsVN2) { return fsVN2; } - else if (fsVN1 == VNForNotAField() || fsVN2 == VNForNotAField()) - { - return VNForNotAField(); - } - else - { - assert(IsVNFunc(fsVN1)); - VNFuncApp funcApp1; - GetVNFunc(fsVN1, &funcApp1); - assert(funcApp1.m_func == VNF_FieldSeq); - ValueNum tailRes = FieldSeqVNAppend(funcApp1.m_args[1], fsVN2); - ValueNum fieldSeqVN = VNForFunc(TYP_REF, VNF_FieldSeq, funcApp1.m_args[0], tailRes); -#ifdef DEBUG - if (m_pComp->verbose) - { - printf(" fieldSeq " STR_VN "%x is ", fieldSeqVN); - vnDump(m_pComp, fieldSeqVN); - printf("\n"); - } -#endif + assert(IsVNFunc(fsVN1)); - return fieldSeqVN; + VNFuncApp funcApp1; + GetVNFunc(fsVN1, &funcApp1); + + if ((funcApp1.m_func == VNF_NotAField) || IsVNNotAField(fsVN2)) + { + return VNForFieldSeq(FieldSeqStore::NotAField()); } -} -ValueNum ValueNumStore::VNForPtrToLoc(var_types typ, ValueNum lclVarVN, ValueNum fieldSeqVN) -{ - if (fieldSeqVN == VNForNotAField()) + assert(funcApp1.m_func == VNF_FieldSeq); + ValueNum tailRes = FieldSeqVNAppend(funcApp1.m_args[1], fsVN2); + ValueNum fieldSeqVN = VNForFunc(TYP_REF, VNF_FieldSeq, funcApp1.m_args[0], tailRes); + +#ifdef DEBUG + if (m_pComp->verbose) { - // To distinguish two different not a fields, append a unique value. - return VNForFunc(typ, VNF_PtrToLoc, lclVarVN, fieldSeqVN, VNForIntCon(++m_uPtrToLocNotAFieldCount)); + printf(" fieldSeq " STR_VN "%x is ", fieldSeqVN); + vnDump(m_pComp, fieldSeqVN); + printf("\n"); } - return VNForFunc(typ, VNF_PtrToLoc, lclVarVN, fieldSeqVN, VNForIntCon(0)); +#endif + + return fieldSeqVN; } ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, GenTreePtr opB) @@ -2650,7 +2657,7 @@ ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, GenTreePtr opB) if (opB->OperGet() == GT_CNS_INT) { FieldSeqNode* fldSeq = opB->gtIntCon.gtFieldSeq; - if ((fldSeq != nullptr) && (fldSeq != FieldSeqStore::NotAField())) + if (fldSeq != nullptr) { return ExtendPtrVN(opA, opB->gtIntCon.gtFieldSeq); } @@ -2660,8 +2667,9 @@ ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, GenTreePtr opB) ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, FieldSeqNode* fldSeq) { + assert(fldSeq != nullptr); + ValueNum res = NoVN; - assert(fldSeq != FieldSeqStore::NotAField()); ValueNum opAvnWx = opA->gtVNPair.GetLiberal(); assert(VNIsValid(opAvnWx)); @@ -2684,7 +2692,7 @@ ValueNum ValueNumStore::ExtendPtrVN(GenTreePtr opA, FieldSeqNode* fldSeq) assert(GetVNFunc(VNNormVal(opA->GetVN(VNK_Conservative)), &consFuncApp) && consFuncApp.Equals(funcApp)); #endif ValueNum fldSeqVN = VNForFieldSeq(fldSeq); - res = VNForPtrToLoc(TYP_BYREF, funcApp.m_args[0], FieldSeqVNAppend(funcApp.m_args[1], fldSeqVN)); + res = VNForFunc(TYP_BYREF, VNF_PtrToLoc, funcApp.m_args[0], FieldSeqVNAppend(funcApp.m_args[1], fldSeqVN)); } else if (funcApp.m_func == VNF_PtrToStatic) { @@ -2917,6 +2925,11 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTreePtr tree, var_types ValueNumStore::TypeOfVN(ValueNum vn) { + if (vn == NoVN) + { + return TYP_UNDEF; + } + Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn)); return c->m_typ; } @@ -2936,6 +2949,11 @@ var_types ValueNumStore::TypeOfVN(ValueNum vn) BasicBlock::loopNumber ValueNumStore::LoopOfVN(ValueNum vn) { + if (vn == NoVN) + { + return MAX_LOOP_NUM; + } + Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn)); return c->m_loopNum; } @@ -3388,6 +3406,7 @@ bool ValueNumStore::IsVNFunc(ValueNum vn) Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn)); switch (c->m_attribs) { + case CEA_NotAField: case CEA_Func0: case CEA_Func1: case CEA_Func2: @@ -3401,6 +3420,11 @@ bool ValueNumStore::IsVNFunc(ValueNum vn) bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp) { + if (vn == NoVN) + { + return false; + } + Chunk* c = m_chunks.GetNoExpand(GetChunkNum(vn)); unsigned offset = ChunkOffset(vn); assert(offset < c->m_numUsed); @@ -3415,8 +3439,8 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp) funcApp->m_args[1] = farg4->m_arg1; funcApp->m_args[2] = farg4->m_arg2; funcApp->m_args[3] = farg4->m_arg3; - } return true; + } case CEA_Func3: { VNDefFunc3Arg* farg3 = &reinterpret_cast<VNDefFunc3Arg*>(c->m_defs)[offset]; @@ -3425,8 +3449,8 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp) funcApp->m_args[0] = farg3->m_arg0; funcApp->m_args[1] = farg3->m_arg1; funcApp->m_args[2] = farg3->m_arg2; - } return true; + } case CEA_Func2: { VNDefFunc2Arg* farg2 = &reinterpret_cast<VNDefFunc2Arg*>(c->m_defs)[offset]; @@ -3434,23 +3458,29 @@ bool ValueNumStore::GetVNFunc(ValueNum vn, VNFuncApp* funcApp) funcApp->m_arity = 2; funcApp->m_args[0] = farg2->m_arg0; funcApp->m_args[1] = farg2->m_arg1; - } return true; + } case CEA_Func1: { VNDefFunc1Arg* farg1 = &reinterpret_cast<VNDefFunc1Arg*>(c->m_defs)[offset]; funcApp->m_func = farg1->m_func; funcApp->m_arity = 1; funcApp->m_args[0] = farg1->m_arg0; - } return true; + } case CEA_Func0: { VNDefFunc0Arg* farg0 = &reinterpret_cast<VNDefFunc0Arg*>(c->m_defs)[offset]; funcApp->m_func = farg0->m_func; funcApp->m_arity = 0; + return true; } + case CEA_NotAField: + { + funcApp->m_func = VNF_NotAField; + funcApp->m_arity = 0; return true; + } default: return false; } @@ -3751,8 +3781,9 @@ static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memo // These need special semantics: GT_COMMA, // == second argument (but with exception(s) from first). GT_ADDR, GT_ARR_BOUNDS_CHECK, - GT_OBJ, // May reference heap memory. - GT_BLK, // May reference heap memory. + GT_OBJ, // May reference heap memory. + GT_BLK, // May reference heap memory. + GT_INIT_VAL, // Not strictly a pass-through. // These control-flow operations need no values. GT_JTRUE, GT_RETURN, GT_SWITCH, GT_RETFILT, GT_CKFINITE}; @@ -3842,10 +3873,9 @@ static const char* s_reservedNameArr[] = { "$VN.No", // -1 NoVN "$VN.Null", // 0 VNForNull() "$VN.ZeroMap", // 1 VNForZeroMap() - "$VN.NotAField", // 2 VNForNotAField() - "$VN.ReadOnlyHeap", // 3 VNForROH() - "$VN.Void", // 4 VNForVoid() - "$VN.EmptyExcSet" // 5 VNForEmptyExcSet() + "$VN.ReadOnlyHeap", // 2 VNForROH() + "$VN.Void", // 3 VNForVoid() + "$VN.EmptyExcSet" // 4 VNForEmptyExcSet() }; // Returns the string name of "vn" when it is a reserved value number, nullptr otherwise @@ -4804,8 +4834,16 @@ void Compiler::fgValueNumberTreeConst(GenTreePtr tree) tree->gtVNPair.SetBoth(vnStore->VNForDoubleCon(tree->gtDblCon.gtDconVal)); break; case TYP_REF: - // Null is the only constant. (Except maybe for String?) - tree->gtVNPair.SetBoth(ValueNumStore::VNForNull()); + if (tree->gtIntConCommon.IconValue() == 0) + { + tree->gtVNPair.SetBoth(ValueNumStore::VNForNull()); + } + else + { + assert(tree->gtFlags == GTF_ICON_STR_HDL); // Constant object can be only frozen string. + tree->gtVNPair.SetBoth( + vnStore->VNForHandle(ssize_t(tree->gtIntConCommon.IconValue()), tree->GetIconHandleFlag())); + } break; case TYP_BYREF: @@ -4903,9 +4941,6 @@ void Compiler::fgValueNumberBlockAssignment(GenTreePtr tree, bool evalAsgLhsInd) } #endif // DEBUG } - // Initblock's are of type void. Give them the void "value" -- they may occur in argument lists, which we - // want to be able to give VN's to. - tree->gtVNPair.SetBoth(ValueNumStore::VNForVoid()); } else { @@ -4913,6 +4948,9 @@ void Compiler::fgValueNumberBlockAssignment(GenTreePtr tree, bool evalAsgLhsInd) // TODO-CQ: Why not be complete, and get this case right? fgMutateHeap(tree DEBUGARG("INITBLK - non local")); } + // Initblock's are of type void. Give them the void "value" -- they may occur in argument lists, which we + // want to be able to give VN's to. + tree->gtVNPair.SetBoth(ValueNumStore::VNForVoid()); } else { @@ -4953,17 +4991,21 @@ void Compiler::fgValueNumberBlockAssignment(GenTreePtr tree, bool evalAsgLhsInd) assert(lhs->OperGet() == GT_IND); lhsAddr = lhs->gtOp.gtOp1; } + // For addr-of-local expressions, lib/cons shouldn't matter. assert(lhsAddr->gtVNPair.BothEqual()); ValueNum lhsAddrVN = lhsAddr->GetVN(VNK_Liberal); // Unpack the PtrToLoc value number of the address. assert(vnStore->IsVNFunc(lhsAddrVN)); + VNFuncApp lhsAddrFuncApp; vnStore->GetVNFunc(lhsAddrVN, &lhsAddrFuncApp); + assert(lhsAddrFuncApp.m_func == VNF_PtrToLoc); assert(vnStore->IsVNConstant(lhsAddrFuncApp.m_args[0]) && vnStore->ConstantValue<unsigned>(lhsAddrFuncApp.m_args[0]) == lhsLclNum); + lhsFldSeq = vnStore->FieldSeqVNToFieldSeq(lhsAddrFuncApp.m_args[1]); } @@ -5598,10 +5640,9 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd) // (we looked in a side table above for its "def" identity). Look up that value. ValueNumPair oldLhsVNPair = lvaTable[lclFld->GetLclNum()].GetPerSsaData(lclFld->GetSsaNum())->m_vnPair; - newLhsVNPair = - vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lclFld->gtFieldSeq, - rhsVNPair, // Pre-value. - lvaGetActualType(lclFld->gtLclNum), compCurBB); + newLhsVNPair = vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lclFld->gtFieldSeq, + rhsVNPair, // Pre-value. + lclFld->TypeGet(), compCurBB); } } lvaTable[lclFld->GetLclNum()].GetPerSsaData(lclDefSsaNum)->m_vnPair = newLhsVNPair; @@ -6034,8 +6075,9 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd) if (newVN == ValueNumStore::NoVN) { assert(arg->gtLclVarCommon.GetSsaNum() != ValueNumStore::NoVN); - newVN = vnStore->VNForPtrToLoc(TYP_BYREF, vnStore->VNForIntCon(arg->gtLclVarCommon.GetLclNum()), - vnStore->VNForFieldSeq(fieldSeq)); + newVN = vnStore->VNForFunc(TYP_BYREF, VNF_PtrToLoc, + vnStore->VNForIntCon(arg->gtLclVarCommon.GetLclNum()), + vnStore->VNForFieldSeq(fieldSeq)); } tree->gtVNPair.SetBoth(newVN); } @@ -6240,17 +6282,12 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd) } tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, addrXvnp); } - else if (!varTypeIsStruct(tree) && vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp) && - (funcApp.m_func == VNF_PtrToArrElem)) + else if (vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp) && (funcApp.m_func == VNF_PtrToArrElem)) { - // TODO-1stClassStructs: The above condition need not exclude struct types, but it is - // excluded for now to minimize diffs. fgValueNumberArrIndexVal(tree, &funcApp, addrXvnp.GetLiberal()); } - else if (!varTypeIsStruct(tree) && addr->IsFieldAddr(this, &obj, &staticOffset, &fldSeq2)) + else if (addr->IsFieldAddr(this, &obj, &staticOffset, &fldSeq2)) { - // TODO-1stClassStructs: The above condition need not exclude struct types, but it is - // excluded for now to minimize diffs. if (fldSeq2 == FieldSeqStore::NotAField()) { tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet())); @@ -6522,6 +6559,9 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd) case GT_JTRUE: case GT_LIST: +#ifndef LEGACY_BACKEND + case GT_FIELD_LIST: +#endif // !LEGACY_BACKEND // These nodes never need to have a ValueNumber tree->gtVNPair.SetBoth(ValueNumStore::NoVN); break; @@ -6667,7 +6707,7 @@ void Compiler::fgValueNumberCastTree(GenTreePtr tree) bool srcIsUnsigned = ((tree->gtFlags & GTF_UNSIGNED) != 0); bool hasOverflowCheck = tree->gtOverflowEx(); - assert(genActualType(castToType) == tree->TypeGet()); // Insure that the resultType is correct + assert(genActualType(castToType) == genActualType(tree->TypeGet())); // Insure that the resultType is correct tree->gtVNPair = vnStore->VNPairForCast(srcVNPair, castToType, castFromType, srcIsUnsigned, hasOverflowCheck); } @@ -6816,6 +6856,7 @@ void Compiler::fgValueNumberHelperCallFunc(GenTreeCall* call, VNFunc vnf, ValueN break; case VNF_ReadyToRunStaticBase: + case VNF_ReadyToRunGenericStaticBase: case VNF_ReadyToRunIsInstanceOf: case VNF_ReadyToRunCastClass: { @@ -7061,11 +7102,11 @@ VNFunc Compiler::fgValueNumberHelperMethVNFunc(CorInfoHelpFunc helpFunc) vnf = VNFunc(GT_MOD); break; case CORINFO_HELP_ULDIV: - vnf = VNFunc(GT_DIV); - break; // Is this the right thing? + vnf = VNFunc(GT_UDIV); + break; case CORINFO_HELP_ULMOD: - vnf = VNFunc(GT_MOD); - break; // Is this the right thing? + vnf = VNFunc(GT_UMOD); + break; case CORINFO_HELP_LNG2DBL: vnf = VNF_Lng2Dbl; @@ -7155,6 +7196,11 @@ VNFunc Compiler::fgValueNumberHelperMethVNFunc(CorInfoHelpFunc helpFunc) case CORINFO_HELP_READYTORUN_STATIC_BASE: vnf = VNF_ReadyToRunStaticBase; break; +#if COR_JIT_EE_VERSION > 460 + case CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE: + vnf = VNF_ReadyToRunGenericStaticBase; + break; +#endif // COR_JIT_EE_VERSION > 460 case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS: vnf = VNF_GetsharedGcstaticBaseDynamicclass; break; |