summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2016-03-07 12:23:09 -0800
committerAndy Ayers <andya@microsoft.com>2016-03-07 13:29:27 -0800
commit96783862204ea1dd91e55ef4c44179535ff68514 (patch)
treef5d8f593ead8af856a6129838a01af17c29e43da /src
parentb440fdf5e0ed03e511a9adcb9196ce324ab2e09a (diff)
downloadcoreclr-96783862204ea1dd91e55ef4c44179535ff68514.tar.gz
coreclr-96783862204ea1dd91e55ef4c44179535ff68514.tar.bz2
coreclr-96783862204ea1dd91e55ef4c44179535ff68514.zip
Inline refactoring: revise candidacy determination
Rework the code to determine the key aspects of candidacy up front rather than figuring it out eventually. In particular this ensures that the two stages of evaulation for inlines both start at the same point for candidates. This will help streamline subsequent work to move the state machine into the policy, since the state machine is only needed for the case where the candidate is a discretionary inline, and the policy now tracks this directly. For the `LegacyPolicy`, if an inline is both smaller than the always inline size and marked force inline, attribute its inlining to its small size. Remove bulk of the of the "evaluation in progress" candidate observations since they don't add much value. As a result `noteCandidate` is not needed as an external API, and can be repurposed internally as `setCandidate`. Change how the prejit root case is tracked to make it explicit from the context rather than a callback to the compiler.
Diffstat (limited to 'src')
-rw-r--r--src/jit/compiler.cpp5
-rw-r--r--src/jit/flowgraph.cpp22
-rw-r--r--src/jit/importer.cpp31
-rw-r--r--src/jit/inline.cpp8
-rw-r--r--src/jit/inline.def9
-rw-r--r--src/jit/inline.h44
-rw-r--r--src/jit/inlinepolicy.cpp134
-rw-r--r--src/jit/inlinepolicy.h17
8 files changed, 131 insertions, 139 deletions
diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp
index 8146f3aa2b..53e24b4764 100644
--- a/src/jit/compiler.cpp
+++ b/src/jit/compiler.cpp
@@ -5059,11 +5059,6 @@ int Compiler::compCompileHelper (CORINFO_MODULE_HANDLE clas
if (compIsForInlining())
{
- if (forceInline)
- {
- compInlineResult->noteCandidate(InlineObservation::CALLEE_IS_FORCE_INLINE);
- }
-
compInlineResult->noteInt(InlineObservation::CALLEE_NUMBER_OF_BASIC_BLOCKS, fgBBcount);
if (compInlineResult->isFailure())
diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp
index 1bb3e1db88..20bc27f6c0 100644
--- a/src/jit/flowgraph.cpp
+++ b/src/jit/flowgraph.cpp
@@ -4214,11 +4214,19 @@ void Compiler::fgFindJumpTargets(const BYTE * codeAddr,
// 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;
+
+ if (compInlineResult != nullptr)
+ {
+ 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) &&
- !(info.compFlags & CORINFO_FLG_FORCEINLINE))
+ if ((codeSize > ALWAYS_INLINE_SIZE) && !isForceInline)
{
// The size of the native code for this method matters for inlining
// decisions.
@@ -4873,16 +4881,6 @@ TOO_FAR:
}
}
}
- else
- {
- if (compIsForInlining())
- {
- // This method's IL was small enough that we didn't use the size model to estimate
- // inlinability. Note that as the latest candidate reason.
- compInlineResult->noteCandidate(InlineObservation::CALLEE_BELOW_ALWAYS_INLINE_SIZE);
- }
- }
-
if (!compIsForInlining() && // None of the local vars in the inlinee should have address taken or been written to.
// Therefore we should NOT need to enter this "if" statement.
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
index 9bb76f118c..fa891036af 100644
--- a/src/jit/importer.cpp
+++ b/src/jit/importer.cpp
@@ -15706,8 +15706,8 @@ void Compiler::impCanInlineNative(int callsiteNativeEstima
calleeNativeSizeEstimate / NATIVE_CALL_SIZE_MULTIPLIER,
threshold / NATIVE_CALL_SIZE_MULTIPLIER, multiplier));
- // Still a viable candidate....update status
- inlineResult->noteCandidate(InlineObservation::CALLSITE_NATIVE_SIZE_ESTIMATE_OK);
+ // Candidate has passed the profitability screen, update candidacy.
+ inlineResult->note(InlineObservation::CALLSITE_NATIVE_SIZE_ESTIMATE_OK);
}
#undef NATIVE_CALL_SIZE_MULTIPLIER
@@ -15751,11 +15751,6 @@ void Compiler::impCanInlineIL(CORINFO_METHOD_HANDLE fncHandle,
return;
}
- if (forceInline)
- {
- inlineResult->noteCandidate(InlineObservation::CALLEE_IS_FORCE_INLINE);
- }
-
// Reject if it has too many locals.
// This is currently an implementation limit due to fixed-size arrays in the
// inline info, rather than a performance heuristic.
@@ -15780,9 +15775,13 @@ void Compiler::impCanInlineIL(CORINFO_METHOD_HANDLE fncHandle,
return;
}
- // Reject large functions
+ // Note force inline state
- inlineResult->noteInt(InlineObservation::CALLEE_NUMBER_OF_IL_BYTES, codeSize);
+ inlineResult->noteBool(InlineObservation::CALLEE_IS_FORCE_INLINE, forceInline);
+
+ // Note IL code size
+
+ inlineResult->noteInt(InlineObservation::CALLEE_IL_CODE_SIZE, codeSize);
if (inlineResult->isFailure())
{
@@ -15797,9 +15796,6 @@ void Compiler::impCanInlineIL(CORINFO_METHOD_HANDLE fncHandle,
{
return;
}
-
- // Still a viable candidate...
- inlineResult->noteCandidate(InlineObservation::CALLEE_CAN_INLINE_IL);
}
/*****************************************************************************
@@ -15984,8 +15980,6 @@ void Compiler::impCheckCanInline(GenTreePtr call,
pInfo->initClassResult = initClassResult;
*(pParam->ppInlineCandidateInfo) = pInfo;
-
- pParam->result->noteCandidate(InlineObservation::CALLEE_CHECK_CAN_INLINE_IL);
_exit:
;
@@ -16091,14 +16085,6 @@ void Compiler::impInlineRecordArgInfo(InlineInfo * pInlineInfo,
printf("\n");
}
#endif
-
- //
- // The current arg does not prevent inlining.
- //
- // This doesn't mean that other information or other args
- // will not prevent inlining of this method.
- //
- inlineResult->noteCandidate(InlineObservation::CALLSITE_ARGS_OK);
}
/*****************************************************************************
@@ -16443,7 +16429,6 @@ void Compiler::impInlineInitVars(InlineInfo * pInlineInfo)
pInlineInfo->hasSIMDTypeArgLocalOrReturn = foundSIMDType;
#endif // FEATURE_SIMD
- inlineResult->noteCandidate(InlineObservation::CALLSITE_LOCALS_OK);
}
diff --git a/src/jit/inline.cpp b/src/jit/inline.cpp
index b0519f2e19..0b582cabe1 100644
--- a/src/jit/inline.cpp
+++ b/src/jit/inline.cpp
@@ -544,7 +544,8 @@ InlineResult::InlineResult(Compiler* compiler,
, inlReported(false)
{
// Set the policy
- inlPolicy = InlinePolicy::getPolicy(compiler);
+ const bool isPrejitRoot = false;
+ inlPolicy = InlinePolicy::getPolicy(compiler, isPrejitRoot);
// Get method handle for caller
inlCaller = inlCompiler->info.compMethodHnd;
@@ -558,7 +559,7 @@ InlineResult::InlineResult(Compiler* compiler,
//------------------------------------------------------------------------
// InlineResult: Construct an InlineResult to evaluate a particular
-// method as a possible inline candidate.
+// method as a possible inline candidate, while prejtting.
//
// Arguments:
// compiler - the compiler instance doing the prejitting
@@ -584,7 +585,8 @@ InlineResult::InlineResult(Compiler* compiler,
, inlReported(false)
{
// Set the policy
- inlPolicy = InlinePolicy::getPolicy(compiler);
+ const bool isPrejitRoot = true;
+ inlPolicy = InlinePolicy::getPolicy(compiler, isPrejitRoot);
}
//------------------------------------------------------------------------
diff --git a/src/jit/inline.def b/src/jit/inline.def
index 2678ee3051..19a5147ce4 100644
--- a/src/jit/inline.def
+++ b/src/jit/inline.def
@@ -74,20 +74,19 @@ 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(BELOW_ALWAYS_INLINE_SIZE, bool, "below ALWAYS_INLINE size", INFORMATION, CALLEE)
-INLINE_OBSERVATION(CAN_INLINE_IL, bool, "IL passes basic checks", INFORMATION, CALLEE)
-INLINE_OBSERVATION(CHECK_CAN_INLINE_IL, bool, "IL passes detailed checks", INFORMATION, CALLEE)
INLINE_OBSERVATION(CLASS_PROMOTABLE, bool, "promotable value class", 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)
+INLINE_OBSERVATION(IS_DISCRETIONARY_INLINE, bool, "can inline, check heuristics", INFORMATION, CALLEE)
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(LOOKS_LIKE_WRAPPER, bool, "thin wrapper around a call", INFORMATION, CALLEE)
INLINE_OBSERVATION(MAXSTACK, int, "maxstack", INFORMATION, CALLEE)
-INLINE_OBSERVATION(IS_MOSTLY_LOAD_STORE, bool, "method is mostly load/store", INFORMATION, CALLEE)
INLINE_OBSERVATION(NATIVE_SIZE_ESTIMATE, double, "native size estimate", 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_IL_BYTES, int, "number of bytes of IL", INFORMATION, CALLEE)
INLINE_OBSERVATION(NUMBER_OF_LOCALS, int, "number of locals", INFORMATION, CALLEE)
// ------ Caller Corectness -------
@@ -141,11 +140,9 @@ INLINE_OBSERVATION(TOO_MANY_LOCALS, bool, "too many locals",
// ------ Call Site Information -------
-INLINE_OBSERVATION(ARGS_OK, bool, "arguments suitable", INFORMATION, CALLSITE)
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(LOCALS_OK, bool, "locals suitable", 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)
diff --git a/src/jit/inline.h b/src/jit/inline.h
index 75367faca9..625e1ea7ed 100644
--- a/src/jit/inline.h
+++ b/src/jit/inline.h
@@ -208,7 +208,7 @@ class InlinePolicy
public:
// Factory method for getting policies
- static InlinePolicy* getPolicy(Compiler* compiler);
+ static InlinePolicy* getPolicy(Compiler* compiler, bool isPrejitRoot);
// Obligatory virtual dtor
virtual ~InlinePolicy() {}
@@ -220,9 +220,8 @@ public:
InlineObservation getObservation() const { return inlObservation; }
// Policy observations
- virtual void noteCandidate(InlineObservation obs) = 0;
virtual void noteSuccess() = 0;
- virtual void note(InlineObservation obs) = 0;
+ virtual void noteBool(InlineObservation obs, bool value) = 0;
virtual void noteFatal(InlineObservation obs) = 0;
virtual void noteInt(InlineObservation obs, int value) = 0;
virtual void noteDouble(InlineObservation obs, double value) = 0;
@@ -240,9 +239,10 @@ public:
protected:
- InlinePolicy()
+ InlinePolicy(bool isPrejitRoot)
: inlDecision(InlineDecision::UNDECIDED)
, inlObservation(InlineObservation::CALLEE_UNUSED_INITIAL)
+ , inlIsPrejitRoot(isPrejitRoot)
{
// empty
}
@@ -255,8 +255,9 @@ private:
protected:
- InlineDecision inlDecision;
+ InlineDecision inlDecision;
InlineObservation inlObservation;
+ bool inlIsPrejitRoot;
};
// InlineResult summarizes what is known about the viability of a
@@ -309,24 +310,6 @@ public:
return inlDecisionIsDecided(inlPolicy->getDecision());
}
- // noteCandidate indicates the prospective inline has passed at least
- // some of the correctness checks and is still a viable inline
- // candidate, but no decision has been made yet.
- //
- // This may be called multiple times as various tests are performed
- // and the candidate gets closer and closer to actually getting
- // inlined.
- void noteCandidate(InlineObservation obs)
- {
- assert(!isDecided());
-
- // Check the impact, it should be INFORMATION
- InlineImpact impact = inlGetImpact(obs);
- assert(impact == InlineImpact::INFORMATION);
-
- inlPolicy->noteCandidate(obs);
- }
-
// noteSuccess means the all the various checks have passed and
// the inline can happen.
void noteSuccess()
@@ -335,13 +318,24 @@ public:
inlPolicy->noteSuccess();
}
- // Make an observation, and update internal state appropriately.
+ // Make a true observation, and update internal state
+ // appropriately.
//
// Caller is expected to call isFailure after this to see whether
// more observation is desired.
void note(InlineObservation obs)
{
- inlPolicy->note(obs);
+ inlPolicy->noteBool(obs, true);
+ }
+
+ // Make a boolean observation, and update internal state
+ // appropriately.
+ //
+ // Caller is expected to call isFailure after this to see whether
+ // more observation is desired.
+ void noteBool(InlineObservation obs, bool value)
+ {
+ inlPolicy->noteBool(obs, value);
}
// Make an observation that must lead to immediate failure.
diff --git a/src/jit/inlinepolicy.cpp b/src/jit/inlinepolicy.cpp
index 31580aff9b..bec5da201b 100644
--- a/src/jit/inlinepolicy.cpp
+++ b/src/jit/inlinepolicy.cpp
@@ -13,7 +13,8 @@
// getPolicy: Factory method for getting an InlinePolicy
//
// Arguments:
-// compiler - the compiler instance that will evaluate inlines
+// compiler - the compiler instance that will evaluate inlines
+// isPrejitRoot - true if this policy is evaluating a prejit root
//
// Return Value:
// InlinePolicy to use in evaluating the inlines
@@ -22,47 +23,15 @@
// Determines which of the various policies should apply,
// and creates (or reuses) a policy instance to use.
-InlinePolicy* InlinePolicy::getPolicy(Compiler* compiler)
+InlinePolicy* InlinePolicy::getPolicy(Compiler* compiler, bool isPrejitRoot)
{
// For now, always create a Legacy policy.
- InlinePolicy* policy = new (compiler, CMK_Inlining) LegacyPolicy(compiler);
+ InlinePolicy* policy = new (compiler, CMK_Inlining) LegacyPolicy(compiler, isPrejitRoot);
return policy;
}
//------------------------------------------------------------------------
-// noteCandidate: handle passing a set of inlining checks successfully
-//
-// Arguments:
-// obs - the current obsevation
-
-void LegacyPolicy::noteCandidate(InlineObservation obs)
-{
- assert(!inlDecisionIsDecided(inlDecision));
-
- // Check the impact, it should be INFORMATION
- InlineImpact impact = inlGetImpact(obs);
- assert(impact == InlineImpact::INFORMATION);
-
- switch (inlDecision)
- {
- case InlineDecision::UNDECIDED:
- case InlineDecision::CANDIDATE:
- // Candidate observations overwrite one another
- inlDecision = InlineDecision::CANDIDATE;
- inlObservation = obs;
- break;
- default:
- // SUCCESS or NEVER or FAILURE or ??
- assert(!"Unexpected inlDecision");
- unreached();
- }
-
- // Now fall through to the general handling.
- note(obs);
-}
-
-//------------------------------------------------------------------------
// noteSuccess: handle finishing all the inlining checks successfully
void LegacyPolicy::noteSuccess()
@@ -76,8 +45,9 @@ void LegacyPolicy::noteSuccess()
//
// Arguments:
// obs - the current obsevation
+// value - the value of the observation
-void LegacyPolicy::note(InlineObservation obs)
+void LegacyPolicy::noteBool(InlineObservation obs, bool value)
{
// Check the impact
InlineImpact impact = inlGetImpact(obs);
@@ -95,35 +65,43 @@ void LegacyPolicy::note(InlineObservation obs)
switch (obs)
{
case InlineObservation::CALLEE_IS_FORCE_INLINE:
- inlIsForceInline = true;
+ // We may make the force-inline observation more than
+ // once. All observations should agree.
+ assert(!inlIsForceInlineKnown || (inlIsForceInline == value));
+ inlIsForceInline = value;
+ inlIsForceInlineKnown = true;
break;
case InlineObservation::CALLEE_IS_INSTANCE_CTOR:
- inlIsInstanceCtor = true;
+ inlIsInstanceCtor = value;
break;
case InlineObservation::CALLEE_CLASS_PROMOTABLE:
- inlIsFromPromotableValueClass = true;
+ inlIsFromPromotableValueClass = value;
break;
case InlineObservation::CALLEE_HAS_SIMD:
- inlHasSimd = true;
+ inlHasSimd = value;
break;
case InlineObservation::CALLEE_LOOKS_LIKE_WRAPPER:
- inlLooksLikeWrapperMethod = true;
+ inlLooksLikeWrapperMethod = value;
break;
case InlineObservation::CALLEE_ARG_FEEDS_CONSTANT_TEST:
- inlArgFeedsConstantTest = true;
+ inlArgFeedsConstantTest = value;
break;
case InlineObservation::CALLEE_ARG_FEEDS_RANGE_CHECK:
- inlArgFeedsRangeCheck = true;
+ inlArgFeedsRangeCheck = value;
break;
case InlineObservation::CALLEE_IS_MOSTLY_LOAD_STORE:
- inlMethodIsMostlyLoadStore = true;
+ inlMethodIsMostlyLoadStore = value;
break;
case InlineObservation::CALLEE_HAS_SWITCH:
// Pass this one on, it should cause inlining to fail.
propagate = true;
break;
case InlineObservation::CALLSITE_CONSTANT_ARG_FEEDS_TEST:
- inlConstantFeedsConstantTest = true;
+ inlConstantFeedsConstantTest = value;
+ break;
+ case InlineObservation::CALLSITE_NATIVE_SIZE_ESTIMATE_OK:
+ // Passed the profitability screen. Update candidacy.
+ setCandidate(obs);
break;
default:
// Ignore the remainder for now
@@ -165,6 +143,8 @@ void LegacyPolicy::noteInt(InlineObservation obs, int value)
{
case InlineObservation::CALLEE_MAXSTACK:
{
+ assert(inlIsForceInlineKnown);
+
unsigned calleeMaxStack = static_cast<unsigned>(value);
if (!inlIsForceInline && (calleeMaxStack > SMALL_STACK_SIZE))
@@ -177,6 +157,7 @@ void LegacyPolicy::noteInt(InlineObservation obs, int value)
case InlineObservation::CALLEE_NUMBER_OF_BASIC_BLOCKS:
{
+ assert(inlIsForceInlineKnown);
assert(value != 0);
unsigned basicBlockCount = static_cast<unsigned>(value);
@@ -189,14 +170,32 @@ void LegacyPolicy::noteInt(InlineObservation obs, int value)
break;
}
- case InlineObservation::CALLEE_NUMBER_OF_IL_BYTES:
+ case InlineObservation::CALLEE_IL_CODE_SIZE:
{
+ assert(inlIsForceInlineKnown);
assert(value != 0);
-
unsigned ilByteSize = static_cast<unsigned>(value);
- if (!inlIsForceInline && (ilByteSize > inlCompiler->getImpInlineSize()))
+ // Now that we know size and forceinline state,
+ // update candidacy.
+ if (ilByteSize <= ALWAYS_INLINE_SIZE)
{
+ // Candidate based on small size
+ setCandidate(InlineObservation::CALLEE_BELOW_ALWAYS_INLINE_SIZE);
+ }
+ else if (inlIsForceInline)
+ {
+ // Candidate based on force inline
+ setCandidate(InlineObservation::CALLEE_IS_FORCE_INLINE);
+ }
+ else if (ilByteSize <= inlCompiler->getImpInlineSize())
+ {
+ // Candidate, pending profitability evaluation
+ setCandidate(InlineObservation::CALLEE_IS_DISCRETIONARY_INLINE);
+ }
+ else
+ {
+ // Callee too big, not a candidate
setNever(InlineObservation::CALLEE_TOO_MUCH_IL);
}
@@ -205,7 +204,6 @@ void LegacyPolicy::noteInt(InlineObservation obs, int value)
default:
// Ignore all other information
- note(obs);
break;
}
}
@@ -219,8 +217,9 @@ void LegacyPolicy::noteInt(InlineObservation obs, int value)
void LegacyPolicy::noteDouble(InlineObservation obs, double value)
{
+ // Ignore for now...
(void) value;
- note(obs);
+ (void) obs;
}
//------------------------------------------------------------------------
@@ -259,8 +258,8 @@ void LegacyPolicy::setFailure(InlineObservation obs)
switch (inlDecision)
{
case InlineDecision::FAILURE:
- // Repeated failure only ok if in prejit scan
- assert(isPrejitScan());
+ // Repeated failure only ok if evaluating a prejit root
+ assert(inlIsPrejitRoot);
break;
case InlineDecision::UNDECIDED:
case InlineDecision::CANDIDATE:
@@ -288,8 +287,8 @@ void LegacyPolicy::setNever(InlineObservation obs)
switch (inlDecision)
{
case InlineDecision::NEVER:
- // Repeated never only ok if in prejit scan
- assert(isPrejitScan());
+ // Repeated never only ok if evaluating a prejit root
+ assert(inlIsPrejitRoot);
break;
case InlineDecision::UNDECIDED:
case InlineDecision::CANDIDATE:
@@ -304,6 +303,33 @@ void LegacyPolicy::setNever(InlineObservation obs)
}
//------------------------------------------------------------------------
+// setCandidate: helper updating candidacy
+//
+// Arguments:
+// obs - the current obsevation
+//
+// Note:
+// Candidate observations are handled here. If the inline has already
+// failed, they're ignored. If there's already a candidate reason,
+// this new reason trumps it.
+
+void LegacyPolicy::setCandidate(InlineObservation obs)
+{
+ // Ignore if this inline is going to fail.
+ if (inlDecisionIsFailure(inlDecision))
+ {
+ return;
+ }
+
+ // We should not have declared success yet.
+ assert(!inlDecisionIsSuccess(inlDecision));
+
+ // Update, overriding any previous candidacy.
+ inlDecision = InlineDecision::CANDIDATE;
+ inlObservation = obs;
+}
+
+//------------------------------------------------------------------------
// determineMultiplier: determine benefit multiplier for this inline
//
// Notes: uses the accumulated set of observations to compute a
diff --git a/src/jit/inlinepolicy.h b/src/jit/inlinepolicy.h
index 42047d1a72..4f831a1e77 100644
--- a/src/jit/inlinepolicy.h
+++ b/src/jit/inlinepolicy.h
@@ -36,10 +36,11 @@ class LegacyPolicy : public InlinePolicy
public:
// Construct a LegacyPolicy
- LegacyPolicy(Compiler* compiler)
- : InlinePolicy()
+ LegacyPolicy(Compiler* compiler, bool isPrejitRoot)
+ : InlinePolicy(isPrejitRoot)
, inlCompiler(compiler)
, inlIsForceInline(false)
+ , inlIsForceInlineKnown(false)
, inlIsInstanceCtor(false)
, inlIsFromPromotableValueClass(false)
, inlHasSimd(false)
@@ -53,10 +54,9 @@ public:
}
// Policy observations
- void noteCandidate(InlineObservation obs) override;
void noteSuccess() override;
- void note(InlineObservation obs) override;
void noteFatal(InlineObservation obs) override;
+ void noteBool(InlineObservation obs, bool value) override;
void noteInt(InlineObservation obs, int value) override;
void noteDouble(InlineObservation obs, double value) override;
@@ -74,22 +74,17 @@ private:
// Helper methods
void noteInternal(InlineObservation obs);
+ void setCandidate(InlineObservation obs);
void setFailure(InlineObservation obs);
void setNever(InlineObservation obs);
- // True if this policy is being used to scan a method during
- // prejitting.
- bool isPrejitScan() const
- {
- return !inlCompiler->compIsForInlining();
- }
-
// Constants
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;