Skip to content

Commit

Permalink
Add IsDevirtualizationCandidate
Browse files Browse the repository at this point in the history
  • Loading branch information
hez2010 committed Feb 18, 2025
1 parent 8a79637 commit ba26707
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/coreclr/jit/fginline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,7 @@ class SubstitutePlaceholdersAndDevirtualizeWalker : public GenTreeVisitor<Substi
if (tree->OperGet() == GT_CALL)
{
GenTreeCall* call = tree->AsCall();
bool tryLateDevirt = call->IsVirtual() && (call->gtCallType == CT_USER_FUNC);
bool tryLateDevirt = call->IsDevirtualizationCandidate(m_compiler);

#ifdef DEBUG
tryLateDevirt = tryLateDevirt && (JitConfig.JitEnableLateDevirtualization() == 1);
Expand Down Expand Up @@ -610,7 +610,7 @@ class SubstitutePlaceholdersAndDevirtualizeWalker : public GenTreeVisitor<Substi
m_compiler->impDevirtualizeCall(call, nullptr, &method, &methodFlags, &contextInput, &context,
isLateDevirtualization, explicitTailCall);

if (!call->IsVirtual())
if (!call->IsDevirtualizationCandidate(m_compiler))
{
assert(context != nullptr);
CORINFO_CALL_INFO callInfo = {};
Expand Down
38 changes: 38 additions & 0 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2417,6 +2417,44 @@ int GenTreeCall::GetNonStandardAddedArgCount(Compiler* compiler) const
return 0;
}

//-------------------------------------------------------------------------
// IsDevirtualizationCandidate: Determine if this GT_CALL node is a devirtualization candidate.
// A call will be unmarked from devirtualization candidate if it
// is devirtualized.
//
// Arguments:
// compiler - the compiler instance so that we can call eeFindHelper
//
// Return Value:
// Returns true if this GT_CALL node is a devirtualization candidate.
//
bool GenTreeCall::IsDevirtualizationCandidate(Compiler* compiler) const
{
return (IsVirtual() && gtCallType == CT_USER_FUNC) ||
(gtCallType == CT_INDIRECT && gtCallAddr->IsCall() &&
gtCallAddr->AsCall()->IsVirtualFunctionPointerLookup(compiler));
}

//-------------------------------------------------------------------------
// IsVirtualFunctionPointerLookup: Determine if this GT_CALL node is a virtual function pointer lookup.
//
// Arguments:
// compiler - the compiler instance so that we can call eeFindHelper
//
// Return Value:
// Returns true if this GT_CALL node is a virtual function pointer lookup.
//
bool GenTreeCall::IsVirtualFunctionPointerLookup(Compiler* compiler) const
{
return gtCallAddr->IsHelperCall(compiler, CORINFO_HELP_VIRTUAL_FUNC_PTR) ||
gtCallAddr->IsHelperCall(compiler, CORINFO_HELP_GVMLOOKUP_FOR_SLOT)
#ifdef FEATURE_READYTORUN
|| gtCallAddr->IsHelperCall(compiler, CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR) ||
gtCallAddr->IsHelperCall(compiler, CORINFO_HELP_READYTORUN_GENERIC_HANDLE)
#endif // FEATURE_READYTORUN
;
}

//-------------------------------------------------------------------------
// IsHelperCall: Determine if this GT_CALL node is a specific helper call.
//
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -5331,6 +5331,10 @@ struct GenTreeCall final : public GenTree
{
return (gtFlags & GTF_CALL_VIRT_KIND_MASK) == GTF_CALL_VIRT_VTABLE;
}

bool IsDevirtualizationCandidate(Compiler* compiler) const;
bool IsVirtualFunctionPointerLookup(Compiler* compiler) const;

bool IsInlineCandidate() const
{
return (gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0;
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ var_types Compiler::impImportCall(OPCODE opcode,
// See if we can devirt if we aren't probing.
if (!probing && opts.OptimizationEnabled())
{
if (call->AsCall()->IsVirtual())
if (call->AsCall()->IsDevirtualizationCandidate(this))
{
// only true object pointers can be virtual
assert(call->AsCall()->gtArgs.HasThisPointer() &&
Expand All @@ -965,7 +965,7 @@ var_types Compiler::impImportCall(OPCODE opcode,
// inlinees.
rawILOffset);

const bool wasDevirtualized = !call->AsCall()->IsVirtual();
const bool wasDevirtualized = !call->AsCall()->IsDevirtualizationCandidate(this);

if (wasDevirtualized)
{
Expand Down Expand Up @@ -8020,9 +8020,9 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
assert(methodFlags != nullptr);
assert(pContextHandle != nullptr);

// This should be a virtual vtable or virtual stub call.
// This should be a devirtualization candidate.
//
assert(call->IsVirtual());
assert(call->IsDevirtualizationCandidate(this));
assert(opts.OptimizationEnabled());

#if defined(DEBUG)
Expand Down

0 comments on commit ba26707

Please sign in to comment.