Skip to content

Commit

Permalink
Guarded devirtualization: multiple type checks (#86551)
Browse files Browse the repository at this point in the history
Co-authored-by: Andy Ayers <andya@microsoft.com>
  • Loading branch information
EgorBo and AndyAyersMS committed May 26, 2023
1 parent 2e45de5 commit 182b013
Show file tree
Hide file tree
Showing 9 changed files with 398 additions and 109 deletions.
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
// 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;
}

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 @@ -12353,10 +12361,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 @@ -17871,7 +17880,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 @@ -5425,20 +5425,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);

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

0 comments on commit 182b013

Please sign in to comment.