void LegacyPolicy::NoteInt(InlineObservation obs, int value) { switch (obs) { case InlineObservation::CALLEE_MAXSTACK: { assert(m_IsForceInlineKnown); unsigned calleeMaxStack = static_cast<unsigned>(value); if (!m_IsForceInline && (calleeMaxStack > SMALL_STACK_SIZE)) { SetNever(InlineObservation::CALLEE_MAXSTACK_TOO_BIG); } break; } case InlineObservation::CALLEE_NUMBER_OF_BASIC_BLOCKS: { assert(m_IsForceInlineKnown); assert(value != 0); unsigned basicBlockCount = static_cast<unsigned>(value); if (!m_IsForceInline && (basicBlockCount > MAX_BASIC_BLOCKS)) { SetNever(InlineObservation::CALLEE_TOO_MANY_BASIC_BLOCKS); } break; } case InlineObservation::CALLEE_IL_CODE_SIZE: { assert(m_IsForceInlineKnown); assert(value != 0); m_CodeSize = static_cast<unsigned>(value); // Now that we know size and forceinline state, // update candidacy. if (m_CodeSize <= ALWAYS_INLINE_SIZE) { // Candidate based on small size SetCandidate(InlineObservation::CALLEE_BELOW_ALWAYS_INLINE_SIZE); } else if (m_IsForceInline) { // Candidate based on force inline SetCandidate(InlineObservation::CALLEE_IS_FORCE_INLINE); } else if (m_CodeSize <= m_Compiler->getImpInlineSize()) { // Candidate, pending profitability evaluation SetCandidate(InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE); } else { // Callee too big, not a candidate SetNever(InlineObservation::CALLEE_TOO_MUCH_IL); } break; } case InlineObservation::CALLEE_OPCODE_NORMED: case InlineObservation::CALLEE_OPCODE: { if (m_StateMachine != nullptr) { OPCODE opcode = static_cast<OPCODE>(value); SM_OPCODE smOpcode = CodeSeqSM::MapToSMOpcode(opcode); noway_assert(smOpcode < SM_COUNT); noway_assert(smOpcode != SM_PREFIX_N); if (obs == InlineObservation::CALLEE_OPCODE_NORMED) { if (smOpcode == SM_LDARGA_S) { smOpcode = SM_LDARGA_S_NORMED; } else if (smOpcode == SM_LDLOCA_S) { smOpcode = SM_LDLOCA_S_NORMED; } } m_StateMachine->Run(smOpcode DEBUGARG(0)); } break; } case InlineObservation::CALLSITE_FREQUENCY: assert(m_CallsiteFrequency == InlineCallsiteFrequency::UNUSED); m_CallsiteFrequency = static_cast<InlineCallsiteFrequency>(value); assert(m_CallsiteFrequency != InlineCallsiteFrequency::UNUSED); break; default: // Ignore all other information break; } }
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); } } }