Skip to content

Commit

Permalink
Clean up GenTreeCall's inline info (#86540)
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorBo committed May 20, 2023
1 parent e7e9dbd commit d7aa91c
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 66 deletions.
6 changes: 3 additions & 3 deletions src/coreclr/jit/fginline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ void Compiler::fgMorphCallInline(GenTreeCall* call, InlineResult* inlineResult)
{
bool inliningFailed = false;

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

// Is this call an inline candidate?
if (call->IsInlineCandidate())
Expand All @@ -778,7 +778,7 @@ 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->gtInlineCandidateInfo->inlinersContext, fgMorphStmt, call);
m_inlineStrategy->NewContext(call->GetInlineCandidateInfo()->inlinersContext, fgMorphStmt, call);
ctx->SetFailed(inlineResult);
#endif
}
Expand Down Expand Up @@ -1045,7 +1045,7 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineRe
inlineInfo.hasSIMDTypeArgLocalOrReturn = false;
#endif // FEATURE_SIMD

InlineCandidateInfo* inlineCandidateInfo = call->gtInlineCandidateInfo;
InlineCandidateInfo* inlineCandidateInfo = call->GetInlineCandidateInfo();
noway_assert(inlineCandidateInfo);
// Store the link to inlineCandidateInfo into inlineInfo
inlineInfo.inlineCandidateInfo = inlineCandidateInfo;
Expand Down
69 changes: 64 additions & 5 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2179,6 +2179,64 @@ GenTree* Compiler::getArrayLengthFromAllocation(GenTree* tree DEBUGARG(BasicBloc
return arrayLength;
}

//-------------------------------------------------------------------------
// SetSingleInlineCadidateInfo: set a single inline candidate info in the current call.
//
// Arguments:
// candidateInfo - inline candidate info
//
void GenTreeCall::SetSingleInlineCadidateInfo(InlineCandidateInfo* candidateInfo)
{
if (candidateInfo != nullptr)
{
gtFlags |= GTF_CALL_INLINE_CANDIDATE;
gtInlineInfoCount = 1;
}
else
{
gtInlineInfoCount = 0;
gtFlags &= ~GTF_CALL_INLINE_CANDIDATE;
gtCallMoreFlags &= ~GTF_CALL_M_GUARDED_DEVIRT;
}
gtInlineCandidateInfo = candidateInfo;
}

//-------------------------------------------------------------------------
// GetGDVCandidateInfo: Get GDV candidate info in the current call by index.
//
// Return Value:
// GDV candidate info
//
InlineCandidateInfo* GenTreeCall::GetGDVCandidateInfo(uint8_t index)
{
assert(index < gtInlineInfoCount);
return &gtInlineCandidateInfo[index];
}

//-------------------------------------------------------------------------
// AddGDVCandidateInfo: Record a guarded devirtualization (GDV) candidate info
// for this call. For now, we only support one GDV candidate per call.
//
// Arguments:
// candidateInfo - GDV candidate info
//
void GenTreeCall::AddGDVCandidateInfo(InlineCandidateInfo* candidateInfo)
{
assert(candidateInfo != nullptr);
if (gtInlineInfoCount == 0)
{
gtInlineCandidateInfo = candidateInfo;
}
else
{
// Allocate a fixed list of InlineCandidateInfo structs
assert(!"multiple GDV candidates are not implemented yet");
}

gtCallMoreFlags |= GTF_CALL_M_GUARDED_DEVIRT;
gtInlineInfoCount++;
}

//-------------------------------------------------------------------------
// HasSideEffects:
// Returns true if this call has any side effects. All non-helpers are considered to have side-effects. Only helpers
Expand Down Expand Up @@ -7758,7 +7816,7 @@ GenTreeCall* Compiler::gtNewCallNode(gtCallTypes callType,
}
else
{
node->gtInlineCandidateInfo = nullptr;
node->ClearInlineInfo();
}
node->gtReturnType = type;

Expand Down Expand Up @@ -9409,6 +9467,7 @@ GenTreeCall* Compiler::gtCloneExprCallHelper(GenTreeCall* tree,
{
copy->gtCallMethHnd = tree->gtCallMethHnd;
copy->gtInlineCandidateInfo = tree->gtInlineCandidateInfo;
copy->gtInlineInfoCount = tree->gtInlineInfoCount;
}

copy->gtCallType = tree->gtCallType;
Expand Down Expand Up @@ -12419,10 +12478,10 @@ void Compiler::gtDispTree(GenTree* tree,
printf(" (FramesRoot last use)");
}

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

gtDispCommonEndLine(tree);
Expand Down Expand Up @@ -17991,7 +18050,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->gtInlineCandidateInfo;
InlineCandidateInfo* inlInfo = call->GetInlineCandidateInfo();
assert(inlInfo != nullptr);

// Grab it as our first cut at a return type.
Expand Down
40 changes: 26 additions & 14 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ enum TargetHandleType : BYTE
struct BasicBlock;
enum BasicBlockFlags : unsigned __int64;
struct InlineCandidateInfo;
struct GuardedDevirtualizationCandidateInfo;
struct HandleHistogramProfileCandidateInfo;
struct LateDevirtualizationInfo;

Expand Down Expand Up @@ -5375,11 +5374,6 @@ struct GenTreeCall final : public GenTree
gtCallMoreFlags &= ~GTF_CALL_M_GUARDED_DEVIRT;
}

void SetGuardedDevirtualizationCandidate()
{
gtCallMoreFlags |= GTF_CALL_M_GUARDED_DEVIRT;
}

void SetIsGuarded()
{
gtCallMoreFlags |= GTF_CALL_M_GUARDED;
Expand Down Expand Up @@ -5435,6 +5429,22 @@ struct GenTreeCall final : public GenTree
return (gtCallMoreFlags & GTF_CALL_M_RETBUFFARG_LCLOPT) != 0;
}

InlineCandidateInfo* GetInlineCandidateInfo()
{
return gtInlineCandidateInfo;
}

void SetSingleInlineCadidateInfo(InlineCandidateInfo* candidateInfo);

InlineCandidateInfo* GetGDVCandidateInfo(uint8_t index = 0);

void AddGDVCandidateInfo(InlineCandidateInfo* candidateInfo);

void ClearInlineInfo()
{
SetSingleInlineCadidateInfo(nullptr);
}

//-----------------------------------------------------------------------------------------
// GetIndirectionCellArgKind: Get the kind of indirection cell used by this call.
//
Expand Down Expand Up @@ -5505,10 +5515,13 @@ struct GenTreeCall final : public GenTree
return mayUseDispatcher && shouldUseDispatcher ? CFGCallKind::Dispatch : CFGCallKind::ValidateAndCall;
}

GenTreeCallFlags gtCallMoreFlags; // in addition to gtFlags
gtCallTypes gtCallType : 3; // value from the gtCallTypes enumeration
var_types gtReturnType : 5; // exact return type
CORINFO_CLASS_HANDLE gtRetClsHnd; // The return type handle of the call if it is a struct; always available
GenTreeCallFlags gtCallMoreFlags; // in addition to gtFlags
gtCallTypes gtCallType : 3; // value from the gtCallTypes enumeration
var_types gtReturnType : 5; // exact return type

uint8_t gtInlineInfoCount; // number of inline candidates for the given call

CORINFO_CLASS_HANDLE gtRetClsHnd; // The return type handle of the call if it is a struct; always available
union {
void* gtStubCallStubAddr; // GTF_CALL_VIRT_STUB - these are never inlined
CORINFO_CLASS_HANDLE gtInitClsHnd; // Used by static init helpers, represents a class they init
Expand All @@ -5518,10 +5531,9 @@ struct GenTreeCall final : public GenTree
// only used for CALLI unmanaged calls (CT_INDIRECT)
GenTree* gtCallCookie;
// gtInlineCandidateInfo is only used when inlining methods
InlineCandidateInfo* gtInlineCandidateInfo;
GuardedDevirtualizationCandidateInfo* gtGuardedDevirtualizationCandidateInfo;
HandleHistogramProfileCandidateInfo* gtHandleHistogramProfileCandidateInfo;
LateDevirtualizationInfo* gtLateDevirtualizationInfo;
InlineCandidateInfo* gtInlineCandidateInfo;
HandleHistogramProfileCandidateInfo* gtHandleHistogramProfileCandidateInfo;
LateDevirtualizationInfo* gtLateDevirtualizationInfo;
CORINFO_GENERIC_HANDLE compileTimeHelperArgumentHandle; // Used to track type handle argument of dynamic helpers
void* gtDirectCallAddress; // Used to pass direct call address between lower and codegen
};
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1702,7 +1702,7 @@ bool Compiler::impSpillStackEntry(unsigned level,
{
JITDUMP("\n*** see V%02u = GT_RET_EXPR, noting temp\n", tnum);
GenTree* call = tree->AsRetExpr()->gtInlineCandidate;
InlineCandidateInfo* ici = call->AsCall()->gtInlineCandidateInfo;
InlineCandidateInfo* ici = call->AsCall()->GetInlineCandidateInfo();
ici->preexistingSpillTemp = tnum;
}
}
Expand Down
24 changes: 10 additions & 14 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ var_types Compiler::impImportCall(OPCODE opcode,
GenTreeRetExpr* retExpr = gtNewInlineCandidateReturnExpr(call->AsCall(), genActualType(callRetTyp));

// Link the retExpr to the call so if necessary we can manipulate it later.
origCall->gtInlineCandidateInfo->retExpr = retExpr;
origCall->GetInlineCandidateInfo()->retExpr = retExpr;

// Propagate retExpr as the placeholder for the call.
call = retExpr;
Expand Down Expand Up @@ -6059,7 +6059,6 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call,
classHandle != NO_CLASS_HANDLE ? "class" : "method",
classHandle != NO_CLASS_HANDLE ? eeGetClassName(classHandle) : eeGetMethodFullName(methodHandle));
setMethodHasGuardedDevirtualization();
call->SetGuardedDevirtualizationCandidate();

// Spill off any GT_RET_EXPR subtrees so we can clone the call.
//
Expand All @@ -6069,7 +6068,7 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call,
// Gather some information for later. Note we actually allocate InlineCandidateInfo
// here, as the devirtualized half of this call will likely become an inline candidate.
//
GuardedDevirtualizationCandidateInfo* pInfo = new (this, CMK_Inlining) InlineCandidateInfo;
InlineCandidateInfo* pInfo = new (this, CMK_Inlining) InlineCandidateInfo;

pInfo->guardedMethodHandle = methodHandle;
pInfo->guardedMethodUnboxedEntryHandle = nullptr;
Expand All @@ -6094,7 +6093,7 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call,
}
}

call->gtGuardedDevirtualizationCandidateInfo = pInfo;
call->AddGDVCandidateInfo(pInfo);
}

//------------------------------------------------------------------------
Expand Down Expand Up @@ -6270,13 +6269,13 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call,

if (call->IsGuardedDevirtualizationCandidate())
{
if (call->gtGuardedDevirtualizationCandidateInfo->guardedMethodUnboxedEntryHandle != nullptr)
if (call->GetGDVCandidateInfo()->guardedMethodUnboxedEntryHandle != nullptr)
{
fncHandle = call->gtGuardedDevirtualizationCandidateInfo->guardedMethodUnboxedEntryHandle;
fncHandle = call->GetGDVCandidateInfo()->guardedMethodUnboxedEntryHandle;
}
else
{
fncHandle = call->gtGuardedDevirtualizationCandidateInfo->guardedMethodHandle;
fncHandle = call->GetGDVCandidateInfo()->guardedMethodHandle;
}
methAttr = info.compCompHnd->getMethodAttribs(fncHandle);
}
Expand Down Expand Up @@ -6377,13 +6376,13 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call,
}

// The old value should be null OR this call should be a guarded devirtualization candidate.
assert((call->gtInlineCandidateInfo == nullptr) || call->IsGuardedDevirtualizationCandidate());
assert((call->GetInlineCandidateInfo() == nullptr) || call->IsGuardedDevirtualizationCandidate());

// The new value should not be null.
assert(inlineCandidateInfo != nullptr);
inlineCandidateInfo->exactContextNeedsRuntimeLookup = exactContextNeedsRuntimeLookup;
inlineCandidateInfo->ilOffset = ilOffset;
call->gtInlineCandidateInfo = inlineCandidateInfo;
call->SetSingleInlineCadidateInfo(inlineCandidateInfo);

// If we're in an inlinee compiler, and have a return spill temp, and this inline candidate
// is also a tail call candidate, it can use the same return spill temp.
Expand All @@ -6396,9 +6395,6 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call,
inlineCandidateInfo->preexistingSpillTemp);
}

// Mark the call node as inline candidate.
call->gtFlags |= GTF_CALL_INLINE_CANDIDATE;

// Let the strategy know there's another candidate.
impInlineRoot()->m_inlineStrategy->NoteCandidate();

Expand Down Expand Up @@ -6895,7 +6891,7 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call,
// Clear the inline candidate info (may be non-null since
// it's a union field used for other things by virtual
// stubs)
call->gtInlineCandidateInfo = nullptr;
call->ClearInlineInfo();
call->gtCallMoreFlags &= ~GTF_CALL_M_HAS_LATE_DEVIRT_INFO;

#if defined(DEBUG)
Expand Down Expand Up @@ -7675,7 +7671,7 @@ void Compiler::impCheckCanInline(GenTreeCall* call,

if (pParam->call->IsGuardedDevirtualizationCandidate())
{
pInfo = pParam->call->gtInlineCandidateInfo;
pInfo = pParam->call->GetInlineCandidateInfo();
}
else
{
Expand Down
18 changes: 9 additions & 9 deletions src/coreclr/jit/indirectcalltransformer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ class IndirectCallTransformer
return;
}

likelihood = origCall->gtGuardedDevirtualizationCandidateInfo->likelihood;
likelihood = origCall->GetGDVCandidateInfo()->likelihood;
assert((likelihood >= 0) && (likelihood <= 100));
JITDUMP("Likelihood of correct guess is %u\n", likelihood);

Expand Down Expand Up @@ -574,7 +574,7 @@ class IndirectCallTransformer
//
lastStmt = checkBlock->lastStmt();

GuardedDevirtualizationCandidateInfo* guardedInfo = origCall->gtGuardedDevirtualizationCandidateInfo;
InlineCandidateInfo* guardedInfo = origCall->GetGDVCandidateInfo();

// Create comparison. On success we will jump to do the indirect call.
GenTree* compare;
Expand Down Expand Up @@ -655,7 +655,7 @@ class IndirectCallTransformer
//
// Note implicit by-ref returns should have already been converted
// so any struct copy we induce here should be cheap.
InlineCandidateInfo* const inlineInfo = origCall->gtInlineCandidateInfo;
InlineCandidateInfo* const inlineInfo = origCall->GetInlineCandidateInfo();

if (!origCall->TypeIs(TYP_VOID))
{
Expand Down Expand Up @@ -736,7 +736,7 @@ class IndirectCallTransformer
{
thenBlock = CreateAndInsertBasicBlock(BBJ_ALWAYS, checkBlock);
thenBlock->bbFlags |= currBlock->bbFlags & BBF_SPLIT_GAINED;
InlineCandidateInfo* inlineInfo = origCall->gtInlineCandidateInfo;
InlineCandidateInfo* inlineInfo = origCall->GetInlineCandidateInfo();
CORINFO_CLASS_HANDLE clsHnd = inlineInfo->guardedClassHandle;

//
Expand Down Expand Up @@ -840,7 +840,7 @@ class IndirectCallTransformer
"inlineable\n");

call->gtFlags &= ~GTF_CALL_INLINE_CANDIDATE;
call->gtInlineCandidateInfo = nullptr;
call->ClearInlineInfo();

if (returnTemp != BAD_VAR_NUM)
{
Expand All @@ -864,7 +864,7 @@ class IndirectCallTransformer
inlineInfo->clsHandle = compiler->info.compCompHnd->getMethodClass(methodHnd);
inlineInfo->exactContextHnd = context;
inlineInfo->preexistingSpillTemp = returnTemp;
call->gtInlineCandidateInfo = inlineInfo;
call->SetSingleInlineCadidateInfo(inlineInfo);

// If there was a ret expr for this call, we need to create a new one
// and append it just after the call.
Expand Down Expand Up @@ -1092,11 +1092,11 @@ class IndirectCallTransformer
GenTreeCall* const call = root->AsCall();

if (call->IsGuardedDevirtualizationCandidate() &&
(call->gtGuardedDevirtualizationCandidateInfo->likelihood >= gdvChainLikelihood))
(call->GetGDVCandidateInfo()->likelihood >= gdvChainLikelihood))
{
JITDUMP("GDV call at [%06u] has likelihood %u >= %u; chaining (%u stmts, %u nodes to dup).\n",
compiler->dspTreeID(call), call->gtGuardedDevirtualizationCandidateInfo->likelihood,
gdvChainLikelihood, chainStatementDup, chainNodeDup);
compiler->dspTreeID(call), call->GetGDVCandidateInfo()->likelihood, gdvChainLikelihood,
chainStatementDup, chainNodeDup);

call->gtCallMoreFlags |= GTF_CALL_M_GUARDED_DEVIRT_CHAIN;
break;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/inline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1281,7 +1281,7 @@ InlineContext* InlineStrategy::NewContext(InlineContext* parentContext, Statemen

if (call->IsInlineCandidate())
{
InlineCandidateInfo* info = call->gtInlineCandidateInfo;
InlineCandidateInfo* info = call->GetInlineCandidateInfo();
context->m_Code = info->methInfo.ILCode;
context->m_ILSize = info->methInfo.ILCodeSize;
context->m_ActualCallOffset = info->ilOffset;
Expand Down
Loading

0 comments on commit d7aa91c

Please sign in to comment.