Skip to content

Commit 686f64e

Browse files
committed
Enable inlining for late devirt
1 parent 4c224ab commit 686f64e

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

src/coreclr/jit/compiler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5109,6 +5109,8 @@ class Compiler
51095109
SpillCliqueSucc
51105110
};
51115111

5112+
friend class SubstitutePlaceholdersAndDevirtualizeWalker;
5113+
51125114
// Abstract class for receiving a callback while walking a spill clique
51135115
class SpillCliqueWalker
51145116
{

src/coreclr/jit/fginline.cpp

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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,
10751106
Compiler::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

Comments
 (0)