JIT: extend VN to understand method table fetch from newobj (#52476)
authorAndy Ayers <andya@microsoft.com>
Sun, 9 May 2021 21:53:40 +0000 (14:53 -0700)
committerGitHub <noreply@github.com>
Sun, 9 May 2021 21:53:40 +0000 (14:53 -0700)
If we see a GT_IND whose base is JitNew, the value number of the IND
is the same as the value number of the class handle for the new.

Partial fix for #52370.

src/coreclr/jit/valuenum.cpp

index 27b4b34..85dacfc 100644 (file)
@@ -8141,30 +8141,51 @@ void Compiler::fgValueNumberTree(GenTree* tree)
             {
                 assert(!isVolatile); // We don't expect both volatile and invariant
 
-                // Is this invariant indirect expected to always return a non-null value?
-                if ((tree->gtFlags & GTF_IND_NONNULL) != 0)
+                // 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))
                 {
-                    assert(tree->gtFlags & GTF_IND_NONFAULTING);
-                    tree->gtVNPair = vnStore->VNPairForFunc(tree->TypeGet(), VNF_NonNullIndirect, addrNvnp);
-                    if (addr->IsCnsIntOrI())
+                    VNFuncApp  funcApp;
+                    const bool addrIsVNFunc = vnStore->GetVNFunc(addrNvnp.GetLiberal(), &funcApp);
+
+                    if (addrIsVNFunc && (funcApp.m_func == VNF_JitNew) && addrNvnp.BothEqual())
                     {
-                        assert(addrXvnp.BothEqual() && (addrXvnp.GetLiberal() == ValueNumStore::VNForEmptyExcSet()));
+                        tree->gtVNPair =
+                            vnStore->VNPWithExc(ValueNumPair(funcApp.m_args[0], funcApp.m_args[0]), addrXvnp);
+                        wasNewobj = true;
+                    }
+                }
+
+                if (!wasNewobj)
+                {
+
+                    // Is this invariant indirect expected to always return a non-null value?
+                    if ((tree->gtFlags & GTF_IND_NONNULL) != 0)
+                    {
+                        assert(tree->gtFlags & GTF_IND_NONFAULTING);
+                        tree->gtVNPair = vnStore->VNPairForFunc(tree->TypeGet(), VNF_NonNullIndirect, addrNvnp);
+                        if (addr->IsCnsIntOrI())
+                        {
+                            assert(addrXvnp.BothEqual() &&
+                                   (addrXvnp.GetLiberal() == ValueNumStore::VNForEmptyExcSet()));
+                        }
+                        else
+                        {
+                            assert(false && "it's not expected to be hit at the moment, but can be allowed.");
+                            // tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, addrXvnp);
+                        }
                     }
                     else
                     {
-                        assert(false && "it's not expected to be hit at the moment, but can be allowed.");
-                        // tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, addrXvnp);
+                        tree->gtVNPair =
+                            ValueNumPair(vnStore->VNForMapSelect(VNK_Liberal, TYP_REF, ValueNumStore::VNForROH(),
+                                                                 addrNvnp.GetLiberal()),
+                                         vnStore->VNForMapSelect(VNK_Conservative, TYP_REF, ValueNumStore::VNForROH(),
+                                                                 addrNvnp.GetConservative()));
+                        tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, addrXvnp);
                     }
                 }
-                else
-                {
-                    tree->gtVNPair =
-                        ValueNumPair(vnStore->VNForMapSelect(VNK_Liberal, TYP_REF, ValueNumStore::VNForROH(),
-                                                             addrNvnp.GetLiberal()),
-                                     vnStore->VNForMapSelect(VNK_Conservative, TYP_REF, ValueNumStore::VNForROH(),
-                                                             addrNvnp.GetConservative()));
-                    tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, addrXvnp);
-                }
             }
             else if (isVolatile)
             {