summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2016-03-08 18:02:56 -0800
committerAndy Ayers <andya@microsoft.com>2016-03-08 18:02:56 -0800
commitd2ab1fbd40343e01fcb71fb9793ee7c681eeb1de (patch)
tree4750d1658892573be1dc1f45df88aa1c45df09be
parent770f74904b900d77853c3e94370bc36fa3e97340 (diff)
parent1876230e5098541c150f2893644fda413484426c (diff)
downloadcoreclr-d2ab1fbd40343e01fcb71fb9793ee7c681eeb1de.tar.gz
coreclr-d2ab1fbd40343e01fcb71fb9793ee7c681eeb1de.tar.bz2
coreclr-d2ab1fbd40343e01fcb71fb9793ee7c681eeb1de.zip
Merge pull request #3574 from AndyAyersMS/InlineRefactorMoveStateMachineMerge
Inline refactoring: move state machine into LegacyPolicy
-rw-r--r--src/jit/compiler.cpp6
-rw-r--r--src/jit/compiler.h3
-rw-r--r--src/jit/flowgraph.cpp209
-rw-r--r--src/jit/inline.def4
-rw-r--r--src/jit/inline.h14
-rw-r--r--src/jit/inlinepolicy.cpp94
-rw-r--r--src/jit/inlinepolicy.h34
-rw-r--r--src/jit/morph.cpp5
8 files changed, 213 insertions, 156 deletions
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index ea120565a0..2c61e8983b 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -4860,9 +4860,9 @@ int Compiler::compCompileHelper (CORINFO_MODULE_HANDLE clas
// do the profitability screening.
if (prejitResult.isCandidate())
{
- // Only needed if the inline is discretionary (not forced)
- // and the size is over the always threshold.
- if (!forceInline && (methodInfo->ILCodeSize > ALWAYS_INLINE_SIZE))
+ // 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.
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 7c4b8f5552..f1e947bd8c 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -8568,9 +8568,6 @@ public:
int compNativeSizeEstimate; // The estimated native size of this method.
-#ifdef DEBUG
- CodeSeqSM fgCodeSeqSm; // The code sequence state machine used in the inliner.
-#endif
private:
#ifdef FEATURE_JIT_METHOD_PERF
JitTimer* pCompJitTimer; // Timer data structure (by phases) for current compilation.
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp
index bd397ab30d..f8ba54e6f9 100644
--- a/src/jit/flowgraph.cpp
+++ b/src/jit/flowgraph.cpp
@@ -4182,90 +4182,53 @@ private:
unsigned slot1;
unsigned depth;
};
+//------------------------------------------------------------------------
+// fgFindJumpTargets: walk the IL stream, determining jump target offsets
+//
+// Arguments:
+// codeAddr - base address of the IL code buffer
+// codeSize - number of bytes in the IL code buffer
+// jumpTarget - [OUT] xxx yuuu
+//
+// 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.
+//
+// May throw an exception if the IL is malformed.
-void Compiler::fgFindJumpTargets(const BYTE * codeAddr,
- IL_OFFSET codeSize,
- BYTE * jumpTarget)
+void Compiler::fgFindJumpTargets(const BYTE* codeAddr,
+ IL_OFFSET codeSize,
+ BYTE* jumpTarget)
{
-
- const BYTE * codeBegp = codeAddr;
- const BYTE * codeEndp = codeAddr + codeSize;
- unsigned varNum;
-
- bool seenJump = false;
-
- OPCODE opcode;
-
- var_types varType = DUMMY_INIT(TYP_UNDEF); // TYP_ type
- typeInfo ti; // Verifier type.
-
-#ifndef DEBUG
- CodeSeqSM LocalSm;
-#endif
-
- CodeSeqSM * pSm = NULL;
-
- SM_OPCODE smOpcode = DUMMY_INIT((SM_OPCODE)0);
-
- unsigned ldStCount = 0; //Number of load/store instructions.
-
- // Keep track of constants and args on the stack.
- fgStack pushedStack;
-
- // Observe force inline state and code size.
- bool isForceInline = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0;
+ const BYTE* codeBegp = codeAddr;
+ const BYTE* codeEndp = codeAddr + codeSize;
+ unsigned varNum;
+ bool seenJump = false;
+ var_types varType = DUMMY_INIT(TYP_UNDEF); // TYP_ type
+ typeInfo ti; // Verifier type.
+ bool typeIsNormed = false;
+ unsigned ldStCount = 0; // Number of load/store instructions.
+ fgStack pushedStack; // Keep track of constants and args on the stack.
+ const bool isForceInline = (info.compFlags & CORINFO_FLG_FORCEINLINE) != 0;
if (compInlineResult != nullptr)
{
+ // Observe force inline state and code size.
compInlineResult->noteBool(InlineObservation::CALLEE_IS_FORCE_INLINE, isForceInline);
compInlineResult->noteInt(InlineObservation::CALLEE_IL_CODE_SIZE, codeSize);
- }
-
- // Determine whether to start the state machine to estimate the size of the
- // native code for this method.
- bool useSm = false;
- if ((codeSize > ALWAYS_INLINE_SIZE) && !isForceInline)
- {
- // The size of the native code for this method matters for inlining
- // decisions.
-
- if (compIsForInlining())
- {
- // This method is being compiled as an inline candidate and will be
- // rejected if its native code is too large.
-
- useSm = true;
- }
- else if ((opts.eeFlags & CORJIT_FLG_PREJIT) &&
- (codeSize <= impInlineSize))
- {
- // This method isn't an inline candidate yet, but it's small enough
- // to be considered for one in the future. Keep track of the
- // estimated native code size; it will be used elsewhere later.
-
- useSm = true;
- }
- }
-
- if (useSm)
- {
-
-#ifdef DEBUG
- pSm = &fgCodeSeqSm;
-#else
- pSm = &LocalSm;
-#endif
- pSm->Start(this);
+ // note that we're starting to look at the opcodes.
+ compInlineResult->note(InlineObservation::CALLEE_BEGIN_OPCODE_SCAN);
}
while (codeAddr < codeEndp)
{
- unsigned sz;
-
- opcode = (OPCODE) getU1LittleEndian(codeAddr);
+ OPCODE opcode = (OPCODE) getU1LittleEndian(codeAddr);
codeAddr += sizeof(__int8);
opts.instrCount++;
+ typeIsNormed = false;
DECODE_OPCODE:
@@ -4274,6 +4237,7 @@ DECODE_OPCODE:
if (opcode >= CEE_COUNT)
BADCODE3("Illegal opcode", ": %02X", (int) opcode);
+ // --- leave ldstcount for now, though it can be moved ---
if ((opcode >= CEE_LDARG_0 && opcode <= CEE_STLOC_S) ||
(opcode >= CEE_LDARG && opcode <= CEE_STLOC))
{
@@ -4299,12 +4263,7 @@ DECODE_OPCODE:
++ldStCount;
}
- sz = opcodeSizes[opcode];
-
- if (pSm)
- {
- smOpcode = CodeSeqSM::MapToSMOpcode(opcode);
- }
+ unsigned sz = opcodeSizes[opcode];
switch (opcode)
{
@@ -4703,11 +4662,8 @@ ADDR_TAKEN:
varNum = compMapILargNum(varNum); // account for possible hidden param
}
- if (pSm)
- {
- varType = (var_types)lvaTable[varNum].lvType;
- ti = lvaTable[varNum].lvVerTypeInfo;
- }
+ varType = (var_types)lvaTable[varNum].lvType;
+ ti = lvaTable[varNum].lvVerTypeInfo;
if (!varTypeIsStruct(&lvaTable[varNum]) && // We will put structs in the stack anyway
// And changing the addrTaken of a local
@@ -4744,21 +4700,7 @@ ADDR_TAKEN:
}
} // compIsForInlining()
- if (pSm &&
- ti.IsValueClass() &&
- !varTypeIsStruct(varType))
- {
-#ifdef DEBUG
- if (verbose)
- printf("Loading address of normed V%02u at IL offset [0x%x]\n", varNum, codeAddr-codeBegp-1);
-#endif
-
- if (smOpcode == SM_LDARGA_S)
- smOpcode = SM_LDARGA_S_NORMED;
- else if (smOpcode == SM_LDLOCA_S)
- smOpcode = SM_LDLOCA_S_NORMED;
- }
-
+ typeIsNormed = ti.IsValueClass() && !varTypeIsStruct(varType);
break;
ARG_WRITE:
@@ -4803,17 +4745,14 @@ ARG_WRITE:
_SkipCodeAddrAdjustment:
;
- if (pSm)
+ if (compInlineResult != nullptr)
{
- noway_assert(smOpcode<SM_COUNT);
- noway_assert(smOpcode != SM_PREFIX_N);
-
- pSm->Run(smOpcode DEBUGARG(0));
+ InlineObservation obs = typeIsNormed ?
+ InlineObservation::CALLEE_OPCODE_NORMED : InlineObservation::CALLEE_OPCODE;
+ compInlineResult->noteInt(obs, opcode);
}
-
}
-
if (codeAddr != codeEndp)
{
TOO_FAR:
@@ -4837,45 +4776,51 @@ TOO_FAR:
}
}
- if (pSm)
+ if (compInlineResult != nullptr)
{
- pSm->End();
- noway_assert(pSm->NativeSize != NATIVE_SIZE_INVALID);
- compNativeSizeEstimate = pSm->NativeSize;
+ compInlineResult->note(InlineObservation::CALLEE_END_OPCODE_SCAN);
-#ifdef DEBUG
- if (verbose)
+ // If we were estimating native code size, grab that data now.
+ if (compInlineResult->hasNativeSizeEstimate())
{
- printf("\n\ncompNativeSizeEstimate=%d\n", compNativeSizeEstimate);
- }
-#endif
+ compNativeSizeEstimate = compInlineResult->determineNativeSizeEstimate();
+ noway_assert(compNativeSizeEstimate != NATIVE_SIZE_INVALID);
+ JITDUMP("\n\ncompNativeSizeEstimate=%d\n", compNativeSizeEstimate);
- if (compIsForInlining())
- {
- // If the inlining decision was obvious from the size of the IL,
- // it should have been made earlier.
- noway_assert(codeSize > ALWAYS_INLINE_SIZE && codeSize <= impInlineSize);
+ // 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())
+ {
+ // If the inlining decision was obvious from the size of the IL,
+ // it should have been made earlier.
+ InlineObservation obs = compInlineResult->getObservation();
+ noway_assert(obs == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE);
- // Make an inlining decision based on the estimated native size.
- int callsiteNativeSizeEstimate = impEstimateCallsiteNativeSize(&impInlineInfo->inlineCandidateInfo->methInfo);
+ // Make an inlining decision based on the estimated native size.
+ int callsiteNativeSizeEstimate = impEstimateCallsiteNativeSize(&impInlineInfo->inlineCandidateInfo->methInfo);
- impCanInlineNative(callsiteNativeSizeEstimate,
- compNativeSizeEstimate,
- impInlineInfo,
- compInlineResult);
+ impCanInlineNative(callsiteNativeSizeEstimate,
+ compNativeSizeEstimate,
+ impInlineInfo,
+ compInlineResult);
- if (compInlineResult->isFailure())
- {
-#ifdef DEBUG
- if (verbose)
+ if (compInlineResult->isFailure())
{
- printf("\n\nInline expansion aborted because of impCanInlineNative: %s %s\n",
- compInlineResult->resultString(),
- compInlineResult->reasonString());
- }
+#ifdef DEBUG
+ if (verbose)
+ {
+ printf("\n\nInline expansion aborted because of impCanInlineNative: %s %s\n",
+ compInlineResult->resultString(),
+ compInlineResult->reasonString());
+ }
#endif
- return;
+ return;
+ }
}
}
}
diff --git a/src/jit/inline.def b/src/jit/inline.def
index 19a5147ce4..9d2b07afb5 100644
--- a/src/jit/inline.def
+++ b/src/jit/inline.def
@@ -73,8 +73,10 @@ INLINE_OBSERVATION(TOO_MUCH_IL, bool, "too many il bytes",
INLINE_OBSERVATION(ARG_FEEDS_CONSTANT_TEST, bool, "argument feeds constant test", INFORMATION, CALLEE)
INLINE_OBSERVATION(ARG_FEEDS_RANGE_CHECK, bool, "argument feeds range check", INFORMATION, CALLEE)
+INLINE_OBSERVATION(BEGIN_OPCODE_SCAN, bool, "prepare to look at opcodes", INFORMATION, CALLEE)
INLINE_OBSERVATION(BELOW_ALWAYS_INLINE_SIZE, bool, "below ALWAYS_INLINE size", INFORMATION, CALLEE)
INLINE_OBSERVATION(CLASS_PROMOTABLE, bool, "promotable value class", INFORMATION, CALLEE)
+INLINE_OBSERVATION(END_OPCODE_SCAN, bool, "done looking at opcodes", INFORMATION, CALLEE)
INLINE_OBSERVATION(HAS_SIMD, bool, "has SIMD arg, local, or ret", INFORMATION, CALLEE)
INLINE_OBSERVATION(HAS_SWITCH, bool, "has switch", INFORMATION, CALLEE)
INLINE_OBSERVATION(IL_CODE_SIZE, int, "number of bytes of IL", INFORMATION, CALLEE)
@@ -85,6 +87,8 @@ INLINE_OBSERVATION(IS_MOSTLY_LOAD_STORE, bool, "method is mostly load/sto
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)
INLINE_OBSERVATION(NUMBER_OF_BASIC_BLOCKS, int, "number of basic blocks", INFORMATION, CALLEE)
INLINE_OBSERVATION(NUMBER_OF_LOCALS, int, "number of locals", INFORMATION, CALLEE)
diff --git a/src/jit/inline.h b/src/jit/inline.h
index 625e1ea7ed..9a5a7bcf7d 100644
--- a/src/jit/inline.h
+++ b/src/jit/inline.h
@@ -228,6 +228,8 @@ public:
// Policy determinations
virtual double determineMultiplier() = 0;
+ virtual bool hasNativeSizeEstimate() = 0;
+ virtual int determineNativeSizeEstimate() = 0;
// Policy policies
virtual bool propagateNeverToRuntime() const = 0;
@@ -363,6 +365,18 @@ public:
return inlPolicy->determineMultiplier();
}
+ // Is there a native size estimate?
+ bool hasNativeSizeEstimate()
+ {
+ return inlPolicy->hasNativeSizeEstimate();
+ }
+
+ // Determine the native size estimate for this inline
+ int determineNativeSizeEstimate()
+ {
+ return inlPolicy->determineNativeSizeEstimate();
+ }
+
// Ensure details of this inlining process are appropriately
// reported when the result goes out of scope.
~InlineResult()
diff --git a/src/jit/inlinepolicy.cpp b/src/jit/inlinepolicy.cpp
index ceace2deca..fd8dd82f09 100644
--- a/src/jit/inlinepolicy.cpp
+++ b/src/jit/inlinepolicy.cpp
@@ -8,6 +8,7 @@
#endif
#include "inlinepolicy.h"
+#include "sm.h"
//------------------------------------------------------------------------
// getPolicy: Factory method for getting an InlinePolicy
@@ -41,12 +42,11 @@ void LegacyPolicy::noteSuccess()
}
//------------------------------------------------------------------------
-// note: handle an observation with non-fatal impact
+// noteBool: handle a boolean observation with non-fatal impact
//
// Arguments:
// obs - the current obsevation
// value - the value of the observation
-
void LegacyPolicy::noteBool(InlineObservation obs, bool value)
{
// Check the impact
@@ -103,6 +103,39 @@ void LegacyPolicy::noteBool(InlineObservation obs, bool value)
// Passed the profitability screen. Update candidacy.
setCandidate(obs);
break;
+ case InlineObservation::CALLEE_BEGIN_OPCODE_SCAN:
+ {
+ // Set up the state machine, if this inline is
+ // discretionary and is still a candidate.
+ if (inlDecisionIsCandidate(inlDecision)
+ && (inlObservation == InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE))
+ {
+ // Better not have a state machine already.
+ assert(inlStateMachine == nullptr);
+ inlStateMachine = new (inlCompiler, CMK_Inlining) CodeSeqSM;
+ inlStateMachine->Start(inlCompiler);
+ }
+ break;
+ }
+
+ 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(inlNativeSizeEstimate == NATIVE_SIZE_INVALID);
+
+ // If we were using the state machine, get it to kick
+ // out a size estimate.
+ if (inlStateMachine != nullptr)
+ {
+ inlStateMachine->End();
+ inlNativeSizeEstimate = inlStateMachine->NativeSize;
+ assert(inlNativeSizeEstimate != NATIVE_SIZE_INVALID);
+ }
+
+ break;
+ }
+
default:
// Ignore the remainder for now
break;
@@ -174,11 +207,11 @@ void LegacyPolicy::noteInt(InlineObservation obs, int value)
{
assert(inlIsForceInlineKnown);
assert(value != 0);
- unsigned ilByteSize = static_cast<unsigned>(value);
+ inlCodeSize = static_cast<unsigned>(value);
// Now that we know size and forceinline state,
// update candidacy.
- if (ilByteSize <= ALWAYS_INLINE_SIZE)
+ if (inlCodeSize <= ALWAYS_INLINE_SIZE)
{
// Candidate based on small size
setCandidate(InlineObservation::CALLEE_BELOW_ALWAYS_INLINE_SIZE);
@@ -188,7 +221,7 @@ void LegacyPolicy::noteInt(InlineObservation obs, int value)
// Candidate based on force inline
setCandidate(InlineObservation::CALLEE_IS_FORCE_INLINE);
}
- else if (ilByteSize <= inlCompiler->getImpInlineSize())
+ else if (inlCodeSize <= inlCompiler->getImpInlineSize())
{
// Candidate, pending profitability evaluation
setCandidate(InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE);
@@ -202,6 +235,32 @@ void LegacyPolicy::noteInt(InlineObservation obs, int value)
break;
}
+ case InlineObservation::CALLEE_OPCODE_NORMED:
+ case InlineObservation::CALLEE_OPCODE:
+ {
+ if (inlStateMachine != 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;
+ }
+ }
+
+ inlStateMachine->Run(smOpcode DEBUGARG(0));
+ }
+ break;
+ }
+
default:
// Ignore all other information
break;
@@ -401,3 +460,28 @@ double LegacyPolicy::determineMultiplier()
return multiplier;
}
+
+//------------------------------------------------------------------------
+// hasNativeCodeSizeEstimate: did this policy estimate native code size
+//
+// Notes:
+// Temporary scaffolding for refactoring work.
+
+bool LegacyPolicy::hasNativeSizeEstimate()
+{
+ return (inlStateMachine != nullptr);
+}
+
+//------------------------------------------------------------------------
+// determineNativeCodeSizeEstimate: return estimated native code size for
+// this inline candidate.
+//
+// Notes:
+// Uses the results of a state machine model for discretionary
+// candidates. Should not be needed for forcded or always
+// candidates.
+
+int LegacyPolicy::determineNativeSizeEstimate()
+{
+ return inlNativeSizeEstimate;
+}
diff --git a/src/jit/inlinepolicy.h b/src/jit/inlinepolicy.h
index 4f831a1e77..45faba9085 100644
--- a/src/jit/inlinepolicy.h
+++ b/src/jit/inlinepolicy.h
@@ -17,6 +17,8 @@
#include "jit.h"
#include "inline.h"
+class CodeSeqSM;
+
// LegacyPolicy implements the inlining policy used by the jit in its
// initial release.
//
@@ -39,6 +41,9 @@ public:
LegacyPolicy(Compiler* compiler, bool isPrejitRoot)
: InlinePolicy(isPrejitRoot)
, inlCompiler(compiler)
+ , inlStateMachine(nullptr)
+ , inlCodeSize(0)
+ , inlNativeSizeEstimate(NATIVE_SIZE_INVALID)
, inlIsForceInline(false)
, inlIsForceInlineKnown(false)
, inlIsInstanceCtor(false)
@@ -55,13 +60,15 @@ public:
// Policy observations
void noteSuccess() override;
- void noteFatal(InlineObservation obs) override;
void noteBool(InlineObservation obs, bool value) override;
+ void noteFatal(InlineObservation obs) override;
void noteInt(InlineObservation obs, int value) override;
void noteDouble(InlineObservation obs, double value) override;
// Policy determinations
double determineMultiplier() override;
+ int determineNativeSizeEstimate() override;
+ bool hasNativeSizeEstimate() override;
// Policy policies
bool propagateNeverToRuntime() const override { return true; }
@@ -82,17 +89,20 @@ private:
const unsigned MAX_BASIC_BLOCKS = 5;
// Data members
- Compiler* inlCompiler;
- bool inlIsForceInline :1;
- bool inlIsForceInlineKnown :1;
- bool inlIsInstanceCtor :1;
- bool inlIsFromPromotableValueClass :1;
- bool inlHasSimd :1;
- bool inlLooksLikeWrapperMethod :1;
- bool inlArgFeedsConstantTest :1;
- bool inlMethodIsMostlyLoadStore :1;
- bool inlArgFeedsRangeCheck :1;
- bool inlConstantFeedsConstantTest :1;
+ Compiler* inlCompiler;
+ CodeSeqSM* inlStateMachine;
+ unsigned inlCodeSize;
+ int inlNativeSizeEstimate;
+ bool inlIsForceInline :1;
+ bool inlIsForceInlineKnown :1;
+ bool inlIsInstanceCtor :1;
+ bool inlIsFromPromotableValueClass :1;
+ bool inlHasSimd :1;
+ bool inlLooksLikeWrapperMethod :1;
+ bool inlArgFeedsConstantTest :1;
+ bool inlMethodIsMostlyLoadStore :1;
+ bool inlArgFeedsRangeCheck :1;
+ bool inlConstantFeedsConstantTest :1;
};
#endif // _INLINE_POLICY_H_
diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp
index 3858a20d25..cacbb909fb 100644
--- a/src/jit/morph.cpp
+++ b/src/jit/morph.cpp
@@ -5658,7 +5658,10 @@ void Compiler::fgMorphCallInline(GenTreeCall* call, InlineResult* inlineR
void Compiler::fgMorphCallInlineHelper(GenTreeCall* call, InlineResult* result)
{
- if (lvaCount >= MAX_LV_NUM_COUNT_FOR_INLINING)
+ // Don't expect any surprises here.
+ assert(result->isCandidate());
+
+ if (lvaCount >= MAX_LV_NUM_COUNT_FOR_INLINING)
{
// For now, attributing this to call site, though it's really
// more of a budget issue (lvaCount currently includes all