diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 18c4d946c2736f..9b580f69c672a4 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -10638,23 +10638,48 @@ void Compiler::fgValueNumberTree(GenTree* tree) { assert(!isVolatile); // We don't expect both volatile and invariant - // Are we dereferencing the method table slot of some newly allocated object? - // - bool wasNewobj = false; - if ((oper == GT_IND) && (addr->TypeGet() == TYP_REF) && (tree->TypeGet() == TYP_I_IMPL)) + bool returnsTypeHandle = false; + if ((oper == GT_IND) && addr->TypeIs(TYP_REF) && tree->TypeIs(TYP_I_IMPL)) { - VNFuncApp funcApp; - const bool addrIsVNFunc = vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp); - - if (addrIsVNFunc && (funcApp.m_func == VNF_JitNew) && addrNvnp.BothEqual()) + // We try to access GC object's type, let's see if we know the exact type already + // First, we're trying to do that via gtGetClassHandle. + // + bool isExact = false; + bool isNonNull = false; + CORINFO_CLASS_HANDLE handle = gtGetClassHandle(addr, &isExact, &isNonNull); + if (isExact && (handle != NO_CLASS_HANDLE)) { - tree->gtVNPair = - vnStore->VNPWithExc(ValueNumPair(funcApp.m_args[0], funcApp.m_args[0]), addrXvnp); - wasNewobj = true; + JITDUMP("IND(obj) is actually a class handle for %s\n", eeGetClassName(handle)); + // Filter out all shared generic instantiations + if ((info.compCompHnd->getClassAttribs(handle) & CORINFO_FLG_SHAREDINST) == 0) + { + void* pEmbedClsHnd; + void* embedClsHnd = (void*)info.compCompHnd->embedClassHandle(handle, &pEmbedClsHnd); + if (pEmbedClsHnd == nullptr) + { + // Skip indirect handles for now since this path is mostly for PGO scenarios + assert(embedClsHnd != nullptr); + ValueNum handleVN = vnStore->VNForHandle((ssize_t)embedClsHnd, GTF_ICON_CLASS_HDL); + tree->gtVNPair = vnStore->VNPWithExc(ValueNumPair(handleVN, handleVN), addrXvnp); + returnsTypeHandle = true; + } + } + } + else + { + // Then, let's see if we can find JitNew at least + VNFuncApp funcApp; + const bool addrIsVNFunc = vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp); + if (addrIsVNFunc && (funcApp.m_func == VNF_JitNew) && addrNvnp.BothEqual()) + { + tree->gtVNPair = + vnStore->VNPWithExc(ValueNumPair(funcApp.m_args[0], funcApp.m_args[0]), addrXvnp); + returnsTypeHandle = true; + } } } - if (!wasNewobj) + if (!returnsTypeHandle) { // Indirections off of addresses for boxed statics represent bases for // the address of the static itself. Here we will use "nullptr" for the