Skip to content

Commit 182b013

Browse files
EgorBoAndyAyersMS
andauthored
Guarded devirtualization: multiple type checks (#86551)
Co-authored-by: Andy Ayers <[email protected]>
1 parent 2e45de5 commit 182b013

9 files changed

+398
-109
lines changed

src/coreclr/jit/compiler.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -4364,6 +4364,7 @@ class Compiler
43644364
InlineResult* inlineResult);
43654365

43664366
void impCheckCanInline(GenTreeCall* call,
4367+
uint8_t candidateIndex,
43674368
CORINFO_METHOD_HANDLE fncHandle,
43684369
unsigned methAttr,
43694370
CORINFO_CONTEXT_HANDLE exactContextHnd,
@@ -4392,10 +4393,12 @@ class Compiler
43924393
IL_OFFSET ilOffset);
43934394

43944395
void impMarkInlineCandidateHelper(GenTreeCall* call,
4396+
uint8_t candidateIndex,
43954397
CORINFO_CONTEXT_HANDLE exactContextHnd,
43964398
bool exactContextNeedsRuntimeLookup,
43974399
CORINFO_CALL_INFO* callInfo,
4398-
IL_OFFSET ilOffset);
4400+
IL_OFFSET ilOffset,
4401+
InlineResult* inlineResult);
43994402

44004403
bool impTailCallRetTypeCompatible(bool allowWidening,
44014404
var_types callerRetType,

src/coreclr/jit/fginline.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ void Compiler::fgMorphCallInline(GenTreeCall* call, InlineResult* inlineResult)
746746
{
747747
bool inliningFailed = false;
748748

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

751751
// Is this call an inline candidate?
752752
if (call->IsInlineCandidate())
@@ -771,8 +771,8 @@ void Compiler::fgMorphCallInline(GenTreeCall* call, InlineResult* inlineResult)
771771
{
772772
#ifdef DEBUG
773773
// In debug we always put all inline attempts into the inline tree.
774-
InlineContext* ctx =
775-
m_inlineStrategy->NewContext(call->GetInlineCandidateInfo()->inlinersContext, fgMorphStmt, call);
774+
InlineContext* ctx = m_inlineStrategy->NewContext(call->GetSingleInlineCandidateInfo()->inlinersContext,
775+
fgMorphStmt, call);
776776
ctx->SetFailed(inlineResult);
777777
#endif
778778
}
@@ -1039,7 +1039,7 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineRe
10391039
inlineInfo.hasSIMDTypeArgLocalOrReturn = false;
10401040
#endif // FEATURE_SIMD
10411041

1042-
InlineCandidateInfo* inlineCandidateInfo = call->GetInlineCandidateInfo();
1042+
InlineCandidateInfo* inlineCandidateInfo = call->GetSingleInlineCandidateInfo();
10431043
noway_assert(inlineCandidateInfo);
10441044
// Store the link to inlineCandidateInfo into inlineInfo
10451045
inlineInfo.inlineCandidateInfo = inlineCandidateInfo;

src/coreclr/jit/gentree.cpp

+24-15
Original file line numberDiff line numberDiff line change
@@ -2164,12 +2164,12 @@ GenTree* Compiler::getArrayLengthFromAllocation(GenTree* tree DEBUGARG(BasicBloc
21642164
}
21652165

21662166
//-------------------------------------------------------------------------
2167-
// SetSingleInlineCadidateInfo: set a single inline candidate info in the current call.
2167+
// SetSingleInlineCandidateInfo: set a single inline candidate info in the current call.
21682168
//
21692169
// Arguments:
21702170
// candidateInfo - inline candidate info
21712171
//
2172-
void GenTreeCall::SetSingleInlineCadidateInfo(InlineCandidateInfo* candidateInfo)
2172+
void GenTreeCall::SetSingleInlineCandidateInfo(InlineCandidateInfo* candidateInfo)
21732173
{
21742174
if (candidateInfo != nullptr)
21752175
{
@@ -2180,9 +2180,9 @@ void GenTreeCall::SetSingleInlineCadidateInfo(InlineCandidateInfo* candidateInfo
21802180
{
21812181
gtInlineInfoCount = 0;
21822182
gtFlags &= ~GTF_CALL_INLINE_CANDIDATE;
2183-
gtCallMoreFlags &= ~GTF_CALL_M_GUARDED_DEVIRT;
21842183
}
21852184
gtInlineCandidateInfo = candidateInfo;
2185+
ClearGuardedDevirtualizationCandidate();
21862186
}
21872187

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

22002200
//-------------------------------------------------------------------------
22012201
// AddGDVCandidateInfo: Record a guarded devirtualization (GDV) candidate info
2202-
// for this call. For now, we only support one GDV candidate per call.
2202+
// for this call. A call can't have more than MAX_GDV_TYPE_CHECKS number of candidates
22032203
//
22042204
// Arguments:
2205+
// comp - Compiler instance
22052206
// candidateInfo - GDV candidate info
22062207
//
2207-
void GenTreeCall::AddGDVCandidateInfo(InlineCandidateInfo* candidateInfo)
2208+
void GenTreeCall::AddGDVCandidateInfo(Compiler* comp, InlineCandidateInfo* candidateInfo)
22082209
{
2210+
assert(gtInlineInfoCount < MAX_GDV_TYPE_CHECKS);
22092211
assert(candidateInfo != nullptr);
2212+
22102213
if (gtInlineInfoCount == 0)
22112214
{
22122215
gtInlineCandidateInfo = candidateInfo;
22132216
}
2217+
else if (gtInlineInfoCount == 1)
2218+
{
2219+
gtInlineCandidateInfo =
2220+
new (comp, CMK_Inlining) InlineCandidateInfo[MAX_GDV_TYPE_CHECKS]{*gtInlineCandidateInfo, *candidateInfo};
2221+
}
22142222
else
22152223
{
2216-
// Allocate a fixed list of InlineCandidateInfo structs
2217-
assert(!"multiple GDV candidates are not implemented yet");
2224+
gtInlineCandidateInfo[gtInlineInfoCount] = *candidateInfo;
22182225
}
22192226

22202227
gtCallMoreFlags |= GTF_CALL_M_GUARDED_DEVIRT;
@@ -7729,10 +7736,11 @@ GenTreeCall* Compiler::gtNewCallNode(gtCallTypes callType,
77297736
node->gtCallType = callType;
77307737
node->gtCallMethHnd = callHnd;
77317738
INDEBUG(node->callSig = nullptr;)
7732-
node->tailCallInfo = nullptr;
7733-
node->gtRetClsHnd = nullptr;
7734-
node->gtControlExpr = nullptr;
7735-
node->gtCallMoreFlags = GTF_CALL_M_EMPTY;
7739+
node->tailCallInfo = nullptr;
7740+
node->gtRetClsHnd = nullptr;
7741+
node->gtControlExpr = nullptr;
7742+
node->gtCallMoreFlags = GTF_CALL_M_EMPTY;
7743+
node->gtInlineInfoCount = 0;
77367744

77377745
if (callType == CT_INDIRECT)
77387746
{
@@ -12353,10 +12361,11 @@ void Compiler::gtDispTree(GenTree* tree,
1235312361
printf(" (FramesRoot last use)");
1235412362
}
1235512363

12356-
if (((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0) && (call->GetInlineCandidateInfo() != nullptr) &&
12357-
(call->GetInlineCandidateInfo()->exactContextHnd != nullptr))
12364+
if (((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0) &&
12365+
(call->GetSingleInlineCandidateInfo() != nullptr) &&
12366+
(call->GetSingleInlineCandidateInfo()->exactContextHnd != nullptr))
1235812367
{
12359-
printf(" (exactContextHnd=0x%p)", dspPtr(call->GetInlineCandidateInfo()->exactContextHnd));
12368+
printf(" (exactContextHnd=0x%p)", dspPtr(call->GetSingleInlineCandidateInfo()->exactContextHnd));
1236012369
}
1236112370

1236212371
gtDispCommonEndLine(tree);
@@ -17871,7 +17880,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b
1787117880
// type class handle in the inline info (for GDV candidates,
1787217881
// this data is valid only for a correct guess, so we cannot
1787317882
// use it).
17874-
InlineCandidateInfo* inlInfo = call->GetInlineCandidateInfo();
17883+
InlineCandidateInfo* inlInfo = call->GetSingleInlineCandidateInfo();
1787517884
assert(inlInfo != nullptr);
1787617885

1787717886
// Grab it as our first cut at a return type.

src/coreclr/jit/gentree.h

+21-5
Original file line numberDiff line numberDiff line change
@@ -5425,20 +5425,36 @@ struct GenTreeCall final : public GenTree
54255425
return (gtCallMoreFlags & GTF_CALL_M_RETBUFFARG_LCLOPT) != 0;
54265426
}
54275427

5428-
InlineCandidateInfo* GetInlineCandidateInfo()
5428+
InlineCandidateInfo* GetSingleInlineCandidateInfo()
54295429
{
5430+
// gtInlineInfoCount can be 0 (not an inline candidate) or 1
5431+
if (gtInlineInfoCount == 0)
5432+
{
5433+
assert(!IsInlineCandidate());
5434+
assert(gtInlineCandidateInfo == nullptr);
5435+
return nullptr;
5436+
}
5437+
else if (gtInlineInfoCount > 1)
5438+
{
5439+
assert(!"Call has multiple inline candidates");
5440+
}
54305441
return gtInlineCandidateInfo;
54315442
}
54325443

5433-
void SetSingleInlineCadidateInfo(InlineCandidateInfo* candidateInfo);
5444+
void SetSingleInlineCandidateInfo(InlineCandidateInfo* candidateInfo);
54345445

5435-
InlineCandidateInfo* GetGDVCandidateInfo(uint8_t index = 0);
5446+
InlineCandidateInfo* GetGDVCandidateInfo(uint8_t index);
54365447

5437-
void AddGDVCandidateInfo(InlineCandidateInfo* candidateInfo);
5448+
void AddGDVCandidateInfo(Compiler* comp, InlineCandidateInfo* candidateInfo);
54385449

54395450
void ClearInlineInfo()
54405451
{
5441-
SetSingleInlineCadidateInfo(nullptr);
5452+
SetSingleInlineCandidateInfo(nullptr);
5453+
}
5454+
5455+
uint8_t GetInlineCandidatesCount()
5456+
{
5457+
return gtInlineInfoCount;
54425458
}
54435459

54445460
//-----------------------------------------------------------------------------------------

src/coreclr/jit/importer.cpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -1704,9 +1704,18 @@ bool Compiler::impSpillStackEntry(unsigned level,
17041704
if (tree->OperGet() == GT_RET_EXPR)
17051705
{
17061706
JITDUMP("\n*** see V%02u = GT_RET_EXPR, noting temp\n", tnum);
1707-
GenTree* call = tree->AsRetExpr()->gtInlineCandidate;
1708-
InlineCandidateInfo* ici = call->AsCall()->GetInlineCandidateInfo();
1709-
ici->preexistingSpillTemp = tnum;
1707+
GenTreeCall* call = tree->AsRetExpr()->gtInlineCandidate->AsCall();
1708+
if (call->IsGuardedDevirtualizationCandidate())
1709+
{
1710+
for (uint8_t i = 0; i < call->GetInlineCandidatesCount(); i++)
1711+
{
1712+
call->GetGDVCandidateInfo(i)->preexistingSpillTemp = tnum;
1713+
}
1714+
}
1715+
else
1716+
{
1717+
call->AsCall()->GetSingleInlineCandidateInfo()->preexistingSpillTemp = tnum;
1718+
}
17101719
}
17111720
}
17121721

0 commit comments

Comments
 (0)