Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4597,7 +4597,7 @@ class Compiler
CORINFO_LOOKUP_KIND* pGenericLookupKind = nullptr);

bool impIsCastHelperEligibleForClassProbe(GenTree* tree);
bool impIsCastHelperMayHaveProfileData(GenTree* tree);
bool impIsCastHelperMayHaveProfileData(CorInfoHelpFunc helper);

GenTree* impCastClassOrIsInstToTree(
GenTree* op1, GenTree* op2, CORINFO_RESOLVED_TOKEN* pResolvedToken, bool isCastClass, IL_OFFSET ilOffset);
Expand Down
56 changes: 44 additions & 12 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2141,21 +2141,17 @@ bool Compiler::impIsCastHelperEligibleForClassProbe(GenTree* tree)
// Returns:
// true if the tree is a cast helper with potential profile data
//
bool Compiler::impIsCastHelperMayHaveProfileData(GenTree* tree)
bool Compiler::impIsCastHelperMayHaveProfileData(CorInfoHelpFunc helper)
{
if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBOPT) || (JitConfig.JitCastProfiling() != 1))
if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBOPT))
{
return false;
}

if (tree->IsCall() && tree->AsCall()->gtCallType == CT_HELPER)
if ((helper == CORINFO_HELP_ISINSTANCEOFINTERFACE) || (helper == CORINFO_HELP_ISINSTANCEOFCLASS) ||
(helper == CORINFO_HELP_CHKCASTCLASS) || (helper == CORINFO_HELP_CHKCASTINTERFACE))
{
const CorInfoHelpFunc helper = eeGetHelperNum(tree->AsCall()->gtCallMethHnd);
if ((helper == CORINFO_HELP_ISINSTANCEOFINTERFACE) || (helper == CORINFO_HELP_ISINSTANCEOFCLASS) ||
(helper == CORINFO_HELP_CHKCASTCLASS) || (helper == CORINFO_HELP_CHKCASTINTERFACE))
{
return true;
}
return true;
}
return false;
}
Expand Down Expand Up @@ -11561,8 +11557,11 @@ GenTree* Compiler::impCastClassOrIsInstToTree(

// Pessimistically assume the jit cannot expand this as an inline test
bool canExpandInline = false;
bool partialExpand = false;
const CorInfoHelpFunc helper = info.compCompHnd->getCastingHelper(pResolvedToken, isCastClass);

GenTree* exactCls = nullptr;

// Legality check.
//
// Not all classclass/isinst operations can be inline expanded.
Expand All @@ -11582,6 +11581,34 @@ GenTree* Compiler::impCastClassOrIsInstToTree(
canExpandInline = impIsClassExact(pResolvedToken->hClass);
}
}

// Check if this cast helper have some profile data
if (impIsCastHelperMayHaveProfileData(helper))
{
LikelyClassRecord likelyClass[1]; // multiple guesses aren't yet supported
if (getLikelyClasses(likelyClass, 1, fgPgoSchema, fgPgoSchemaCount, fgPgoData, ilOffset) > 0)
{
assert(likelyClass != nullptr);
CORINFO_CLASS_HANDLE likelyCls = likelyClass->clsHandle;

if ((likelyCls != NO_CLASS_HANDLE) &&
(likelyClass->likelihood > (UINT32)JitConfig.JitGuardedDevirtualizationChainLikelihood()))
{
if ((info.compCompHnd->compareTypesForCast(likelyCls, pResolvedToken->hClass) ==
TypeCompareState::Must))
{
assert((info.compCompHnd->getClassAttribs(likelyCls) &
(CORINFO_FLG_INTERFACE | CORINFO_FLG_ABSTRACT)) == 0);
JITDUMP("Adding \"is %s (%X)\" check as a fast path for %s using PGO data.\n",
eeGetClassName(likelyCls), likelyCls, isCastClass ? "castclass" : "isinst");

canExpandInline = true;
partialExpand = true;
exactCls = gtNewIconEmbClsHndNode(likelyCls);
}
}
}
}
}

const bool expandInline = canExpandInline && shouldExpandInline;
Expand Down Expand Up @@ -11633,13 +11660,13 @@ GenTree* Compiler::impCastClassOrIsInstToTree(
//

GenTree* op2Var = op2;
if (isCastClass)
if (isCastClass && !partialExpand)
{
op2Var = fgInsertCommaFormTemp(&op2);
lvaTable[op2Var->AsLclVarCommon()->GetLclNum()].lvIsCSE = true;
}
temp = gtNewMethodTableLookup(temp);
condMT = gtNewOperNode(GT_NE, TYP_INT, temp, op2);
condMT = gtNewOperNode(GT_NE, TYP_INT, temp, exactCls != nullptr ? exactCls : op2);

GenTree* condNull;
//
Expand All @@ -11664,7 +11691,12 @@ GenTree* Compiler::impCastClassOrIsInstToTree(
//
const CorInfoHelpFunc specialHelper = CORINFO_HELP_CHKCASTCLASS_SPECIAL;

condTrue = gtNewHelperCallNode(specialHelper, TYP_REF, gtNewCallArgs(op2Var, gtClone(op1)));
condTrue =
gtNewHelperCallNode(specialHelper, TYP_REF, gtNewCallArgs(partialExpand ? op2 : op2Var, gtClone(op1)));
}
else if (partialExpand)
{
condTrue = gtNewHelperCallNode(helper, TYP_REF, gtNewCallArgs(op2, gtClone(op1)));
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/jitconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ CONFIG_STRING(JitEnablePatchpointRange, W("JitEnablePatchpointRange"))
// Profile instrumentation options
CONFIG_INTEGER(JitMinimalJitProfiling, W("JitMinimalJitProfiling"), 1)
CONFIG_INTEGER(JitMinimalPrejitProfiling, W("JitMinimalPrejitProfiling"), 0)
CONFIG_INTEGER(JitCastProfiling, W("JitCastProfiling"), 0) // Profile castclass and isinst
CONFIG_INTEGER(JitCastProfiling, W("JitCastProfiling"), 1) // CI test, will disable it back
CONFIG_INTEGER(JitClassProfiling, W("JitClassProfiling"), 1) // Profile virtual and interface calls
CONFIG_INTEGER(JitEdgeProfiling, W("JitEdgeProfiling"), 1) // Profile edges instead of blocks
CONFIG_INTEGER(JitCollect64BitCounts, W("JitCollect64BitCounts"), 0) // Collect counts as 64-bit values.
Expand Down