void InlineResult::report() { // User may have suppressed reporting via setReported(). If so, do nothing. if (inlReported) { return; } inlReported = true; #ifdef DEBUG // Optionally dump the result if (VERBOSE) { const char* format = "INLINER: during '%s' result '%s' reason '%s' for '%s' calling '%s'\n"; const char* caller = (inlCaller == nullptr) ? "n/a" : inlCompiler->eeGetMethodFullName(inlCaller); const char* callee = (inlCallee == nullptr) ? "n/a" : inlCompiler->eeGetMethodFullName(inlCallee); JITDUMP(format, inlContext, resultString(), reasonString(), caller, callee); } // If the inline failed, leave information on the call so we can // later recover what observation lead to the failure. if (isFailure() && (inlCall != nullptr)) { // compiler should have revoked candidacy on the call by now assert((inlCall->gtFlags & GTF_CALL_INLINE_CANDIDATE) == 0); inlCall->gtInlineObservation = static_cast<unsigned>(inlObservation); } #endif // DEBUG if (isDecided()) { const char* format = "INLINER: during '%s' result '%s' reason '%s'\n"; JITLOG_THIS(inlCompiler, (LL_INFO100000, format, inlContext, resultString(), reasonString())); COMP_HANDLE comp = inlCompiler->info.compCompHnd; comp->reportInliningDecision(inlCaller, inlCallee, result(), reasonString()); } }
void InlineResult::Report() { // If we weren't actually inlining, user may have suppressed // reporting via setReported(). If so, do nothing. if (m_Reported) { return; } m_Reported = true; #ifdef DEBUG const char* callee = nullptr; // Optionally dump the result if (VERBOSE) { const char* format = "INLINER: during '%s' result '%s' reason '%s' for '%s' calling '%s'\n"; const char* caller = (m_Caller == nullptr) ? "n/a" : m_RootCompiler->eeGetMethodFullName(m_Caller); callee = (m_Callee == nullptr) ? "n/a" : m_RootCompiler->eeGetMethodFullName(m_Callee); JITDUMP(format, m_Context, ResultString(), ReasonString(), caller, callee); } // If the inline failed, leave information on the call so we can // later recover what observation lead to the failure. if (IsFailure() && (m_Call != nullptr)) { // compiler should have revoked candidacy on the call by now assert((m_Call->gtFlags & GTF_CALL_INLINE_CANDIDATE) == 0); m_Call->gtInlineObservation = m_Policy->GetObservation(); } #endif // DEBUG // Was the result NEVER? If so we might want to propagate this to // the runtime. if (IsNever() && m_Policy->PropagateNeverToRuntime()) { // If we know the callee, and if the observation that got us // to this Never inline state is something *other* than // IS_NOINLINE, then we've uncovered a reason why this method // can't ever be inlined. Update the callee method attributes // so that future inline attempts for this callee fail faster. InlineObservation obs = m_Policy->GetObservation(); if ((m_Callee != nullptr) && (obs != InlineObservation::CALLEE_IS_NOINLINE)) { #ifdef DEBUG if (VERBOSE) { const char* obsString = InlGetObservationString(obs); JITDUMP("\nINLINER: Marking %s as NOINLINE because of %s\n", callee, obsString); } #endif // DEBUG COMP_HANDLE comp = m_RootCompiler->info.compCompHnd; comp->setMethodAttribs(m_Callee, CORINFO_FLG_BAD_INLINEE); } } if (IsDecided()) { const char* format = "INLINER: during '%s' result '%s' reason '%s'\n"; JITLOG_THIS(m_RootCompiler, (LL_INFO100000, format, m_Context, ResultString(), ReasonString())); COMP_HANDLE comp = m_RootCompiler->info.compCompHnd; comp->reportInliningDecision(m_Caller, m_Callee, Result(), ReasonString()); } }
void LegacyPolicy::DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) { assert(InlDecisionIsCandidate(m_Decision)); assert(m_Observation == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE); const int calleeNativeSizeEstimate = DetermineNativeSizeEstimate(); const int callsiteNativeSizeEstimate = DetermineCallsiteNativeSizeEstimate(methodInfo); const double multiplier = DetermineMultiplier(); const int threshold = (int)(callsiteNativeSizeEstimate * multiplier); JITDUMP("calleeNativeSizeEstimate=%d\n", calleeNativeSizeEstimate) JITDUMP("callsiteNativeSizeEstimate=%d\n", callsiteNativeSizeEstimate); JITDUMP("benefit multiplier=%g\n", multiplier); JITDUMP("threshold=%d\n", threshold); #if DEBUG // Size estimates are in bytes * 10 const double sizeDescaler = 10.0; #endif // Reject if callee size is over the threshold if (calleeNativeSizeEstimate > threshold) { // Inline appears to be unprofitable JITLOG_THIS(m_Compiler, (LL_INFO100000, "Native estimate for function size exceedsn threshold" " for inlining %g > %g (multiplier = %g)\n", calleeNativeSizeEstimate / sizeDescaler, threshold / sizeDescaler, multiplier)); // Fail the inline if (m_IsPrejitRoot) { SetNever(InlineObservation::CALLEE_NOT_PROFITABLE_INLINE); } else { SetFailure(InlineObservation::CALLSITE_NOT_PROFITABLE_INLINE); } } else { // Inline appears to be profitable JITLOG_THIS(m_Compiler, (LL_INFO100000, "Native estimate for function size is within threshold" " for inlining %g <= %g (multiplier = %g)\n", calleeNativeSizeEstimate / sizeDescaler, threshold / sizeDescaler, multiplier)); // Update candidacy if (m_IsPrejitRoot) { SetCandidate(InlineObservation::CALLEE_IS_PROFITABLE_INLINE); } else { SetCandidate(InlineObservation::CALLSITE_IS_PROFITABLE_INLINE); } } }