Inline refactoring: move profitability assessment to LegacyPolicy
authorAndy Ayers <andya@microsoft.com>
Thu, 10 Mar 2016 00:04:11 +0000 (16:04 -0800)
committerAndy Ayers <andya@microsoft.com>
Thu, 10 Mar 2016 02:20:38 +0000 (18:20 -0800)
LegacyPolicy now encapsulates all the computations needed to evaluate
whether an inline is profitable or not.

This completes the main objective of the refactoring effort, which
was to preserve and encapsulate the current inliner's behavior.

src/jit/compiler.cpp
src/jit/compiler.h
src/jit/flowgraph.cpp
src/jit/importer.cpp
src/jit/inline.def
src/jit/inline.h
src/jit/inlinepolicy.cpp
src/jit/inlinepolicy.h

index a9fdc77..d32bf28 100644 (file)
@@ -1407,8 +1407,6 @@ void                Compiler::compInit(ArenaAllocator * pAlloc, InlineInfo * inl
 
     compMaxUncheckedOffsetForNullObject = MAX_UNCHECKED_OFFSET_FOR_NULL_OBJECT;
 
-    compNativeSizeEstimate = NATIVE_SIZE_INVALID;
-
     for (unsigned i = 0; i < MAX_LOOP_NUM; i++)
     {
         AllVarSetOps::AssignNoCopy(this, optLoopTable[i].lpAsgVars, AllVarSetOps::UninitVal());
@@ -4843,46 +4841,25 @@ int           Compiler::compCompileHelper (CORINFO_MODULE_HANDLE            clas
             // the code in fgFindJumpTargets references that data
             // member extensively.
             assert(compInlineResult == nullptr);
+            assert(impInlineInfo == nullptr);
             compInlineResult = &prejitResult;
 
             // Find the basic blocks. We must do this regardless of
             // inlineability, since we are prejitting this method.
             //
-            // Among other things, this will set compNativeSizeEstimate
-            // for the subset of methods we check below.
+            // This will also update the status of this method as
+            // an inline candidate.
             fgFindBasicBlocks();
 
             // Undo the temporary setup.
             assert(compInlineResult == &prejitResult);
             compInlineResult = nullptr;
 
-            // If this method is still a viable inline candidate,
-            // do the profitability screening.
-            if (prejitResult.IsCandidate())
-            {
-                // Only needed if the inline is discretionary.
-                InlineObservation obs = prejitResult.GetObservation();
-                if (obs == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE)
-                {
-                    // We should have run the CodeSeq state machine
-                    // and got the native size estimate.
-                    assert(compNativeSizeEstimate != NATIVE_SIZE_INVALID);
-
-                    // Estimate the call site impact
-                    int callsiteNativeSizeEstimate =
-                        prejitResult.DetermineCallsiteNativeSizeEstimate(methodInfo);
-
-                    // See if we're willing to pay for inlining this method
-                    impCanInlineNative(callsiteNativeSizeEstimate,
-                                       compNativeSizeEstimate,
-                                       nullptr, // Calculate static inlining hint.
-                                       &prejitResult);
-                }
-            }
-            else
+            // If still a viable, discretionary inline, assess
+            // profitability.
+            if (prejitResult.IsDiscretionaryCandidate())
             {
-                // If it's not a candidate, it should be a failure.
-                assert(prejitResult.IsFailure());
+                prejitResult.DetermineProfitability(methodInfo);
             }
 
             // Handle the results of the inline analysis.
index 125cba0..c7b97b0 100644 (file)
@@ -3108,10 +3108,8 @@ private:
 
     static BOOL         impIsAddressInLocal(GenTreePtr tree, GenTreePtr * lclVarTreeOut);
 
-    void                impCanInlineNative(int              callsiteNativeEstimate, 
-                                           int              calleeNativeSizeEstimate,
-                                           InlineInfo*      pInlineInfo,
-                                           InlineResult*    inlineResult);
+    void                impMakeDiscretionaryInlineObservations(InlineInfo*   pInlineInfo,
+                                                               InlineResult* inlineResult);
 
     // STATIC inlining decision based on the IL code. 
     void                impCanInlineIL(CORINFO_METHOD_HANDLE  fncHandle,
@@ -8569,10 +8567,6 @@ public:
                                                     // This can be overwritten by setting complus_JITInlineSize env variable.
 #define IMPLEMENTATION_MAX_INLINE_SIZE  _UI16_MAX   // Maximum method size supported by this implementation 
                                          
-#define NATIVE_SIZE_INVALID  (-10000)                
-
-    int                     compNativeSizeEstimate;     // The estimated native size of this method.
-
 private:
 #ifdef FEATURE_JIT_METHOD_PERF
     JitTimer*                     pCompJitTimer;           // Timer data structure (by phases) for current compilation.
index 5e7e713..32686dd 100644 (file)
@@ -4182,6 +4182,7 @@ private:
     unsigned slot1;
     unsigned depth;
 };
+
 //------------------------------------------------------------------------
 // fgFindJumpTargets: walk the IL stream, determining jump target offsets
 //
@@ -4782,46 +4783,39 @@ TOO_FAR:
     {
         compInlineResult->Note(InlineObservation::CALLEE_END_OPCODE_SCAN);
 
-        // If the inline is viable and discretionary, we need to get
-        // an estimate for the callee native code size.
-        if (compInlineResult->IsCandidate()
-            && (compInlineResult->GetObservation() == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE))
+        // If the inline is viable and discretionary, do the
+        // profitability screening.
+        if (compInlineResult->IsDiscretionaryCandidate())
         {
-            compNativeSizeEstimate = compInlineResult->DetermineNativeSizeEstimate();
-            noway_assert(compNativeSizeEstimate != NATIVE_SIZE_INVALID);
-            JITDUMP("\n\ncompNativeSizeEstimate=%d\n", compNativeSizeEstimate);
+            // Make some callsite specific observations that will feed
+            // into the profitability model.
+            impMakeDiscretionaryInlineObservations(impInlineInfo, compInlineResult);
+
+            // None of those observations should have changed the
+            // inline's viability.
+            assert(compInlineResult->IsCandidate());
 
-            // If we're inlining, use the size estimate to do further
-            // screening.
-            //
-            // If we're in the prejit-root case we do something
-            // similar as part of the prejit screen over in
-            // compCompileHelper.
             if (compIsForInlining())
             {
-                // Make an inlining decision based on the estimated native size.
-                int callsiteNativeSizeEstimate =
-                    compInlineResult->DetermineCallsiteNativeSizeEstimate(
-                        &impInlineInfo->inlineCandidateInfo->methInfo);
-
-                impCanInlineNative(callsiteNativeSizeEstimate,
-                                   compNativeSizeEstimate,
-                                   impInlineInfo,
-                                   compInlineResult);
-
+                // Assess profitability...
+                CORINFO_METHOD_INFO* methodInfo = &impInlineInfo->inlineCandidateInfo->methInfo;
+                compInlineResult->DetermineProfitability(methodInfo);
+                
                 if (compInlineResult->IsFailure())
                 {
-#ifdef DEBUG
-                    if (verbose)
-                    {
-                        printf("\n\nInline expansion aborted because of impCanInlineNative: %s %s\n",
-                               compInlineResult->ResultString(),
-                               compInlineResult->ReasonString());
-                    }
-#endif
-
+                    JITDUMP("\n\nInline expansion aborted, inline not profitable\n");
                     return;
                 }
+                else
+                {
+                    // The inline is still viable.
+                    assert(compInlineResult->IsCandidate());
+                }
+            }
+            else
+            {
+                // Prejit root case. Profitability assessment for this
+                // is done over in compCompileHelper.
             }
         }
     }
index 56b0477..10d783f 100644 (file)
@@ -15467,13 +15467,21 @@ BOOL     Compiler::impIsAddressInLocal(GenTreePtr tree, GenTreePtr * lclVarTreeO
     }
 }
 
-/*****************************************************************************
- */
+//------------------------------------------------------------------------
+// impMakeDiscretionaryInlineObservations: make observations that help
+// determine the profitability of a discretionary inline
+//
+// Arguments:
+//    pInlineInfo -- InlineInfo for the inline, or null for the prejit root
+//    inlineResult -- InlineResult accumulating information about this inline
+//
+// Notes:
+//    If inlining or prejitting the root, this method also makes
+//    various observations about the method that factor into inline
+//    decisions. It sets `compNativeSizeEstimate` as a side effect.
 
-void             Compiler::impCanInlineNative(int           callsiteNativeEstimate,
-                                              int           calleeNativeSizeEstimate,
-                                              InlineInfo*   pInlineInfo,     // NULL for static inlining hint for ngen.
-                                              InlineResult* inlineResult)
+void Compiler::impMakeDiscretionaryInlineObservations(InlineInfo*   pInlineInfo,
+                                                      InlineResult* inlineResult)
 {
     assert(pInlineInfo != NULL &&  compIsForInlining() ||  // Perform the actual inlining.
            pInlineInfo == NULL && !compIsForInlining()     // Calculate the static inlining hint for ngen.
@@ -15487,8 +15495,6 @@ void             Compiler::impCanInlineNative(int           callsiteNativeEstima
     // shouldn't be relying on the result of this method.
     assert(inlineResult->GetObservation() == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE);
 
-    JITDUMP("\ncalleeNativeSizeEstimate=%d, callsiteNativeEstimate=%d.\n", calleeNativeSizeEstimate, callsiteNativeEstimate);
-
     // Note if this method is an instance constructor
     if ((info.compFlags & CORINFO_FLG_CONSTRUCTOR) != 0 &&
         (info.compFlags & CORINFO_FLG_STATIC)      == 0)
@@ -15549,53 +15555,6 @@ void             Compiler::impCanInlineNative(int           callsiteNativeEstima
     }
 
     inlineResult->NoteInt(InlineObservation::CALLSITE_FREQUENCY, static_cast<int>(frequency));
-
-    // Determine multiplier given the various observations.
-    double multiplier = inlineResult->DetermineMultiplier();
-
-    // Note the various estimates we've obtained.
-    inlineResult->NoteInt(InlineObservation::CALLEE_NATIVE_SIZE_ESTIMATE, calleeNativeSizeEstimate);
-    inlineResult->NoteInt(InlineObservation::CALLSITE_NATIVE_SIZE_ESTIMATE, callsiteNativeEstimate);
-    inlineResult->NoteDouble(InlineObservation::CALLSITE_BENEFIT_MULTIPLIER, multiplier);
-
-    int threshold = (int)(callsiteNativeEstimate * multiplier);
-
-    JITDUMP("\ncalleeNativeSizeEstimate=%d, threshold=%d.\n", calleeNativeSizeEstimate, threshold);
-        
-#define NATIVE_CALL_SIZE_MULTIPLIER (10.0)
-    if (calleeNativeSizeEstimate > threshold)
-    {
-#ifdef DEBUG
-        char * message = (char *)compAllocator->allocateMemory(128);
-        sprintf(message, "Native estimate for function size exceeds threshold %g > %g (multiplier = %g).",
-                calleeNativeSizeEstimate / NATIVE_CALL_SIZE_MULTIPLIER,
-                threshold / NATIVE_CALL_SIZE_MULTIPLIER, multiplier);
-        //pInlineInfo is null when we're determining the static hint for inlining.
-#else
-        const char * message = "Native estimate for function size exceeds threshold.";
-#endif
-
-        if (pInlineInfo != nullptr) 
-        {
-            inlineResult->NoteFatal(InlineObservation::CALLSITE_EXCEEDS_THRESHOLD);
-        }
-        else 
-        {
-            // Static hint case.... here the "callee" is the function being assessed.
-            inlineResult->NoteFatal(InlineObservation::CALLEE_EXCEEDS_THRESHOLD);
-        }
-    }
-    else 
-    {
-       JITLOG((LL_INFO100000, "Native estimate for function size is within threshold for inlining %g <= %g (multiplier = %g)\n",
-                 calleeNativeSizeEstimate / NATIVE_CALL_SIZE_MULTIPLIER,
-                 threshold / NATIVE_CALL_SIZE_MULTIPLIER, multiplier));
-
-       // Candidate has passed the profitability screen, update candidacy.
-       inlineResult->Note(InlineObservation::CALLSITE_NATIVE_SIZE_ESTIMATE_OK);
-    }
-
-#undef NATIVE_CALL_SIZE_MULTIPLIER
 }
 
 
index c2e6082..554b60a 100644 (file)
@@ -35,7 +35,7 @@ INLINE_OBSERVATION(HAS_DELEGATE_INVOKE,       bool,   "delegate invoke",
 INLINE_OBSERVATION(HAS_EH,                    bool,   "has exception handling",        FATAL,       CALLEE)
 INLINE_OBSERVATION(HAS_ENDFILTER,             bool,   "has endfilter",                 FATAL,       CALLEE)
 INLINE_OBSERVATION(HAS_ENDFINALLY,            bool,   "has endfinally",                FATAL,       CALLEE)
-INLINE_OBSERVATION(HAS_LEAVE,                 bool,   "has leave"    ,                 FATAL,       CALLEE)
+INLINE_OBSERVATION(HAS_LEAVE,                 bool,   "has leave",                     FATAL,       CALLEE)
 INLINE_OBSERVATION(HAS_MANAGED_VARARGS,       bool,   "managed varargs",               FATAL,       CALLEE)
 INLINE_OBSERVATION(HAS_NATIVE_VARARGS,        bool,   "native varargs",                FATAL,       CALLEE)
 INLINE_OBSERVATION(HAS_NO_BODY,               bool,   "has no body",                   FATAL,       CALLEE)
@@ -54,6 +54,7 @@ INLINE_OBSERVATION(MARKED_AS_SKIPPED,         bool,   "skipped by complus reques
 INLINE_OBSERVATION(MAXSTACK_TOO_BIG,          bool,   "maxstack too big"  ,            FATAL,       CALLEE)
 INLINE_OBSERVATION(NEEDS_SECURITY_CHECK,      bool,   "needs security check",          FATAL,       CALLEE)
 INLINE_OBSERVATION(NO_METHOD_INFO,            bool,   "cannot get method info",        FATAL,       CALLEE)
+INLINE_OBSERVATION(NOT_PROFITABLE_INLINE,     bool,   "unprofitable inline",           FATAL,       CALLEE)
 INLINE_OBSERVATION(RETURN_TYPE_IS_COMPOSITE,  bool,   "has composite return type",     FATAL,       CALLEE)
 INLINE_OBSERVATION(STACK_CRAWL_MARK,          bool,   "uses stack crawl mark",         FATAL,       CALLEE)
 INLINE_OBSERVATION(STFLD_NEEDS_HELPER,        bool,   "stfld needs helper",            FATAL,       CALLEE)
@@ -84,9 +85,9 @@ INLINE_OBSERVATION(IS_DISCRETIONARY_INLINE,   bool,   "can inline, check heurist
 INLINE_OBSERVATION(IS_FORCE_INLINE,           bool,   "aggressive inline attribute",   INFORMATION, CALLEE)
 INLINE_OBSERVATION(IS_INSTANCE_CTOR,          bool,   "instance constructor",          INFORMATION, CALLEE)
 INLINE_OBSERVATION(IS_MOSTLY_LOAD_STORE,      bool,   "method is mostly load/store",   INFORMATION, CALLEE)
+INLINE_OBSERVATION(IS_PROFITABLE_INLINE,      bool,   "profitable inline",             INFORMATION, CALLEE)
 INLINE_OBSERVATION(LOOKS_LIKE_WRAPPER,        bool,   "thin wrapper around a call",    INFORMATION, CALLEE)
 INLINE_OBSERVATION(MAXSTACK,                  int,    "maxstack",                      INFORMATION, CALLEE)
-INLINE_OBSERVATION(NATIVE_SIZE_ESTIMATE,      double, "native size estimate",          INFORMATION, CALLEE)
 INLINE_OBSERVATION(OPCODE,                    int,    "next opcode in IL stream",      INFORMATION, CALLEE)
 INLINE_OBSERVATION(OPCODE_NORMED,             int,    "next opcode in IL stream",      INFORMATION, CALLEE)
 INLINE_OBSERVATION(NUMBER_OF_ARGUMENTS,       int,    "number of arguments",           INFORMATION, CALLEE)
@@ -134,6 +135,7 @@ INLINE_OBSERVATION(LDARGA_NOT_LOCAL_VAR,      bool,   "ldarga not on local var",
 INLINE_OBSERVATION(LDFLD_NEEDS_HELPER,        bool,   "ldfld needs helper",            FATAL,       CALLSITE)
 INLINE_OBSERVATION(LDVIRTFN_ON_NON_VIRTUAL,   bool,   "ldvirtfn on non-virtual",       FATAL,       CALLSITE)
 INLINE_OBSERVATION(NOT_CANDIDATE,             bool,   "not inline candidate",          FATAL,       CALLSITE)
+INLINE_OBSERVATION(NOT_PROFITABLE_INLINE,     bool,   "unprofitable inline",           FATAL,       CALLSITE)
 INLINE_OBSERVATION(REQUIRES_SAME_THIS,        bool,   "requires same this",            FATAL,       CALLSITE)
 INLINE_OBSERVATION(RETURN_TYPE_MISMATCH,      bool,   "return type mismatch",          FATAL,       CALLSITE)
 INLINE_OBSERVATION(STFLD_NEEDS_HELPER,        bool,   "stfld needs helper",            FATAL,       CALLSITE)
@@ -144,12 +146,10 @@ INLINE_OBSERVATION(TOO_MANY_LOCALS,           bool,   "too many locals",
 
 // ------ Call Site Information ------- 
 
-INLINE_OBSERVATION(BENEFIT_MULTIPLIER,        double, "benefit multiplier",            INFORMATION, CALLSITE)
 INLINE_OBSERVATION(CONSTANT_ARG_FEEDS_TEST,   bool,   "constant argument feeds test",  INFORMATION, CALLSITE)
 INLINE_OBSERVATION(DEPTH,                     int,    "depth",                         INFORMATION, CALLSITE)
 INLINE_OBSERVATION(FREQUENCY,                 int,    "execution frequency",           INFORMATION, CALLSITE)
-INLINE_OBSERVATION(NATIVE_SIZE_ESTIMATE,      double, "native size estimate",          INFORMATION, CALLSITE)
-INLINE_OBSERVATION(NATIVE_SIZE_ESTIMATE_OK,   bool,   "native size estimate ok",       INFORMATION, CALLSITE)
+INLINE_OBSERVATION(IS_PROFITABLE_INLINE,      bool,   "profitable inline",             INFORMATION, CALLSITE)
 
 // ------ Final Sentinel ------- 
 
index 923140d..8e1cbea 100644 (file)
@@ -241,9 +241,7 @@ public:
     virtual void NoteDouble(InlineObservation obs, double value) = 0;
 
     // Policy determinations
-    virtual double DetermineMultiplier() = 0;
-    virtual int DetermineNativeSizeEstimate() = 0;
-    virtual int DetermineCallsiteNativeSizeEstimate(CORINFO_METHOD_INFO* methodInfo) = 0;
+    virtual void DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) = 0;
 
     // Policy policies
     virtual bool PropagateNeverToRuntime() const = 0;
@@ -320,6 +318,16 @@ public:
         return InlDecisionIsCandidate(m_Policy->GetDecision());
     }
 
+    // Has the policy determined this inline attempt is still viable
+    // and is a discretionary inline?
+    bool IsDiscretionaryCandidate() const
+    {
+        bool result = InlDecisionIsCandidate(m_Policy->GetDecision()) &&             
+            (m_Policy->GetObservation() == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE);
+
+        return result;
+    }
+
     // Has the policy made a determination?
     bool IsDecided() const
     {
@@ -373,22 +381,10 @@ public:
         m_Policy->NoteDouble(obs, value);
     }
 
-    // Determine the benfit multiplier for this inline.
-    double DetermineMultiplier()
-    {
-        return m_Policy->DetermineMultiplier();
-    }
-
-    // Determine the native size estimate for this inline
-    int DetermineNativeSizeEstimate()
-    {
-        return m_Policy->DetermineNativeSizeEstimate();
-    }
-
-    // Determine the native size estimate for this call site
-    int DetermineCallsiteNativeSizeEstimate(CORINFO_METHOD_INFO* methodInfo)
+    // Determine if this inline is profitable
+    void DetermineProfitability(CORINFO_METHOD_INFO* methodInfo)
     {
-        return m_Policy->DetermineCallsiteNativeSizeEstimate(methodInfo);
+        return m_Policy->DetermineProfitability(methodInfo);
     }
 
     // Ensure details of this inlining process are appropriately
index a712ec7..a5956d1 100644 (file)
@@ -99,10 +99,6 @@ void LegacyPolicy::NoteBool(InlineObservation obs, bool value)
         case InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST:
             m_ConstantFeedsConstantTest = value;
             break;
-        case InlineObservation::CALLSITE_NATIVE_SIZE_ESTIMATE_OK:
-            // Passed the profitability screen. Update candidacy.
-            SetCandidate(obs);
-            break;
         case InlineObservation::CALLEE_BEGIN_OPCODE_SCAN:
             {
                 // Set up the state machine, if this inline is
@@ -120,17 +116,9 @@ void LegacyPolicy::NoteBool(InlineObservation obs, bool value)
 
         case InlineObservation::CALLEE_END_OPCODE_SCAN:
             {
-                // We only expect to see this observation once, so the
-                // native size estimate should have its initial value.
-                assert(m_NativeSizeEstimate == NATIVE_SIZE_INVALID);
-
-                // If we were using the state machine, get it to kick
-                // out a size estimate.
                 if (m_StateMachine != nullptr)
                 {
                     m_StateMachine->End();
-                    m_NativeSizeEstimate = m_StateMachine->NativeSize;
-                    assert(m_NativeSizeEstimate != NATIVE_SIZE_INVALID);
                 }
 
                 break;
@@ -525,11 +513,9 @@ double LegacyPolicy::DetermineMultiplier()
 int LegacyPolicy::DetermineNativeSizeEstimate()
 {
     // Should be a discretionary candidate.
-    assert(m_Observation == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE);
-    // Should have a valid state machine estimate.
-    assert(m_NativeSizeEstimate != NATIVE_SIZE_INVALID);
+    assert(m_StateMachine != nullptr);
 
-    return m_NativeSizeEstimate;
+    return m_StateMachine->NativeSize;
 }
 
 //------------------------------------------------------------------------
@@ -594,3 +580,82 @@ int LegacyPolicy::DetermineCallsiteNativeSizeEstimate(CORINFO_METHOD_INFO* methI
 
     return callsiteSize;
 }
+
+//------------------------------------------------------------------------
+// DetermineProfitability: determine if this inline is profitable
+//
+// Arguments:
+//    methodInfo -- method info for the callee
+//
+// Notes:
+//    A profitable inline is one that is projected to have a beneficial
+//    size/speed tradeoff.
+//
+//    It is expected that this method is only invoked for discretionary
+//    candidates, since it does not make sense to do this assessment for
+//    failed, always, or forced inlines.
+
+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);
+        }
+    }
+}
index 0f9138f..34e1b99 100644 (file)
@@ -43,7 +43,6 @@ public:
         , m_Compiler(compiler)
         , m_StateMachine(nullptr)
         , m_CodeSize(0)
-        , m_NativeSizeEstimate(NATIVE_SIZE_INVALID)
         , m_CallsiteFrequency(InlineCallsiteFrequency::UNUSED)
         , m_IsForceInline(false)
         , m_IsForceInlineKnown(false)
@@ -67,9 +66,7 @@ public:
     void NoteDouble(InlineObservation obs, double value) override;
 
     // Policy determinations
-    double DetermineMultiplier() override;
-    int DetermineNativeSizeEstimate() override;
-    int DetermineCallsiteNativeSizeEstimate(CORINFO_METHOD_INFO* methodInfo) override;
+    void DetermineProfitability(CORINFO_METHOD_INFO* methodInfo) override;
 
     // Policy policies
     bool PropagateNeverToRuntime() const override { return true; }
@@ -85,6 +82,9 @@ private:
     void SetCandidate(InlineObservation obs);
     void SetFailure(InlineObservation obs);
     void SetNever(InlineObservation obs);
+    double DetermineMultiplier();
+    int DetermineNativeSizeEstimate();
+    int DetermineCallsiteNativeSizeEstimate(CORINFO_METHOD_INFO* methodInfo);
 
     // Constants
     const unsigned MAX_BASIC_BLOCKS = 5;
@@ -93,7 +93,6 @@ private:
     Compiler*               m_Compiler;
     CodeSeqSM*              m_StateMachine;
     unsigned                m_CodeSize;
-    int                     m_NativeSizeEstimate;
     InlineCallsiteFrequency m_CallsiteFrequency;
     bool                    m_IsForceInline :1;
     bool                    m_IsForceInlineKnown :1;