Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Guarded devirtualization: multiple type checks #86551

Merged
merged 18 commits into from
May 26, 2023
5 changes: 4 additions & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4364,6 +4364,7 @@ class Compiler
InlineResult* inlineResult);

void impCheckCanInline(GenTreeCall* call,
uint8_t candidateIndex,
CORINFO_METHOD_HANDLE fncHandle,
unsigned methAttr,
CORINFO_CONTEXT_HANDLE exactContextHnd,
Expand Down Expand Up @@ -4392,10 +4393,12 @@ class Compiler
IL_OFFSET ilOffset);

void impMarkInlineCandidateHelper(GenTreeCall* call,
uint8_t candidateIndex,
CORINFO_CONTEXT_HANDLE exactContextHnd,
bool exactContextNeedsRuntimeLookup,
CORINFO_CALL_INFO* callInfo,
IL_OFFSET ilOffset);
IL_OFFSET ilOffset,
InlineResult* inlineResult);

bool impTailCallRetTypeCompatible(bool allowWidening,
var_types callerRetType,
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/jit/fginline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ void Compiler::fgMorphCallInline(GenTreeCall* call, InlineResult* inlineResult)
{
bool inliningFailed = false;

InlineCandidateInfo* inlCandInfo = call->GetInlineCandidateInfo();
InlineCandidateInfo* inlCandInfo = call->GetSingleInlineCandidateInfo();

// Is this call an inline candidate?
if (call->IsInlineCandidate())
Expand All @@ -771,8 +771,8 @@ void Compiler::fgMorphCallInline(GenTreeCall* call, InlineResult* inlineResult)
{
#ifdef DEBUG
// In debug we always put all inline attempts into the inline tree.
InlineContext* ctx =
m_inlineStrategy->NewContext(call->GetInlineCandidateInfo()->inlinersContext, fgMorphStmt, call);
InlineContext* ctx = m_inlineStrategy->NewContext(call->GetSingleInlineCandidateInfo()->inlinersContext,
fgMorphStmt, call);
ctx->SetFailed(inlineResult);
#endif
}
Expand Down Expand Up @@ -1039,7 +1039,7 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineRe
inlineInfo.hasSIMDTypeArgLocalOrReturn = false;
#endif // FEATURE_SIMD

InlineCandidateInfo* inlineCandidateInfo = call->GetInlineCandidateInfo();
InlineCandidateInfo* inlineCandidateInfo = call->GetSingleInlineCandidateInfo();
noway_assert(inlineCandidateInfo);
// Store the link to inlineCandidateInfo into inlineInfo
inlineInfo.inlineCandidateInfo = inlineCandidateInfo;
Expand Down
39 changes: 24 additions & 15 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2164,12 +2164,12 @@ GenTree* Compiler::getArrayLengthFromAllocation(GenTree* tree DEBUGARG(BasicBloc
}

//-------------------------------------------------------------------------
// SetSingleInlineCadidateInfo: set a single inline candidate info in the current call.
// SetSingleInlineCandidateInfo: set a single inline candidate info in the current call.
//
// Arguments:
// candidateInfo - inline candidate info
//
void GenTreeCall::SetSingleInlineCadidateInfo(InlineCandidateInfo* candidateInfo)
void GenTreeCall::SetSingleInlineCandidateInfo(InlineCandidateInfo* candidateInfo)
{
if (candidateInfo != nullptr)
{
Expand All @@ -2180,9 +2180,9 @@ void GenTreeCall::SetSingleInlineCadidateInfo(InlineCandidateInfo* candidateInfo
{
gtInlineInfoCount = 0;
gtFlags &= ~GTF_CALL_INLINE_CANDIDATE;
gtCallMoreFlags &= ~GTF_CALL_M_GUARDED_DEVIRT;
}
gtInlineCandidateInfo = candidateInfo;
ClearGuardedDevirtualizationCandidate();
}

//-------------------------------------------------------------------------
Expand All @@ -2199,22 +2199,29 @@ InlineCandidateInfo* GenTreeCall::GetGDVCandidateInfo(uint8_t index)

//-------------------------------------------------------------------------
// AddGDVCandidateInfo: Record a guarded devirtualization (GDV) candidate info
// for this call. For now, we only support one GDV candidate per call.
// for this call. A call can't have more than MAX_GDV_TYPE_CHECKS number of candidates
//
// Arguments:
// comp - Compiler instance
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
// candidateInfo - GDV candidate info
//
void GenTreeCall::AddGDVCandidateInfo(InlineCandidateInfo* candidateInfo)
void GenTreeCall::AddGDVCandidateInfo(Compiler* comp, InlineCandidateInfo* candidateInfo)
{
assert(gtInlineInfoCount < MAX_GDV_TYPE_CHECKS);
assert(candidateInfo != nullptr);

if (gtInlineInfoCount == 0)
{
gtInlineCandidateInfo = candidateInfo;
}
else if (gtInlineInfoCount == 1)
{
gtInlineCandidateInfo =
new (comp, CMK_Inlining) InlineCandidateInfo[MAX_GDV_TYPE_CHECKS]{*gtInlineCandidateInfo, *candidateInfo};
}
else
{
// Allocate a fixed list of InlineCandidateInfo structs
assert(!"multiple GDV candidates are not implemented yet");
gtInlineCandidateInfo[gtInlineInfoCount] = *candidateInfo;
EgorBo marked this conversation as resolved.
Show resolved Hide resolved
}

gtCallMoreFlags |= GTF_CALL_M_GUARDED_DEVIRT;
Expand Down Expand Up @@ -7729,10 +7736,11 @@ GenTreeCall* Compiler::gtNewCallNode(gtCallTypes callType,
node->gtCallType = callType;
node->gtCallMethHnd = callHnd;
INDEBUG(node->callSig = nullptr;)
node->tailCallInfo = nullptr;
node->gtRetClsHnd = nullptr;
node->gtControlExpr = nullptr;
node->gtCallMoreFlags = GTF_CALL_M_EMPTY;
node->tailCallInfo = nullptr;
node->gtRetClsHnd = nullptr;
node->gtControlExpr = nullptr;
node->gtCallMoreFlags = GTF_CALL_M_EMPTY;
node->gtInlineInfoCount = 0;

if (callType == CT_INDIRECT)
{
Expand Down Expand Up @@ -12346,10 +12354,11 @@ void Compiler::gtDispTree(GenTree* tree,
printf(" (FramesRoot last use)");
}

if (((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0) && (call->GetInlineCandidateInfo() != nullptr) &&
(call->GetInlineCandidateInfo()->exactContextHnd != nullptr))
if (((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0) &&
(call->GetSingleInlineCandidateInfo() != nullptr) &&
(call->GetSingleInlineCandidateInfo()->exactContextHnd != nullptr))
{
printf(" (exactContextHnd=0x%p)", dspPtr(call->GetInlineCandidateInfo()->exactContextHnd));
printf(" (exactContextHnd=0x%p)", dspPtr(call->GetSingleInlineCandidateInfo()->exactContextHnd));
}

gtDispCommonEndLine(tree);
Expand Down Expand Up @@ -17864,7 +17873,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b
// type class handle in the inline info (for GDV candidates,
// this data is valid only for a correct guess, so we cannot
// use it).
InlineCandidateInfo* inlInfo = call->GetInlineCandidateInfo();
InlineCandidateInfo* inlInfo = call->GetSingleInlineCandidateInfo();
assert(inlInfo != nullptr);

// Grab it as our first cut at a return type.
Expand Down
26 changes: 21 additions & 5 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -5421,20 +5421,36 @@ struct GenTreeCall final : public GenTree
return (gtCallMoreFlags & GTF_CALL_M_RETBUFFARG_LCLOPT) != 0;
}

InlineCandidateInfo* GetInlineCandidateInfo()
InlineCandidateInfo* GetSingleInlineCandidateInfo()
{
// gtInlineInfoCount can be 0 (not an inline candidate) or 1
if (gtInlineInfoCount == 0)
{
assert(!IsInlineCandidate());
assert(gtInlineCandidateInfo == nullptr);
return nullptr;
}
else if (gtInlineInfoCount > 1)
{
assert(!"Call has multiple inline candidates");
}
return gtInlineCandidateInfo;
}

void SetSingleInlineCadidateInfo(InlineCandidateInfo* candidateInfo);
void SetSingleInlineCandidateInfo(InlineCandidateInfo* candidateInfo);

InlineCandidateInfo* GetGDVCandidateInfo(uint8_t index = 0);
InlineCandidateInfo* GetGDVCandidateInfo(uint8_t index);
EgorBo marked this conversation as resolved.
Show resolved Hide resolved

void AddGDVCandidateInfo(InlineCandidateInfo* candidateInfo);
void AddGDVCandidateInfo(Compiler* comp, InlineCandidateInfo* candidateInfo);

void ClearInlineInfo()
{
SetSingleInlineCadidateInfo(nullptr);
SetSingleInlineCandidateInfo(nullptr);
}

uint8_t GetInlineCandidatesCount()
{
return gtInlineInfoCount;
}

//-----------------------------------------------------------------------------------------
Expand Down
15 changes: 12 additions & 3 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1704,9 +1704,18 @@ bool Compiler::impSpillStackEntry(unsigned level,
if (tree->OperGet() == GT_RET_EXPR)
{
JITDUMP("\n*** see V%02u = GT_RET_EXPR, noting temp\n", tnum);
GenTree* call = tree->AsRetExpr()->gtInlineCandidate;
InlineCandidateInfo* ici = call->AsCall()->GetInlineCandidateInfo();
ici->preexistingSpillTemp = tnum;
GenTreeCall* call = tree->AsRetExpr()->gtInlineCandidate->AsCall();
if (call->IsGuardedDevirtualizationCandidate())
{
for (uint8_t i = 0; i < call->GetInlineCandidatesCount(); i++)
{
call->GetGDVCandidateInfo(i)->preexistingSpillTemp = tnum;
}
}
else
{
call->AsCall()->GetSingleInlineCandidateInfo()->preexistingSpillTemp = tnum;
}
}
}

Expand Down