@@ -586,8 +586,36 @@ class SubstitutePlaceholdersAndDevirtualizeWalker : public GenTreeVisitor<Substi
586586                }
587587
588588                CORINFO_CONTEXT_HANDLE contextInput = context;
589+                 context                             = nullptr ;
589590                m_compiler->impDevirtualizeCall (call, nullptr , &method, &methodFlags, &contextInput, &context,
590591                                                isLateDevirtualization, explicitTailCall);
592+                 if  (context != nullptr )
593+                 {
594+                     IL_OFFSET         ilOffset = m_compiler->compCurStmt ->GetDebugInfo ().GetLocation ().GetOffset ();
595+                     CORINFO_CALL_INFO callInfo = {};
596+                     callInfo.hMethod            = method;
597+                     callInfo.methodFlags        = methodFlags;
598+                     m_compiler->impMarkInlineCandidate (call, context, false , &callInfo, ilOffset);
599+ 
600+                     const  bool  isInlineCandidate = call->IsInlineCandidate ();
601+ 
602+                     if  (isInlineCandidate)
603+                     {
604+                         Statement* stmt = m_compiler->gtNewStmt (call);
605+                         m_compiler->fgInsertStmtBefore (m_compiler->compCurBB , m_compiler->compCurStmt , stmt);
606+                         GenTreeRetExpr* retExpr =
607+                             m_compiler->gtNewInlineCandidateReturnExpr (call->AsCall (), genActualType (call->TypeGet ()));
608+                         *pTree = retExpr;
609+ 
610+                         call->GetSingleInlineCandidateInfo ()->retExpr             = retExpr;
611+                         call->GetSingleInlineCandidateInfo ()->exactContextHandle  = context;
612+                         INDEBUG (call->gtInlineContext  = call->GetSingleInlineCandidateInfo ()->inlinersContext );
613+ 
614+                         JITDUMP (" New inline candidate due to late devirtualization:" 
615+                         DISPTREE (call);
616+                         m_compiler->compCurStmt  = stmt;
617+                     }
618+                 }
591619                m_madeChanges = true ;
592620            }
593621        }
@@ -730,11 +758,11 @@ PhaseStatus Compiler::fgInline()
730758    do 
731759    {
732760        //  Make the current basic block address available globally
733-         compCurBB = block;
734- 
735-         for  (Statement*  const   stmt : block-> Statements () )
761+         compCurBB        = block;
762+         Statement* stmt = block-> firstStmt (); 
763+         while  ( stmt !=  nullptr )
736764        {
737- 
765+             compCurStmt = stmt; 
738766#if  defined(DEBUG)
739767            //  In debug builds we want the inline tree to show all failed
740768            //  inlines. Some inlines may fail very early and never make it to
@@ -756,6 +784,7 @@ PhaseStatus Compiler::fgInline()
756784            //  replacement may have enabled optimizations by providing more
757785            //  specific types for trees or variables.
758786            walker.WalkTree (stmt->GetRootNodePointer (), nullptr );
787+             stmt = compCurStmt;
759788
760789            GenTree* expr = stmt->GetRootNode ();
761790
@@ -805,6 +834,8 @@ PhaseStatus Compiler::fgInline()
805834                madeChanges = true ;
806835                stmt->SetRootNode (expr->AsOp ()->gtOp1 );
807836            }
837+ 
838+             stmt = stmt->GetNextStmt ();
808839        }
809840
810841        block = block->Next ();
@@ -1075,7 +1106,8 @@ void Compiler::fgMorphCallInlineHelper(GenTreeCall* call, InlineResult* result,
10751106Compiler::fgWalkResult Compiler::fgFindNonInlineCandidate (GenTree** pTree, fgWalkData* data)
10761107{
10771108    GenTree* tree = *pTree;
1078-     if  (tree->gtOper  == GT_CALL)
1109+     //  We may get late devirtualization opportunities for virtual calls that are not inline candidates.
1110+     if  (tree->gtOper  == GT_CALL && !tree->AsCall ()->IsVirtual ())
10791111    {
10801112        Compiler*    compiler = data->compiler ;
10811113        Statement*   stmt     = (Statement*)data->pCallbackData ;
0 commit comments