diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 0c2e8a0e103e20..2cf1fc4708abea 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7526,7 +7526,8 @@ class Compiler CORINFO_CLASS_HANDLE* classGuesses, CORINFO_METHOD_HANDLE* methodGuesses, int* candidatesCount, - unsigned* likelihoods); + unsigned* likelihoods, + bool verboseLogging = true); void considerGuardedDevirtualization(GenTreeCall* call, IL_OFFSET ilOffset, diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 0dad8ba0b82562..9a0e9b6156930a 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -12995,6 +12995,20 @@ void Compiler::gtDispTree(GenTree* tree, } } + // Dump profile if any + if (call->IsHelperCall() && impIsCastHelperMayHaveProfileData(eeGetHelperNum(call->gtCallMethHnd))) + { + CORINFO_CLASS_HANDLE likelyClasses[MAX_GDV_TYPE_CHECKS] = {}; + unsigned likelyLikelihoods[MAX_GDV_TYPE_CHECKS] = {}; + int likelyClassCount = 0; + pickGDV(call, call->gtCastHelperILOffset, false, likelyClasses, nullptr, &likelyClassCount, + likelyLikelihoods, false); + if (likelyClassCount > 0) + { + printf(" (%d%% likely '%s')", likelyLikelihoods[0], eeGetClassName(likelyClasses[0])); + } + } + gtDispCommonEndLine(tree); if (!topOnly) diff --git a/src/coreclr/jit/helperexpansion.cpp b/src/coreclr/jit/helperexpansion.cpp index 87f3e7b67d7fc5..c4f8f91492eb96 100644 --- a/src/coreclr/jit/helperexpansion.cpp +++ b/src/coreclr/jit/helperexpansion.cpp @@ -1942,10 +1942,6 @@ enum class TypeCheckPassedAction CallHelper_AlwaysThrows, }; -// Some arbitrary limit on the number of guesses we can make -// The actual number of guesses is usually much smaller -#define MAX_CAST_GUESSES 8 - //------------------------------------------------------------------------------ // PickCandidatesForTypeCheck: picks classes to use as fast type checks against // the object being casted. The function also defines the strategy to follow @@ -1954,7 +1950,7 @@ enum class TypeCheckPassedAction // Arguments: // comp - Compiler instance // castHelper - Cast helper call to expand -// candidates - [out] Classes (guesses) to use in the fast path (up to MAX_CAST_GUESSES) +// candidates - [out] Classes (guesses) to use in the fast path (up to MAX_GDV_TYPE_CHECKS) // commonCls - [out] Common denominator class for the fast and the fallback paths. // likelihoods - [out] Likelihoods of successful type checks [0..100] // typeCheckFailed - [out] Action to perform if the type check fails @@ -2160,9 +2156,9 @@ static int PickCandidatesForTypeCheck(Compiler* comp, ///////////////////////////////////////////////////////////////////////////////////////////////////// // Let's re-use GDV's threshold on how many guesses we can make (can be 3 by default). - const int maxTypeChecks = min(comp->getGDVMaxTypeChecks(), MAX_CAST_GUESSES); + const int maxTypeChecks = min(comp->getGDVMaxTypeChecks(), MAX_GDV_TYPE_CHECKS); - CORINFO_CLASS_HANDLE exactClasses[MAX_CAST_GUESSES] = {}; + CORINFO_CLASS_HANDLE exactClasses[MAX_GDV_TYPE_CHECKS] = {}; const int numExactClasses = comp->info.compCompHnd->getExactClasses(castToCls, maxTypeChecks, exactClasses); bool allTrulyExact = true; for (int i = 0; i < numExactClasses; i++) @@ -2234,9 +2230,9 @@ static int PickCandidatesForTypeCheck(Compiler* comp, // 3) Consult with PGO data ///////////////////////////////////////////////////////////////////////////////////////////////////// - CORINFO_CLASS_HANDLE likelyClasses[MAX_CAST_GUESSES] = {}; - unsigned likelyLikelihoods[MAX_CAST_GUESSES] = {}; - int likelyClassCount = 0; + CORINFO_CLASS_HANDLE likelyClasses[MAX_GDV_TYPE_CHECKS] = {}; + unsigned likelyLikelihoods[MAX_GDV_TYPE_CHECKS] = {}; + int likelyClassCount = 0; comp->pickGDV(castHelper, castHelper->gtCastHelperILOffset, false, likelyClasses, nullptr, &likelyClassCount, likelyLikelihoods); @@ -2364,8 +2360,8 @@ bool Compiler::fgLateCastExpansionForCall(BasicBlock** pBlock, Statement* stmt, TypeCheckFailedAction typeCheckFailedAction; TypeCheckPassedAction typeCheckPassedAction; CORINFO_CLASS_HANDLE commonCls; - CORINFO_CLASS_HANDLE expectedExactClasses[MAX_CAST_GUESSES] = {}; - unsigned likelihoods[MAX_CAST_GUESSES] = {}; + CORINFO_CLASS_HANDLE expectedExactClasses[MAX_GDV_TYPE_CHECKS] = {}; + unsigned likelihoods[MAX_GDV_TYPE_CHECKS] = {}; const int numOfCandidates = PickCandidatesForTypeCheck(this, call, expectedExactClasses, &commonCls, likelihoods, &typeCheckFailedAction, &typeCheckPassedAction); @@ -2450,8 +2446,8 @@ bool Compiler::fgLateCastExpansionForCall(BasicBlock** pBlock, Statement* stmt, // Block 2: typeCheckBb(s) // TODO-InlineCast: if likelyCls == expectedCls we can consider saving to a local to re-use. - BasicBlock* typeChecksBbs[MAX_CAST_GUESSES] = {}; - BasicBlock* lastTypeCheckBb = nullcheckBb; + BasicBlock* typeChecksBbs[MAX_GDV_TYPE_CHECKS] = {}; + BasicBlock* lastTypeCheckBb = nullcheckBb; for (int candidateId = 0; candidateId < numOfCandidates; candidateId++) { const CORINFO_CLASS_HANDLE expectedCls = expectedExactClasses[candidateId]; diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 1f4438ede7e143..dcbb58816c6bef 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -6750,6 +6750,7 @@ void Compiler::addFatPointerCandidate(GenTreeCall* call) // methodGuesses - [out] the methods to guess for (mutually exclusive with classGuess) // candidatesCount - [out] number of guesses // likelihoods - [out] estimates of the likelihoods that the guesses will succeed +// verboseLogging - whether or not to do verbose logging // void Compiler::pickGDV(GenTreeCall* call, IL_OFFSET ilOffset, @@ -6757,7 +6758,8 @@ void Compiler::pickGDV(GenTreeCall* call, CORINFO_CLASS_HANDLE* classGuesses, CORINFO_METHOD_HANDLE* methodGuesses, int* candidatesCount, - unsigned* likelihoods) + unsigned* likelihoods, + bool verboseLogging) { *candidatesCount = 0; @@ -6789,12 +6791,15 @@ void Compiler::pickGDV(GenTreeCall* call, if ((numberOfClasses < 1) && (numberOfMethods < 1)) { - JITDUMP("No likely class or method, sorry\n"); + if (verboseLogging) + { + JITDUMP("No likely class or method, sorry\n"); + } return; } #ifdef DEBUG - if ((verbose || JitConfig.EnableExtraSuperPmiQueries()) && (numberOfClasses > 0)) + if ((verbose || JitConfig.EnableExtraSuperPmiQueries()) && (numberOfClasses > 0) && verboseLogging) { JITDUMP("Likely classes for call [%06u]", dspTreeID(call)); if (!call->IsHelperCall()) @@ -6964,8 +6969,12 @@ void Compiler::pickGDV(GenTreeCall* call, classGuesses[guessIdx] = (CORINFO_CLASS_HANDLE)likelyClasses[guessIdx].handle; likelihoods[guessIdx] = likelyClasses[guessIdx].likelihood; *candidatesCount = *candidatesCount + 1; - JITDUMP("Accepting type %s with likelihood %u as a candidate\n", eeGetClassName(classGuesses[guessIdx]), - likelihoods[guessIdx]) + + if (verboseLogging) + { + JITDUMP("Accepting type %s with likelihood %u as a candidate\n", + eeGetClassName(classGuesses[guessIdx]), likelihoods[guessIdx]) + } } else { @@ -6988,8 +6997,11 @@ void Compiler::pickGDV(GenTreeCall* call, return; } - JITDUMP("Not guessing for method; likelihood is below %s call threshold %u\n", - call->IsDelegateInvoke() ? "delegate" : "virtual", likelihoodThreshold); + if (verboseLogging) + { + JITDUMP("Not guessing for method; likelihood is below %s call threshold %u\n", + call->IsDelegateInvoke() ? "delegate" : "virtual", likelihoodThreshold); + } } }